]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc_init: add custom argument parser
authorRicardoSanchezA <ricardo.sanchez@utexas.edu>
Wed, 6 Dec 2017 15:30:44 +0000 (09:30 -0600)
committerRicardoSanchezA <ricardo.sanchez@utexas.edu>
Wed, 6 Dec 2017 15:30:44 +0000 (09:30 -0600)
lxc_init.c should not depend on tools/arguments.{c,h}, thus it needs its own custom argument parser

Signed-off-by: RicardoSanchezA <ricardo.sanchez@utexas.edu>
src/lxc/Makefile.am
src/lxc/lxc_init.c

index 868615e29cf8f0f985e4db2ebb27af3f1c1c7d8e..b688b0e9d25ef051daac16688f1c905bd3ecdc0b 100644 (file)
@@ -276,7 +276,7 @@ lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c
 lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c
 lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c
 lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c
-init_lxc_SOURCES = lxc_init.c tools/arguments.c
+init_lxc_SOURCES = lxc_init.c
 lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c
 lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c
 lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c
@@ -304,8 +304,7 @@ endif
 if HAVE_STATIC_LIBCAP
 sbin_PROGRAMS += init.lxc.static
 
-init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c \
-                         tools/arguments.c
+init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c
 
 if !HAVE_GETLINE
 if HAVE_FGETLN
index 91e2ce3768a00d4c30cea66cfc820a91b79138c7..71ec17e73cc3f1252e1a32bc0ae77ccc2e8a6163 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <ctype.h>
 
 #include <lxc/lxccontainer.h>
 
-#include "tools/arguments.h"
 #include "error.h"
 #include "initutils.h"
 #include "log.h"
+#include "version.h"
+
+/* option keys for long only options */
+#define OPT_USAGE 0x1000
+#define OPT_VERSION OPT_USAGE - 1   
 
 lxc_log_define(lxc_init, lxc);
 
@@ -51,27 +56,40 @@ static void interrupt_handler(int sig)
                was_interrupted = sig;
 }
 
-static const struct option my_longopts[] = {
-       LXC_COMMON_OPTIONS
+static struct option long_options[] = {
+           { "name",        required_argument, 0, 'n'         }, 
+           { "help",        no_argument,       0, 'h'         }, 
+           { "usage",       no_argument,       0, OPT_USAGE   }, 
+           { "version",     no_argument,       0, OPT_VERSION }, 
+           { "quiet",       no_argument,       0, 'q'         }, 
+           { "logfile",     required_argument, 0, 'o'         }, 
+           { "logpriority", required_argument, 0, 'l'         }, 
+           { "lxcpath",     required_argument, 0, 'P'         }, 
+           { 0,             0,                 0, 0           }
+       };
+static char short_options[] = "n:hqo:l:P:";
+
+struct arguments {
+       const struct option *options;
+       const char *shortopts;
+
+       const char *name;
+       char *log_file;
+       char *log_priority;
+       int quiet;
+       const char *lxcpath;
+
+       /* remaining arguments */
+       char *const *argv;
+       int argc;
 };
 
-static int my_parser(struct lxc_arguments *args, int c, char *arg)
-{
-       return 0;
-}
+static int arguments_parse(struct arguments *my_args, int argc,
+                              char *const argv[]);
 
-static struct lxc_arguments my_args = {
-       .progname = "lxc-init",
-       .help     = "\
---name=NAME -- COMMAND\n\
-\n\
-lxc-init start a COMMAND as PID 2 inside a container\n\
-\n\
-Options :\n\
-  -n, --name=NAME        NAME of the container\n\
-",
-       .options   = my_longopts,
-       .parser    = my_parser,
+static struct arguments my_args = {
+       .options   = long_options,
+       .shortopts = short_options
 };
 
 int main(int argc, char *argv[])
@@ -83,15 +101,15 @@ int main(int argc, char *argv[])
        sigset_t mask, omask;
        int have_status = 0, shutdown = 0;
 
-       if (lxc_arguments_parse(&my_args, argc, argv))
+       if (arguments_parse(&my_args, argc, argv))
                exit(EXIT_FAILURE);
 
+       log.prefix = "lxc-init";
        log.name = my_args.name;
        log.file = my_args.log_file;
        log.level = my_args.log_priority;
-       log.prefix = my_args.progname;
        log.quiet = my_args.quiet;
-       log.lxcpath = my_args.lxcpath[0];
+       log.lxcpath = my_args.lxcpath;
 
        ret = lxc_log_init(&log);
        if (ret < 0)
@@ -293,3 +311,139 @@ out:
                exit(EXIT_FAILURE);
        exit(ret);
 }
+
+
+
+static void print_usage(const struct option longopts[])
+
+{
+       int i;
+       const struct option *opt;
+
+       fprintf(stderr, "Usage: lxc-init ");
+
+       for (opt = longopts, i = 1; opt->name; opt++, i++) {
+               int j;
+               char *uppername;
+
+               uppername = strdup(opt->name);
+               if (!uppername)
+                       exit(-ENOMEM);
+
+               for (j = 0; uppername[j]; j++)
+                       uppername[j] = toupper(uppername[j]);
+
+               fprintf(stderr, "[");
+
+               if (isprint(opt->val))
+                       fprintf(stderr, "-%c|", opt->val);
+
+               fprintf(stderr, "--%s", opt->name);
+
+               if (opt->has_arg == required_argument)
+                       fprintf(stderr, "=%s", uppername);
+
+               if (opt->has_arg == optional_argument)
+                       fprintf(stderr, "[=%s]", uppername);
+
+               fprintf(stderr, "] ");
+
+               if (!(i % 4))
+                       fprintf(stderr, "\n\t");
+
+               free(uppername);
+       }
+
+       fprintf(stderr, "\n");
+       exit(0);
+}
+
+static void print_version()
+{
+       printf("%s%s\n", LXC_VERSION, LXC_DEVEL ? "-devel" : "");
+       exit(0);
+}
+
+static void print_help(int code)
+{
+       fprintf(stderr, "\
+Usage: lxc-init --name=NAME -- COMMAND\n\
+\n\
+  lxc-init start a COMMAND as PID 2 inside a container\n\
+\n\
+Options :\n\
+  -n, --name=NAME                  NAME of the container\n\
+  -o, --logfile=FILE               Output log to FILE instead of stderr\n\
+  -l, --logpriority=LEVEL          Set log priority to LEVEL\n\
+  -q, --quiet                      Don't produce any output\n\
+  -P, --lxcpath=PATH               Use specified container path\n\
+  -?, --help                       Give this help list\n\
+      --usage                      Give a short usage message\n\
+      --version                    Print the version number\n\
+\n\
+Mandatory or optional arguments to long options are also mandatory or optional\n\
+for any corresponding short options.\n\
+\n\
+See the lxc-init man page for further information.\n\n");
+
+       exit(code);
+}
+
+static int arguments_parse(struct arguments *args, int argc,
+                              char *const argv[])
+{
+       while (true) {
+               int c;
+               int index = 0;
+
+               c = getopt_long(argc, argv, args->shortopts, args->options, &index);
+               if (c == -1)
+                       break;
+               switch (c) {
+               case 'n':
+                       args->name = optarg;
+                       break;
+               case 'o':
+                       args->log_file = optarg;
+                       break;
+               case 'l':
+                       args->log_priority = optarg;
+                       break;
+               case 'q':
+                       args->quiet = 1;
+                       break;
+               case 'P':
+                       remove_trailing_slashes(optarg);
+                       args->lxcpath = optarg;
+                       break;
+               case OPT_USAGE:
+                       print_usage(args->options);
+               case OPT_VERSION:
+                       print_version();
+               case '?':
+                       print_help(1);
+               case 'h':
+                       print_help(0);
+               }
+       }
+
+       /*
+        * Reclaim the remaining command arguments
+        */
+       args->argv = &argv[optind];
+       args->argc = argc - optind;
+
+       /* If no lxcpath was given, use default */
+       if (!args->lxcpath) {
+               args->lxcpath = lxc_global_config_value("lxc.lxcpath");
+       }
+
+       /* Check the command options */
+       if (!args->name) {
+               if(!args->quiet)
+                       fprintf(stderr, "lxc-init: missing container name, use --name option\n");
+               return -1;
+       }
+
+       return 0;
+}