X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=vserver-start%2Fmain.c;fp=vserver-start%2Fmain.c;h=ab7c0fb98ea13d9aef4b6b27b4383cfb2fc0e4a0;hb=3f3cf95f755f3ef1c31ad8e38153deb4ee214c66;hp=0000000000000000000000000000000000000000;hpb=bfa4b37aaa195007a09bc166e8c8563d5a3c2ef1;p=util-vserver.git diff --git a/vserver-start/main.c b/vserver-start/main.c new file mode 100644 index 0000000..ab7c0fb --- /dev/null +++ b/vserver-start/main.c @@ -0,0 +1,200 @@ +// $Id: main.c,v 1.5 2005/03/19 02:07:40 ensc Exp $ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "vserver-start.h" +#include "vshelper.h" +#include "pathconfig.h" +#include "interface.h" +#include "configuration.h" +#include "mount.h" +#include "undo.h" + +#include "lib_internal/util.h" +#include "lib_internal/errinfo.h" +#include "lib_internal/sys_clone.h" +#include "lib/vserver.h" +#include "lib/internal.h" + +#include +#include +#include +#include +#include + +#define ENSC_WRAPPERS_VSERVER 1 +#define ENSC_WRAPPERS_SOCKET 1 +#define ENSC_WRAPPERS_UNISTD 1 +#define ENSC_WRAPPERS_FCNTL 1 +#define ENSC_WRAPPERS_STDLIB 1 +#include + +struct Options opts; +struct Configuration cfg; +int wrapper_exit_code; + +static void +env2Str(char const **var, char const *env, bool req) +{ + char const * tmp = getenv(env); + if (req && tmp==0) { + WRITE_MSG(2, "vserver.start: required environment variable $"); + WRITE_STR(2, env); + WRITE_STR(2, " not set; aborting...\n"); + exit(1); + } + + *var = tmp; + unsetenv(env); +} + +static void +env2Bool(bool *var, char const *env, bool req) +{ + char const * tmp; + env2Str(&tmp, env, req); + *var = !(tmp==0 || atoi(tmp)==0); +} + +static void +initGlobals() +{ + env2Str (&opts.VSERVER_DIR, "VSERVER_DIR", true); + env2Str (&opts.VSERVER_NAME, "VSERVER_NAME", true); + env2Bool(&opts.OPTION_DEBUG, "OPTION_DEBUG", false); + env2Bool(&opts.OPTION_DEFAULTTTY, "OPTION_DEFAULTTTY", false); +} + +static void +initLock() +{ + size_t l = strlen(opts.VSERVER_DIR); + char tmp[sizeof(LOCKDIR "/vserver..startup") + l]; + char * ptr = tmp; + struct ErrorInformation err = { .app = 0 }; + int fd; + + ptr = Xmemcpy(ptr, LOCKDIR "/vserver.", sizeof(LOCKDIR "/vserver.")-1); + ((char *)(Xmemcpy(ptr, opts.VSERVER_DIR, l)))[0] = '\0'; + ptr += canonifyVserverName(ptr); + ptr = Xmemcpy(ptr, ".startup", sizeof(".startup")); + *ptr = '\0'; + + if (!lockfile(&fd, tmp, LOCK_EX, 30, &err)) { + WRITE_MSG(2, "vserver.start: failed to lock '"); + WRITE_STR(2, tmp); + WRITE_MSG(2, "': "); + ErrInfo_writeErrno(&err); + exit(1); + } +} + +static void +checkConstraints() +{ + xid_t xid; + bool is_running; + struct vc_vx_info info; + + xid = vc_getVserverCtx(opts.VSERVER_DIR, vcCFG_RECENT_FULL, + true, &is_running); + + if (xid!=VC_NOCTX && vc_get_vx_info(xid, &info)!=-1) { + WRITE_MSG(2, "vserver.start: vserver '"); + WRITE_STR(2, opts.VSERVER_NAME); + WRITE_MSG(2, "' already running; aborting...\n"); + exit(1); + } + + Vshelper_doSanityCheck(); +} + +static void +setCFlag(xid_t xid, uint_least64_t value) +{ + struct vc_ctx_flags flags = { + .flagword = value, + .mask = value + }; + + Evc_set_cflags(xid, &flags); +} + +int main(int UNUSED argc, char UNUSED *argv[]) +{ + Cfg_init(&cfg); + + initGlobals(); + initLock(); + checkConstraints(); + + int sync_fd[2]; + char c; + xid_t xid; + char buf[sizeof(xid)*3 + 2]; + PathInfo cfgdir = { .d = opts.VSERVER_DIR, .l = strlen(opts.VSERVER_DIR) }; + + Esocketpair(AF_UNIX, SOCK_STREAM, 0, sync_fd); + Efcntl(sync_fd[0], F_SETFD, FD_CLOEXEC); + Efcntl(sync_fd[1], F_SETFD, FD_CLOEXEC); + + getConfiguration(&cfg, &cfgdir); + pid_t pid = sys_clone(CLONE_NEWNS|SIGCHLD, 0); + FatalErrnoError(pid==-1, "sys_clone()"); + + switch (pid) { + case 0 : + Undo_init(); + execScriptlets(&cfgdir, opts.VSERVER_NAME, "prepre-start"); + activateInterfaces(&cfg.interfaces); + + xid = Evc_ctx_create(cfg.xid); + setCFlag(xid, VC_VXF_INFO_NAMESPACE); + + mountVserver(&cfg); + // prepareInit(&cfg, &cfgdir); + + Esend(sync_fd[0], &xid, sizeof xid, MSG_NOSIGNAL); + // 'pre-start.parent' will be executed now in the parent-context + Erecv(sync_fd[0], &c, 1, 0); + execScriptlets(&cfgdir, opts.VSERVER_NAME, "pre-start"); + + if (cfg.nice) + Enice(atoi(cfg.nice)); + if (opts.OPTION_DEFAULTTTY) + setDefaultTTY(&cfgdir, 0); + + + + Undo_detach(); + break; + + default : + Erecv(sync_fd[1], &xid, sizeof xid, 0); + utilvserver_fmt_uint(buf, xid); + Esetenv("CHILD_XID", buf, 1); + + execScriptlets(&cfgdir, opts.VSERVER_NAME, "pre-start.parent"); + Esend(sync_fd[1], ".", 1, MSG_NOSIGNAL); + + break; + } +}