3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "vserver-start.h"
25 #include "pathconfig.h"
26 #include "interface.h"
27 #include "configuration.h"
31 #include "lib_internal/util.h"
32 #include "lib_internal/errinfo.h"
33 #include "lib_internal/sys_clone.h"
34 #include "lib/vserver.h"
35 #include "lib/internal.h"
41 #include <sys/socket.h>
43 #define ENSC_WRAPPERS_VSERVER 1
44 #define ENSC_WRAPPERS_SOCKET 1
45 #define ENSC_WRAPPERS_UNISTD 1
46 #define ENSC_WRAPPERS_FCNTL 1
47 #define ENSC_WRAPPERS_STDLIB 1
48 #include <ensc_wrappers/wrappers.h>
51 struct Configuration cfg;
52 int wrapper_exit_code;
55 env2Str(char const **var, char const *env, bool req)
57 char const * tmp = getenv(env);
59 WRITE_MSG(2, "vserver.start: required environment variable $");
61 WRITE_STR(2, " not set; aborting...\n");
70 env2Bool(bool *var, char const *env, bool req)
73 env2Str(&tmp, env, req);
74 *var = !(tmp==0 || atoi(tmp)==0);
80 env2Str (&opts.VSERVER_DIR, "VSERVER_DIR", true);
81 env2Str (&opts.VSERVER_NAME, "VSERVER_NAME", true);
82 env2Bool(&opts.OPTION_DEBUG, "OPTION_DEBUG", false);
83 env2Bool(&opts.OPTION_DEFAULTTTY, "OPTION_DEFAULTTTY", false);
89 size_t l = strlen(opts.VSERVER_DIR);
90 char tmp[sizeof(LOCKDIR "/vserver..startup") + l];
92 struct ErrorInformation err = { .app = 0 };
95 ptr = Xmemcpy(ptr, LOCKDIR "/vserver.", sizeof(LOCKDIR "/vserver.")-1);
96 ((char *)(Xmemcpy(ptr, opts.VSERVER_DIR, l)))[0] = '\0';
97 ptr += canonifyVserverName(ptr);
98 ptr = Xmemcpy(ptr, ".startup", sizeof(".startup"));
101 if (!lockfile(&fd, tmp, F_LOCK, 30, &err)) {
102 WRITE_MSG(2, "vserver.start: failed to lock '");
105 ErrInfo_writeErrno(&err);
115 struct vc_vx_info info;
117 xid = vc_getVserverCtx(opts.VSERVER_DIR, vcCFG_RECENT_FULL,
118 true, &is_running, vcCTX_XID);
120 if (xid!=VC_NOCTX && vc_get_vx_info(xid, &info)!=-1) {
121 WRITE_MSG(2, "vserver.start: vserver '");
122 WRITE_STR(2, opts.VSERVER_NAME);
123 WRITE_MSG(2, "' already running; aborting...\n");
127 Vshelper_doSanityCheck();
131 setCFlag(xid_t xid, uint_least64_t value)
133 struct vc_ctx_flags flags = {
138 Evc_set_cflags(xid, &flags);
141 int main(int UNUSED argc, char UNUSED *argv[])
152 char buf[sizeof(xid)*3 + 2];
153 PathInfo cfgdir = { .d = opts.VSERVER_DIR, .l = strlen(opts.VSERVER_DIR) };
155 Esocketpair(AF_UNIX, SOCK_STREAM, 0, sync_fd);
156 Efcntl(sync_fd[0], F_SETFD, FD_CLOEXEC);
157 Efcntl(sync_fd[1], F_SETFD, FD_CLOEXEC);
159 getConfiguration(&cfg, &cfgdir);
160 pid_t pid = sys_clone(CLONE_NEWNS|SIGCHLD, 0);
161 FatalErrnoError(pid==-1, "sys_clone()");
166 execScriptlets(&cfgdir, opts.VSERVER_NAME, "prepre-start");
167 activateInterfaces(&cfg.interfaces);
169 xid = Evc_ctx_create(cfg.xid, NULL);
170 setCFlag(xid, VC_VXF_INFO_NAMESPACE);
173 // prepareInit(&cfg, &cfgdir);
175 Esend(sync_fd[0], &xid, sizeof xid, MSG_NOSIGNAL);
176 // 'pre-start.parent' will be executed now in the parent-context
177 Erecv(sync_fd[0], &c, 1, 0);
178 execScriptlets(&cfgdir, opts.VSERVER_NAME, "pre-start");
181 Enice(atoi(cfg.nice));
182 if (opts.OPTION_DEFAULTTTY)
183 setDefaultTTY(&cfgdir, 0);
191 Erecv(sync_fd[1], &xid, sizeof xid, 0);
192 utilvserver_fmt_uint(buf, xid);
193 Esetenv("CHILD_XID", buf, 1);
195 execScriptlets(&cfgdir, opts.VSERVER_NAME, "pre-start.parent");
196 Esend(sync_fd[1], ".", 1, MSG_NOSIGNAL);