miscbltin.c revision 17987
1118459Smtm/*-
2118459Smtm * Copyright (c) 1991, 1993
3118459Smtm *	The Regents of the University of California.  All rights reserved.
4118459Smtm *
5118459Smtm * This code is derived from software contributed to Berkeley by
6118459Smtm * Kenneth Almquist.
7118459Smtm *
8118459Smtm * Redistribution and use in source and binary forms, with or without
9118459Smtm * modification, are permitted provided that the following conditions
10118459Smtm * are met:
11118459Smtm * 1. Redistributions of source code must retain the above copyright
12118459Smtm *    notice, this list of conditions and the following disclaimer.
13118459Smtm * 2. Redistributions in binary form must reproduce the above copyright
14118459Smtm *    notice, this list of conditions and the following disclaimer in the
15118459Smtm *    documentation and/or other materials provided with the distribution.
16118459Smtm * 3. All advertising materials mentioning features or use of this software
17118459Smtm *    must display the following acknowledgement:
18118459Smtm *	This product includes software developed by the University of
19118459Smtm *	California, Berkeley and its contributors.
20118459Smtm * 4. Neither the name of the University nor the names of its contributors
21118459Smtm *    may be used to endorse or promote products derived from this software
22118459Smtm *    without specific prior written permission.
23118459Smtm *
24118459Smtm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25118459Smtm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26118459Smtm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27118459Smtm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28118459Smtm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29118459Smtm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30118459Smtm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31118459Smtm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32118459Smtm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33118459Smtm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34118459Smtm * SUCH DAMAGE.
35118459Smtm *
36118459Smtm *	$Id: miscbltin.c,v 1.4 1995/10/21 00:47:30 joerg Exp $
37 */
38
39#ifndef lint
40static char sccsid[] = "@(#)miscbltin.c	8.4 (Berkeley) 5/4/95";
41#endif /* not lint */
42
43/*
44 * Miscelaneous builtins.
45 */
46
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <sys/time.h>
50#include <sys/resource.h>
51#include <unistd.h>
52#include <ctype.h>
53
54#include "shell.h"
55#include "options.h"
56#include "var.h"
57#include "output.h"
58#include "memalloc.h"
59#include "error.h"
60#include "mystring.h"
61
62#undef eflag
63
64extern char **argptr;		/* argument list for builtin command */
65
66
67/*
68 * The read builtin.  The -e option causes backslashes to escape the
69 * following character.
70 *
71 * This uses unbuffered input, which may be avoidable in some cases.
72 */
73
74int
75readcmd(argc, argv)
76	int argc;
77	char **argv;
78{
79	char **ap;
80	int backslash;
81	char c;
82	int eflag;
83	char *prompt;
84	char *ifs;
85	char *p;
86	int startword;
87	int status;
88	int i;
89
90	eflag = 0;
91	prompt = NULL;
92	while ((i = nextopt("ep:")) != '\0') {
93		if (i == 'p')
94			prompt = optarg;
95		else
96			eflag = 1;
97	}
98	if (prompt && isatty(0)) {
99		out2str(prompt);
100		flushall();
101	}
102	if (*(ap = argptr) == NULL)
103		error("arg count");
104	if ((ifs = bltinlookup("IFS", 1)) == NULL)
105		ifs = nullstr;
106	status = 0;
107	startword = 1;
108	backslash = 0;
109	STARTSTACKSTR(p);
110	for (;;) {
111		if (read(0, &c, 1) != 1) {
112			status = 1;
113			break;
114		}
115		if (c == '\0')
116			continue;
117		if (backslash) {
118			backslash = 0;
119			if (c != '\n')
120				STPUTC(c, p);
121			continue;
122		}
123		if (eflag && c == '\\') {
124			backslash++;
125			continue;
126		}
127		if (c == '\n')
128			break;
129		if (startword && *ifs == ' ' && strchr(ifs, c)) {
130			continue;
131		}
132		startword = 0;
133		if (backslash && c == '\\') {
134			if (read(0, &c, 1) != 1) {
135				status = 1;
136				break;
137			}
138			STPUTC(c, p);
139		} else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
140			STACKSTRNUL(p);
141			setvar(*ap, stackblock(), 0);
142			ap++;
143			startword = 1;
144			STARTSTACKSTR(p);
145		} else {
146			STPUTC(c, p);
147		}
148	}
149	STACKSTRNUL(p);
150	setvar(*ap, stackblock(), 0);
151	while (*++ap != NULL)
152		setvar(*ap, nullstr, 0);
153	return status;
154}
155
156
157
158int
159umaskcmd(argc, argv)
160	int argc;
161	char **argv;
162{
163	char *ap;
164	int mask;
165	int i;
166	int symbolic_mode = 0;
167
168	while ((i = nextopt("S")) != '\0') {
169		symbolic_mode = 1;
170	}
171
172	INTOFF;
173	mask = umask(0);
174	umask(mask);
175	INTON;
176
177	if ((ap = *argptr) == NULL) {
178		if (symbolic_mode) {
179			char u[4], g[4], o[4];
180
181			i = 0;
182			if ((mask & S_IRUSR) == 0)
183				u[i++] = 'r';
184			if ((mask & S_IWUSR) == 0)
185				u[i++] = 'w';
186			if ((mask & S_IXUSR) == 0)
187				u[i++] = 'x';
188			u[i] = '\0';
189
190			i = 0;
191			if ((mask & S_IRGRP) == 0)
192				g[i++] = 'r';
193			if ((mask & S_IWGRP) == 0)
194				g[i++] = 'w';
195			if ((mask & S_IXGRP) == 0)
196				g[i++] = 'x';
197			g[i] = '\0';
198
199			i = 0;
200			if ((mask & S_IROTH) == 0)
201				o[i++] = 'r';
202			if ((mask & S_IWOTH) == 0)
203				o[i++] = 'w';
204			if ((mask & S_IXOTH) == 0)
205				o[i++] = 'x';
206			o[i] = '\0';
207
208			out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
209		} else {
210			out1fmt("%.4o\n", mask);
211		}
212	} else {
213		if (isdigit(*ap)) {
214			mask = 0;
215			do {
216				if (*ap >= '8' || *ap < '0')
217					error("Illegal number: %s", argv[1]);
218				mask = (mask << 3) + (*ap - '0');
219			} while (*++ap != '\0');
220			umask(mask);
221		} else {
222			void *set;
223			if ((set = setmode (ap)) == 0)
224					error("Illegal number: %s", ap);
225
226			mask = getmode (set, ~mask & 0777);
227			umask(~mask & 0777);
228		}
229	}
230	return 0;
231}
232
233/*
234 * ulimit builtin
235 *
236 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
237 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
238 * ash by J.T. Conklin.
239 *
240 * Public domain.
241 */
242
243struct limits {
244	const char *name;
245	int	cmd;
246	int	factor;	/* multiply by to get rlim_{cur,max} values */
247	char	option;
248};
249
250static const struct limits limits[] = {
251#ifdef RLIMIT_CPU
252	{ "time(seconds)",		RLIMIT_CPU,	   1, 't' },
253#endif
254#ifdef RLIMIT_FSIZE
255	{ "file(512-blocks)",		RLIMIT_FSIZE,	 512, 'f' },
256#endif
257#ifdef RLIMIT_DATA
258	{ "data(kbytes)",		RLIMIT_DATA,	1024, 'd' },
259#endif
260#ifdef RLIMIT_STACK
261	{ "stack(kbytes)",		RLIMIT_STACK,	1024, 's' },
262#endif
263#ifdef  RLIMIT_CORE
264	{ "coredump(512-blocks)",	RLIMIT_CORE,	 512, 'c' },
265#endif
266#ifdef RLIMIT_RSS
267	{ "memory(kbytes)",		RLIMIT_RSS,	1024, 'm' },
268#endif
269#ifdef RLIMIT_MEMLOCK
270	{ "lockedmem(kbytes)",		RLIMIT_MEMLOCK, 1024, 'l' },
271#endif
272#ifdef RLIMIT_NPROC
273	{ "process(processes)",		RLIMIT_NPROC,      1, 'u' },
274#endif
275#ifdef RLIMIT_NOFILE
276	{ "nofiles(descriptors)",	RLIMIT_NOFILE,     1, 'n' },
277#endif
278#ifdef RLIMIT_VMEM
279	{ "vmemory(kbytes)",		RLIMIT_VMEM,	1024, 'v' },
280#endif
281#ifdef RLIMIT_SWAP
282	{ "swap(kbytes)",		RLIMIT_SWAP,	1024, 'w' },
283#endif
284	{ (char *) 0,			0,		   0,  '\0' }
285};
286
287int
288ulimitcmd(argc, argv)
289	int argc;
290	char **argv;
291{
292	register int	c;
293	quad_t val;
294	enum { SOFT = 0x1, HARD = 0x2 }
295			how = SOFT | HARD;
296	const struct limits	*l;
297	int		set, all = 0;
298	int		optc, what;
299	struct rlimit	limit;
300
301	what = 'f';
302	while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
303		switch (optc) {
304		case 'H':
305			how = HARD;
306			break;
307		case 'S':
308			how = SOFT;
309			break;
310		case 'a':
311			all = 1;
312			break;
313		default:
314			what = optc;
315		}
316
317	for (l = limits; l->name && l->option != what; l++)
318		;
319	if (!l->name)
320		error("ulimit: internal error (%c)\n", what);
321
322	set = *argptr ? 1 : 0;
323	if (set) {
324		char *p = *argptr;
325
326		if (all || argptr[1])
327			error("ulimit: too many arguments\n");
328		if (strcmp(p, "unlimited") == 0)
329			val = RLIM_INFINITY;
330		else {
331			val = (quad_t) 0;
332
333			while ((c = *p++) >= '0' && c <= '9')
334			{
335				val = (val * 10) + (long)(c - '0');
336				if (val < (quad_t) 0)
337					break;
338			}
339			if (c)
340				error("ulimit: bad number\n");
341			val *= l->factor;
342		}
343	}
344	if (all) {
345		for (l = limits; l->name; l++) {
346			getrlimit(l->cmd, &limit);
347			if (how & SOFT)
348				val = limit.rlim_cur;
349			else if (how & HARD)
350				val = limit.rlim_max;
351
352			out1fmt("%-20s ", l->name);
353			if (val == RLIM_INFINITY)
354				out1fmt("unlimited\n");
355			else
356			{
357				val /= l->factor;
358				out1fmt("%ld\n", (long) val);
359			}
360		}
361		return 0;
362	}
363
364	getrlimit(l->cmd, &limit);
365	if (set) {
366		if (how & SOFT)
367			limit.rlim_cur = val;
368		if (how & HARD)
369			limit.rlim_max = val;
370		if (setrlimit(l->cmd, &limit) < 0)
371			error("ulimit: bad limit\n");
372	} else {
373		if (how & SOFT)
374			val = limit.rlim_cur;
375		else if (how & HARD)
376			val = limit.rlim_max;
377	}
378
379	if (!set) {
380		if (val == RLIM_INFINITY)
381			out1fmt("unlimited\n");
382		else
383		{
384			val /= l->factor;
385			out1fmt("%ld\n", (long) val);
386		}
387	}
388	return 0;
389}
390