liblxc_la_SOURCES = \
+ arguments.c arguments.h \
create.c \
destroy.c \
start.c \
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
#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;
}
/* 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;
}
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;
}
}