Contents of /trunk/mkinitrd-magellan/klibc/usr/dash/miscbltin.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 10588 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 10588 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) 1991, 1993 |
3 | * The Regents of the University of California. All rights reserved. |
4 | * Copyright (c) 1997-2005 |
5 | * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. |
6 | * |
7 | * This code is derived from software contributed to Berkeley by |
8 | * Kenneth Almquist. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. Neither the name of the University nor the names of its contributors |
19 | * may be used to endorse or promote products derived from this software |
20 | * without specific prior written permission. |
21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. |
33 | */ |
34 | |
35 | /* |
36 | * Miscelaneous builtins. |
37 | */ |
38 | |
39 | #include <sys/types.h> /* quad_t */ |
40 | #include <sys/param.h> /* BSD4_4 */ |
41 | #include <sys/stat.h> |
42 | #include <sys/time.h> |
43 | #include <sys/resource.h> |
44 | #include <unistd.h> |
45 | #include <stdlib.h> |
46 | #include <ctype.h> |
47 | #include <stdint.h> |
48 | #include <time.h> /* strtotimeval() */ |
49 | |
50 | #include "shell.h" |
51 | #include "options.h" |
52 | #include "var.h" |
53 | #include "output.h" |
54 | #include "memalloc.h" |
55 | #include "error.h" |
56 | #include "miscbltin.h" |
57 | #include "mystring.h" |
58 | #include "main.h" |
59 | |
60 | #undef rflag |
61 | |
62 | |
63 | |
64 | /* |
65 | * The read builtin. The -e option causes backslashes to escape the |
66 | * following character. |
67 | * |
68 | * This uses unbuffered input, which may be avoidable in some cases. |
69 | */ |
70 | |
71 | int |
72 | readcmd(int argc, char **argv) |
73 | { |
74 | char **ap; |
75 | int backslash; |
76 | char c; |
77 | int rflag; |
78 | char *prompt; |
79 | const char *ifs; |
80 | char *p; |
81 | int startword; |
82 | int status; |
83 | int timeout; |
84 | int i; |
85 | fd_set set; |
86 | struct timeval ts, t0, t1, to; |
87 | |
88 | ts.tv_sec = ts.tv_usec = 0; |
89 | |
90 | rflag = 0; |
91 | timeout = 0; |
92 | prompt = NULL; |
93 | while ((i = nextopt("p:rt:")) != '\0') { |
94 | switch(i) { |
95 | case 'p': |
96 | prompt = optionarg; |
97 | break; |
98 | case 't': |
99 | p = strtotimeval(optionarg, &ts); |
100 | if (*p || (!ts.tv_sec && !ts.tv_usec)) |
101 | sh_error("invalid timeout"); |
102 | timeout = 1; |
103 | break; |
104 | case 'r': |
105 | rflag = 1; |
106 | break; |
107 | default: |
108 | break; |
109 | } |
110 | } |
111 | if (prompt && isatty(0)) { |
112 | out2str(prompt); |
113 | #ifdef FLUSHERR |
114 | flushall(); |
115 | #endif |
116 | } |
117 | if (*(ap = argptr) == NULL) |
118 | sh_error("arg count"); |
119 | if ((ifs = bltinlookup("IFS")) == NULL) |
120 | ifs = defifs; |
121 | status = 0; |
122 | startword = 1; |
123 | backslash = 0; |
124 | if (timeout) { |
125 | gettimeofday(&t0, NULL); |
126 | |
127 | /* ts += t0; */ |
128 | ts.tv_usec += t0.tv_usec; |
129 | while (ts.tv_usec >= 1000000) { |
130 | ts.tv_sec++; |
131 | ts.tv_usec -= 1000000; |
132 | } |
133 | ts.tv_sec += t0.tv_sec; |
134 | } |
135 | STARTSTACKSTR(p); |
136 | for (;;) { |
137 | if (timeout) { |
138 | gettimeofday(&t1, NULL); |
139 | if (t1.tv_sec > ts.tv_sec || |
140 | (t1.tv_sec == ts.tv_sec && |
141 | t1.tv_usec >= ts.tv_usec)) { |
142 | status = 1; |
143 | break; /* Timeout! */ |
144 | } |
145 | |
146 | /* to = ts - t1; */ |
147 | if (ts.tv_usec >= t1.tv_usec) { |
148 | to.tv_usec = ts.tv_usec - t1.tv_usec; |
149 | to.tv_sec = ts.tv_sec - t1.tv_sec; |
150 | } else { |
151 | to.tv_usec = ts.tv_usec - t1.tv_usec + 1000000; |
152 | to.tv_sec = ts.tv_sec - t1.tv_sec - 1; |
153 | } |
154 | |
155 | FD_ZERO(&set); |
156 | FD_SET(0, &set); |
157 | if (select(1, &set, NULL, NULL, &to) != 1) { |
158 | status = 1; |
159 | break; /* Timeout! */ |
160 | } |
161 | } |
162 | if (read(0, &c, 1) != 1) { |
163 | status = 1; |
164 | break; |
165 | } |
166 | if (c == '\0') |
167 | continue; |
168 | if (backslash) { |
169 | backslash = 0; |
170 | if (c != '\n') |
171 | goto put; |
172 | continue; |
173 | } |
174 | if (!rflag && c == '\\') { |
175 | backslash++; |
176 | continue; |
177 | } |
178 | if (c == '\n') |
179 | break; |
180 | if (startword && *ifs == ' ' && strchr(ifs, c)) { |
181 | continue; |
182 | } |
183 | startword = 0; |
184 | if (ap[1] != NULL && strchr(ifs, c) != NULL) { |
185 | STACKSTRNUL(p); |
186 | setvar(*ap, stackblock(), 0); |
187 | ap++; |
188 | startword = 1; |
189 | STARTSTACKSTR(p); |
190 | } else { |
191 | put: |
192 | STPUTC(c, p); |
193 | } |
194 | } |
195 | STACKSTRNUL(p); |
196 | /* Remove trailing blanks */ |
197 | while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL) |
198 | *p = '\0'; |
199 | setvar(*ap, stackblock(), 0); |
200 | while (*++ap != NULL) |
201 | setvar(*ap, nullstr, 0); |
202 | return status; |
203 | } |
204 | |
205 | |
206 | |
207 | /* |
208 | * umask builtin |
209 | * |
210 | * This code was ripped from pdksh 5.2.14 and hacked for use with |
211 | * dash by Herbert Xu. |
212 | * |
213 | * Public domain. |
214 | */ |
215 | |
216 | int |
217 | umaskcmd(int argc, char **argv) |
218 | { |
219 | char *ap; |
220 | int mask; |
221 | int i; |
222 | int symbolic_mode = 0; |
223 | |
224 | while ((i = nextopt("S")) != '\0') { |
225 | symbolic_mode = 1; |
226 | } |
227 | |
228 | INTOFF; |
229 | mask = umask(0); |
230 | umask(mask); |
231 | INTON; |
232 | |
233 | if ((ap = *argptr) == NULL) { |
234 | if (symbolic_mode) { |
235 | char buf[18]; |
236 | int j; |
237 | |
238 | mask = ~mask; |
239 | ap = buf; |
240 | for (i = 0; i < 3; i++) { |
241 | *ap++ = "ugo"[i]; |
242 | *ap++ = '='; |
243 | for (j = 0; j < 3; j++) |
244 | if (mask & (1 << (8 - (3*i + j)))) |
245 | *ap++ = "rwx"[j]; |
246 | *ap++ = ','; |
247 | } |
248 | ap[-1] = '\0'; |
249 | out1fmt("%s\n", buf); |
250 | } else { |
251 | out1fmt("%.4o\n", mask); |
252 | } |
253 | } else { |
254 | int new_mask; |
255 | |
256 | if (isdigit(*ap)) { |
257 | new_mask = 0; |
258 | do { |
259 | if (*ap >= '8' || *ap < '0') |
260 | sh_error(illnum, *argptr); |
261 | new_mask = (new_mask << 3) + (*ap - '0'); |
262 | } while (*++ap != '\0'); |
263 | } else { |
264 | int positions, new_val; |
265 | char op; |
266 | |
267 | mask = ~mask; |
268 | new_mask = mask; |
269 | positions = 0; |
270 | while (*ap) { |
271 | while (*ap && strchr("augo", *ap)) |
272 | switch (*ap++) { |
273 | case 'a': positions |= 0111; break; |
274 | case 'u': positions |= 0100; break; |
275 | case 'g': positions |= 0010; break; |
276 | case 'o': positions |= 0001; break; |
277 | } |
278 | if (!positions) |
279 | positions = 0111; /* default is a */ |
280 | if (!strchr("=+-", op = *ap)) |
281 | break; |
282 | ap++; |
283 | new_val = 0; |
284 | while (*ap && strchr("rwxugoXs", *ap)) |
285 | switch (*ap++) { |
286 | case 'r': new_val |= 04; break; |
287 | case 'w': new_val |= 02; break; |
288 | case 'x': new_val |= 01; break; |
289 | case 'u': new_val |= mask >> 6; |
290 | break; |
291 | case 'g': new_val |= mask >> 3; |
292 | break; |
293 | case 'o': new_val |= mask >> 0; |
294 | break; |
295 | case 'X': if (mask & 0111) |
296 | new_val |= 01; |
297 | break; |
298 | case 's': /* ignored */ |
299 | break; |
300 | } |
301 | new_val = (new_val & 07) * positions; |
302 | switch (op) { |
303 | case '-': |
304 | new_mask &= ~new_val; |
305 | break; |
306 | case '=': |
307 | new_mask = new_val |
308 | | (new_mask & ~(positions * 07)); |
309 | break; |
310 | case '+': |
311 | new_mask |= new_val; |
312 | } |
313 | if (*ap == ',') { |
314 | positions = 0; |
315 | ap++; |
316 | } else if (!strchr("=+-", *ap)) |
317 | break; |
318 | } |
319 | if (*ap) { |
320 | sh_error("Illegal mode: %s", *argptr); |
321 | return 1; |
322 | } |
323 | new_mask = ~new_mask; |
324 | } |
325 | umask(new_mask); |
326 | } |
327 | return 0; |
328 | } |
329 | |
330 | #ifdef HAVE_GETRLIMIT |
331 | /* |
332 | * ulimit builtin |
333 | * |
334 | * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and |
335 | * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with |
336 | * ash by J.T. Conklin. |
337 | * |
338 | * Public domain. |
339 | */ |
340 | |
341 | struct limits { |
342 | const char *name; |
343 | int cmd; |
344 | int factor; /* multiply by to get rlim_{cur,max} values */ |
345 | char option; |
346 | }; |
347 | |
348 | static const struct limits limits[] = { |
349 | #ifdef RLIMIT_CPU |
350 | { "time(seconds)", RLIMIT_CPU, 1, 't' }, |
351 | #endif |
352 | #ifdef RLIMIT_FSIZE |
353 | { "file(blocks)", RLIMIT_FSIZE, 512, 'f' }, |
354 | #endif |
355 | #ifdef RLIMIT_DATA |
356 | { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, |
357 | #endif |
358 | #ifdef RLIMIT_STACK |
359 | { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, |
360 | #endif |
361 | #ifdef RLIMIT_CORE |
362 | { "coredump(blocks)", RLIMIT_CORE, 512, 'c' }, |
363 | #endif |
364 | #ifdef RLIMIT_RSS |
365 | { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, |
366 | #endif |
367 | #ifdef RLIMIT_MEMLOCK |
368 | { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, |
369 | #endif |
370 | #ifdef RLIMIT_NPROC |
371 | { "process", RLIMIT_NPROC, 1, 'p' }, |
372 | #endif |
373 | #ifdef RLIMIT_NOFILE |
374 | { "nofiles", RLIMIT_NOFILE, 1, 'n' }, |
375 | #endif |
376 | #ifdef RLIMIT_AS |
377 | { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' }, |
378 | #endif |
379 | #ifdef RLIMIT_LOCKS |
380 | { "locks", RLIMIT_LOCKS, 1, 'w' }, |
381 | #endif |
382 | { (char *) 0, 0, 0, '\0' } |
383 | }; |
384 | |
385 | enum limtype { SOFT = 0x1, HARD = 0x2 }; |
386 | |
387 | static void printlim(enum limtype how, const struct rlimit *limit, |
388 | const struct limits *l) |
389 | { |
390 | rlim_t val; |
391 | |
392 | val = limit->rlim_max; |
393 | if (how & SOFT) |
394 | val = limit->rlim_cur; |
395 | |
396 | if (val == RLIM_INFINITY) |
397 | out1fmt("unlimited\n"); |
398 | else { |
399 | val /= l->factor; |
400 | out1fmt("%jd\n", (intmax_t) val); |
401 | } |
402 | } |
403 | |
404 | int |
405 | ulimitcmd(int argc, char **argv) |
406 | { |
407 | int c; |
408 | rlim_t val = 0; |
409 | enum limtype how = SOFT | HARD; |
410 | const struct limits *l; |
411 | int set, all = 0; |
412 | int optc, what; |
413 | struct rlimit limit; |
414 | |
415 | what = 'f'; |
416 | while ((optc = nextopt("HSa" |
417 | #ifdef RLIMIT_CPU |
418 | "t" |
419 | #endif |
420 | #ifdef RLIMIT_FSIZE |
421 | "f" |
422 | #endif |
423 | #ifdef RLIMIT_DATA |
424 | "d" |
425 | #endif |
426 | #ifdef RLIMIT_STACK |
427 | "s" |
428 | #endif |
429 | #ifdef RLIMIT_CORE |
430 | "c" |
431 | #endif |
432 | #ifdef RLIMIT_RSS |
433 | "m" |
434 | #endif |
435 | #ifdef RLIMIT_MEMLOCK |
436 | "l" |
437 | #endif |
438 | #ifdef RLIMIT_NPROC |
439 | "p" |
440 | #endif |
441 | #ifdef RLIMIT_NOFILE |
442 | "n" |
443 | #endif |
444 | #ifdef RLIMIT_AS |
445 | "v" |
446 | #endif |
447 | #ifdef RLIMIT_LOCKS |
448 | "w" |
449 | #endif |
450 | )) != '\0') |
451 | switch (optc) { |
452 | case 'H': |
453 | how = HARD; |
454 | break; |
455 | case 'S': |
456 | how = SOFT; |
457 | break; |
458 | case 'a': |
459 | all = 1; |
460 | break; |
461 | default: |
462 | what = optc; |
463 | } |
464 | |
465 | for (l = limits; l->option != what; l++) |
466 | ; |
467 | |
468 | set = *argptr ? 1 : 0; |
469 | if (set) { |
470 | char *p = *argptr; |
471 | |
472 | if (all || argptr[1]) |
473 | sh_error("too many arguments"); |
474 | if (strcmp(p, "unlimited") == 0) |
475 | val = RLIM_INFINITY; |
476 | else { |
477 | val = (rlim_t) 0; |
478 | |
479 | while ((c = *p++) >= '0' && c <= '9') |
480 | { |
481 | val = (val * 10) + (long)(c - '0'); |
482 | if (val < (rlim_t) 0) |
483 | break; |
484 | } |
485 | if (c) |
486 | sh_error("bad number"); |
487 | val *= l->factor; |
488 | } |
489 | } |
490 | if (all) { |
491 | for (l = limits; l->name; l++) { |
492 | getrlimit(l->cmd, &limit); |
493 | out1fmt("%-20s ", l->name); |
494 | printlim(how, &limit, l); |
495 | } |
496 | return 0; |
497 | } |
498 | |
499 | getrlimit(l->cmd, &limit); |
500 | if (set) { |
501 | if (how & HARD) |
502 | limit.rlim_max = val; |
503 | if (how & SOFT) |
504 | limit.rlim_cur = val; |
505 | if (setrlimit(l->cmd, &limit) < 0) |
506 | sh_error("error setting limit (%s)", strerror(errno)); |
507 | } else { |
508 | printlim(how, &limit, l); |
509 | } |
510 | return 0; |
511 | } |
512 | #endif |