]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/lxc_start.c
shutdown the container when powering off the container
[mirror_lxc.git] / src / lxc / lxc_start.c
index ed7af47565201238464bcc72afae27b4e5168532..37f9fd8c2f3b8e24dbaf24b34d028cb0c264c544 100644 (file)
  * 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;
 }