miscbltin.c revision 18016
1276371Semaste/*-
2260684Skaiw * Copyright (c) 1991, 1993
3260684Skaiw *	The Regents of the University of California.  All rights reserved.
4260684Skaiw *
5260684Skaiw * This code is derived from software contributed to Berkeley by
6260684Skaiw * Kenneth Almquist.
7260684Skaiw *
8260684Skaiw * Redistribution and use in source and binary forms, with or without
9260684Skaiw * modification, are permitted provided that the following conditions
10260684Skaiw * are met:
11260684Skaiw * 1. Redistributions of source code must retain the above copyright
12260684Skaiw *    notice, this list of conditions and the following disclaimer.
13260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
14260684Skaiw *    notice, this list of conditions and the following disclaimer in the
15260684Skaiw *    documentation and/or other materials provided with the distribution.
16260684Skaiw * 3. All advertising materials mentioning features or use of this software
17260684Skaiw *    must display the following acknowledgement:
18260684Skaiw *	This product includes software developed by the University of
19260684Skaiw *	California, Berkeley and its contributors.
20260684Skaiw * 4. Neither the name of the University nor the names of its contributors
21260684Skaiw *    may be used to endorse or promote products derived from this software
22260684Skaiw *    without specific prior written permission.
23260684Skaiw *
24260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27260684Skaiw * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34260684Skaiw * SUCH DAMAGE.
35260684Skaiw *
36260684Skaiw *	$Id: miscbltin.c,v 1.5 1996/09/01 10:20:46 peter Exp $
37260684Skaiw */
38260684Skaiw
39260684Skaiw#ifndef lint
40260684Skaiwstatic char sccsid[] = "@(#)miscbltin.c	8.4 (Berkeley) 5/4/95";
41260684Skaiw#endif /* not lint */
42276371Semaste
43260684Skaiw/*
44260684Skaiw * Miscelaneous builtins.
45260684Skaiw */
46260684Skaiw
47260684Skaiw#include <sys/types.h>
48260684Skaiw#include <sys/stat.h>
49260684Skaiw#include <sys/time.h>
50260684Skaiw#include <sys/resource.h>
51260684Skaiw#include <unistd.h>
52260684Skaiw#include <ctype.h>
53260684Skaiw#include <errno.h>
54260684Skaiw
55260684Skaiw#include "shell.h"
56260684Skaiw#include "options.h"
57260684Skaiw#include "var.h"
58260684Skaiw#include "output.h"
59260684Skaiw#include "memalloc.h"
60260684Skaiw#include "error.h"
61260684Skaiw#include "mystring.h"
62260684Skaiw
63260684Skaiw#undef eflag
64260684Skaiw
65260684Skaiwextern char **argptr;		/* argument list for builtin command */
66260684Skaiw
67260684Skaiw
68260684Skaiw/*
69260684Skaiw * The read builtin.  The -e option causes backslashes to escape the
70260684Skaiw * following character.
71260684Skaiw *
72260684Skaiw * This uses unbuffered input, which may be avoidable in some cases.
73260684Skaiw */
74260684Skaiw
75260684Skaiwint
76260684Skaiwreadcmd(argc, argv)
77260684Skaiw	int argc;
78260684Skaiw	char **argv;
79260684Skaiw{
80260684Skaiw	char **ap;
81260684Skaiw	int backslash;
82260684Skaiw	char c;
83260684Skaiw	int eflag;
84260684Skaiw	char *prompt;
85260684Skaiw	char *ifs;
86260684Skaiw	char *p;
87260684Skaiw	int startword;
88260684Skaiw	int status;
89260684Skaiw	int i;
90260684Skaiw
91260684Skaiw	eflag = 0;
92260684Skaiw	prompt = NULL;
93260684Skaiw	while ((i = nextopt("ep:")) != '\0') {
94260684Skaiw		if (i == 'p')
95260684Skaiw			prompt = optarg;
96260684Skaiw		else
97260684Skaiw			eflag = 1;
98260684Skaiw	}
99260684Skaiw	if (prompt && isatty(0)) {
100260684Skaiw		out2str(prompt);
101260684Skaiw		flushall();
102260684Skaiw	}
103260684Skaiw	if (*(ap = argptr) == NULL)
104260684Skaiw		error("arg count");
105260684Skaiw	if ((ifs = bltinlookup("IFS", 1)) == NULL)
106260684Skaiw		ifs = nullstr;
107260684Skaiw	status = 0;
108260684Skaiw	startword = 1;
109260684Skaiw	backslash = 0;
110260684Skaiw	STARTSTACKSTR(p);
111260684Skaiw	for (;;) {
112260684Skaiw		if (read(0, &c, 1) != 1) {
113260684Skaiw			status = 1;
114260684Skaiw			break;
115260684Skaiw		}
116260684Skaiw		if (c == '\0')
117260684Skaiw			continue;
118260684Skaiw		if (backslash) {
119260684Skaiw			backslash = 0;
120276371Semaste			if (c != '\n')
121276371Semaste				STPUTC(c, p);
122260684Skaiw			continue;
123260684Skaiw		}
124260684Skaiw		if (eflag && c == '\\') {
125260684Skaiw			backslash++;
126260684Skaiw			continue;
127260684Skaiw		}
128260684Skaiw		if (c == '\n')
129260684Skaiw			break;
130260684Skaiw		if (startword && *ifs == ' ' && strchr(ifs, c)) {
131260684Skaiw			continue;
132260684Skaiw		}
133260684Skaiw		startword = 0;
134260684Skaiw		if (backslash && c == '\\') {
135260684Skaiw			if (read(0, &c, 1) != 1) {
136260684Skaiw				status = 1;
137260684Skaiw				break;
138260684Skaiw			}
139260684Skaiw			STPUTC(c, p);
140260684Skaiw		} else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
141260684Skaiw			STACKSTRNUL(p);
142260684Skaiw			setvar(*ap, stackblock(), 0);
143260684Skaiw			ap++;
144260684Skaiw			startword = 1;
145276371Semaste			STARTSTACKSTR(p);
146276371Semaste		} else {
147260684Skaiw			STPUTC(c, p);
148260684Skaiw		}
149260684Skaiw	}
150260684Skaiw	STACKSTRNUL(p);
151260684Skaiw	setvar(*ap, stackblock(), 0);
152260684Skaiw	while (*++ap != NULL)
153260684Skaiw		setvar(*ap, nullstr, 0);
154260684Skaiw	return status;
155260684Skaiw}
156260684Skaiw
157260684Skaiw
158260684Skaiw
159260684Skaiwint
160276371Semasteumaskcmd(argc, argv)
161260684Skaiw	int argc;
162260684Skaiw	char **argv;
163260684Skaiw{
164260684Skaiw	char *ap;
165260684Skaiw	int mask;
166260684Skaiw	int i;
167260684Skaiw	int symbolic_mode = 0;
168260684Skaiw
169260684Skaiw	while ((i = nextopt("S")) != '\0') {
170260684Skaiw		symbolic_mode = 1;
171260684Skaiw	}
172260684Skaiw
173260684Skaiw	INTOFF;
174260684Skaiw	mask = umask(0);
175276371Semaste	umask(mask);
176260684Skaiw	INTON;
177260684Skaiw
178260684Skaiw	if ((ap = *argptr) == NULL) {
179260684Skaiw		if (symbolic_mode) {
180260684Skaiw			char u[4], g[4], o[4];
181260684Skaiw
182260684Skaiw			i = 0;
183276371Semaste			if ((mask & S_IRUSR) == 0)
184276371Semaste				u[i++] = 'r';
185260684Skaiw			if ((mask & S_IWUSR) == 0)
186260684Skaiw				u[i++] = 'w';
187260684Skaiw			if ((mask & S_IXUSR) == 0)
188276371Semaste				u[i++] = 'x';
189260684Skaiw			u[i] = '\0';
190260684Skaiw
191260684Skaiw			i = 0;
192260684Skaiw			if ((mask & S_IRGRP) == 0)
193260684Skaiw				g[i++] = 'r';
194260684Skaiw			if ((mask & S_IWGRP) == 0)
195260684Skaiw				g[i++] = 'w';
196260684Skaiw			if ((mask & S_IXGRP) == 0)
197260684Skaiw				g[i++] = 'x';
198260684Skaiw			g[i] = '\0';
199260684Skaiw
200260684Skaiw			i = 0;
201260684Skaiw			if ((mask & S_IROTH) == 0)
202260684Skaiw				o[i++] = 'r';
203260684Skaiw			if ((mask & S_IWOTH) == 0)
204260684Skaiw				o[i++] = 'w';
205260684Skaiw			if ((mask & S_IXOTH) == 0)
206260684Skaiw				o[i++] = 'x';
207260684Skaiw			o[i] = '\0';
208260684Skaiw
209276371Semaste			out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
210260684Skaiw		} else {
211260684Skaiw			out1fmt("%.4o\n", mask);
212260684Skaiw		}
213260684Skaiw	} else {
214260684Skaiw		if (isdigit(*ap)) {
215260684Skaiw			mask = 0;
216260684Skaiw			do {
217260684Skaiw				if (*ap >= '8' || *ap < '0')
218260684Skaiw					error("Illegal number: %s", argv[1]);
219260684Skaiw				mask = (mask << 3) + (*ap - '0');
220260684Skaiw			} while (*++ap != '\0');
221260684Skaiw			umask(mask);
222260684Skaiw		} else {
223260684Skaiw			void *set;
224260684Skaiw			if ((set = setmode (ap)) == 0)
225260684Skaiw					error("Illegal number: %s", ap);
226260684Skaiw
227260684Skaiw			mask = getmode (set, ~mask & 0777);
228260684Skaiw			umask(~mask & 0777);
229260684Skaiw		}
230260684Skaiw	}
231260684Skaiw	return 0;
232260684Skaiw}
233260684Skaiw
234260684Skaiw/*
235260684Skaiw * ulimit builtin
236260684Skaiw *
237260684Skaiw * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
238260684Skaiw * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
239260684Skaiw * ash by J.T. Conklin.
240 *
241 * Public domain.
242 */
243
244struct limits {
245	const char *name;
246	const char *units;
247	int	cmd;
248	int	factor;	/* multiply by to get rlim_{cur,max} values */
249	char	option;
250};
251
252static const struct limits limits[] = {
253#ifdef RLIMIT_CPU
254	{ "cpu time",		"seconds",	RLIMIT_CPU,	   1, 't' },
255#endif
256#ifdef RLIMIT_FSIZE
257	{ "file size",		"512-blocks",	RLIMIT_FSIZE,	 512, 'f' },
258#endif
259#ifdef RLIMIT_DATA
260	{ "data seg size",	"kbytes",	RLIMIT_DATA,	1024, 'd' },
261#endif
262#ifdef RLIMIT_STACK
263	{ "stack size",		"kbytes",	RLIMIT_STACK,	1024, 's' },
264#endif
265#ifdef  RLIMIT_CORE
266	{ "core file size",	"512-blocks",	RLIMIT_CORE,	 512, 'c' },
267#endif
268#ifdef RLIMIT_RSS
269	{ "max memory size",	"kbytes",	RLIMIT_RSS,	1024, 'm' },
270#endif
271#ifdef RLIMIT_MEMLOCK
272	{ "locked memory",	"kbytes",	RLIMIT_MEMLOCK, 1024, 'l' },
273#endif
274#ifdef RLIMIT_NPROC
275	{ "max user processes",	(char *)0,	RLIMIT_NPROC,      1, 'u' },
276#endif
277#ifdef RLIMIT_NOFILE
278	{ "open files",		(char *)0,	RLIMIT_NOFILE,     1, 'n' },
279#endif
280#ifdef RLIMIT_VMEM
281	{ "virtual mem size",	"kbytes",	RLIMIT_VMEM,	1024, 'v' },
282#endif
283#ifdef RLIMIT_SWAP
284	{ "swap limit",		"kbytes",	RLIMIT_SWAP,	1024, 'w' },
285#endif
286	{ (char *) 0,		(char *)0,	0,		   0, '\0' }
287};
288
289int
290ulimitcmd(argc, argv)
291	int argc;
292	char **argv;
293{
294	register int	c;
295	quad_t val;
296	enum { SOFT = 0x1, HARD = 0x2 }
297			how = SOFT | HARD;
298	const struct limits	*l;
299	int		set, all = 0;
300	int		optc, what;
301	struct rlimit	limit;
302
303	what = 'f';
304	while ((optc = nextopt("HSatfdsmcnul")) != '\0')
305		switch (optc) {
306		case 'H':
307			how = HARD;
308			break;
309		case 'S':
310			how = SOFT;
311			break;
312		case 'a':
313			all = 1;
314			break;
315		default:
316			what = optc;
317		}
318
319	for (l = limits; l->name && l->option != what; l++)
320		;
321	if (!l->name)
322		error("internal error (%c)", what);
323
324	set = *argptr ? 1 : 0;
325	if (set) {
326		char *p = *argptr;
327
328		if (all || argptr[1])
329			error("too many arguments");
330		if (strcmp(p, "unlimited") == 0)
331			val = RLIM_INFINITY;
332		else {
333			val = (quad_t) 0;
334
335			while ((c = *p++) >= '0' && c <= '9')
336			{
337				val = (val * 10) + (long)(c - '0');
338				if (val < (quad_t) 0)
339					break;
340			}
341			if (c)
342				error("bad number");
343			val *= l->factor;
344		}
345	}
346	if (all) {
347		for (l = limits; l->name; l++) {
348			char optbuf[40];
349			if (getrlimit(l->cmd, &limit) < 0)
350				error("can't get limit: %s", strerror(errno));
351			if (how & SOFT)
352				val = limit.rlim_cur;
353			else if (how & HARD)
354				val = limit.rlim_max;
355
356			if (l->units)
357				snprintf(optbuf, sizeof(optbuf),
358					"%s (%s, -%c) ", l->name, l->units, l->option);
359			else
360				snprintf(optbuf, sizeof(optbuf),
361					"%s (-%c) ", l->name, l->option);
362			out1fmt("%32s ", optbuf);
363			if (val == RLIM_INFINITY)
364				out1fmt("unlimited\n");
365			else
366			{
367				val /= l->factor;
368				out1fmt("%ld\n", (long) val);
369			}
370		}
371		return 0;
372	}
373
374	if (getrlimit(l->cmd, &limit) < 0)
375		error("can't get limit: %s", strerror(errno));
376	if (set) {
377		if (how & SOFT)
378			limit.rlim_cur = val;
379		if (how & HARD)
380			limit.rlim_max = val;
381		if (setrlimit(l->cmd, &limit) < 0)
382			error("bad limit: %s", strerror(errno));
383	} else {
384		if (how & SOFT)
385			val = limit.rlim_cur;
386		else if (how & HARD)
387			val = limit.rlim_max;
388	}
389
390	if (!set) {
391		if (val == RLIM_INFINITY)
392			out1fmt("unlimited\n");
393		else
394		{
395			val /= l->factor;
396			out1fmt("%ld\n", (long) val);
397		}
398	}
399	return 0;
400}
401