]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
add long options step1
authorMichel Normand <normand@fr.ibm.com>
Mon, 18 May 2009 20:11:45 +0000 (22:11 +0200)
committerDaniel Lezcano <dlezcano@fr.ibm.com>
Mon, 18 May 2009 20:11:45 +0000 (22:11 +0200)
add the long options to lxc-execute as an exemple
of usage of the new functions added in src/lxc/arguments.*

Signed-off-by: Michel Normand <normand@fr.ibm.com>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
src/lxc/Makefile.am
src/lxc/arguments.c [new file with mode: 0644]
src/lxc/arguments.h [new file with mode: 0644]
src/lxc/lxc_execute.c

index 09a981c727d1ce44213921f423811b4d264701eb..57b3caeb62fb14bba8536b88829f0d20bbad0c13 100644 (file)
@@ -19,6 +19,7 @@ pkginclude_HEADERS = \
 
 
 liblxc_la_SOURCES = \
+       arguments.c arguments.h \
        create.c \
        destroy.c \
        start.c \
diff --git a/src/lxc/arguments.c b/src/lxc/arguments.c
new file mode 100644 (file)
index 0000000..3527be4
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ * Michel Normand <normand at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>             /* for isprint() */
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "arguments.h"
+
+/*---------------------------------------------------------------------------*/
+static int build_shortopts(const struct option *a_options,
+                          char *a_shortopts, size_t a_size)
+{
+       const struct option *opt;
+       int i = 0;
+
+       if (!a_options || !a_shortopts || !a_size)
+               return -1;
+
+       for (opt = a_options; opt->name; opt++) {
+
+               if (!isascii(opt->val))
+                       continue;
+
+               if (i < a_size)
+                       a_shortopts[i++] = opt->val;
+               else
+                       goto is2big;
+
+               if (opt->has_arg == no_argument)
+                       continue;
+
+               if (i < a_size)
+                       a_shortopts[i++] = ':';
+               else
+                       goto is2big;
+
+               if (opt->has_arg == required_argument)
+                       continue;
+
+               if (i < a_size)
+                       a_shortopts[i++] = ':';
+               else
+                       goto is2big;
+       }
+
+       if (i < a_size)
+               a_shortopts[i] = '\0';
+       else
+               goto is2big;
+
+       return 0;
+
+      is2big:
+       errno = E2BIG;
+       return -1;
+}
+
+/*---------------------------------------------------------------------------*/
+static void print_usage(const struct option longopts[],
+                       const struct lxc_arguments *a_args)
+
+{
+       int i;
+       const struct option *opt;
+
+       fprintf(stderr, "Usage: %s ", a_args->progname);
+
+       for (opt = longopts, i = 1; opt->name; opt++, i++) {
+               int j;
+               char *uppername = strdup(opt->name);
+
+               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_help(const struct lxc_arguments *args, int code)
+{
+       fprintf(stderr, "\
+Usage: %s %s\
+\n\
+Common options :\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\
+  -?, --help                       Give this help list\n\
+      --usage                      Give a short usage message\n\
+\n\
+Mandatory or optional arguments to long options are also mandatory or optional\n\
+for any corresponding short options.\n\
+\n\
+See the %s man page for further information.\n\n",
+       args->progname, args->help, args->progname);
+
+       exit(code);
+}
+
+extern int lxc_arguments_parse(struct lxc_arguments *args,
+                              int argc, char * const argv[])
+{
+       char shortopts[256];
+       int  ret = 0;
+
+       ret = build_shortopts(args->options, shortopts, sizeof(shortopts));
+       if (ret < 0) {
+               lxc_error(args, "build_shortopts() failed : %s",
+                         strerror(errno));
+               return ret;
+       }
+
+       while (1)  {
+               int c, index = 0;
+
+               c = getopt_long(argc, argv, 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 OPT_USAGE: print_usage(args->options, args);
+               case '?':       print_help(args, 1);
+               case 'h':       print_help(args, 0);
+               default:
+                       if (args->parser) {
+                               ret = args->parser(args, c, optarg);
+                               if (ret)
+                                       goto error;
+                       }
+               }
+       }
+
+       /*
+        * Reclaim the remaining command arguments
+        */
+       args->argv = &argv[optind];
+       args->argc = argc - optind;
+
+       /* Check the command options */
+
+       if (!args->name) {
+               lxc_error(args, "missing container name, use --name option");
+               return -1;
+       }
+
+       if (args->checker)
+               ret = args->checker(args);
+error:
+       if (ret)
+               lxc_error(args, "could not parse command line");
+       return ret;
+}
diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h
new file mode 100644 (file)
index 0000000..262355f
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ * Michel Normand <normand at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __arguments_h
+#define __arguments_h
+
+#include <getopt.h>
+
+struct lxc_arguments;
+
+typedef int (*lxc_arguments_parser_t) (struct lxc_arguments *, int, char*);
+typedef int (*lxc_arguments_checker_t) (const struct lxc_arguments *);
+
+struct lxc_arguments {
+       const char *help;
+       const char *progname;
+       const struct option* options;
+       lxc_arguments_parser_t parser;
+       lxc_arguments_checker_t checker;
+
+       const char *name;
+       char *log_file;
+       char *log_priority;
+       int quiet;
+       const char *rcfile;
+
+       /* remaining arguments */
+       char *const *argv;
+       int argc;
+};
+
+#define LXC_COMMON_OPTIONS \
+       {"name", required_argument, 0, 'n'}, \
+       {"help", no_argument, 0, 'h'}, \
+       {"usage", no_argument,  0, OPT_USAGE}, \
+       {"quiet", no_argument,  0, 'q'}, \
+       {"logfile", required_argument, 0, 'o'}, \
+       {"logpriority", required_argument, 0, 'l'}, \
+       {0, 0, 0, 0}
+
+/* option keys for long only options */
+#define        OPT_USAGE 0x1000
+
+extern int lxc_arguments_parse(struct lxc_arguments *a_args,
+                              int argc, char *const argv[]);
+extern const char *lxc_strerror(int errnum);
+
+#define lxc_error(arg, fmt, args...) if (!(arg)->quiet)                        \
+       fprintf(stderr, "%s: " fmt "\n", (arg)->progname,  ## args)
+
+#endif
index 7ddc534dbc765c3b716603ea4605156556510186..92d8076f4ff471ea823db830ac06bcf94bd5c67c 100644 (file)
 
 #include <lxc/lxc.h>
 #include "confile.h"
+#include "arguments.h"
 
 lxc_log_define(lxc_execute, lxc);
 
-void usage(char *cmd)
+static int my_checker(const struct lxc_arguments* args)
 {
-       fprintf(stderr, "%s <command>\n", basename(cmd));
-       fprintf(stderr, "\t -n <name>      : name of the container\n");
-       fprintf(stderr, "\t [-f <confile>] : path of the configuration file\n");
-       fprintf(stderr, "\t[-o <logfile>]    : path of the log file\n");
-       fprintf(stderr, "\t[-l <logpriority>]: log level priority\n");
-       fprintf(stderr, "\t[-q ]             : be quiet\n");
-       _exit(1);
+       if (!args->argc) {
+               lxc_error(args, "missing command to execute !");
+               return -1;
+       }
+       return 0;
+}
+
+static int my_parser(struct lxc_arguments* args, int c, char* arg)
+{
+       switch (c) {
+       case 'f': args->rcfile = arg; break;
+       }
+       return 0;
 }
 
+static const struct option my_longopts[] = {
+       {"rcfile", required_argument, 0, 'f'},
+       LXC_COMMON_OPTIONS
+};
+
+static struct lxc_arguments my_args = {
+       .progname = "lxc-execute",
+       .help     = "\
+--name=NAME -- COMMAND\n\
+\n\
+lxc-execute creates a container with the identifier NAME\n\
+and execs COMMAND into this container.\n\
+\n\
+Options :\n\
+  -n, --name=NAME   NAME for name of the container\n\
+  -f, --rcfile=FILE Load configuration file FILE\n",
+       .options  = my_longopts,
+       .parser   = my_parser,
+       .checker  = my_checker,
+};
+
 int main(int argc, char *argv[])
 {
-       const char *name = NULL, *file = NULL;
-       const char *log_file = NULL, *log_priority = NULL;
        static char **args;
        char path[MAXPATHLEN];
        int opt;
        int nbargs = 0;
        int autodestroy = 0;
        int ret = 1;
-       int quiet = 0;
        struct lxc_conf lxc_conf;
 
-       while ((opt = getopt(argc, argv, "f:n:o:l:q")) != -1) {
-               switch (opt) {
-               case 'n':
-                       name = optarg;
-                       break;
-               case 'f':
-                       file = optarg;
-                       break;
-               case 'o':
-                       log_file = optarg;
-                       break;
-               case 'l':
-                       log_priority = optarg;
-                       break;
-               case 'q':
-                       quiet = 1;
-                       break;
-               }
-
-               nbargs++;
-       }
-
-       if (!name || !argv[optind] || !strlen(argv[optind]))
-               usage(argv[0]);
+       if (lxc_arguments_parse(&my_args, argc, argv))
+               goto out;
 
-       argc -= nbargs;
-       
-       if (lxc_log_init(log_file, log_priority, basename(argv[0]), quiet))
+       if (lxc_log_init(my_args.log_file, my_args.log_priority,
+                        my_args.progname, my_args.quiet))
                goto out;
 
        if (lxc_conf_init(&lxc_conf))
                goto out;
 
-       if (file && lxc_config_read(file, &lxc_conf))
+       if (my_args.rcfile && lxc_config_read(my_args.rcfile, &lxc_conf))
                goto out;
 
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
+       snprintf(path, MAXPATHLEN, LXCPATH "/%s", my_args.name);
        if (access(path, R_OK)) {
-               if (lxc_create(name, &lxc_conf))
+               if (lxc_create(my_args.name, &lxc_conf))
                        goto out;
                autodestroy = 1;
        }
@@ -105,7 +107,7 @@ int main(int argc, char *argv[])
        /* lxc-init --mount-procfs -- .... */
        args = malloc((argc + 3)*sizeof(*args));
        if (!args) {
-               ERROR("failed to allocate memory for '%s'", name);
+               ERROR("failed to allocate memory for '%s'", my_args.name);
                goto out;
        }
 
@@ -114,20 +116,20 @@ int main(int argc, char *argv[])
        args[nbargs++] = "--mount-procfs";
        args[nbargs++] = "--";
 
-       for (opt = 0; opt < argc; opt++)
-               args[nbargs++] = argv[optind++];
+       for (opt = 0; opt < my_args.argc; opt++)
+               args[nbargs++] = my_args.argv[opt];
 
-       ret = lxc_start(name, args);
+       ret = lxc_start(my_args.name, args);
        if (ret) {
-               ERROR("failed to start '%s'", name);
+               ERROR("failed to start '%s'", my_args.name);
                goto out;
        }
 
        ret = 0;
 out:
        if (autodestroy) {
-               if (lxc_destroy(name)) {
-                       ERROR("failed to destroy '%s'", name);
+               if (lxc_destroy(my_args.name)) {
+                       ERROR("failed to destroy '%s'", my_args.name);
                        ret = 1;
                }
        }