From: Michel Normand Date: Mon, 18 May 2009 20:11:45 +0000 (+0200) Subject: add long options step1 X-Git-Tag: lxc_0_6_3~89 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cda02a28c0f41feb359ebbddd68ed5f1dcd4930e;p=thirdparty%2Flxc.git add long options step1 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 Signed-off-by: Daniel Lezcano --- diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index 09a981c72..57b3caeb6 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -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 index 000000000..3527be41d --- /dev/null +++ b/src/lxc/arguments.c @@ -0,0 +1,203 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * Michel Normand + * + * 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 +#include +#include +#include +#include /* for isprint() */ +#include +#include +#include +#include + +#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 index 000000000..262355fa1 --- /dev/null +++ b/src/lxc/arguments.h @@ -0,0 +1,71 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * Michel Normand + * + * 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 + +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 diff --git a/src/lxc/lxc_execute.c b/src/lxc/lxc_execute.c index 7ddc534db..92d8076f4 100644 --- a/src/lxc/lxc_execute.c +++ b/src/lxc/lxc_execute.c @@ -32,72 +32,74 @@ #include #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 \n", basename(cmd)); - fprintf(stderr, "\t -n : name of the container\n"); - fprintf(stderr, "\t [-f ] : path of the configuration file\n"); - fprintf(stderr, "\t[-o ] : path of the log file\n"); - fprintf(stderr, "\t[-l ]: 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; } }