Magellan Linux

Contents of /trunk/mkinitrd-magellan/busybox/runit/chpst.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 10033 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 /*
2 Copyright (c) 2001-2006, Gerrit Pape
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, 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
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
29 /* Dependencies on runit_lib.c removed */
30
31 #include "busybox.h"
32
33 #include <dirent.h>
34
35 // Must match constants in chpst_main!
36 #define OPT_verbose (option_mask32 & 0x2000)
37 #define OPT_pgrp (option_mask32 & 0x4000)
38 #define OPT_nostdin (option_mask32 & 0x8000)
39 #define OPT_nostdout (option_mask32 & 0x10000)
40 #define OPT_nostderr (option_mask32 & 0x20000)
41
42 static char *set_user;
43 static char *env_user;
44 static const char *env_dir;
45 static long limitd = -2;
46 static long limits = -2;
47 static long limitl = -2;
48 static long limita = -2;
49 static long limito = -2;
50 static long limitp = -2;
51 static long limitf = -2;
52 static long limitc = -2;
53 static long limitr = -2;
54 static long limitt = -2;
55 static int nicelvl;
56 static const char *root;
57
58 static void suidgid(char *user)
59 {
60 struct bb_uidgid_t ugid;
61
62 if (!get_uidgid(&ugid, user, 1)) {
63 bb_error_msg_and_die("unknown user/group: %s", user);
64 }
65 if (setgroups(1, &ugid.gid) == -1)
66 bb_perror_msg_and_die("setgroups");
67 xsetgid(ugid.gid);
68 xsetuid(ugid.uid);
69 }
70
71 static void euidgid(char *user)
72 {
73 struct bb_uidgid_t ugid;
74
75 if (!get_uidgid(&ugid, user, 1)) {
76 bb_error_msg_and_die("unknown user/group: %s", user);
77 }
78 xsetenv("GID", utoa(ugid.gid));
79 xsetenv("UID", utoa(ugid.uid));
80 }
81
82 static void edir(const char *directory_name)
83 {
84 int wdir;
85 DIR *dir;
86 struct dirent *d;
87 int fd;
88
89 wdir = xopen(".", O_RDONLY | O_NDELAY);
90 xchdir(directory_name);
91 dir = opendir(".");
92 if (!dir)
93 bb_perror_msg_and_die("opendir %s", directory_name);
94 for (;;) {
95 errno = 0;
96 d = readdir(dir);
97 if (!d) {
98 if (errno)
99 bb_perror_msg_and_die("readdir %s",
100 directory_name);
101 break;
102 }
103 if (d->d_name[0] == '.') continue;
104 fd = open(d->d_name, O_RDONLY | O_NDELAY);
105 if (fd < 0) {
106 if ((errno == EISDIR) && env_dir) {
107 if (OPT_verbose)
108 bb_perror_msg("warning: %s/%s is a directory",
109 directory_name, d->d_name);
110 continue;
111 } else
112 bb_perror_msg_and_die("open %s/%s",
113 directory_name, d->d_name);
114 }
115 if (fd >= 0) {
116 char buf[256];
117 char *tail;
118 int size;
119
120 size = safe_read(fd, buf, sizeof(buf)-1);
121 if (size < 0)
122 bb_perror_msg_and_die("read %s/%s",
123 directory_name, d->d_name);
124 if (size == 0) {
125 unsetenv(d->d_name);
126 continue;
127 }
128 buf[size] = '\n';
129 tail = memchr(buf, '\n', sizeof(buf));
130 /* skip trailing whitespace */;
131 while (1) {
132 if (tail[0]==' ') tail[0] = '\0';
133 if (tail[0]=='\t') tail[0] = '\0';
134 if (tail[0]=='\n') tail[0] = '\0';
135 if (tail == buf) break;
136 tail--;
137 }
138 xsetenv(d->d_name, buf);
139 }
140 }
141 closedir(dir);
142 if (fchdir(wdir) == -1) bb_perror_msg_and_die("fchdir");
143 close(wdir);
144 }
145
146 static void limit(int what, long l)
147 {
148 struct rlimit r;
149
150 if (getrlimit(what, &r) == -1) bb_perror_msg_and_die("getrlimit");
151 if ((l < 0) || (l > r.rlim_max))
152 r.rlim_cur = r.rlim_max;
153 else
154 r.rlim_cur = l;
155 if (setrlimit(what, &r) == -1) bb_perror_msg_and_die("setrlimit");
156 }
157
158 static void slimit(void)
159 {
160 if (limitd >= -1) {
161 #ifdef RLIMIT_DATA
162 limit(RLIMIT_DATA, limitd);
163 #else
164 if (OPT_verbose) bb_error_msg("system does not support %s",
165 "RLIMIT_DATA");
166 #endif
167 }
168 if (limits >= -1) {
169 #ifdef RLIMIT_STACK
170 limit(RLIMIT_STACK, limits);
171 #else
172 if (OPT_verbose) bb_error_msg("system does not support %s",
173 "RLIMIT_STACK");
174 #endif
175 }
176 if (limitl >= -1) {
177 #ifdef RLIMIT_MEMLOCK
178 limit(RLIMIT_MEMLOCK, limitl);
179 #else
180 if (OPT_verbose) bb_error_msg("system does not support %s",
181 "RLIMIT_MEMLOCK");
182 #endif
183 }
184 if (limita >= -1) {
185 #ifdef RLIMIT_VMEM
186 limit(RLIMIT_VMEM, limita);
187 #else
188 #ifdef RLIMIT_AS
189 limit(RLIMIT_AS, limita);
190 #else
191 if (OPT_verbose)
192 bb_error_msg("system does not support %s",
193 "RLIMIT_VMEM");
194 #endif
195 #endif
196 }
197 if (limito >= -1) {
198 #ifdef RLIMIT_NOFILE
199 limit(RLIMIT_NOFILE, limito);
200 #else
201 #ifdef RLIMIT_OFILE
202 limit(RLIMIT_OFILE, limito);
203 #else
204 if (OPT_verbose)
205 bb_error_msg("system does not support %s",
206 "RLIMIT_NOFILE");
207 #endif
208 #endif
209 }
210 if (limitp >= -1) {
211 #ifdef RLIMIT_NPROC
212 limit(RLIMIT_NPROC, limitp);
213 #else
214 if (OPT_verbose) bb_error_msg("system does not support %s",
215 "RLIMIT_NPROC");
216 #endif
217 }
218 if (limitf >= -1) {
219 #ifdef RLIMIT_FSIZE
220 limit(RLIMIT_FSIZE, limitf);
221 #else
222 if (OPT_verbose) bb_error_msg("system does not support %s",
223 "RLIMIT_FSIZE");
224 #endif
225 }
226 if (limitc >= -1) {
227 #ifdef RLIMIT_CORE
228 limit(RLIMIT_CORE, limitc);
229 #else
230 if (OPT_verbose) bb_error_msg("system does not support %s",
231 "RLIMIT_CORE");
232 #endif
233 }
234 if (limitr >= -1) {
235 #ifdef RLIMIT_RSS
236 limit(RLIMIT_RSS, limitr);
237 #else
238 if (OPT_verbose) bb_error_msg("system does not support %s",
239 "RLIMIT_RSS");
240 #endif
241 }
242 if (limitt >= -1) {
243 #ifdef RLIMIT_CPU
244 limit(RLIMIT_CPU, limitt);
245 #else
246 if (OPT_verbose) bb_error_msg("system does not support %s",
247 "RLIMIT_CPU");
248 #endif
249 }
250 }
251
252 /* argv[0] */
253 static void setuidgid(int, char **);
254 static void envuidgid(int, char **);
255 static void envdir(int, char **);
256 static void softlimit(int, char **);
257
258 int chpst_main(int argc, char **argv)
259 {
260 if (applet_name[3] == 'd') envdir(argc, argv);
261 if (applet_name[1] == 'o') softlimit(argc, argv);
262 if (applet_name[0] == 's') setuidgid(argc, argv);
263 if (applet_name[0] == 'e') envuidgid(argc, argv);
264 // otherwise we are chpst
265
266 {
267 char *m,*d,*o,*p,*f,*c,*r,*t,*n;
268 getopt32(argc, argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",
269 &set_user,&env_user,&env_dir,
270 &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);
271 // if (option_mask32 & 0x1) // -u
272 // if (option_mask32 & 0x2) // -U
273 // if (option_mask32 & 0x4) // -e
274 if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m
275 if (option_mask32 & 0x10) limitd = xatoul(d); // -d
276 if (option_mask32 & 0x20) limito = xatoul(o); // -o
277 if (option_mask32 & 0x40) limitp = xatoul(p); // -p
278 if (option_mask32 & 0x80) limitf = xatoul(f); // -f
279 if (option_mask32 & 0x100) limitc = xatoul(c); // -c
280 if (option_mask32 & 0x200) limitr = xatoul(r); // -r
281 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
282 // if (option_mask32 & 0x800) // -/
283 if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n
284 // The below consts should match #defines at top!
285 //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v
286 //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P
287 //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0
288 //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1
289 //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2
290 }
291 argv += optind;
292 if (!argv || !*argv) bb_show_usage();
293
294 if (OPT_pgrp) setsid();
295 if (env_dir) edir(env_dir);
296 if (root) {
297 xchdir(root);
298 if (chroot(".") == -1)
299 bb_perror_msg_and_die("chroot");
300 }
301 slimit();
302 if (nicelvl) {
303 errno = 0;
304 if (nice(nicelvl) == -1)
305 bb_perror_msg_and_die("nice");
306 }
307 if (env_user) euidgid(env_user);
308 if (set_user) suidgid(set_user);
309 if (OPT_nostdin) close(0);
310 if (OPT_nostdout) close(1);
311 if (OPT_nostderr) close(2);
312 execvp(argv[0], argv);
313 bb_perror_msg_and_die("exec %s", argv[0]);
314 }
315
316 static void setuidgid(int argc, char **argv)
317 {
318 const char *account;
319
320 account = *++argv;
321 if (!account) bb_show_usage();
322 if (!*++argv) bb_show_usage();
323 suidgid((char*)account);
324 execvp(argv[0], argv);
325 bb_perror_msg_and_die("exec %s", argv[0]);
326 }
327
328 static void envuidgid(int argc, char **argv)
329 {
330 const char *account;
331
332 account = *++argv;
333 if (!account) bb_show_usage();
334 if (!*++argv) bb_show_usage();
335 euidgid((char*)account);
336 execvp(argv[0], argv);
337 bb_perror_msg_and_die("exec %s", argv[0]);
338 }
339
340 static void envdir(int argc, char **argv)
341 {
342 const char *dir;
343
344 dir = *++argv;
345 if (!dir) bb_show_usage();
346 if (!*++argv) bb_show_usage();
347 edir(dir);
348 execvp(argv[0], argv);
349 bb_perror_msg_and_die("exec %s", argv[0]);
350 }
351
352 static void softlimit(int argc, char **argv)
353 {
354 char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
355 getopt32(argc, argv, "+a:c:d:f:l:m:o:p:r:s:t:",
356 &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);
357 if (option_mask32 & 0x001) limita = xatoul(a); // -a
358 if (option_mask32 & 0x002) limitc = xatoul(c); // -c
359 if (option_mask32 & 0x004) limitd = xatoul(d); // -d
360 if (option_mask32 & 0x008) limitf = xatoul(f); // -f
361 if (option_mask32 & 0x010) limitl = xatoul(l); // -l
362 if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m
363 if (option_mask32 & 0x040) limito = xatoul(o); // -o
364 if (option_mask32 & 0x080) limitp = xatoul(p); // -p
365 if (option_mask32 & 0x100) limitr = xatoul(r); // -r
366 if (option_mask32 & 0x200) limits = xatoul(s); // -s
367 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
368 argv += optind;
369 if (!argv[0]) bb_show_usage();
370 slimit();
371 execvp(argv[0], argv);
372 bb_perror_msg_and_die("exec %s", argv[0]);
373 }