]>
git.proxmox.com Git - mirror_lxc.git/blob - src/liblxc/execute.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/prctl.h>
38 #include <sys/mount.h>
39 #include <netinet/in.h>
49 #include <namespace.h>
52 LXC_TTY_HANDLER(SIGINT
);
53 LXC_TTY_HANDLER(SIGQUIT
);
55 int lxc_execute(const char *name
, int argc
, char *argv
[],
56 lxc_callback_t preexec
, void *data
)
58 char *init
= NULL
, *val
= NULL
, *vinit
= "[vinit]";
59 int fd
, lock
, sv
[2], sync
= 0, err
= -1;
63 lock
= lxc_get_lock(name
);
65 lxc_log_error("'%s' is busy", name
);
70 lxc_log_error("failed to acquire lock on '%s':%s",
71 name
, strerror(-lock
));
75 fcntl(lock
, F_SETFD
, FD_CLOEXEC
);
77 if (lxc_setstate(name
, STARTING
)) {
78 lxc_log_error("failed to set state %s", state2str(STARTING
));
82 if (socketpair(AF_LOCAL
, SOCK_STREAM
, 0, sv
)) {
83 lxc_log_syserror("failed to create communication socketpair");
87 LXC_TTY_ADD_HANDLER(SIGINT
);
88 LXC_TTY_ADD_HANDLER(SIGQUIT
);
90 clone_flags
= CLONE_NEWPID
|CLONE_NEWIPC
|CLONE_NEWNS
;
91 if (conf_has_utsname(name
))
92 clone_flags
|= CLONE_NEWUTS
;
93 if (conf_has_network(name
))
94 clone_flags
|= CLONE_NEWNET
;
96 pid
= fork_ns(clone_flags
);
98 lxc_log_syserror("failed to fork into a new namespace");
106 lxc_log_syserror("failed to fork");
112 fcntl(sv
[0], F_SETFD
, FD_CLOEXEC
);
114 if (write(sv
[0], &sync
, sizeof(sync
)) < 0) {
115 lxc_log_syserror("failed to write socket");
119 if (read(sv
[0], &sync
, sizeof(sync
)) < 0) {
120 lxc_log_syserror("failed to read socket");
124 if (lxc_setup(name
)) {
125 lxc_log_error("failed to setup the container");
128 if (mount("proc", "/proc", "proc", 0, NULL
)) {
129 lxc_log_error("failed to mount '/proc'");
132 if (mount("sysfs", "/sys", "sysfs", 0, NULL
)) {
133 lxc_log_syserror("failed to mount '/sys'");
134 /* continue: non fatal error until sysfs not per
139 if (preexec(name
, argc
, argv
, data
)) {
140 lxc_log_error("preexec callback has failed");
144 execvp(argv
[0], argv
);
146 lxc_log_syserror("failed to exec %s", argv
[0]);
147 if (write(sv
[0], &sync
, sizeof(sync
)) < 0)
148 lxc_log_syserror("failed to write the socket");
158 if (prctl(PR_SET_NAME
, vinit
, 0, 0, 0))
159 lxc_log_syserror("failed to set process name");
166 if (wait(&status
) < 0) {
171 lxc_log_syserror("failed to wait child");
179 if (read(sv
[1], &sync
, sizeof(sync
)) < 0) {
180 lxc_log_syserror("failed to read the socket");
184 if (clone_flags
& CLONE_NEWNET
&& conf_create_network(name
, pid
)) {
185 lxc_log_error("failed to create the configured network");
186 goto err_create_network
;
189 if (write(sv
[1], &sync
, sizeof(sync
)) < 0) {
190 lxc_log_syserror("failed to write the socket");
194 err
= read(sv
[1], &sync
, sizeof(sync
));
196 lxc_log_error("failed to read the socket");
201 lxc_log_error("something went wrong with %d", pid
);
202 /* TODO : check status etc ... */
203 waitpid(pid
, NULL
, 0);
204 goto err_child_failed
;
207 asprintf(&init
, LXCPATH
"/%s/init", name
);
208 fd
= open(init
, O_WRONLY
|O_CREAT
, S_IRUSR
|S_IWUSR
);
210 lxc_log_syserror("failed to open %s", init
);
214 asprintf(&val
, "%d", pid
);
215 if (write(fd
, val
, strlen(val
)) < 0) {
216 lxc_log_syserror("failed to write init pid");
220 if (lxc_link_nsgroup(name
, pid
))
221 lxc_log_warning("cgroupfs not found: cgroup disabled");
223 if (lxc_setstate(name
, RUNNING
)) {
224 lxc_log_error("failed to set state to %s", state2str(RUNNING
));
225 goto err_state_failed
;
229 if (waitpid(pid
, NULL
, 0) < 0) {
232 lxc_log_syserror("failed to wait the pid %d", pid
);
233 goto err_waitpid_failed
;
236 if (lxc_setstate(name
, STOPPING
))
237 lxc_log_error("failed to set state %s", state2str(STOPPING
));
239 if (clone_flags
& CLONE_NEWNET
&& conf_destroy_network(name
))
240 lxc_log_error("failed to destroy the network");
244 if (lxc_setstate(name
, STOPPED
))
245 lxc_log_error("failed to set state %s", state2str(STOPPED
));
247 lxc_unlink_nsgroup(name
);
262 conf_destroy_network(name
);
267 if (lxc_setstate(name
, ABORTING
))
268 lxc_log_error("failed to set state %s", state2str(STOPPED
));
272 LXC_TTY_DEL_HANDLER(SIGQUIT
);
273 LXC_TTY_DEL_HANDLER(SIGINT
);