Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/dash/miscbltin.c

Parent Directory Parent Directory | Revision Log 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)
-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