Remove advertising header from all userland binaries.
[dragonfly.git] / bin / sh / miscbltin.c
blob2552052fb211c4a39d272404a0f064bc8ee1d91d
1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * @(#)miscbltin.c 8.4 (Berkeley) 5/4/95
33 * $FreeBSD: head/bin/sh/miscbltin.c 246167 2013-01-31 22:10:57Z jilles $
37 * Miscellaneous builtins.
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/time.h>
43 #include <sys/resource.h>
44 #include <unistd.h>
45 #include <errno.h>
46 #include <stdint.h>
47 #include <stdio.h>
48 #include <stdlib.h>
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 "mystring.h"
57 #include "syntax.h"
59 int readcmd(int, char **);
60 int umaskcmd(int, char **);
61 int ulimitcmd(int, char **);
63 #undef eflag
66 * The read builtin. The -r option causes backslashes to be treated like
67 * ordinary characters.
69 * This uses unbuffered input, which may be avoidable in some cases.
71 * Note that if IFS=' :' then read x y should work so that:
72 * 'a b' x='a', y='b'
73 * ' a b ' x='a', y='b'
74 * ':b' x='', y='b'
75 * ':' x='', y=''
76 * '::' x='', y=''
77 * ': :' x='', y=''
78 * ':::' x='', y='::'
79 * ':b c:' x='', y='b c:'
82 int
83 readcmd(int argc __unused, char **argv __unused)
85 char **ap;
86 int backslash;
87 char c;
88 int rflag;
89 const char *prompt;
90 const char *ifs;
91 char *p;
92 int startword;
93 int status;
94 int i;
95 int is_ifs;
96 int saveall = 0;
97 struct timeval tv;
98 char *tvptr;
99 fd_set ifds;
101 rflag = 0;
102 prompt = NULL;
103 tv.tv_sec = -1;
104 tv.tv_usec = 0;
105 while ((i = nextopt("erp:t:")) != '\0') {
106 switch(i) {
107 case 'p':
108 prompt = shoptarg;
109 break;
110 case 'e':
111 break;
112 case 'r':
113 rflag = 1;
114 break;
115 case 't':
116 tv.tv_sec = strtol(shoptarg, &tvptr, 0);
117 if (tvptr == shoptarg)
118 error("timeout value");
119 switch(*tvptr) {
120 case 0:
121 case 's':
122 break;
123 case 'h':
124 tv.tv_sec *= 60;
125 /* FALLTHROUGH */
126 case 'm':
127 tv.tv_sec *= 60;
128 break;
129 default:
130 error("timeout unit");
132 break;
135 if (prompt && isatty(0)) {
136 out2str(prompt);
137 flushall();
139 if (*(ap = argptr) == NULL)
140 error("arg count");
141 if ((ifs = bltinlookup("IFS", 1)) == NULL)
142 ifs = " \t\n";
144 if (tv.tv_sec >= 0) {
146 * Wait for something to become available.
148 FD_ZERO(&ifds);
149 FD_SET(0, &ifds);
150 status = select(1, &ifds, NULL, NULL, &tv);
152 * If there's nothing ready, return an error.
154 if (status <= 0)
155 return(1);
158 status = 0;
159 startword = 2;
160 backslash = 0;
161 STARTSTACKSTR(p);
162 for (;;) {
163 if (read(STDIN_FILENO, &c, 1) != 1) {
164 status = 1;
165 break;
167 if (c == '\0')
168 continue;
169 CHECKSTRSPACE(1, p);
170 if (backslash) {
171 backslash = 0;
172 startword = 0;
173 if (c != '\n')
174 USTPUTC(c, p);
175 continue;
177 if (!rflag && c == '\\') {
178 backslash++;
179 continue;
181 if (c == '\n')
182 break;
183 if (strchr(ifs, c))
184 is_ifs = strchr(" \t\n", c) ? 1 : 2;
185 else
186 is_ifs = 0;
188 if (startword != 0) {
189 if (is_ifs == 1) {
190 /* Ignore leading IFS whitespace */
191 if (saveall)
192 USTPUTC(c, p);
193 continue;
195 if (is_ifs == 2 && startword == 1) {
196 /* Only one non-whitespace IFS per word */
197 startword = 2;
198 if (saveall)
199 USTPUTC(c, p);
200 continue;
204 if (is_ifs == 0) {
205 /* append this character to the current variable */
206 startword = 0;
207 if (saveall)
208 /* Not just a spare terminator */
209 saveall++;
210 USTPUTC(c, p);
211 continue;
214 /* end of variable... */
215 startword = is_ifs;
217 if (ap[1] == NULL) {
218 /* Last variable needs all IFS chars */
219 saveall++;
220 USTPUTC(c, p);
221 continue;
224 STACKSTRNUL(p);
225 setvar(*ap, stackblock(), 0);
226 ap++;
227 STARTSTACKSTR(p);
229 STACKSTRNUL(p);
231 /* Remove trailing IFS chars */
232 for (; stackblock() <= --p; *p = 0) {
233 if (!strchr(ifs, *p))
234 break;
235 if (strchr(" \t\n", *p))
236 /* Always remove whitespace */
237 continue;
238 if (saveall > 1)
239 /* Don't remove non-whitespace unless it was naked */
240 break;
242 setvar(*ap, stackblock(), 0);
244 /* Set any remaining args to "" */
245 while (*++ap != NULL)
246 setvar(*ap, nullstr, 0);
247 return status;
253 umaskcmd(int argc __unused, char **argv __unused)
255 char *ap;
256 int mask;
257 int i;
258 int symbolic_mode = 0;
260 while ((i = nextopt("S")) != '\0') {
261 symbolic_mode = 1;
264 INTOFF;
265 mask = umask(0);
266 umask(mask);
267 INTON;
269 if ((ap = *argptr) == NULL) {
270 if (symbolic_mode) {
271 char u[4], g[4], o[4];
273 i = 0;
274 if ((mask & S_IRUSR) == 0)
275 u[i++] = 'r';
276 if ((mask & S_IWUSR) == 0)
277 u[i++] = 'w';
278 if ((mask & S_IXUSR) == 0)
279 u[i++] = 'x';
280 u[i] = '\0';
282 i = 0;
283 if ((mask & S_IRGRP) == 0)
284 g[i++] = 'r';
285 if ((mask & S_IWGRP) == 0)
286 g[i++] = 'w';
287 if ((mask & S_IXGRP) == 0)
288 g[i++] = 'x';
289 g[i] = '\0';
291 i = 0;
292 if ((mask & S_IROTH) == 0)
293 o[i++] = 'r';
294 if ((mask & S_IWOTH) == 0)
295 o[i++] = 'w';
296 if ((mask & S_IXOTH) == 0)
297 o[i++] = 'x';
298 o[i] = '\0';
300 out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
301 } else {
302 out1fmt("%.4o\n", mask);
304 } else {
305 if (is_digit(*ap)) {
306 mask = 0;
307 do {
308 if (*ap >= '8' || *ap < '0')
309 error("Illegal number: %s", *argptr);
310 mask = (mask << 3) + (*ap - '0');
311 } while (*++ap != '\0');
312 umask(mask);
313 } else {
314 void *set;
315 INTOFF;
316 if ((set = setmode (ap)) == NULL)
317 error("Illegal number: %s", ap);
319 mask = getmode (set, ~mask & 0777);
320 umask(~mask & 0777);
321 free(set);
322 INTON;
325 return 0;
329 * ulimit builtin
331 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
332 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
333 * ash by J.T. Conklin.
335 * Public domain.
338 struct limits {
339 const char *name;
340 const char *units;
341 int cmd;
342 int factor; /* multiply by to get rlim_{cur,max} values */
343 char option;
346 static const struct limits limits[] = {
347 #ifdef RLIMIT_CPU
348 { "cpu time", "seconds", RLIMIT_CPU, 1, 't' },
349 #endif
350 #ifdef RLIMIT_FSIZE
351 { "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' },
352 #endif
353 #ifdef RLIMIT_DATA
354 { "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' },
355 #endif
356 #ifdef RLIMIT_STACK
357 { "stack size", "kbytes", RLIMIT_STACK, 1024, 's' },
358 #endif
359 #ifdef RLIMIT_CORE
360 { "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' },
361 #endif
362 #ifdef RLIMIT_RSS
363 { "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' },
364 #endif
365 #ifdef RLIMIT_MEMLOCK
366 { "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' },
367 #endif
368 #ifdef RLIMIT_NPROC
369 { "max user processes", NULL, RLIMIT_NPROC, 1, 'u' },
370 #endif
371 #ifdef RLIMIT_NOFILE
372 { "open files", NULL, RLIMIT_NOFILE, 1, 'n' },
373 #endif
374 #ifdef RLIMIT_VMEM
375 { "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' },
376 #endif
377 #ifdef RLIMIT_SWAP
378 { "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' },
379 #endif
380 #ifdef RLIMIT_SBSIZE
381 { "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' },
382 #endif
383 #ifdef RLIMIT_POSIXLOCK
384 { "posixlocks", NULL, RLIMIT_POSIXLOCK, 1, 'k' },
385 #endif
386 { NULL, NULL, 0, 0, '\0' }
390 ulimitcmd(int argc __unused, char **argv __unused)
392 int c;
393 rlim_t val = 0;
394 enum { SOFT = 0x1, HARD = 0x2 }
395 how = SOFT | HARD;
396 const struct limits *l;
397 int set, all = 0;
398 int optc, what;
399 struct rlimit limit;
401 what = 'f';
402 while ((optc = nextopt("HSatfdsmcnuvlbk")) != '\0')
403 switch (optc) {
404 case 'H':
405 how = HARD;
406 break;
407 case 'S':
408 how = SOFT;
409 break;
410 case 'a':
411 all = 1;
412 break;
413 default:
414 what = optc;
417 for (l = limits; l->name && l->option != what; l++)
419 if (!l->name)
420 error("internal error (%c)", what);
422 set = *argptr ? 1 : 0;
423 if (set) {
424 char *p = *argptr;
426 if (all || argptr[1])
427 error("too many arguments");
428 if (strcmp(p, "unlimited") == 0)
429 val = RLIM_INFINITY;
430 else {
431 val = 0;
433 while ((c = *p++) >= '0' && c <= '9')
435 val = (val * 10) + (long)(c - '0');
436 if (val < 0)
437 break;
439 if (c)
440 error("bad number");
441 val *= l->factor;
444 if (all) {
445 for (l = limits; l->name; l++) {
446 char optbuf[40];
447 if (getrlimit(l->cmd, &limit) < 0)
448 error("can't get limit: %s", strerror(errno));
449 if (how & SOFT)
450 val = limit.rlim_cur;
451 else if (how & HARD)
452 val = limit.rlim_max;
454 if (l->units)
455 snprintf(optbuf, sizeof(optbuf),
456 "(%s, -%c) ", l->units, l->option);
457 else
458 snprintf(optbuf, sizeof(optbuf),
459 "(-%c) ", l->option);
460 out1fmt("%-18s %18s ", l->name, optbuf);
461 if (val == RLIM_INFINITY)
462 out1str("unlimited\n");
463 else
465 val /= l->factor;
466 out1fmt("%jd\n", (intmax_t)val);
469 return 0;
472 if (getrlimit(l->cmd, &limit) < 0)
473 error("can't get limit: %s", strerror(errno));
474 if (set) {
475 if (how & SOFT)
476 limit.rlim_cur = val;
477 if (how & HARD)
478 limit.rlim_max = val;
479 if (setrlimit(l->cmd, &limit) < 0)
480 error("bad limit: %s", strerror(errno));
481 } else {
482 if (how & SOFT)
483 val = limit.rlim_cur;
484 else if (how & HARD)
485 val = limit.rlim_max;
487 if (val == RLIM_INFINITY)
488 out1str("unlimited\n");
489 else
491 val /= l->factor;
492 out1fmt("%jd\n", (intmax_t)val);
495 return 0;