Annotation of src/bin/sh/miscbltin.c, Revision 1.37.2.1
1.37.2.1! jym 1: /* $NetBSD: miscbltin.c,v 1.38 2009/03/29 01:02:49 mrg Exp $ */
1.13 cgd 2:
1.1 cgd 3: /*-
1.7 jtc 4: * Copyright (c) 1991, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 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.
1.32 agc 18: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 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:
1.19 christos 35: #include <sys/cdefs.h>
1.1 cgd 36: #ifndef lint
1.13 cgd 37: #if 0
1.14 christos 38: static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
1.13 cgd 39: #else
1.37.2.1! jym 40: __RCSID("$NetBSD: miscbltin.c,v 1.38 2009/03/29 01:02:49 mrg Exp $");
1.13 cgd 41: #endif
1.1 cgd 42: #endif /* not lint */
43:
44: /*
45: * Miscelaneous builtins.
46: */
47:
1.23 christos 48: #include <sys/types.h> /* quad_t */
49: #include <sys/param.h> /* BSD4_4 */
1.8 jtc 50: #include <sys/stat.h>
1.14 christos 51: #include <sys/time.h>
52: #include <sys/resource.h>
1.9 jtc 53: #include <unistd.h>
1.27 christos 54: #include <stdlib.h>
1.9 jtc 55: #include <ctype.h>
1.28 christos 56: #include <errno.h>
1.14 christos 57:
1.1 cgd 58: #include "shell.h"
59: #include "options.h"
60: #include "var.h"
61: #include "output.h"
62: #include "memalloc.h"
63: #include "error.h"
1.19 christos 64: #include "miscbltin.h"
1.1 cgd 65: #include "mystring.h"
66:
1.20 kleink 67: #undef rflag
1.1 cgd 68:
69:
70:
71: /*
1.35 dsl 72: * The read builtin.
73: * Backslahes escape the next char unless -r is specified.
1.1 cgd 74: *
75: * This uses unbuffered input, which may be avoidable in some cases.
1.35 dsl 76: *
77: * Note that if IFS=' :' then read x y should work so that:
78: * 'a b' x='a', y='b'
79: * ' a b ' x='a', y='b'
80: * ':b' x='', y='b'
81: * ':' x='', y=''
82: * '::' x='', y=''
83: * ': :' x='', y=''
84: * ':::' x='', y='::'
85: * ':b c:' x='', y='b c:'
1.1 cgd 86: */
87:
1.12 cgd 88: int
1.31 christos 89: readcmd(int argc, char **argv)
1.12 cgd 90: {
1.1 cgd 91: char **ap;
92: char c;
1.20 kleink 93: int rflag;
1.1 cgd 94: char *prompt;
1.35 dsl 95: const char *ifs;
1.1 cgd 96: char *p;
97: int startword;
98: int status;
99: int i;
1.35 dsl 100: int is_ifs;
101: int saveall = 0;
1.1 cgd 102:
1.20 kleink 103: rflag = 0;
1.1 cgd 104: prompt = NULL;
1.20 kleink 105: while ((i = nextopt("p:r")) != '\0') {
1.1 cgd 106: if (i == 'p')
1.30 christos 107: prompt = optionarg;
1.1 cgd 108: else
1.20 kleink 109: rflag = 1;
1.1 cgd 110: }
1.35 dsl 111:
1.1 cgd 112: if (prompt && isatty(0)) {
113: out2str(prompt);
114: flushall();
115: }
1.35 dsl 116:
1.6 cgd 117: if (*(ap = argptr) == NULL)
1.1 cgd 118: error("arg count");
1.35 dsl 119:
1.1 cgd 120: if ((ifs = bltinlookup("IFS", 1)) == NULL)
1.35 dsl 121: ifs = " \t\n";
122:
1.1 cgd 123: status = 0;
1.35 dsl 124: startword = 2;
1.1 cgd 125: STARTSTACKSTR(p);
126: for (;;) {
127: if (read(0, &c, 1) != 1) {
128: status = 1;
129: break;
130: }
131: if (c == '\0')
132: continue;
1.35 dsl 133: if (c == '\\' && !rflag) {
134: if (read(0, &c, 1) != 1) {
135: status = 1;
136: break;
137: }
1.1 cgd 138: if (c != '\n')
139: STPUTC(c, p);
140: continue;
141: }
142: if (c == '\n')
143: break;
1.35 dsl 144: if (strchr(ifs, c))
145: is_ifs = strchr(" \t\n", c) ? 1 : 2;
146: else
147: is_ifs = 0;
148:
149: if (startword != 0) {
150: if (is_ifs == 1) {
151: /* Ignore leading IFS whitespace */
152: if (saveall)
153: STPUTC(c, p);
154: continue;
155: }
156: if (is_ifs == 2 && startword == 1) {
157: /* Only one non-whitespace IFS per word */
158: startword = 2;
159: if (saveall)
160: STPUTC(c, p);
161: continue;
162: }
163: }
164:
165: if (is_ifs == 0) {
166: /* append this character to the current variable */
167: startword = 0;
168: if (saveall)
169: /* Not just a spare terminator */
170: saveall++;
171: STPUTC(c, p);
1.1 cgd 172: continue;
173: }
1.35 dsl 174:
175: /* end of variable... */
176: startword = is_ifs;
177:
178: if (ap[1] == NULL) {
179: /* Last variable needs all IFS chars */
180: saveall++;
1.1 cgd 181: STPUTC(c, p);
1.35 dsl 182: continue;
1.1 cgd 183: }
1.35 dsl 184:
185: STACKSTRNUL(p);
186: setvar(*ap, stackblock(), 0);
187: ap++;
188: STARTSTACKSTR(p);
1.1 cgd 189: }
190: STACKSTRNUL(p);
1.35 dsl 191:
192: /* Remove trailing IFS chars */
193: for (; stackblock() <= --p; *p = 0) {
194: if (!strchr(ifs, *p))
195: break;
196: if (strchr(" \t\n", *p))
197: /* Always remove whitespace */
198: continue;
199: if (saveall > 1)
200: /* Don't remove non-whitespace unless it was naked */
201: break;
202: }
1.1 cgd 203: setvar(*ap, stackblock(), 0);
1.35 dsl 204:
205: /* Set any remaining args to "" */
1.1 cgd 206: while (*++ap != NULL)
207: setvar(*ap, nullstr, 0);
208: return status;
209: }
210:
211:
212:
1.12 cgd 213: int
1.31 christos 214: umaskcmd(int argc, char **argv)
1.12 cgd 215: {
1.8 jtc 216: char *ap;
1.1 cgd 217: int mask;
218: int i;
1.8 jtc 219: int symbolic_mode = 0;
220:
221: while ((i = nextopt("S")) != '\0') {
222: symbolic_mode = 1;
223: }
1.1 cgd 224:
1.8 jtc 225: INTOFF;
226: mask = umask(0);
227: umask(mask);
228: INTON;
229:
230: if ((ap = *argptr) == NULL) {
231: if (symbolic_mode) {
232: char u[4], g[4], o[4];
233:
234: i = 0;
235: if ((mask & S_IRUSR) == 0)
236: u[i++] = 'r';
237: if ((mask & S_IWUSR) == 0)
238: u[i++] = 'w';
239: if ((mask & S_IXUSR) == 0)
240: u[i++] = 'x';
241: u[i] = '\0';
242:
243: i = 0;
244: if ((mask & S_IRGRP) == 0)
245: g[i++] = 'r';
246: if ((mask & S_IWGRP) == 0)
247: g[i++] = 'w';
248: if ((mask & S_IXGRP) == 0)
249: g[i++] = 'x';
250: g[i] = '\0';
251:
252: i = 0;
253: if ((mask & S_IROTH) == 0)
254: o[i++] = 'r';
255: if ((mask & S_IWOTH) == 0)
256: o[i++] = 'w';
257: if ((mask & S_IXOTH) == 0)
258: o[i++] = 'x';
259: o[i] = '\0';
260:
261: out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
262: } else {
263: out1fmt("%.4o\n", mask);
264: }
1.1 cgd 265: } else {
1.25 christos 266: if (isdigit((unsigned char)*ap)) {
1.8 jtc 267: mask = 0;
268: do {
269: if (*ap >= '8' || *ap < '0')
270: error("Illegal number: %s", argv[1]);
271: mask = (mask << 3) + (*ap - '0');
272: } while (*++ap != '\0');
273: umask(mask);
274: } else {
1.16 christos 275: void *set;
1.8 jtc 276:
1.26 itohy 277: INTOFF;
278: if ((set = setmode(ap)) != 0) {
279: mask = getmode(set, ~mask & 0777);
280: ckfree(set);
281: }
282: INTON;
283: if (!set)
1.36 christos 284: error("Cannot set mode `%s' (%s)", ap,
285: strerror(errno));
1.26 itohy 286:
1.8 jtc 287: umask(~mask & 0777);
1.14 christos 288: }
289: }
290: return 0;
291: }
292:
293: /*
294: * ulimit builtin
295: *
296: * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
297: * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
298: * ash by J.T. Conklin.
299: *
300: * Public domain.
301: */
302:
303: struct limits {
304: const char *name;
305: int cmd;
306: int factor; /* multiply by to get rlim_{cur,max} values */
307: char option;
308: };
309:
310: static const struct limits limits[] = {
311: #ifdef RLIMIT_CPU
312: { "time(seconds)", RLIMIT_CPU, 1, 't' },
313: #endif
314: #ifdef RLIMIT_FSIZE
315: { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
316: #endif
317: #ifdef RLIMIT_DATA
318: { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
319: #endif
320: #ifdef RLIMIT_STACK
321: { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
322: #endif
323: #ifdef RLIMIT_CORE
324: { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
325: #endif
326: #ifdef RLIMIT_RSS
327: { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
328: #endif
329: #ifdef RLIMIT_MEMLOCK
330: { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
331: #endif
332: #ifdef RLIMIT_NPROC
333: { "process(processes)", RLIMIT_NPROC, 1, 'p' },
334: #endif
335: #ifdef RLIMIT_NOFILE
336: { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
337: #endif
338: #ifdef RLIMIT_VMEM
339: { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
340: #endif
341: #ifdef RLIMIT_SWAP
342: { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
343: #endif
1.33 christos 344: #ifdef RLIMIT_SBSIZE
1.34 lukem 345: { "sbsize(bytes)", RLIMIT_SBSIZE, 1, 'b' },
1.33 christos 346: #endif
1.14 christos 347: { (char *) 0, 0, 0, '\0' }
348: };
349:
350: int
1.31 christos 351: ulimitcmd(int argc, char **argv)
1.14 christos 352: {
1.17 tls 353: int c;
1.19 christos 354: rlim_t val = 0;
1.14 christos 355: enum { SOFT = 0x1, HARD = 0x2 }
356: how = SOFT | HARD;
357: const struct limits *l;
358: int set, all = 0;
359: int optc, what;
360: struct rlimit limit;
361:
362: what = 'f';
1.37.2.1! jym 363: while ((optc = nextopt("HSabtfdsmcnplv")) != '\0')
1.14 christos 364: switch (optc) {
365: case 'H':
366: how = HARD;
367: break;
368: case 'S':
369: how = SOFT;
370: break;
371: case 'a':
372: all = 1;
373: break;
374: default:
375: what = optc;
376: }
377:
378: for (l = limits; l->name && l->option != what; l++)
379: ;
380: if (!l->name)
1.28 christos 381: error("internal error (%c)", what);
1.14 christos 382:
383: set = *argptr ? 1 : 0;
384: if (set) {
385: char *p = *argptr;
386:
387: if (all || argptr[1])
1.28 christos 388: error("too many arguments");
1.14 christos 389: if (strcmp(p, "unlimited") == 0)
390: val = RLIM_INFINITY;
391: else {
1.15 jtc 392: val = (rlim_t) 0;
1.14 christos 393:
394: while ((c = *p++) >= '0' && c <= '9')
395: val = (val * 10) + (long)(c - '0');
396: if (c)
1.28 christos 397: error("bad number");
1.14 christos 398: val *= l->factor;
399: }
400: }
401: if (all) {
402: for (l = limits; l->name; l++) {
403: getrlimit(l->cmd, &limit);
404: if (how & SOFT)
405: val = limit.rlim_cur;
406: else if (how & HARD)
407: val = limit.rlim_max;
408:
409: out1fmt("%-20s ", l->name);
410: if (val == RLIM_INFINITY)
411: out1fmt("unlimited\n");
412: else
413: {
414: val /= l->factor;
1.18 christos 415: #ifdef BSD4_4
1.29 lukem 416: out1fmt("%lld\n", (long long) val);
1.18 christos 417: #else
418: out1fmt("%ld\n", (long) val);
419: #endif
1.14 christos 420: }
421: }
422: return 0;
423: }
424:
425: getrlimit(l->cmd, &limit);
426: if (set) {
1.28 christos 427: if (how & HARD)
428: limit.rlim_max = val;
1.14 christos 429: if (how & SOFT)
430: limit.rlim_cur = val;
431: if (setrlimit(l->cmd, &limit) < 0)
1.28 christos 432: error("error setting limit (%s)", strerror(errno));
1.14 christos 433: } else {
434: if (how & SOFT)
435: val = limit.rlim_cur;
436: else if (how & HARD)
437: val = limit.rlim_max;
438:
439: if (val == RLIM_INFINITY)
440: out1fmt("unlimited\n");
441: else
442: {
443: val /= l->factor;
1.18 christos 444: #ifdef BSD4_4
1.29 lukem 445: out1fmt("%lld\n", (long long) val);
1.18 christos 446: #else
447: out1fmt("%ld\n", (long) val);
448: #endif
1.8 jtc 449: }
1.1 cgd 450: }
451: return 0;
452: }
CVSweb <webmaster@jp.NetBSD.org>