]>
Commit | Line | Data |
---|---|---|
05f05512 | 1 | /* |
2 | * lxc: linux Container library | |
3 | * | |
4 | * (C) Copyright IBM Corp. 2007, 2008 | |
5 | * | |
6 | * Authors: | |
7 | * Daniel Lezcano <dlezcano at fr.ibm.com> | |
8 | * | |
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. | |
13 | * | |
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. | |
18 | * | |
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 | |
22 | */ | |
23 | ||
24 | #include <stdio.h> | |
25 | #include <unistd.h> | |
26 | #include <stdlib.h> | |
27 | #include <errno.h> | |
b0a33c1e | 28 | #include <signal.h> |
8559e703 | 29 | #include <libgen.h> |
0e322d22 | 30 | #include <sys/stat.h> |
05f05512 | 31 | #include <sys/types.h> |
32 | #include <sys/wait.h> | |
0af683cf | 33 | #include <sys/capability.h> |
05f05512 | 34 | #define _GNU_SOURCE |
35 | #include <getopt.h> | |
00b3c2e2 | 36 | |
00b3c2e2 | 37 | #include <lxc/log.h> |
00b3c2e2 | 38 | #include <lxc/error.h> |
698287d8 | 39 | #include "utils.h" |
8559e703 MN |
40 | |
41 | lxc_log_define(lxc_init, lxc); | |
05f05512 | 42 | |
8559e703 | 43 | static int quiet; |
05f05512 | 44 | |
45 | static struct option options[] = { | |
8559e703 MN |
46 | { "quiet", no_argument, &quiet, 1 }, |
47 | { 0, 0, 0, 0 }, | |
05f05512 | 48 | }; |
49 | ||
e4b3fe58 | 50 | static int was_interrupted = 0; |
51 | ||
0af683cf | 52 | static int cap_reset(void) |
53 | { | |
54 | cap_t cap = cap_init(); | |
55 | int ret = 0; | |
56 | ||
57 | if (!cap) { | |
58 | ERROR("cap_init() failed : %m"); | |
59 | return -1; | |
60 | } | |
61 | ||
62 | if (cap_set_proc(cap)) { | |
63 | ERROR("cap_set_proc() failed : %m"); | |
64 | ret = -1; | |
65 | } | |
66 | ||
67 | cap_free(cap); | |
68 | return ret; | |
69 | } | |
70 | ||
05f05512 | 71 | int main(int argc, char *argv[]) |
72 | { | |
e4b3fe58 | 73 | |
74 | void interrupt_handler(int sig) | |
75 | { | |
76 | if (!was_interrupted) | |
77 | was_interrupted = sig; | |
78 | } | |
79 | ||
05f05512 | 80 | pid_t pid; |
05f05512 | 81 | int nbargs = 0; |
b0ed5e64 | 82 | int err = -1; |
05f05512 | 83 | char **aargv; |
e4b3fe58 | 84 | sigset_t mask, omask; |
85 | int i; | |
05f05512 | 86 | |
87 | while (1) { | |
88 | int ret = getopt_long_only(argc, argv, "", options, NULL); | |
8559e703 | 89 | if (ret == -1) { |
05f05512 | 90 | break; |
8559e703 | 91 | } |
341553f7 | 92 | if (ret == '?') |
b0ed5e64 | 93 | exit(err); |
341553f7 | 94 | |
05f05512 | 95 | nbargs++; |
96 | } | |
97 | ||
341553f7 | 98 | if (lxc_log_init(NULL, 0, basename(argv[0]), quiet)) |
b0ed5e64 | 99 | exit(err); |
8559e703 | 100 | |
05f05512 | 101 | if (!argv[optind]) { |
8559e703 | 102 | ERROR("missing command to launch"); |
b0ed5e64 | 103 | exit(err); |
05f05512 | 104 | } |
105 | ||
106 | aargv = &argv[optind]; | |
107 | argc -= nbargs; | |
108 | ||
e4b3fe58 | 109 | sigfillset(&mask); |
110 | sigprocmask(SIG_SETMASK, &mask, &omask); | |
111 | ||
112 | for (i = 1; i < NSIG; i++) { | |
113 | struct sigaction act; | |
114 | ||
115 | sigfillset(&act.sa_mask); | |
116 | act.sa_flags = 0; | |
117 | act.sa_handler = interrupt_handler; | |
118 | sigaction(i, &act, NULL); | |
119 | } | |
120 | ||
0af683cf | 121 | if (lxc_setup_fs()) |
122 | exit(err); | |
123 | ||
124 | if (cap_reset()) | |
125 | exit(err); | |
126 | ||
05f05512 | 127 | pid = fork(); |
128 | ||
129 | if (pid < 0) | |
b0ed5e64 | 130 | exit(err); |
05f05512 | 131 | |
132 | if (!pid) { | |
133 | ||
e4b3fe58 | 134 | for (i = 1; i < NSIG; i++) |
135 | signal(i, SIG_DFL); | |
136 | sigprocmask(SIG_SETMASK, &omask, NULL); | |
137 | ||
72439b9f MN |
138 | NOTICE("about to exec '%s'", aargv[0]); |
139 | ||
05f05512 | 140 | execvp(aargv[0], aargv); |
0af683cf | 141 | ERROR("failed to exec: '%s' : %m", aargv[0]); |
b0ed5e64 | 142 | exit(err); |
05f05512 | 143 | } |
144 | ||
e4b3fe58 | 145 | sigprocmask(SIG_SETMASK, &omask, NULL); |
146 | ||
affaa6da MN |
147 | /* no need of other inherited fds but stderr */ |
148 | close(fileno(stdin)); | |
149 | close(fileno(stdout)); | |
150 | ||
37c3dfc9 | 151 | err = 0; |
05f05512 | 152 | for (;;) { |
153 | int status; | |
37c3dfc9 | 154 | int orphan = 0; |
b0ed5e64 MN |
155 | pid_t waited_pid; |
156 | ||
e4b3fe58 | 157 | if (was_interrupted) { |
158 | kill(pid, was_interrupted); | |
159 | was_interrupted = 0; | |
160 | } | |
161 | ||
b0ed5e64 MN |
162 | waited_pid = wait(&status); |
163 | if (waited_pid < 0) { | |
05f05512 | 164 | if (errno == ECHILD) |
b0ed5e64 | 165 | goto out; |
05f05512 | 166 | if (errno == EINTR) |
167 | continue; | |
b0ed5e64 MN |
168 | ERROR("failed to wait child : %s", strerror(errno)); |
169 | goto out; | |
05f05512 | 170 | } |
37c3dfc9 MN |
171 | |
172 | /* | |
173 | * keep the exit code of started application (not wrapped pid) | |
174 | * and continue to wait for the end of the orphan group. | |
175 | */ | |
176 | if ((waited_pid != pid) || (orphan ==1)) | |
177 | continue; | |
178 | orphan = 1; | |
179 | err = lxc_error_set_and_log(waited_pid, status); | |
05f05512 | 180 | } |
b0ed5e64 MN |
181 | out: |
182 | return err; | |
05f05512 | 183 | } |
6e4bb2e0 | 184 |