* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define _GNU_SOURCE
#include <stdio.h>
+#undef _GNU_SOURCE
#include <libgen.h>
+#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
#include <sys/param.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/if.h>
-#include <lxc/lxc.h>
+#include "log.h"
+#include "lxc.h"
+#include "conf.h"
+#include "cgroup.h"
+#include "utils.h"
+#include "config.h"
+#include "confile.h"
+#include "arguments.h"
-void usage(char *cmd)
+lxc_log_define(lxc_start_ui, lxc_start);
+
+static struct lxc_list defines;
+
+static int my_parser(struct lxc_arguments* args, int c, char* arg)
{
- fprintf(stderr, "%s <command>\n", basename(cmd));
- fprintf(stderr, "\t -n <name> : name of the container\n");
- _exit(1);
+ switch (c) {
+ case 'd': args->daemonize = 1; break;
+ case 'f': args->rcfile = arg; break;
+ case 's': return lxc_config_define_add(&defines, arg);
+ }
+ return 0;
}
+static const struct option my_longopts[] = {
+ {"daemon", no_argument, 0, 'd'},
+ {"rcfile", required_argument, 0, 'f'},
+ {"define", required_argument, 0, 's'},
+ LXC_COMMON_OPTIONS
+};
+
+static struct lxc_arguments my_args = {
+ .progname = "lxc-start",
+ .help = "\
+--name=NAME -- COMMAND\n\
+\n\
+lxc-start start COMMAND in specified container NAME\n\
+\n\
+Options :\n\
+ -n, --name=NAME NAME for name of the container\n\
+ -d, --daemon daemonize the container\n\
+ -f, --rcfile=FILE Load configuration file FILE\n\
+ -s, --define KEY=VAL Assign VAL to configuration variable KEY\n",
+ .options = my_longopts,
+ .parser = my_parser,
+ .checker = NULL,
+ .daemonize = 0,
+};
+
int main(int argc, char *argv[])
{
- char opt;
- char *name = NULL;
- char **args;
- int err = LXC_ERROR_INTERNAL, nbargs = 0;
- struct termios tios;
+ char *const *args;
+ int err = -1;
- char *default_args[] = {
+ char *const default_args[] = {
"/sbin/init",
'\0',
};
- while ((opt = getopt(argc, argv, "n:")) != -1) {
- switch (opt) {
- case 'n':
- name = optarg;
- break;
- }
+ char *rcfile = NULL;
+ struct lxc_conf *conf;
- nbargs++;
- }
+ lxc_list_init(&defines);
+
+ if (lxc_arguments_parse(&my_args, argc, argv))
+ return err;
- if (!argv[optind] || !strlen(argv[optind]))
+ if (!my_args.argc)
args = default_args;
+ else
+ args = my_args.argv;
+
+ if (lxc_log_init(my_args.log_file, my_args.log_priority,
+ my_args.progname, my_args.quiet))
+ return err;
+
+ /* rcfile is specified in the cli option */
+ if (my_args.rcfile)
+ rcfile = (char *)my_args.rcfile;
else {
- args = &argv[optind];
- argc -= nbargs;
+ if (!asprintf(&rcfile, LXCPATH "/%s/config", my_args.name)) {
+ SYSERROR("failed to allocate memory");
+ return err;
+ }
+
+ /* container configuration does not exist */
+ if (access(rcfile, F_OK)) {
+ free(rcfile);
+ rcfile = NULL;
+ }
+ }
+
+ conf = lxc_conf_init();
+ if (!conf) {
+ ERROR("failed to initialize configuration");
+ return err;
+ }
+
+ if (rcfile && lxc_config_read(rcfile, conf)) {
+ ERROR("failed to read configuration file");
+ return err;
}
- if (!name)
- usage(argv[0]);
+ if (lxc_config_define_load(&defines, conf))
+ return err;
- if (tcgetattr(0, &tios)) {
- lxc_log_error("failed to get current terminal settings");
- fprintf(stderr, "%s\n", lxc_strerror(err));
- return 1;
+ if (!rcfile && !strcmp("/sbin/init", args[0])) {
+ ERROR("no configuration file for '/sbin/init' (may crash the host)");
+ return err;
}
- err = lxc_start(name, args);
- if (err) {
- fprintf(stderr, "%s\n", lxc_strerror(err));
- err = 1;
+ if (my_args.daemonize) {
+
+ /* do not chdir as we want to open the log file,
+ * change the directory right after.
+ * do not close 0, 1, 2, we want to do that
+ * ourself because we don't want /dev/null
+ * being reopened.
+ */
+ if (daemon(1, 1)) {
+ SYSERROR("failed to daemonize '%s'", my_args.name);
+ return err;
+ }
+
+ close(0);
+ close(1);
+ close(2);
+
+ if (my_args.log_file) {
+ open(my_args.log_file, O_WRONLY | O_CLOEXEC);
+ open(my_args.log_file, O_RDONLY | O_CLOEXEC);
+ open(my_args.log_file, O_RDONLY | O_CLOEXEC);
+ }
}
- if (tcsetattr(0, TCSAFLUSH, &tios))
- lxc_log_syserror("failed to restore terminal attributes");
+ err = lxc_start(my_args.name, args, conf);
return err;
}