xref: /csrg-svn/bin/sh/miscbltin.c (revision 69272)
147129Sbostic /*-
260698Sbostic  * Copyright (c) 1991, 1993
360698Sbostic  *	The Regents of the University of California.  All rights reserved.
447129Sbostic  *
547129Sbostic  * This code is derived from software contributed to Berkeley by
647129Sbostic  * Kenneth Almquist.
747129Sbostic  *
847129Sbostic  * %sccs.include.redist.c%
947129Sbostic  */
1047129Sbostic 
1147129Sbostic #ifndef lint
12*69272Schristos static char sccsid[] = "@(#)miscbltin.c	8.4 (Berkeley) 05/04/95";
1347129Sbostic #endif /* not lint */
1447129Sbostic 
1547129Sbostic /*
1647129Sbostic  * Miscelaneous builtins.
1747129Sbostic  */
1847129Sbostic 
1968925Sbostic #include <sys/types.h>
2068925Sbostic #include <sys/stat.h>
21*69272Schristos #include <sys/time.h>
22*69272Schristos #include <sys/resource.h>
23*69272Schristos #include <unistd.h>
24*69272Schristos #include <ctype.h>
25*69272Schristos 
2647129Sbostic #include "shell.h"
2747129Sbostic #include "options.h"
2847129Sbostic #include "var.h"
2947129Sbostic #include "output.h"
3047129Sbostic #include "memalloc.h"
3147129Sbostic #include "error.h"
3247129Sbostic #include "mystring.h"
3347129Sbostic 
3447129Sbostic #undef eflag
3547129Sbostic 
3647129Sbostic extern char **argptr;		/* argument list for builtin command */
3747129Sbostic 
3847129Sbostic 
3947129Sbostic /*
4047129Sbostic  * The read builtin.  The -e option causes backslashes to escape the
4147129Sbostic  * following character.
4247129Sbostic  *
4347129Sbostic  * This uses unbuffered input, which may be avoidable in some cases.
4447129Sbostic  */
4547129Sbostic 
46*69272Schristos int
readcmd(argc,argv)47*69272Schristos readcmd(argc, argv)
48*69272Schristos 	int argc;
49*69272Schristos 	char **argv;
50*69272Schristos {
5147129Sbostic 	char **ap;
5247129Sbostic 	int backslash;
5347129Sbostic 	char c;
5447129Sbostic 	int eflag;
5547129Sbostic 	char *prompt;
5647129Sbostic 	char *ifs;
5747129Sbostic 	char *p;
5847129Sbostic 	int startword;
5947129Sbostic 	int status;
6047129Sbostic 	int i;
6147129Sbostic 
6247129Sbostic 	eflag = 0;
6347129Sbostic 	prompt = NULL;
6447297Smarc 	while ((i = nextopt("ep:")) != '\0') {
6547129Sbostic 		if (i == 'p')
6647129Sbostic 			prompt = optarg;
6747129Sbostic 		else
6847129Sbostic 			eflag = 1;
6947129Sbostic 	}
7047129Sbostic 	if (prompt && isatty(0)) {
7147129Sbostic 		out2str(prompt);
7247129Sbostic 		flushall();
7347129Sbostic 	}
7466823Sbostic 	if (*(ap = argptr) == NULL)
7547129Sbostic 		error("arg count");
7647129Sbostic 	if ((ifs = bltinlookup("IFS", 1)) == NULL)
7747129Sbostic 		ifs = nullstr;
7847129Sbostic 	status = 0;
7947129Sbostic 	startword = 1;
8047129Sbostic 	backslash = 0;
8147129Sbostic 	STARTSTACKSTR(p);
8247129Sbostic 	for (;;) {
8347129Sbostic 		if (read(0, &c, 1) != 1) {
8447129Sbostic 			status = 1;
8547129Sbostic 			break;
8647129Sbostic 		}
8747129Sbostic 		if (c == '\0')
8847129Sbostic 			continue;
8947129Sbostic 		if (backslash) {
9047129Sbostic 			backslash = 0;
9147129Sbostic 			if (c != '\n')
9247129Sbostic 				STPUTC(c, p);
9347129Sbostic 			continue;
9447129Sbostic 		}
9547129Sbostic 		if (eflag && c == '\\') {
9647129Sbostic 			backslash++;
9747129Sbostic 			continue;
9847129Sbostic 		}
9947129Sbostic 		if (c == '\n')
10047129Sbostic 			break;
10147129Sbostic 		if (startword && *ifs == ' ' && strchr(ifs, c)) {
10247129Sbostic 			continue;
10347129Sbostic 		}
10447129Sbostic 		startword = 0;
10547129Sbostic 		if (backslash && c == '\\') {
10647129Sbostic 			if (read(0, &c, 1) != 1) {
10747129Sbostic 				status = 1;
10847129Sbostic 				break;
10947129Sbostic 			}
11047129Sbostic 			STPUTC(c, p);
11147129Sbostic 		} else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11247129Sbostic 			STACKSTRNUL(p);
11347129Sbostic 			setvar(*ap, stackblock(), 0);
11447129Sbostic 			ap++;
11547129Sbostic 			startword = 1;
11647129Sbostic 			STARTSTACKSTR(p);
11747129Sbostic 		} else {
11847129Sbostic 			STPUTC(c, p);
11947129Sbostic 		}
12047129Sbostic 	}
12147129Sbostic 	STACKSTRNUL(p);
12247129Sbostic 	setvar(*ap, stackblock(), 0);
12347129Sbostic 	while (*++ap != NULL)
12447129Sbostic 		setvar(*ap, nullstr, 0);
12547129Sbostic 	return status;
12647129Sbostic }
12747129Sbostic 
12847129Sbostic 
12947129Sbostic 
130*69272Schristos int
umaskcmd(argc,argv)131*69272Schristos umaskcmd(argc, argv)
132*69272Schristos 	int argc;
133*69272Schristos 	char **argv;
134*69272Schristos {
13568925Sbostic 	char *ap;
13647129Sbostic 	int mask;
13747129Sbostic 	int i;
13868925Sbostic 	int symbolic_mode = 0;
13947129Sbostic 
14068925Sbostic 	while ((i = nextopt("S")) != '\0') {
14168925Sbostic 		symbolic_mode = 1;
14268925Sbostic 	}
14368925Sbostic 
14468925Sbostic 	INTOFF;
14568925Sbostic 	mask = umask(0);
14668925Sbostic 	umask(mask);
14768925Sbostic 	INTON;
14868925Sbostic 
14968925Sbostic 	if ((ap = *argptr) == NULL) {
15068925Sbostic 		if (symbolic_mode) {
15168925Sbostic 			char u[4], g[4], o[4];
15268925Sbostic 
15368925Sbostic 			i = 0;
15468925Sbostic 			if ((mask & S_IRUSR) == 0)
15568925Sbostic 				u[i++] = 'r';
15668925Sbostic 			if ((mask & S_IWUSR) == 0)
15768925Sbostic 				u[i++] = 'w';
15868925Sbostic 			if ((mask & S_IXUSR) == 0)
15968925Sbostic 				u[i++] = 'x';
16068925Sbostic 			u[i] = '\0';
16168925Sbostic 
16268925Sbostic 			i = 0;
16368925Sbostic 			if ((mask & S_IRGRP) == 0)
16468925Sbostic 				g[i++] = 'r';
16568925Sbostic 			if ((mask & S_IWGRP) == 0)
16668925Sbostic 				g[i++] = 'w';
16768925Sbostic 			if ((mask & S_IXGRP) == 0)
16868925Sbostic 				g[i++] = 'x';
16968925Sbostic 			g[i] = '\0';
17068925Sbostic 
17168925Sbostic 			i = 0;
17268925Sbostic 			if ((mask & S_IROTH) == 0)
17368925Sbostic 				o[i++] = 'r';
17468925Sbostic 			if ((mask & S_IWOTH) == 0)
17568925Sbostic 				o[i++] = 'w';
17668925Sbostic 			if ((mask & S_IXOTH) == 0)
17768925Sbostic 				o[i++] = 'x';
17868925Sbostic 			o[i] = '\0';
17968925Sbostic 
18068925Sbostic 			out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
18168925Sbostic 		} else {
18268925Sbostic 			out1fmt("%.4o\n", mask);
18368925Sbostic 		}
18447129Sbostic 	} else {
18568925Sbostic 		if (isdigit(*ap)) {
18668925Sbostic 			mask = 0;
18768925Sbostic 			do {
18868925Sbostic 				if (*ap >= '8' || *ap < '0')
18968925Sbostic 					error("Illegal number: %s", argv[1]);
19068925Sbostic 				mask = (mask << 3) + (*ap - '0');
19168925Sbostic 			} while (*++ap != '\0');
19268925Sbostic 			umask(mask);
19368925Sbostic 		} else {
19468925Sbostic 			void *set;
19568925Sbostic 			if ((set = setmode (ap)) == 0)
19668925Sbostic 					error("Illegal number: %s", ap);
19768925Sbostic 
19868925Sbostic 			mask = getmode (set, ~mask & 0777);
19968925Sbostic 			umask(~mask & 0777);
20068925Sbostic 		}
20147129Sbostic 	}
20247129Sbostic 	return 0;
20347129Sbostic }
204*69272Schristos 
205*69272Schristos /*
206*69272Schristos  * ulimit builtin
207*69272Schristos  *
208*69272Schristos  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
209*69272Schristos  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
210*69272Schristos  * ash by J.T. Conklin.
211*69272Schristos  *
212*69272Schristos  * Public domain.
213*69272Schristos  */
214*69272Schristos 
215*69272Schristos struct limits {
216*69272Schristos 	const char *name;
217*69272Schristos 	int	cmd;
218*69272Schristos 	int	factor;	/* multiply by to get rlim_{cur,max} values */
219*69272Schristos 	char	option;
220*69272Schristos };
221*69272Schristos 
222*69272Schristos static const struct limits limits[] = {
223*69272Schristos #ifdef RLIMIT_CPU
224*69272Schristos 	{ "time(seconds)",		RLIMIT_CPU,	   1, 't' },
225*69272Schristos #endif
226*69272Schristos #ifdef RLIMIT_FSIZE
227*69272Schristos 	{ "file(blocks)",		RLIMIT_FSIZE,	 512, 'f' },
228*69272Schristos #endif
229*69272Schristos #ifdef RLIMIT_DATA
230*69272Schristos 	{ "data(kbytes)",		RLIMIT_DATA,	1024, 'd' },
231*69272Schristos #endif
232*69272Schristos #ifdef RLIMIT_STACK
233*69272Schristos 	{ "stack(kbytes)",		RLIMIT_STACK,	1024, 's' },
234*69272Schristos #endif
235*69272Schristos #ifdef  RLIMIT_CORE
236*69272Schristos 	{ "coredump(blocks)",		RLIMIT_CORE,	 512, 'c' },
237*69272Schristos #endif
238*69272Schristos #ifdef RLIMIT_RSS
239*69272Schristos 	{ "memory(kbytes)",		RLIMIT_RSS,	1024, 'm' },
240*69272Schristos #endif
241*69272Schristos #ifdef RLIMIT_MEMLOCK
242*69272Schristos 	{ "locked memory(kbytes)",	RLIMIT_MEMLOCK, 1024, 'l' },
243*69272Schristos #endif
244*69272Schristos #ifdef RLIMIT_NPROC
245*69272Schristos 	{ "process(processes)",		RLIMIT_NPROC,      1, 'p' },
246*69272Schristos #endif
247*69272Schristos #ifdef RLIMIT_NOFILE
248*69272Schristos 	{ "nofiles(descriptors)",	RLIMIT_NOFILE,     1, 'n' },
249*69272Schristos #endif
250*69272Schristos #ifdef RLIMIT_VMEM
251*69272Schristos 	{ "vmemory(kbytes)",		RLIMIT_VMEM,	1024, 'v' },
252*69272Schristos #endif
253*69272Schristos #ifdef RLIMIT_SWAP
254*69272Schristos 	{ "swap(kbytes)",		RLIMIT_SWAP,	1024, 'w' },
255*69272Schristos #endif
256*69272Schristos 	{ (char *) 0,			0,		   0,  '\0' }
257*69272Schristos };
258*69272Schristos 
259*69272Schristos int
ulimitcmd(argc,argv)260*69272Schristos ulimitcmd(argc, argv)
261*69272Schristos 	int argc;
262*69272Schristos 	char **argv;
263*69272Schristos {
264*69272Schristos 	register int	c;
265*69272Schristos 	quad_t val;
266*69272Schristos 	enum { SOFT = 0x1, HARD = 0x2 }
267*69272Schristos 			how = SOFT | HARD;
268*69272Schristos 	const struct limits	*l;
269*69272Schristos 	int		set, all = 0;
270*69272Schristos 	int		optc, what;
271*69272Schristos 	struct rlimit	limit;
272*69272Schristos 
273*69272Schristos 	what = 'f';
274*69272Schristos 	while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
275*69272Schristos 		switch (optc) {
276*69272Schristos 		case 'H':
277*69272Schristos 			how = HARD;
278*69272Schristos 			break;
279*69272Schristos 		case 'S':
280*69272Schristos 			how = SOFT;
281*69272Schristos 			break;
282*69272Schristos 		case 'a':
283*69272Schristos 			all = 1;
284*69272Schristos 			break;
285*69272Schristos 		default:
286*69272Schristos 			what = optc;
287*69272Schristos 		}
288*69272Schristos 
289*69272Schristos 	for (l = limits; l->name && l->option != what; l++)
290*69272Schristos 		;
291*69272Schristos 	if (!l->name)
292*69272Schristos 		error("ulimit: internal error (%c)\n", what);
293*69272Schristos 
294*69272Schristos 	set = *argptr ? 1 : 0;
295*69272Schristos 	if (set) {
296*69272Schristos 		char *p = *argptr;
297*69272Schristos 
298*69272Schristos 		if (all || argptr[1])
299*69272Schristos 			error("ulimit: too many arguments\n");
300*69272Schristos 		if (strcmp(p, "unlimited") == 0)
301*69272Schristos 			val = RLIM_INFINITY;
302*69272Schristos 		else {
303*69272Schristos 			val = (quad_t) 0;
304*69272Schristos 
305*69272Schristos 			while ((c = *p++) >= '0' && c <= '9')
306*69272Schristos 			{
307*69272Schristos 				val = (val * 10) + (long)(c - '0');
308*69272Schristos 				if (val < (quad_t) 0)
309*69272Schristos 					break;
310*69272Schristos 			}
311*69272Schristos 			if (c)
312*69272Schristos 				error("ulimit: bad number\n");
313*69272Schristos 			val *= l->factor;
314*69272Schristos 		}
315*69272Schristos 	}
316*69272Schristos 	if (all) {
317*69272Schristos 		for (l = limits; l->name; l++) {
318*69272Schristos 			getrlimit(l->cmd, &limit);
319*69272Schristos 			if (how & SOFT)
320*69272Schristos 				val = limit.rlim_cur;
321*69272Schristos 			else if (how & HARD)
322*69272Schristos 				val = limit.rlim_max;
323*69272Schristos 
324*69272Schristos 			out1fmt("%-20s ", l->name);
325*69272Schristos 			if (val == RLIM_INFINITY)
326*69272Schristos 				out1fmt("unlimited\n");
327*69272Schristos 			else
328*69272Schristos 			{
329*69272Schristos 				val /= l->factor;
330*69272Schristos 				out1fmt("%ld\n", (long) val);
331*69272Schristos 			}
332*69272Schristos 		}
333*69272Schristos 		return 0;
334*69272Schristos 	}
335*69272Schristos 
336*69272Schristos 	getrlimit(l->cmd, &limit);
337*69272Schristos 	if (set) {
338*69272Schristos 		if (how & SOFT)
339*69272Schristos 			limit.rlim_cur = val;
340*69272Schristos 		if (how & HARD)
341*69272Schristos 			limit.rlim_max = val;
342*69272Schristos 		if (setrlimit(l->cmd, &limit) < 0)
343*69272Schristos 			error("ulimit: bad limit\n");
344*69272Schristos 	} else {
345*69272Schristos 		if (how & SOFT)
346*69272Schristos 			val = limit.rlim_cur;
347*69272Schristos 		else if (how & HARD)
348*69272Schristos 			val = limit.rlim_max;
349*69272Schristos 	}
350*69272Schristos 
351*69272Schristos 	if (!set) {
352*69272Schristos 		if (val == RLIM_INFINITY)
353*69272Schristos 			out1fmt("unlimited\n");
354*69272Schristos 		else
355*69272Schristos 		{
356*69272Schristos 			val /= l->factor;
357*69272Schristos 			out1fmt("%ld\n", (long) val);
358*69272Schristos 		}
359*69272Schristos 	}
360*69272Schristos 	return 0;
361*69272Schristos }
362