xref: /minix3/bin/sh/miscbltin.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: miscbltin.c,v 1.43 2015/05/09 13:28:55 christos Exp $	*/
2d90bee97SLionel Sambuc 
3d90bee97SLionel Sambuc /*-
4d90bee97SLionel Sambuc  * Copyright (c) 1991, 1993
5d90bee97SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
6d90bee97SLionel Sambuc  *
7d90bee97SLionel Sambuc  * This code is derived from software contributed to Berkeley by
8d90bee97SLionel Sambuc  * Kenneth Almquist.
9d90bee97SLionel Sambuc  *
10d90bee97SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
11d90bee97SLionel Sambuc  * modification, are permitted provided that the following conditions
12d90bee97SLionel Sambuc  * are met:
13d90bee97SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14d90bee97SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15d90bee97SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16d90bee97SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17d90bee97SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18d90bee97SLionel Sambuc  * 3. Neither the name of the University nor the names of its contributors
19d90bee97SLionel Sambuc  *    may be used to endorse or promote products derived from this software
20d90bee97SLionel Sambuc  *    without specific prior written permission.
21d90bee97SLionel Sambuc  *
22d90bee97SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23d90bee97SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24d90bee97SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25d90bee97SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26d90bee97SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27d90bee97SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28d90bee97SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29d90bee97SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30d90bee97SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31d90bee97SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32d90bee97SLionel Sambuc  * SUCH DAMAGE.
33d90bee97SLionel Sambuc  */
34d90bee97SLionel Sambuc 
35d90bee97SLionel Sambuc #include <sys/cdefs.h>
36d90bee97SLionel Sambuc #ifndef lint
37d90bee97SLionel Sambuc #if 0
38d90bee97SLionel Sambuc static char sccsid[] = "@(#)miscbltin.c	8.4 (Berkeley) 5/4/95";
39d90bee97SLionel Sambuc #else
40*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: miscbltin.c,v 1.43 2015/05/09 13:28:55 christos Exp $");
41d90bee97SLionel Sambuc #endif
42d90bee97SLionel Sambuc #endif /* not lint */
43d90bee97SLionel Sambuc 
44d90bee97SLionel Sambuc /*
45d90bee97SLionel Sambuc  * Miscelaneous builtins.
46d90bee97SLionel Sambuc  */
47d90bee97SLionel Sambuc 
48d90bee97SLionel Sambuc #include <sys/types.h>		/* quad_t */
49d90bee97SLionel Sambuc #include <sys/param.h>		/* BSD4_4 */
50d90bee97SLionel Sambuc #include <sys/stat.h>
51d90bee97SLionel Sambuc #include <sys/time.h>
52d90bee97SLionel Sambuc #include <sys/resource.h>
53d90bee97SLionel Sambuc #include <unistd.h>
54d90bee97SLionel Sambuc #include <stdlib.h>
55d90bee97SLionel Sambuc #include <ctype.h>
56d90bee97SLionel Sambuc #include <errno.h>
57d90bee97SLionel Sambuc 
58d90bee97SLionel Sambuc #include "shell.h"
59d90bee97SLionel Sambuc #include "options.h"
60d90bee97SLionel Sambuc #include "var.h"
61d90bee97SLionel Sambuc #include "output.h"
62d90bee97SLionel Sambuc #include "memalloc.h"
63d90bee97SLionel Sambuc #include "error.h"
64d90bee97SLionel Sambuc #include "builtins.h"
65d90bee97SLionel Sambuc #include "mystring.h"
66d90bee97SLionel Sambuc 
67d90bee97SLionel Sambuc #undef rflag
68d90bee97SLionel Sambuc 
69d90bee97SLionel Sambuc 
70d90bee97SLionel Sambuc 
71d90bee97SLionel Sambuc /*
72d90bee97SLionel Sambuc  * The read builtin.
73d90bee97SLionel Sambuc  * Backslahes escape the next char unless -r is specified.
74d90bee97SLionel Sambuc  *
75d90bee97SLionel Sambuc  * This uses unbuffered input, which may be avoidable in some cases.
76d90bee97SLionel Sambuc  *
77d90bee97SLionel Sambuc  * Note that if IFS=' :' then read x y should work so that:
78d90bee97SLionel Sambuc  * 'a b'	x='a', y='b'
79d90bee97SLionel Sambuc  * ' a b '	x='a', y='b'
80d90bee97SLionel Sambuc  * ':b'		x='',  y='b'
81d90bee97SLionel Sambuc  * ':'		x='',  y=''
82d90bee97SLionel Sambuc  * '::'		x='',  y=''
83d90bee97SLionel Sambuc  * ': :'	x='',  y=''
84d90bee97SLionel Sambuc  * ':::'	x='',  y='::'
85d90bee97SLionel Sambuc  * ':b c:'	x='',  y='b c:'
86d90bee97SLionel Sambuc  */
87d90bee97SLionel Sambuc 
88d90bee97SLionel Sambuc int
readcmd(int argc,char ** argv)89d90bee97SLionel Sambuc readcmd(int argc, char **argv)
90d90bee97SLionel Sambuc {
91d90bee97SLionel Sambuc 	char **ap;
92d90bee97SLionel Sambuc 	char c;
93d90bee97SLionel Sambuc 	int rflag;
94d90bee97SLionel Sambuc 	char *prompt;
95d90bee97SLionel Sambuc 	const char *ifs;
96d90bee97SLionel Sambuc 	char *p;
97d90bee97SLionel Sambuc 	int startword;
98d90bee97SLionel Sambuc 	int status;
99d90bee97SLionel Sambuc 	int i;
100d90bee97SLionel Sambuc 	int is_ifs;
101d90bee97SLionel Sambuc 	int saveall = 0;
102d90bee97SLionel Sambuc 
103d90bee97SLionel Sambuc 	rflag = 0;
104d90bee97SLionel Sambuc 	prompt = NULL;
105d90bee97SLionel Sambuc 	while ((i = nextopt("p:r")) != '\0') {
106d90bee97SLionel Sambuc 		if (i == 'p')
107d90bee97SLionel Sambuc 			prompt = optionarg;
108d90bee97SLionel Sambuc 		else
109d90bee97SLionel Sambuc 			rflag = 1;
110d90bee97SLionel Sambuc 	}
111d90bee97SLionel Sambuc 
112d90bee97SLionel Sambuc 	if (prompt && isatty(0)) {
113d90bee97SLionel Sambuc 		out2str(prompt);
114d90bee97SLionel Sambuc 		flushall();
115d90bee97SLionel Sambuc 	}
116d90bee97SLionel Sambuc 
117d90bee97SLionel Sambuc 	if (*(ap = argptr) == NULL)
118d90bee97SLionel Sambuc 		error("arg count");
119d90bee97SLionel Sambuc 
120d90bee97SLionel Sambuc 	if ((ifs = bltinlookup("IFS", 1)) == NULL)
121d90bee97SLionel Sambuc 		ifs = " \t\n";
122d90bee97SLionel Sambuc 
123d90bee97SLionel Sambuc 	status = 0;
124d90bee97SLionel Sambuc 	startword = 2;
125d90bee97SLionel Sambuc 	STARTSTACKSTR(p);
126d90bee97SLionel Sambuc 	for (;;) {
127d90bee97SLionel Sambuc 		if (read(0, &c, 1) != 1) {
128d90bee97SLionel Sambuc 			status = 1;
129d90bee97SLionel Sambuc 			break;
130d90bee97SLionel Sambuc 		}
131d90bee97SLionel Sambuc 		if (c == '\0')
132d90bee97SLionel Sambuc 			continue;
133d90bee97SLionel Sambuc 		if (c == '\\' && !rflag) {
134d90bee97SLionel Sambuc 			if (read(0, &c, 1) != 1) {
135d90bee97SLionel Sambuc 				status = 1;
136d90bee97SLionel Sambuc 				break;
137d90bee97SLionel Sambuc 			}
138d90bee97SLionel Sambuc 			if (c != '\n')
139d90bee97SLionel Sambuc 				STPUTC(c, p);
140d90bee97SLionel Sambuc 			continue;
141d90bee97SLionel Sambuc 		}
142d90bee97SLionel Sambuc 		if (c == '\n')
143d90bee97SLionel Sambuc 			break;
144d90bee97SLionel Sambuc 		if (strchr(ifs, c))
145d90bee97SLionel Sambuc 			is_ifs = strchr(" \t\n", c) ? 1 : 2;
146d90bee97SLionel Sambuc 		else
147d90bee97SLionel Sambuc 			is_ifs = 0;
148d90bee97SLionel Sambuc 
149d90bee97SLionel Sambuc 		if (startword != 0) {
150d90bee97SLionel Sambuc 			if (is_ifs == 1) {
151d90bee97SLionel Sambuc 				/* Ignore leading IFS whitespace */
152d90bee97SLionel Sambuc 				if (saveall)
153d90bee97SLionel Sambuc 					STPUTC(c, p);
154d90bee97SLionel Sambuc 				continue;
155d90bee97SLionel Sambuc 			}
156d90bee97SLionel Sambuc 			if (is_ifs == 2 && startword == 1) {
157d90bee97SLionel Sambuc 				/* Only one non-whitespace IFS per word */
158d90bee97SLionel Sambuc 				startword = 2;
159d90bee97SLionel Sambuc 				if (saveall)
160d90bee97SLionel Sambuc 					STPUTC(c, p);
161d90bee97SLionel Sambuc 				continue;
162d90bee97SLionel Sambuc 			}
163d90bee97SLionel Sambuc 		}
164d90bee97SLionel Sambuc 
165d90bee97SLionel Sambuc 		if (is_ifs == 0) {
166d90bee97SLionel Sambuc 			/* append this character to the current variable */
167d90bee97SLionel Sambuc 			startword = 0;
168d90bee97SLionel Sambuc 			if (saveall)
169d90bee97SLionel Sambuc 				/* Not just a spare terminator */
170d90bee97SLionel Sambuc 				saveall++;
171d90bee97SLionel Sambuc 			STPUTC(c, p);
172d90bee97SLionel Sambuc 			continue;
173d90bee97SLionel Sambuc 		}
174d90bee97SLionel Sambuc 
175d90bee97SLionel Sambuc 		/* end of variable... */
176d90bee97SLionel Sambuc 		startword = is_ifs;
177d90bee97SLionel Sambuc 
178d90bee97SLionel Sambuc 		if (ap[1] == NULL) {
179d90bee97SLionel Sambuc 			/* Last variable needs all IFS chars */
180d90bee97SLionel Sambuc 			saveall++;
181d90bee97SLionel Sambuc 			STPUTC(c, p);
182d90bee97SLionel Sambuc 			continue;
183d90bee97SLionel Sambuc 		}
184d90bee97SLionel Sambuc 
185d90bee97SLionel Sambuc 		STACKSTRNUL(p);
186d90bee97SLionel Sambuc 		setvar(*ap, stackblock(), 0);
187d90bee97SLionel Sambuc 		ap++;
188d90bee97SLionel Sambuc 		STARTSTACKSTR(p);
189d90bee97SLionel Sambuc 	}
190d90bee97SLionel Sambuc 	STACKSTRNUL(p);
191d90bee97SLionel Sambuc 
192d90bee97SLionel Sambuc 	/* Remove trailing IFS chars */
193d90bee97SLionel Sambuc 	for (; stackblock() <= --p; *p = 0) {
194d90bee97SLionel Sambuc 		if (!strchr(ifs, *p))
195d90bee97SLionel Sambuc 			break;
196d90bee97SLionel Sambuc 		if (strchr(" \t\n", *p))
197d90bee97SLionel Sambuc 			/* Always remove whitespace */
198d90bee97SLionel Sambuc 			continue;
199d90bee97SLionel Sambuc 		if (saveall > 1)
200d90bee97SLionel Sambuc 			/* Don't remove non-whitespace unless it was naked */
201d90bee97SLionel Sambuc 			break;
202d90bee97SLionel Sambuc 	}
203d90bee97SLionel Sambuc 	setvar(*ap, stackblock(), 0);
204d90bee97SLionel Sambuc 
205d90bee97SLionel Sambuc 	/* Set any remaining args to "" */
206d90bee97SLionel Sambuc 	while (*++ap != NULL)
207d90bee97SLionel Sambuc 		setvar(*ap, nullstr, 0);
208d90bee97SLionel Sambuc 	return status;
209d90bee97SLionel Sambuc }
210d90bee97SLionel Sambuc 
211d90bee97SLionel Sambuc 
212d90bee97SLionel Sambuc 
213d90bee97SLionel Sambuc int
umaskcmd(int argc,char ** argv)214d90bee97SLionel Sambuc umaskcmd(int argc, char **argv)
215d90bee97SLionel Sambuc {
216d90bee97SLionel Sambuc 	char *ap;
217d90bee97SLionel Sambuc 	int mask;
218d90bee97SLionel Sambuc 	int i;
219d90bee97SLionel Sambuc 	int symbolic_mode = 0;
220d90bee97SLionel Sambuc 
221d90bee97SLionel Sambuc 	while ((i = nextopt("S")) != '\0') {
222d90bee97SLionel Sambuc 		symbolic_mode = 1;
223d90bee97SLionel Sambuc 	}
224d90bee97SLionel Sambuc 
225d90bee97SLionel Sambuc 	INTOFF;
226d90bee97SLionel Sambuc 	mask = umask(0);
227d90bee97SLionel Sambuc 	umask(mask);
228d90bee97SLionel Sambuc 	INTON;
229d90bee97SLionel Sambuc 
230d90bee97SLionel Sambuc 	if ((ap = *argptr) == NULL) {
231d90bee97SLionel Sambuc 		if (symbolic_mode) {
232d90bee97SLionel Sambuc 			char u[4], g[4], o[4];
233d90bee97SLionel Sambuc 
234d90bee97SLionel Sambuc 			i = 0;
235d90bee97SLionel Sambuc 			if ((mask & S_IRUSR) == 0)
236d90bee97SLionel Sambuc 				u[i++] = 'r';
237d90bee97SLionel Sambuc 			if ((mask & S_IWUSR) == 0)
238d90bee97SLionel Sambuc 				u[i++] = 'w';
239d90bee97SLionel Sambuc 			if ((mask & S_IXUSR) == 0)
240d90bee97SLionel Sambuc 				u[i++] = 'x';
241d90bee97SLionel Sambuc 			u[i] = '\0';
242d90bee97SLionel Sambuc 
243d90bee97SLionel Sambuc 			i = 0;
244d90bee97SLionel Sambuc 			if ((mask & S_IRGRP) == 0)
245d90bee97SLionel Sambuc 				g[i++] = 'r';
246d90bee97SLionel Sambuc 			if ((mask & S_IWGRP) == 0)
247d90bee97SLionel Sambuc 				g[i++] = 'w';
248d90bee97SLionel Sambuc 			if ((mask & S_IXGRP) == 0)
249d90bee97SLionel Sambuc 				g[i++] = 'x';
250d90bee97SLionel Sambuc 			g[i] = '\0';
251d90bee97SLionel Sambuc 
252d90bee97SLionel Sambuc 			i = 0;
253d90bee97SLionel Sambuc 			if ((mask & S_IROTH) == 0)
254d90bee97SLionel Sambuc 				o[i++] = 'r';
255d90bee97SLionel Sambuc 			if ((mask & S_IWOTH) == 0)
256d90bee97SLionel Sambuc 				o[i++] = 'w';
257d90bee97SLionel Sambuc 			if ((mask & S_IXOTH) == 0)
258d90bee97SLionel Sambuc 				o[i++] = 'x';
259d90bee97SLionel Sambuc 			o[i] = '\0';
260d90bee97SLionel Sambuc 
261d90bee97SLionel Sambuc 			out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
262d90bee97SLionel Sambuc 		} else {
263d90bee97SLionel Sambuc 			out1fmt("%.4o\n", mask);
264d90bee97SLionel Sambuc 		}
265d90bee97SLionel Sambuc 	} else {
266d90bee97SLionel Sambuc 		if (isdigit((unsigned char)*ap)) {
267d90bee97SLionel Sambuc 			mask = 0;
268d90bee97SLionel Sambuc 			do {
269d90bee97SLionel Sambuc 				if (*ap >= '8' || *ap < '0')
270d90bee97SLionel Sambuc 					error("Illegal number: %s", argv[1]);
271d90bee97SLionel Sambuc 				mask = (mask << 3) + (*ap - '0');
272d90bee97SLionel Sambuc 			} while (*++ap != '\0');
273d90bee97SLionel Sambuc 			umask(mask);
274d90bee97SLionel Sambuc 		} else {
275d90bee97SLionel Sambuc 			void *set;
276d90bee97SLionel Sambuc 
277d90bee97SLionel Sambuc 			INTOFF;
278d90bee97SLionel Sambuc 			if ((set = setmode(ap)) != 0) {
279d90bee97SLionel Sambuc 				mask = getmode(set, ~mask & 0777);
280d90bee97SLionel Sambuc 				ckfree(set);
281d90bee97SLionel Sambuc 			}
282d90bee97SLionel Sambuc 			INTON;
283d90bee97SLionel Sambuc 			if (!set)
284d90bee97SLionel Sambuc 				error("Cannot set mode `%s' (%s)", ap,
285d90bee97SLionel Sambuc 				    strerror(errno));
286d90bee97SLionel Sambuc 
287d90bee97SLionel Sambuc 			umask(~mask & 0777);
288d90bee97SLionel Sambuc 		}
289d90bee97SLionel Sambuc 	}
290d90bee97SLionel Sambuc 	return 0;
291d90bee97SLionel Sambuc }
292d90bee97SLionel Sambuc 
293d90bee97SLionel Sambuc /*
294d90bee97SLionel Sambuc  * ulimit builtin
295d90bee97SLionel Sambuc  *
296d90bee97SLionel Sambuc  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
297d90bee97SLionel Sambuc  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
298d90bee97SLionel Sambuc  * ash by J.T. Conklin.
299d90bee97SLionel Sambuc  *
300d90bee97SLionel Sambuc  * Public domain.
301d90bee97SLionel Sambuc  */
302d90bee97SLionel Sambuc 
303d90bee97SLionel Sambuc struct limits {
304d90bee97SLionel Sambuc 	const char *name;
305d90bee97SLionel Sambuc 	const char *unit;
306d90bee97SLionel Sambuc 	int	cmd;
307d90bee97SLionel Sambuc 	int	factor;	/* multiply by to get rlim_{cur,max} values */
308d90bee97SLionel Sambuc 	char	option;
309d90bee97SLionel Sambuc };
310d90bee97SLionel Sambuc 
311d90bee97SLionel Sambuc static const struct limits limits[] = {
312d90bee97SLionel Sambuc #ifdef RLIMIT_CPU
313d90bee97SLionel Sambuc 	{ "time",	"seconds",	RLIMIT_CPU,	   1, 't' },
314d90bee97SLionel Sambuc #endif
315d90bee97SLionel Sambuc #ifdef RLIMIT_FSIZE
316d90bee97SLionel Sambuc 	{ "file",	"blocks",	RLIMIT_FSIZE,	 512, 'f' },
317d90bee97SLionel Sambuc #endif
318d90bee97SLionel Sambuc #ifdef RLIMIT_DATA
319d90bee97SLionel Sambuc 	{ "data",	"kbytes",	RLIMIT_DATA,	1024, 'd' },
320d90bee97SLionel Sambuc #endif
321d90bee97SLionel Sambuc #ifdef RLIMIT_STACK
322d90bee97SLionel Sambuc 	{ "stack",	"kbytes",	RLIMIT_STACK,	1024, 's' },
323d90bee97SLionel Sambuc #endif
324d90bee97SLionel Sambuc #ifdef  RLIMIT_CORE
325d90bee97SLionel Sambuc 	{ "coredump",	"blocks",	RLIMIT_CORE,	 512, 'c' },
326d90bee97SLionel Sambuc #endif
327d90bee97SLionel Sambuc #ifdef RLIMIT_RSS
328d90bee97SLionel Sambuc 	{ "memory",	"kbytes",	RLIMIT_RSS,	1024, 'm' },
329d90bee97SLionel Sambuc #endif
330d90bee97SLionel Sambuc #ifdef RLIMIT_MEMLOCK
331d90bee97SLionel Sambuc 	{ "locked memory","kbytes",	RLIMIT_MEMLOCK, 1024, 'l' },
332d90bee97SLionel Sambuc #endif
333d90bee97SLionel Sambuc #ifdef RLIMIT_NTHR
334d90bee97SLionel Sambuc 	{ "thread",	"threads",	RLIMIT_NTHR,       1, 'r' },
335d90bee97SLionel Sambuc #endif
336d90bee97SLionel Sambuc #ifdef RLIMIT_NPROC
337d90bee97SLionel Sambuc 	{ "process",	"processes",	RLIMIT_NPROC,      1, 'p' },
338d90bee97SLionel Sambuc #endif
339d90bee97SLionel Sambuc #ifdef RLIMIT_NOFILE
340d90bee97SLionel Sambuc 	{ "nofiles",	"descriptors",	RLIMIT_NOFILE,     1, 'n' },
341d90bee97SLionel Sambuc #endif
342d90bee97SLionel Sambuc #ifdef RLIMIT_VMEM
343d90bee97SLionel Sambuc 	{ "vmemory",	"kbytes",	RLIMIT_VMEM,	1024, 'v' },
344d90bee97SLionel Sambuc #endif
345d90bee97SLionel Sambuc #ifdef RLIMIT_SWAP
346d90bee97SLionel Sambuc 	{ "swap",	"kbytes",	RLIMIT_SWAP,	1024, 'w' },
347d90bee97SLionel Sambuc #endif
348d90bee97SLionel Sambuc #ifdef RLIMIT_SBSIZE
349d90bee97SLionel Sambuc 	{ "sbsize",	"bytes",	RLIMIT_SBSIZE,	   1, 'b' },
350d90bee97SLionel Sambuc #endif
351d90bee97SLionel Sambuc 	{ NULL,		NULL,		0,		   0,  '\0' }
352d90bee97SLionel Sambuc };
353d90bee97SLionel Sambuc 
354d90bee97SLionel Sambuc int
ulimitcmd(int argc,char ** argv)355d90bee97SLionel Sambuc ulimitcmd(int argc, char **argv)
356d90bee97SLionel Sambuc {
357d90bee97SLionel Sambuc 	int	c;
358d90bee97SLionel Sambuc 	rlim_t val = 0;
359d90bee97SLionel Sambuc 	enum { SOFT = 0x1, HARD = 0x2 }
360d90bee97SLionel Sambuc 			how = SOFT | HARD;
361d90bee97SLionel Sambuc 	const struct limits	*l;
362d90bee97SLionel Sambuc 	int		set, all = 0;
363d90bee97SLionel Sambuc 	int		optc, what;
364d90bee97SLionel Sambuc 	struct rlimit	limit;
365d90bee97SLionel Sambuc 
366d90bee97SLionel Sambuc 	what = 'f';
367d90bee97SLionel Sambuc 	while ((optc = nextopt("HSabtfdscmlrpnv")) != '\0')
368d90bee97SLionel Sambuc 		switch (optc) {
369d90bee97SLionel Sambuc 		case 'H':
370d90bee97SLionel Sambuc 			how = HARD;
371d90bee97SLionel Sambuc 			break;
372d90bee97SLionel Sambuc 		case 'S':
373d90bee97SLionel Sambuc 			how = SOFT;
374d90bee97SLionel Sambuc 			break;
375d90bee97SLionel Sambuc 		case 'a':
376d90bee97SLionel Sambuc 			all = 1;
377d90bee97SLionel Sambuc 			break;
378d90bee97SLionel Sambuc 		default:
379d90bee97SLionel Sambuc 			what = optc;
380d90bee97SLionel Sambuc 		}
381d90bee97SLionel Sambuc 
382d90bee97SLionel Sambuc 	for (l = limits; l->name && l->option != what; l++)
383d90bee97SLionel Sambuc 		;
384d90bee97SLionel Sambuc 	if (!l->name)
385d90bee97SLionel Sambuc 		error("internal error (%c)", what);
386d90bee97SLionel Sambuc 
387d90bee97SLionel Sambuc 	set = *argptr ? 1 : 0;
388d90bee97SLionel Sambuc 	if (set) {
389d90bee97SLionel Sambuc 		char *p = *argptr;
390d90bee97SLionel Sambuc 
391d90bee97SLionel Sambuc 		if (all || argptr[1])
392d90bee97SLionel Sambuc 			error("too many arguments");
393d90bee97SLionel Sambuc 		if (strcmp(p, "unlimited") == 0)
394d90bee97SLionel Sambuc 			val = RLIM_INFINITY;
395d90bee97SLionel Sambuc 		else {
396d90bee97SLionel Sambuc 			val = (rlim_t) 0;
397d90bee97SLionel Sambuc 
398d90bee97SLionel Sambuc 			while ((c = *p++) >= '0' && c <= '9')
399d90bee97SLionel Sambuc 				val = (val * 10) + (long)(c - '0');
400d90bee97SLionel Sambuc 			if (c)
401d90bee97SLionel Sambuc 				error("bad number");
402d90bee97SLionel Sambuc 			val *= l->factor;
403d90bee97SLionel Sambuc 		}
404d90bee97SLionel Sambuc 	}
405d90bee97SLionel Sambuc 	if (all) {
406d90bee97SLionel Sambuc 		for (l = limits; l->name; l++) {
407d90bee97SLionel Sambuc 			getrlimit(l->cmd, &limit);
408d90bee97SLionel Sambuc 			if (how & SOFT)
409d90bee97SLionel Sambuc 				val = limit.rlim_cur;
410d90bee97SLionel Sambuc 			else if (how & HARD)
411d90bee97SLionel Sambuc 				val = limit.rlim_max;
412d90bee97SLionel Sambuc 
413d90bee97SLionel Sambuc 			out1fmt("%-13s (-%c %-11s) ", l->name, l->option,
414d90bee97SLionel Sambuc 			    l->unit);
415d90bee97SLionel Sambuc 			if (val == RLIM_INFINITY)
416d90bee97SLionel Sambuc 				out1fmt("unlimited\n");
417d90bee97SLionel Sambuc 			else
418d90bee97SLionel Sambuc 			{
419d90bee97SLionel Sambuc 				val /= l->factor;
420d90bee97SLionel Sambuc #ifdef BSD4_4
421d90bee97SLionel Sambuc 				out1fmt("%lld\n", (long long) val);
422d90bee97SLionel Sambuc #else
423d90bee97SLionel Sambuc 				out1fmt("%ld\n", (long) val);
424d90bee97SLionel Sambuc #endif
425d90bee97SLionel Sambuc 			}
426d90bee97SLionel Sambuc 		}
427d90bee97SLionel Sambuc 		return 0;
428d90bee97SLionel Sambuc 	}
429d90bee97SLionel Sambuc 
430*0a6a1f1dSLionel Sambuc 	if (getrlimit(l->cmd, &limit) == -1)
431*0a6a1f1dSLionel Sambuc 		error("error getting limit (%s)", strerror(errno));
432d90bee97SLionel Sambuc 	if (set) {
433d90bee97SLionel Sambuc 		if (how & HARD)
434d90bee97SLionel Sambuc 			limit.rlim_max = val;
435d90bee97SLionel Sambuc 		if (how & SOFT)
436d90bee97SLionel Sambuc 			limit.rlim_cur = val;
437d90bee97SLionel Sambuc 		if (setrlimit(l->cmd, &limit) < 0)
438d90bee97SLionel Sambuc 			error("error setting limit (%s)", strerror(errno));
439d90bee97SLionel Sambuc 	} else {
440d90bee97SLionel Sambuc 		if (how & SOFT)
441d90bee97SLionel Sambuc 			val = limit.rlim_cur;
442d90bee97SLionel Sambuc 		else if (how & HARD)
443d90bee97SLionel Sambuc 			val = limit.rlim_max;
444d90bee97SLionel Sambuc 
445d90bee97SLionel Sambuc 		if (val == RLIM_INFINITY)
446d90bee97SLionel Sambuc 			out1fmt("unlimited\n");
447d90bee97SLionel Sambuc 		else
448d90bee97SLionel Sambuc 		{
449d90bee97SLionel Sambuc 			val /= l->factor;
450d90bee97SLionel Sambuc #ifdef BSD4_4
451d90bee97SLionel Sambuc 			out1fmt("%lld\n", (long long) val);
452d90bee97SLionel Sambuc #else
453d90bee97SLionel Sambuc 			out1fmt("%ld\n", (long) val);
454d90bee97SLionel Sambuc #endif
455d90bee97SLionel Sambuc 		}
456d90bee97SLionel Sambuc 	}
457d90bee97SLionel Sambuc 	return 0;
458d90bee97SLionel Sambuc }
459