]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/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>
44 LXC_TTY_HANDLER(SIGINT
);
45 LXC_TTY_HANDLER(SIGQUIT
);
47 int lxc_execute(const char *name
, int argc
, char *argv
[],
48 lxc_callback_t preexec
, void *data
)
50 char *init
= NULL
, *val
= NULL
, *vinit
= "[vinit]";
51 int fd
, lock
, sv
[2], sync
= 0, err
= -1;
55 lock
= lxc_get_lock(name
);
57 lxc_log_error("'%s' is busy", name
);
62 lxc_log_error("failed to acquire lock on '%s':%s",
63 name
, strerror(-lock
));
67 if (lxc_setstate(name
, STARTING
)) {
68 lxc_log_error("failed to set state %s", lxc_state2str(STARTING
));
72 if (socketpair(AF_LOCAL
, SOCK_STREAM
, 0, sv
)) {
73 lxc_log_syserror("failed to create communication socketpair");
77 LXC_TTY_ADD_HANDLER(SIGINT
);
78 LXC_TTY_ADD_HANDLER(SIGQUIT
);
80 clone_flags
= CLONE_NEWPID
|CLONE_NEWIPC
|CLONE_NEWNS
;
81 if (conf_has_utsname(name
))
82 clone_flags
|= CLONE_NEWUTS
;
83 if (conf_has_network(name
))
84 clone_flags
|= CLONE_NEWNET
;
86 pid
= fork_ns(clone_flags
);
88 lxc_log_syserror("failed to fork into a new namespace");
96 lxc_log_syserror("failed to fork");
102 fcntl(sv
[0], F_SETFD
, FD_CLOEXEC
);
104 if (write(sv
[0], &sync
, sizeof(sync
)) < 0) {
105 lxc_log_syserror("failed to write socket");
109 if (read(sv
[0], &sync
, sizeof(sync
)) < 0) {
110 lxc_log_syserror("failed to read socket");
114 if (lxc_setup(name
)) {
115 lxc_log_error("failed to setup the container");
119 if (mount("proc", "/proc", "proc", 0, NULL
)) {
120 lxc_log_syserror("failed to mount '/proc'");
124 if (conf_has_network(name
))
125 if (mount("sysfs", "/sys", "sysfs", 0, NULL
)) {
126 lxc_log_syserror("failed to mount '/sys'");
127 /* continue: non fatal error until sysfs not per
132 if (preexec(name
, argc
, argv
, data
)) {
133 lxc_log_error("preexec callback has failed");
137 execvp(argv
[0], argv
);
138 lxc_log_syserror("failed to exec %s", argv
[0]);
140 if (write(sv
[0], &sync
, sizeof(sync
)) < 0)
141 lxc_log_syserror("failed to write the socket");
151 if (prctl(PR_SET_NAME
, vinit
, 0, 0, 0))
152 lxc_log_syserror("failed to set process name");
159 if (wait(&status
) < 0) {
164 lxc_log_syserror("failed to wait child");
172 if (read(sv
[1], &sync
, sizeof(sync
)) < 0) {
173 lxc_log_syserror("failed to read the socket");
177 if (clone_flags
& CLONE_NEWNET
&& conf_create_network(name
, pid
)) {
178 lxc_log_error("failed to create the configured network");
179 goto err_create_network
;
182 if (write(sv
[1], &sync
, sizeof(sync
)) < 0) {
183 lxc_log_syserror("failed to write the socket");
187 err
= read(sv
[1], &sync
, sizeof(sync
));
189 lxc_log_error("failed to read the socket");
194 lxc_log_error("something went wrong with %d", pid
);
195 /* TODO : check status etc ... */
196 waitpid(pid
, NULL
, 0);
197 goto err_child_failed
;
200 asprintf(&init
, LXCPATH
"/%s/init", name
);
201 fd
= open(init
, O_WRONLY
|O_CREAT
|O_TRUNC
, S_IRUSR
|S_IWUSR
);
203 lxc_log_syserror("failed to open %s", init
);
207 asprintf(&val
, "%d", pid
);
208 if (write(fd
, val
, strlen(val
)) < 0) {
209 lxc_log_syserror("failed to write init pid");
213 if (lxc_link_nsgroup(name
, pid
))
214 lxc_log_warning("cgroupfs not found: cgroup disabled");
216 if (lxc_setstate(name
, RUNNING
)) {
217 lxc_log_error("failed to set state to %s", lxc_state2str(RUNNING
));
218 goto err_state_failed
;
222 if (waitpid(pid
, NULL
, 0) < 0) {
225 lxc_log_syserror("failed to wait the pid %d", pid
);
226 goto err_waitpid_failed
;
229 if (lxc_setstate(name
, STOPPING
))
230 lxc_log_error("failed to set state %s", lxc_state2str(STOPPING
));
232 if (clone_flags
& CLONE_NEWNET
&& conf_destroy_network(name
))
233 lxc_log_error("failed to destroy the network");
237 if (lxc_setstate(name
, STOPPED
))
238 lxc_log_error("failed to set state %s", lxc_state2str(STOPPED
));
240 lxc_unlink_nsgroup(name
);
255 conf_destroy_network(name
);
260 if (lxc_setstate(name
, ABORTING
))
261 lxc_log_error("failed to set state %s", lxc_state2str(STOPPED
));
265 LXC_TTY_DEL_HANDLER(SIGQUIT
);
266 LXC_TTY_DEL_HANDLER(SIGINT
);