Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide 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 niro 532 /*-
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