]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/execute.c
Use on_path to find init.lxc
[mirror_lxc.git] / src / lxc / execute.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29
30 #include "conf.h"
31 #include "log.h"
32 #include "start.h"
33 #include "utils.h"
34
35 lxc_log_define(lxc_execute, lxc_start);
36
37 struct execute_args {
38 char *const *argv;
39 int quiet;
40 };
41
42 /* historically lxc-init has been under /usr/lib/lxc and under
43 * /usr/lib/$ARCH/lxc. It now lives as $prefix/sbin/init.lxc.
44 */
45 static char *choose_init(void)
46 {
47 char *retv = NULL;
48 int ret, env_set = 0;
49 struct stat mystat;
50
51 if (!getenv("PATH")) {
52 if (setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 0))
53 SYSERROR("Failed to setenv");
54 env_set = 1;
55 }
56
57 retv = on_path("init.lxc");
58
59 if (env_set) {
60 if (unsetenv("PATH"))
61 SYSERROR("Failed to unsetenv");
62 }
63
64 if (retv)
65 return retv;
66
67 retv = malloc(PATH_MAX);
68 if (!retv)
69 return NULL;
70
71 ret = snprintf(retv, PATH_MAX, SBINDIR "/init.lxc");
72 if (ret < 0 || ret >= PATH_MAX) {
73 ERROR("pathname too long");
74 goto out1;
75 }
76
77 ret = stat(retv, &mystat);
78 if (ret == 0)
79 return retv;
80
81 ret = snprintf(retv, PATH_MAX, LXCINITDIR "/lxc/lxc-init");
82 if (ret < 0 || ret >= PATH_MAX) {
83 ERROR("pathname too long");
84 goto out1;
85 }
86
87 ret = stat(retv, &mystat);
88 if (ret == 0)
89 return retv;
90
91 ret = snprintf(retv, PATH_MAX, "/usr/lib/lxc/lxc-init");
92 if (ret < 0 || ret >= PATH_MAX) {
93 ERROR("pathname too long");
94 goto out1;
95 }
96 ret = stat(retv, &mystat);
97 if (ret == 0)
98 return retv;
99 ret = snprintf(retv, PATH_MAX, "/sbin/lxc-init");
100 if (ret < 0 || ret >= PATH_MAX) {
101 ERROR("pathname too long");
102 goto out1;
103 }
104 ret = stat(retv, &mystat);
105 if (ret == 0)
106 return retv;
107 out1:
108 free(retv);
109 return NULL;
110 }
111
112 static int execute_start(struct lxc_handler *handler, void* data)
113 {
114 int j, i = 0;
115 struct execute_args *my_args = data;
116 char **argv;
117 int argc = 0, argc_add;
118 char *initpath;
119
120 while (my_args->argv[argc++]);
121
122 argc_add = 4;
123 if (my_args->quiet)
124 argc_add++;
125 if (!handler->conf->rootfs.path) {
126 argc_add += 4;
127 if (lxc_log_has_valid_level())
128 argc_add += 2;
129 }
130
131 argv = malloc((argc + argc_add) * sizeof(*argv));
132 if (!argv)
133 goto out1;
134
135 initpath = choose_init();
136 if (!initpath) {
137 ERROR("Failed to find an lxc-init");
138 goto out2;
139 }
140 argv[i++] = initpath;
141 if (my_args->quiet)
142 argv[i++] = "--quiet";
143 if (!handler->conf->rootfs.path) {
144 argv[i++] = "--name";
145 argv[i++] = (char *)handler->name;
146 argv[i++] = "--lxcpath";
147 argv[i++] = (char *)handler->lxcpath;
148
149 if (lxc_log_has_valid_level()) {
150 argv[i++] = "--logpriority";
151 argv[i++] = (char *)
152 lxc_log_priority_to_string(lxc_log_get_level());
153 }
154 }
155 argv[i++] = "--";
156 for (j = 0; j < argc; j++)
157 argv[i++] = my_args->argv[j];
158 argv[i++] = NULL;
159
160 NOTICE("exec'ing '%s'", my_args->argv[0]);
161
162 execvp(argv[0], argv);
163 SYSERROR("failed to exec %s", argv[0]);
164 free(initpath);
165 out2:
166 free(argv);
167 out1:
168 return 1;
169 }
170
171 static int execute_post_start(struct lxc_handler *handler, void* data)
172 {
173 struct execute_args *my_args = data;
174 NOTICE("'%s' started with pid '%d'", my_args->argv[0], handler->pid);
175 return 0;
176 }
177
178 static struct lxc_operations execute_start_ops = {
179 .start = execute_start,
180 .post_start = execute_post_start
181 };
182
183 int lxc_execute(const char *name, char *const argv[], int quiet,
184 struct lxc_conf *conf, const char *lxcpath)
185 {
186 struct execute_args args = {
187 .argv = argv,
188 .quiet = quiet
189 };
190
191 if (lxc_check_inherited(conf, -1))
192 return -1;
193
194 conf->is_execute = 1;
195 return __lxc_start(name, conf, &execute_start_ops, &args, lxcpath);
196 }