struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char *lxcpath) { struct lxc_handler *handler; handler = malloc(sizeof(*handler)); if (!handler) return NULL; memset(handler, 0, sizeof(*handler)); handler->ttysock[0] = handler->ttysock[1] = -1; handler->conf = conf; handler->lxcpath = lxcpath; handler->pinfd = -1; lsm_init(); handler->name = strdup(name); if (!handler->name) { ERROR("failed to allocate memory"); goto out_free; } if (lxc_cmd_init(name, handler, lxcpath)) goto out_free_name; if (lxc_read_seccomp_config(conf) != 0) { ERROR("failed loading seccomp policy"); goto out_close_maincmd_fd; } /* Begin by setting the state to STARTING */ if (lxc_set_state(name, handler, STARTING)) { ERROR("failed to set state '%s'", lxc_state2str(STARTING)); goto out_close_maincmd_fd; } /* Start of environment variable setup for hooks */ if (name && setenv("LXC_NAME", name, 1)) { SYSERROR("failed to set environment variable for container name"); } if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) { SYSERROR("failed to set environment variable for config path"); } if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) { SYSERROR("failed to set environment variable for rootfs mount"); } if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) { SYSERROR("failed to set environment variable for rootfs mount"); } if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) { SYSERROR("failed to set environment variable for console path"); } if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) { SYSERROR("failed to set environment variable for console log"); } /* End of environment variable setup for hooks */ if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) { ERROR("failed to run pre-start hooks for container '%s'.", name); goto out_aborting; } /* the signal fd has to be created before forking otherwise * if the child process exits before we setup the signal fd, * the event will be lost and the command will be stuck */ handler->sigfd = setup_signal_fd(&handler->oldmask); if (handler->sigfd < 0) { ERROR("failed to set sigchild fd handler"); goto out_delete_tty; } /* do this after setting up signals since it might unblock SIGWINCH */ if (lxc_console_create(conf)) { ERROR("failed to create console"); goto out_restore_sigmask; } if (ttys_shift_ids(conf) < 0) { ERROR("Failed to shift tty into container"); goto out_restore_sigmask; } INFO("'%s' is initialized", name); return handler; out_restore_sigmask: sigprocmask(SIG_SETMASK, &handler->oldmask, NULL); out_delete_tty: lxc_delete_tty(&conf->tty_info); out_aborting: lxc_set_state(name, handler, ABORTING); out_close_maincmd_fd: close(conf->maincmd_fd); conf->maincmd_fd = -1; out_free_name: free(handler->name); handler->name = NULL; out_free: free(handler); return NULL; }
struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char *lxcpath) { int i; struct lxc_handler *handler; handler = malloc(sizeof(*handler)); if (!handler) return NULL; memset(handler, 0, sizeof(*handler)); handler->ttysock[0] = handler->ttysock[1] = -1; handler->conf = conf; handler->lxcpath = lxcpath; handler->pinfd = -1; for (i = 0; i < LXC_NS_MAX; i++) handler->nsfd[i] = -1; lsm_init(); handler->name = strdup(name); if (!handler->name) { ERROR("Failed to allocate memory."); goto out_free; } if (lxc_cmd_init(name, handler, lxcpath)) goto out_free_name; if (lxc_read_seccomp_config(conf) != 0) { ERROR("Failed loading seccomp policy."); goto out_close_maincmd_fd; } /* Begin by setting the state to STARTING. */ if (lxc_set_state(name, handler, STARTING)) { ERROR("Failed to set state for container \"%s\" to \"%s\".", name, lxc_state2str(STARTING)); goto out_close_maincmd_fd; } /* Start of environment variable setup for hooks. */ if (name && setenv("LXC_NAME", name, 1)) SYSERROR("Failed to set environment variable: LXC_NAME=%s.", name); if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) SYSERROR("Failed to set environment variable: LXC_CONFIG_FILE=%s.", conf->rcfile); if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) SYSERROR("Failed to set environment variable: LXC_ROOTFS_MOUNT=%s.", conf->rootfs.mount); if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) SYSERROR("Failed to set environment variable: LXC_ROOTFS_PATH=%s.", conf->rootfs.path); if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) SYSERROR("Failed to set environment variable: LXC_CONSOLE=%s.", conf->console.path); if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) SYSERROR("Failed to set environment variable: LXC_CONSOLE_LOGPATH=%s.", conf->console.log_path); if (setenv("LXC_CGNS_AWARE", "1", 1)) SYSERROR("Failed to set environment variable LXC_CGNS_AWARE=1."); /* End of environment variable setup for hooks. */ if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) { ERROR("Failed to run lxc.hook.pre-start for container \"%s\".", name); goto out_aborting; } /* The signal fd has to be created before forking otherwise if the child * process exits before we setup the signal fd, the event will be lost * and the command will be stuck. */ handler->sigfd = setup_signal_fd(&handler->oldmask); if (handler->sigfd < 0) { ERROR("Failed to setup SIGCHLD fd handler."); goto out_delete_tty; } /* Do this after setting up signals since it might unblock SIGWINCH. */ if (lxc_console_create(conf)) { ERROR("Failed to create console for container \"%s\".", name); goto out_restore_sigmask; } if (ttys_shift_ids(conf) < 0) { ERROR("Failed to shift tty into container."); goto out_restore_sigmask; } INFO("Container \"%s\" is initialized.", name); return handler; out_restore_sigmask: sigprocmask(SIG_SETMASK, &handler->oldmask, NULL); out_delete_tty: lxc_delete_tty(&conf->tty_info); out_aborting: lxc_set_state(name, handler, ABORTING); out_close_maincmd_fd: close(conf->maincmd_fd); conf->maincmd_fd = -1; out_free_name: free(handler->name); handler->name = NULL; out_free: free(handler); return NULL; }