blob: 63da4797f8a6220b6f1b6d548d6c6720a652b176 [file] [log] [blame]
Denis Vlasenko9bff26c2006-10-20 19:40:44 +00001/*
2Copyright (c) 2001-2006, Gerrit Pape
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
Denis Vlasenkod18f52b2008-03-02 12:53:15 +000028/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
Denis Vlasenko83ea6432006-11-16 02:27:24 +000029/* Dependencies on runit_lib.c removed */
Denis Vlasenko9bff26c2006-10-20 19:40:44 +000030
Pere Orga5bc8c002011-04-11 03:29:49 +020031//usage:#define chpst_trivial_usage
32//usage: "[-vP012] [-u USER[:GRP]] [-U USER[:GRP]] [-e DIR]\n"
33//usage: " [-/ DIR] [-n NICE] [-m BYTES] [-d BYTES] [-o N]\n"
34//usage: " [-p N] [-f BYTES] [-c BYTES] PROG ARGS"
35//usage:#define chpst_full_usage "\n\n"
36//usage: "Change the process state, run PROG\n"
37//usage: "\nOptions:"
38//usage: "\n -u USER[:GRP] Set uid and gid"
39//usage: "\n -U USER[:GRP] Set $UID and $GID in environment"
40//usage: "\n -e DIR Set environment variables as specified by files"
41//usage: "\n in DIR: file=1st_line_of_file"
42//usage: "\n -/ DIR Chroot to DIR"
43//usage: "\n -n NICE Add NICE to nice value"
44//usage: "\n -m BYTES Same as -d BYTES -s BYTES -l BYTES"
45//usage: "\n -d BYTES Limit data segment"
46//usage: "\n -o N Limit number of open files per process"
47//usage: "\n -p N Limit number of processes per uid"
48//usage: "\n -f BYTES Limit output file sizes"
49//usage: "\n -c BYTES Limit core file size"
50//usage: "\n -v Verbose"
51//usage: "\n -P Create new process group"
52//usage: "\n -0 Close stdin"
53//usage: "\n -1 Close stdout"
54//usage: "\n -2 Close stderr"
55//usage:
56//usage:#define envdir_trivial_usage
57//usage: "DIR PROG ARGS"
58//usage:#define envdir_full_usage "\n\n"
59//usage: "Set various environment variables as specified by files\n"
60//usage: "in the directory DIR, run PROG"
61//usage:
62//usage:#define envuidgid_trivial_usage
63//usage: "USER PROG ARGS"
64//usage:#define envuidgid_full_usage "\n\n"
65//usage: "Set $UID to USER's uid and $GID to USER's gid, run PROG"
66//usage:
67//usage:#define setuidgid_trivial_usage
68//usage: "USER PROG ARGS"
69//usage:#define setuidgid_full_usage "\n\n"
70//usage: "Set uid and gid to USER's uid and gid, drop supplementary group ids,\n"
71//usage: "run PROG"
72//usage:
73//usage:#define softlimit_trivial_usage
74//usage: "[-a BYTES] [-m BYTES] [-d BYTES] [-s BYTES] [-l BYTES]\n"
75//usage: " [-f BYTES] [-c BYTES] [-r BYTES] [-o N] [-p N] [-t N]\n"
76//usage: " PROG ARGS"
77//usage:#define softlimit_full_usage "\n\n"
78//usage: "Set soft resource limits, then run PROG\n"
79//usage: "\nOptions:"
80//usage: "\n -a BYTES Limit total size of all segments"
81//usage: "\n -m BYTES Same as -d BYTES -s BYTES -l BYTES -a BYTES"
82//usage: "\n -d BYTES Limit data segment"
83//usage: "\n -s BYTES Limit stack segment"
84//usage: "\n -l BYTES Limit locked memory size"
85//usage: "\n -o N Limit number of open files per process"
86//usage: "\n -p N Limit number of processes per uid"
87//usage: "\nOptions controlling file sizes:"
88//usage: "\n -f BYTES Limit output file sizes"
89//usage: "\n -c BYTES Limit core file size"
90//usage: "\nEfficiency opts:"
91//usage: "\n -r BYTES Limit resident set size"
92//usage: "\n -t N Limit CPU time, process receives"
93//usage: "\n a SIGXCPU after N seconds"
94
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000095#include "libbb.h"
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +000096
Denis Vlasenkob3571492008-07-30 21:23:26 +000097/*
98Five applets here: chpst, envdir, envuidgid, setuidgid, softlimit.
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +000099
Denis Vlasenkob3571492008-07-30 21:23:26 +0000100Only softlimit and chpst are taking options:
101
102# common
103-o N Limit number of open files per process
104-p N Limit number of processes per uid
105-m BYTES Same as -d BYTES -s BYTES -l BYTES [-a BYTES]
106-d BYTES Limit data segment
107-f BYTES Limit output file sizes
108-c BYTES Limit core file size
109# softlimit
110-a BYTES Limit total size of all segments
111-s BYTES Limit stack segment
112-l BYTES Limit locked memory size
113-r BYTES Limit resident set size
114-t N Limit CPU time
115# chpst
116-u USER[:GRP] Set uid and gid
117-U USER[:GRP] Set $UID and $GID in environment
118-e DIR Set environment variables as specified by files in DIR
119-/ DIR Chroot to DIR
120-n NICE Add NICE to nice value
121-v Verbose
122-P Create new process group
123-0 -1 -2 Close fd 0,1,2
124
125Even though we accept all these options for both softlimit and chpst,
126they are not to be advertised on their help texts.
127We have enough problems with feature creep in other people's
128software, don't want to add our own.
129
130envdir, envuidgid, setuidgid take no options, but they reuse code which
131handles -e, -U and -u.
132*/
133
134enum {
135 OPT_a = (1 << 0) * ENABLE_SOFTLIMIT,
136 OPT_c = (1 << 1) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
137 OPT_d = (1 << 2) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
138 OPT_f = (1 << 3) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
139 OPT_l = (1 << 4) * ENABLE_SOFTLIMIT,
140 OPT_m = (1 << 5) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
141 OPT_o = (1 << 6) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
142 OPT_p = (1 << 7) * (ENABLE_SOFTLIMIT || ENABLE_CHPST),
143 OPT_r = (1 << 8) * ENABLE_SOFTLIMIT,
144 OPT_s = (1 << 9) * ENABLE_SOFTLIMIT,
145 OPT_t = (1 << 10) * ENABLE_SOFTLIMIT,
146 OPT_u = (1 << 11) * (ENABLE_CHPST || ENABLE_SETUIDGID),
147 OPT_U = (1 << 12) * (ENABLE_CHPST || ENABLE_ENVUIDGID),
148 OPT_e = (1 << 13) * (ENABLE_CHPST || ENABLE_ENVDIR),
149 OPT_root = (1 << 14) * ENABLE_CHPST,
150 OPT_n = (1 << 15) * ENABLE_CHPST,
151 OPT_v = (1 << 16) * ENABLE_CHPST,
152 OPT_P = (1 << 17) * ENABLE_CHPST,
153 OPT_0 = (1 << 18) * ENABLE_CHPST,
154 OPT_1 = (1 << 19) * ENABLE_CHPST,
155 OPT_2 = (1 << 20) * ENABLE_CHPST,
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000156};
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000157
Bernhard Reutner-Fischerca254492009-10-26 23:27:07 +0100158/* TODO: use recursive_action? */
Denys Vlasenkoadf922e2009-10-08 14:35:37 +0200159static NOINLINE void edir(const char *directory_name)
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000160{
161 int wdir;
162 DIR *dir;
163 struct dirent *d;
164 int fd;
165
166 wdir = xopen(".", O_RDONLY | O_NDELAY);
167 xchdir(directory_name);
Bernhard Reutner-Fischerca254492009-10-26 23:27:07 +0100168 dir = xopendir(".");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000169 for (;;) {
Denys Vlasenko695fa512010-01-06 18:16:39 +0100170 char buf[256];
Denis Vlasenko9895dfd2008-04-01 16:13:14 +0000171 char *tail;
172 int size;
173
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000174 errno = 0;
175 d = readdir(dir);
176 if (!d) {
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000177 if (errno)
178 bb_perror_msg_and_die("readdir %s",
179 directory_name);
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000180 break;
181 }
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000182 if (d->d_name[0] == '.')
183 continue;
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000184 fd = open(d->d_name, O_RDONLY | O_NDELAY);
185 if (fd < 0) {
Denis Vlasenkob3571492008-07-30 21:23:26 +0000186 if ((errno == EISDIR) && directory_name) {
187 if (option_mask32 & OPT_v)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000188 bb_perror_msg("warning: %s/%s is a directory",
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +0200189 directory_name, d->d_name);
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000190 continue;
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +0200191 }
192 bb_perror_msg_and_die("open %s/%s",
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000193 directory_name, d->d_name);
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000194 }
Denis Vlasenko9895dfd2008-04-01 16:13:14 +0000195 size = full_read(fd, buf, sizeof(buf)-1);
196 close(fd);
197 if (size < 0)
198 bb_perror_msg_and_die("read %s/%s",
199 directory_name, d->d_name);
200 if (size == 0) {
201 unsetenv(d->d_name);
202 continue;
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000203 }
Denis Vlasenko9895dfd2008-04-01 16:13:14 +0000204 buf[size] = '\n';
205 tail = strchr(buf, '\n');
206 /* skip trailing whitespace */
207 while (1) {
208 *tail = '\0';
209 tail--;
210 if (tail < buf || !isspace(*tail))
211 break;
212 }
213 xsetenv(d->d_name, buf);
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000214 }
215 closedir(dir);
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000216 if (fchdir(wdir) == -1)
217 bb_perror_msg_and_die("fchdir");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000218 close(wdir);
219}
220
221static void limit(int what, long l)
222{
223 struct rlimit r;
224
Denis Vlasenko4e6d5112008-03-12 22:14:34 +0000225 /* Never fails under Linux (except if you pass it bad arguments) */
226 getrlimit(what, &r);
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000227 if ((l < 0) || (l > r.rlim_max))
228 r.rlim_cur = r.rlim_max;
229 else
230 r.rlim_cur = l;
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000231 if (setrlimit(what, &r) == -1)
232 bb_perror_msg_and_die("setrlimit");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000233}
234
Denis Vlasenkob3571492008-07-30 21:23:26 +0000235int chpst_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
236int chpst_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000237{
Denis Vlasenkob3571492008-07-30 21:23:26 +0000238 struct bb_uidgid_t ugid;
Denis Vlasenkoec73d302008-08-05 17:43:29 +0000239 char *set_user = set_user; /* for compiler */
240 char *env_user = env_user;
241 char *env_dir = env_dir;
Denis Vlasenkob3571492008-07-30 21:23:26 +0000242 char *root;
243 char *nicestr;
244 unsigned limita;
245 unsigned limitc;
246 unsigned limitd;
247 unsigned limitf;
248 unsigned limitl;
249 unsigned limitm;
250 unsigned limito;
251 unsigned limitp;
252 unsigned limitr;
253 unsigned limits;
254 unsigned limitt;
255 unsigned opt;
256
257 if ((ENABLE_CHPST && applet_name[0] == 'c')
258 || (ENABLE_SOFTLIMIT && applet_name[1] == 'o')
259 ) {
260 // FIXME: can we live with int-sized limits?
261 // can we live with 40000 days?
262 // if yes -> getopt converts strings to numbers for us
263 opt_complementary = "-1:a+:c+:d+:f+:l+:m+:o+:p+:r+:s+:t+";
264 opt = getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:u:U:e:"
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000265 IF_CHPST("/:n:vP012"),
Denis Vlasenkob3571492008-07-30 21:23:26 +0000266 &limita, &limitc, &limitd, &limitf, &limitl,
267 &limitm, &limito, &limitp, &limitr, &limits, &limitt,
268 &set_user, &env_user, &env_dir
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000269 IF_CHPST(, &root, &nicestr));
Denis Vlasenkob3571492008-07-30 21:23:26 +0000270 argv += optind;
271 if (opt & OPT_m) { // -m means -asld
272 limita = limits = limitl = limitd = limitm;
273 opt |= (OPT_s | OPT_l | OPT_a | OPT_d);
274 }
275 } else {
276 option_mask32 = opt = 0;
277 argv++;
Denis Vlasenkob9c262b2008-08-20 22:19:27 +0000278 if (!*argv)
279 bb_show_usage();
Denis Vlasenkob3571492008-07-30 21:23:26 +0000280 }
281
282 // envdir?
283 if (ENABLE_ENVDIR && applet_name[3] == 'd') {
284 env_dir = *argv++;
285 opt |= OPT_e;
286 }
287
288 // setuidgid?
Denis Vlasenkob9c262b2008-08-20 22:19:27 +0000289 if (ENABLE_SETUIDGID && applet_name[1] == 'e') {
Denis Vlasenkob3571492008-07-30 21:23:26 +0000290 set_user = *argv++;
291 opt |= OPT_u;
292 }
293
294 // envuidgid?
Denis Vlasenko69ed3092008-08-15 21:03:17 +0000295 if (ENABLE_ENVUIDGID && applet_name[0] == 'e' && applet_name[3] == 'u') {
Denis Vlasenkob3571492008-07-30 21:23:26 +0000296 env_user = *argv++;
297 opt |= OPT_U;
298 }
299
300 // we must have PROG [ARGS]
301 if (!*argv)
302 bb_show_usage();
303
304 // set limits
305 if (opt & OPT_d) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000306#ifdef RLIMIT_DATA
307 limit(RLIMIT_DATA, limitd);
308#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000309 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000310 bb_error_msg("system does not support RLIMIT_%s",
311 "DATA");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000312#endif
313 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000314 if (opt & OPT_s) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000315#ifdef RLIMIT_STACK
316 limit(RLIMIT_STACK, limits);
317#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000318 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000319 bb_error_msg("system does not support RLIMIT_%s",
320 "STACK");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000321#endif
322 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000323 if (opt & OPT_l) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000324#ifdef RLIMIT_MEMLOCK
325 limit(RLIMIT_MEMLOCK, limitl);
326#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000327 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000328 bb_error_msg("system does not support RLIMIT_%s",
329 "MEMLOCK");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000330#endif
331 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000332 if (opt & OPT_a) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000333#ifdef RLIMIT_VMEM
334 limit(RLIMIT_VMEM, limita);
335#else
336#ifdef RLIMIT_AS
337 limit(RLIMIT_AS, limita);
338#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000339 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000340 bb_error_msg("system does not support RLIMIT_%s",
341 "VMEM");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000342#endif
343#endif
344 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000345 if (opt & OPT_o) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000346#ifdef RLIMIT_NOFILE
347 limit(RLIMIT_NOFILE, limito);
348#else
349#ifdef RLIMIT_OFILE
350 limit(RLIMIT_OFILE, limito);
351#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000352 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000353 bb_error_msg("system does not support RLIMIT_%s",
354 "NOFILE");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000355#endif
356#endif
357 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000358 if (opt & OPT_p) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000359#ifdef RLIMIT_NPROC
360 limit(RLIMIT_NPROC, limitp);
361#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000362 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000363 bb_error_msg("system does not support RLIMIT_%s",
364 "NPROC");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000365#endif
366 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000367 if (opt & OPT_f) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000368#ifdef RLIMIT_FSIZE
369 limit(RLIMIT_FSIZE, limitf);
370#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000371 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000372 bb_error_msg("system does not support RLIMIT_%s",
373 "FSIZE");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000374#endif
375 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000376 if (opt & OPT_c) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000377#ifdef RLIMIT_CORE
378 limit(RLIMIT_CORE, limitc);
379#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000380 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000381 bb_error_msg("system does not support RLIMIT_%s",
382 "CORE");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000383#endif
384 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000385 if (opt & OPT_r) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000386#ifdef RLIMIT_RSS
387 limit(RLIMIT_RSS, limitr);
388#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000389 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000390 bb_error_msg("system does not support RLIMIT_%s",
391 "RSS");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000392#endif
393 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000394 if (opt & OPT_t) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000395#ifdef RLIMIT_CPU
396 limit(RLIMIT_CPU, limitt);
397#else
Denis Vlasenkob3571492008-07-30 21:23:26 +0000398 if (opt & OPT_v)
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000399 bb_error_msg("system does not support RLIMIT_%s",
400 "CPU");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000401#endif
402 }
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000403
Denis Vlasenkob3571492008-07-30 21:23:26 +0000404 if (opt & OPT_P)
405 setsid();
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000406
Denis Vlasenkob3571492008-07-30 21:23:26 +0000407 if (opt & OPT_e)
408 edir(env_dir);
Denis Vlasenko23e3e252007-10-05 21:23:49 +0000409
Denis Vlasenkob3571492008-07-30 21:23:26 +0000410 // FIXME: chrooted jail must have /etc/passwd if we move this after chroot!
411 // OTOH chroot fails for non-roots!
412 // SOLUTION: cache uid/gid before chroot, apply uid/gid after
413 if (opt & OPT_U) {
414 xget_uidgid(&ugid, env_user);
415 xsetenv("GID", utoa(ugid.gid));
416 xsetenv("UID", utoa(ugid.uid));
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000417 }
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000418
Denis Vlasenkob3571492008-07-30 21:23:26 +0000419 if (opt & OPT_u) {
420 xget_uidgid(&ugid, set_user);
421 }
422
423 if (opt & OPT_root) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000424 xchdir(root);
Denis Vlasenko394eebe2008-02-25 20:30:24 +0000425 xchroot(".");
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000426 }
Denis Vlasenkob3571492008-07-30 21:23:26 +0000427
428 if (opt & OPT_u) {
429 if (setgroups(1, &ugid.gid) == -1)
430 bb_perror_msg_and_die("setgroups");
431 xsetgid(ugid.gid);
432 xsetuid(ugid.uid);
433 }
434
435 if (opt & OPT_n) {
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000436 errno = 0;
Denis Vlasenkob3571492008-07-30 21:23:26 +0000437 if (nice(xatoi(nicestr)) == -1)
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000438 bb_perror_msg_and_die("nice");
439 }
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000440
Denis Vlasenkob3571492008-07-30 21:23:26 +0000441 if (opt & OPT_0)
442 close(STDIN_FILENO);
443 if (opt & OPT_1)
444 close(STDOUT_FILENO);
445 if (opt & OPT_2)
446 close(STDERR_FILENO);
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000447
Pascal Bellard21e8e8d2010-07-04 00:57:03 +0200448 BB_EXECVP_or_die(argv);
Denis Vlasenkof0a97fb2006-10-03 17:52:24 +0000449}