Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1122 - (hide annotations) (download)
Wed Aug 18 21:11:40 2010 UTC (13 years, 8 months ago) by niro
File MIME type: text/plain
File size: 11644 byte(s)
-updated to klibc-1.5.19
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 niro 1122 #include "expand.h"
60     #include "parser.h"
61 niro 532
62     #undef rflag
63    
64    
65 niro 1122 /** handle one line of the read command.
66     * more fields than variables -> remainder shall be part of last variable.
67     * less fields than variables -> remaining variables unset.
68     *
69     * @param line complete line of input
70     * @param ap argument (variable) list
71     * @param len length of line including trailing '\0'
72     */
73     static void
74     readcmd_handle_line(char *line, char **ap, size_t len)
75     {
76     struct arglist arglist;
77     struct strlist *sl;
78     char *s, *backup;
79 niro 532
80 niro 1122 /* ifsbreakup will fiddle with stack region... */
81     s = grabstackstr(line + len);
82    
83     /* need a copy, so that delimiters aren't lost
84     * in case there are more fields than variables */
85     backup = sstrdup(line);
86    
87     arglist.lastp = &arglist.list;
88     recordregion(0, len - 1, 0);
89    
90     ifsbreakup(s, &arglist);
91     *arglist.lastp = NULL;
92     removerecordregions(0);
93    
94     for (sl = arglist.list; sl; sl = sl->next) {
95     /* remaining fields present, but no variables left. */
96     if (!ap[1]) {
97     size_t offset;
98     char *remainder;
99    
100     /* FIXME little bit hacky, assuming that ifsbreakup
101     * will not modify the length of the string */
102     offset = sl->text - s;
103     remainder = backup + offset;
104     rmescapes(remainder);
105     setvar(*ap, remainder, 0);
106    
107     return;
108     }
109    
110     /* set variable to field */
111     rmescapes(sl->text);
112     setvar(*ap, sl->text, 0);
113     ap++;
114     }
115    
116     /* nullify remaining arguments */
117     do {
118     setvar(*ap, nullstr, 0);
119     } while (*++ap);
120     }
121    
122 niro 532 /*
123     * The read builtin. The -e option causes backslashes to escape the
124 niro 1122 * following character. The -p option followed by an argument prompts
125     * with the argument.
126 niro 532 *
127     * This uses unbuffered input, which may be avoidable in some cases.
128     */
129    
130     int
131     readcmd(int argc, char **argv)
132     {
133     char **ap;
134     int backslash;
135     char c;
136     int rflag;
137     char *prompt;
138     char *p;
139     int status;
140     int timeout;
141     int i;
142     fd_set set;
143     struct timeval ts, t0, t1, to;
144    
145     ts.tv_sec = ts.tv_usec = 0;
146    
147     rflag = 0;
148     timeout = 0;
149     prompt = NULL;
150     while ((i = nextopt("p:rt:")) != '\0') {
151     switch(i) {
152     case 'p':
153     prompt = optionarg;
154     break;
155     case 't':
156     p = strtotimeval(optionarg, &ts);
157     if (*p || (!ts.tv_sec && !ts.tv_usec))
158     sh_error("invalid timeout");
159     timeout = 1;
160     break;
161     case 'r':
162     rflag = 1;
163     break;
164     default:
165     break;
166     }
167     }
168     if (prompt && isatty(0)) {
169     out2str(prompt);
170     #ifdef FLUSHERR
171     flushall();
172     #endif
173     }
174     if (*(ap = argptr) == NULL)
175     sh_error("arg count");
176     status = 0;
177     backslash = 0;
178     if (timeout) {
179     gettimeofday(&t0, NULL);
180    
181     /* ts += t0; */
182     ts.tv_usec += t0.tv_usec;
183     while (ts.tv_usec >= 1000000) {
184     ts.tv_sec++;
185     ts.tv_usec -= 1000000;
186     }
187     ts.tv_sec += t0.tv_sec;
188     }
189     STARTSTACKSTR(p);
190     for (;;) {
191     if (timeout) {
192     gettimeofday(&t1, NULL);
193     if (t1.tv_sec > ts.tv_sec ||
194     (t1.tv_sec == ts.tv_sec &&
195     t1.tv_usec >= ts.tv_usec)) {
196     status = 1;
197     break; /* Timeout! */
198     }
199    
200     /* to = ts - t1; */
201     if (ts.tv_usec >= t1.tv_usec) {
202     to.tv_usec = ts.tv_usec - t1.tv_usec;
203     to.tv_sec = ts.tv_sec - t1.tv_sec;
204     } else {
205     to.tv_usec = ts.tv_usec - t1.tv_usec + 1000000;
206     to.tv_sec = ts.tv_sec - t1.tv_sec - 1;
207     }
208    
209     FD_ZERO(&set);
210     FD_SET(0, &set);
211     if (select(1, &set, NULL, NULL, &to) != 1) {
212     status = 1;
213     break; /* Timeout! */
214     }
215     }
216     if (read(0, &c, 1) != 1) {
217     status = 1;
218     break;
219     }
220     if (c == '\0')
221     continue;
222     if (backslash) {
223 niro 1122 if (c == '\n')
224     goto resetbs;
225     STPUTC(CTLESC, p);
226     goto put;
227 niro 532 }
228     if (!rflag && c == '\\') {
229     backslash++;
230     continue;
231     }
232     if (c == '\n')
233     break;
234     put:
235 niro 1122 STPUTC(c, p);
236     resetbs:
237     backslash = 0;
238 niro 532 }
239     STACKSTRNUL(p);
240 niro 1122 readcmd_handle_line(stackblock(), ap, p + 1 - (char *)stackblock());
241 niro 532 return status;
242     }
243    
244    
245    
246     /*
247     * umask builtin
248     *
249     * This code was ripped from pdksh 5.2.14 and hacked for use with
250     * dash by Herbert Xu.
251     *
252     * Public domain.
253     */
254    
255     int
256     umaskcmd(int argc, char **argv)
257     {
258     char *ap;
259     int mask;
260     int i;
261     int symbolic_mode = 0;
262    
263     while ((i = nextopt("S")) != '\0') {
264     symbolic_mode = 1;
265     }
266    
267     INTOFF;
268     mask = umask(0);
269     umask(mask);
270     INTON;
271    
272     if ((ap = *argptr) == NULL) {
273     if (symbolic_mode) {
274     char buf[18];
275     int j;
276    
277     mask = ~mask;
278     ap = buf;
279     for (i = 0; i < 3; i++) {
280     *ap++ = "ugo"[i];
281     *ap++ = '=';
282     for (j = 0; j < 3; j++)
283     if (mask & (1 << (8 - (3*i + j))))
284     *ap++ = "rwx"[j];
285     *ap++ = ',';
286     }
287     ap[-1] = '\0';
288     out1fmt("%s\n", buf);
289     } else {
290     out1fmt("%.4o\n", mask);
291     }
292     } else {
293     int new_mask;
294    
295 niro 1122 if (isdigit((unsigned char) *ap)) {
296 niro 532 new_mask = 0;
297     do {
298     if (*ap >= '8' || *ap < '0')
299     sh_error(illnum, *argptr);
300     new_mask = (new_mask << 3) + (*ap - '0');
301     } while (*++ap != '\0');
302     } else {
303     int positions, new_val;
304     char op;
305    
306     mask = ~mask;
307     new_mask = mask;
308     positions = 0;
309     while (*ap) {
310     while (*ap && strchr("augo", *ap))
311     switch (*ap++) {
312     case 'a': positions |= 0111; break;
313     case 'u': positions |= 0100; break;
314     case 'g': positions |= 0010; break;
315     case 'o': positions |= 0001; break;
316     }
317     if (!positions)
318     positions = 0111; /* default is a */
319     if (!strchr("=+-", op = *ap))
320     break;
321     ap++;
322     new_val = 0;
323     while (*ap && strchr("rwxugoXs", *ap))
324     switch (*ap++) {
325     case 'r': new_val |= 04; break;
326     case 'w': new_val |= 02; break;
327     case 'x': new_val |= 01; break;
328     case 'u': new_val |= mask >> 6;
329     break;
330     case 'g': new_val |= mask >> 3;
331     break;
332     case 'o': new_val |= mask >> 0;
333     break;
334     case 'X': if (mask & 0111)
335     new_val |= 01;
336     break;
337     case 's': /* ignored */
338     break;
339     }
340     new_val = (new_val & 07) * positions;
341     switch (op) {
342     case '-':
343     new_mask &= ~new_val;
344     break;
345     case '=':
346     new_mask = new_val
347     | (new_mask & ~(positions * 07));
348     break;
349     case '+':
350     new_mask |= new_val;
351     }
352     if (*ap == ',') {
353     positions = 0;
354     ap++;
355     } else if (!strchr("=+-", *ap))
356     break;
357     }
358     if (*ap) {
359     sh_error("Illegal mode: %s", *argptr);
360     return 1;
361     }
362     new_mask = ~new_mask;
363     }
364     umask(new_mask);
365     }
366     return 0;
367     }
368    
369     #ifdef HAVE_GETRLIMIT
370     /*
371     * ulimit builtin
372     *
373     * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
374     * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
375     * ash by J.T. Conklin.
376     *
377     * Public domain.
378     */
379    
380     struct limits {
381     const char *name;
382     int cmd;
383     int factor; /* multiply by to get rlim_{cur,max} values */
384     char option;
385     };
386    
387     static const struct limits limits[] = {
388     #ifdef RLIMIT_CPU
389     { "time(seconds)", RLIMIT_CPU, 1, 't' },
390     #endif
391     #ifdef RLIMIT_FSIZE
392     { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
393     #endif
394     #ifdef RLIMIT_DATA
395     { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
396     #endif
397     #ifdef RLIMIT_STACK
398     { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
399     #endif
400     #ifdef RLIMIT_CORE
401     { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
402     #endif
403     #ifdef RLIMIT_RSS
404     { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
405     #endif
406     #ifdef RLIMIT_MEMLOCK
407     { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
408     #endif
409     #ifdef RLIMIT_NPROC
410     { "process", RLIMIT_NPROC, 1, 'p' },
411     #endif
412     #ifdef RLIMIT_NOFILE
413     { "nofiles", RLIMIT_NOFILE, 1, 'n' },
414     #endif
415     #ifdef RLIMIT_AS
416     { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
417     #endif
418     #ifdef RLIMIT_LOCKS
419     { "locks", RLIMIT_LOCKS, 1, 'w' },
420     #endif
421     { (char *) 0, 0, 0, '\0' }
422     };
423    
424     enum limtype { SOFT = 0x1, HARD = 0x2 };
425    
426     static void printlim(enum limtype how, const struct rlimit *limit,
427     const struct limits *l)
428     {
429     rlim_t val;
430    
431     val = limit->rlim_max;
432     if (how & SOFT)
433     val = limit->rlim_cur;
434    
435     if (val == RLIM_INFINITY)
436     out1fmt("unlimited\n");
437     else {
438     val /= l->factor;
439     out1fmt("%jd\n", (intmax_t) val);
440     }
441     }
442    
443     int
444     ulimitcmd(int argc, char **argv)
445     {
446     int c;
447     rlim_t val = 0;
448     enum limtype how = SOFT | HARD;
449     const struct limits *l;
450     int set, all = 0;
451     int optc, what;
452     struct rlimit limit;
453    
454     what = 'f';
455     while ((optc = nextopt("HSa"
456     #ifdef RLIMIT_CPU
457     "t"
458     #endif
459     #ifdef RLIMIT_FSIZE
460     "f"
461     #endif
462     #ifdef RLIMIT_DATA
463     "d"
464     #endif
465     #ifdef RLIMIT_STACK
466     "s"
467     #endif
468     #ifdef RLIMIT_CORE
469     "c"
470     #endif
471     #ifdef RLIMIT_RSS
472     "m"
473     #endif
474     #ifdef RLIMIT_MEMLOCK
475     "l"
476     #endif
477     #ifdef RLIMIT_NPROC
478     "p"
479     #endif
480     #ifdef RLIMIT_NOFILE
481     "n"
482     #endif
483     #ifdef RLIMIT_AS
484     "v"
485     #endif
486     #ifdef RLIMIT_LOCKS
487     "w"
488     #endif
489     )) != '\0')
490     switch (optc) {
491     case 'H':
492     how = HARD;
493     break;
494     case 'S':
495     how = SOFT;
496     break;
497     case 'a':
498     all = 1;
499     break;
500     default:
501     what = optc;
502     }
503    
504     for (l = limits; l->option != what; l++)
505     ;
506    
507     set = *argptr ? 1 : 0;
508     if (set) {
509     char *p = *argptr;
510    
511     if (all || argptr[1])
512     sh_error("too many arguments");
513     if (strcmp(p, "unlimited") == 0)
514     val = RLIM_INFINITY;
515     else {
516     val = (rlim_t) 0;
517    
518     while ((c = *p++) >= '0' && c <= '9')
519     {
520     val = (val * 10) + (long)(c - '0');
521     if (val < (rlim_t) 0)
522     break;
523     }
524     if (c)
525     sh_error("bad number");
526     val *= l->factor;
527     }
528     }
529     if (all) {
530     for (l = limits; l->name; l++) {
531     getrlimit(l->cmd, &limit);
532     out1fmt("%-20s ", l->name);
533     printlim(how, &limit, l);
534     }
535     return 0;
536     }
537    
538     getrlimit(l->cmd, &limit);
539     if (set) {
540     if (how & HARD)
541     limit.rlim_max = val;
542     if (how & SOFT)
543     limit.rlim_cur = val;
544     if (setrlimit(l->cmd, &limit) < 0)
545     sh_error("error setting limit (%s)", strerror(errno));
546     } else {
547     printlim(how, &limit, l);
548     }
549     return 0;
550     }
551     #endif