14b88c807SRodney W. Grimes /*-
28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni *
44b88c807SRodney W. Grimes * Copyright (c) 1991, 1993
54b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved.
64b88c807SRodney W. Grimes *
74b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by
84b88c807SRodney W. Grimes * Kenneth Almquist.
94b88c807SRodney W. Grimes *
104b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
114b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions
124b88c807SRodney W. Grimes * are met:
134b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
154b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
164b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
174b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution.
18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
194b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software
204b88c807SRodney W. Grimes * without specific prior written permission.
214b88c807SRodney W. Grimes *
224b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
234b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
244b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
254b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
264b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
274b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
284b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
294b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
304b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
314b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
324b88c807SRodney W. Grimes * SUCH DAMAGE.
334b88c807SRodney W. Grimes */
344b88c807SRodney W. Grimes
354b88c807SRodney W. Grimes /*
3646be34b9SKris Kennaway * Miscellaneous builtins.
374b88c807SRodney W. Grimes */
384b88c807SRodney W. Grimes
39aa9caaf6SPeter Wemm #include <sys/types.h>
40aa9caaf6SPeter Wemm #include <sys/stat.h>
41aa9caaf6SPeter Wemm #include <sys/time.h>
42aa9caaf6SPeter Wemm #include <sys/resource.h>
43aa9caaf6SPeter Wemm #include <unistd.h>
4416992ff4SPeter Wemm #include <errno.h>
450c1661b7SMaxime Henrion #include <stdint.h>
464417f629SPeter Wemm #include <stdio.h>
471f40b47bSMartin Cracauer #include <stdlib.h>
48aa9caaf6SPeter Wemm
494b88c807SRodney W. Grimes #include "shell.h"
504b88c807SRodney W. Grimes #include "options.h"
514b88c807SRodney W. Grimes #include "var.h"
524b88c807SRodney W. Grimes #include "output.h"
534b88c807SRodney W. Grimes #include "memalloc.h"
544b88c807SRodney W. Grimes #include "error.h"
554b88c807SRodney W. Grimes #include "mystring.h"
5658570ac4SJilles Tjoelker #include "syntax.h"
57c4539460SJilles Tjoelker #include "trap.h"
584b88c807SRodney W. Grimes
594b88c807SRodney W. Grimes #undef eflag
604b88c807SRodney W. Grimes
61be860ca2SHiroki Sato #define READ_BUFLEN 1024
62be860ca2SHiroki Sato struct fdctx {
63be860ca2SHiroki Sato int fd;
64be860ca2SHiroki Sato size_t off; /* offset in buf */
65be860ca2SHiroki Sato size_t buflen;
66be860ca2SHiroki Sato char *ep; /* tail pointer */
67be860ca2SHiroki Sato char buf[READ_BUFLEN];
68be860ca2SHiroki Sato };
69be860ca2SHiroki Sato
70be860ca2SHiroki Sato static void fdctx_init(int, struct fdctx *);
71be860ca2SHiroki Sato static void fdctx_destroy(struct fdctx *);
72be860ca2SHiroki Sato static ssize_t fdgetc(struct fdctx *, char *);
7379ea0bd9SStefan Farfeleder int readcmd(int, char **);
7479ea0bd9SStefan Farfeleder int umaskcmd(int, char **);
7579ea0bd9SStefan Farfeleder int ulimitcmd(int, char **);
7679ea0bd9SStefan Farfeleder
77be860ca2SHiroki Sato static void
fdctx_init(int fd,struct fdctx * fdc)78be860ca2SHiroki Sato fdctx_init(int fd, struct fdctx *fdc)
79be860ca2SHiroki Sato {
80be860ca2SHiroki Sato off_t cur;
81be860ca2SHiroki Sato
82be860ca2SHiroki Sato /* Check if fd is seekable. */
83be860ca2SHiroki Sato cur = lseek(fd, 0, SEEK_CUR);
84be860ca2SHiroki Sato *fdc = (struct fdctx){
85be860ca2SHiroki Sato .fd = fd,
86be860ca2SHiroki Sato .buflen = (cur != -1) ? READ_BUFLEN : 1,
87be860ca2SHiroki Sato .ep = &fdc->buf[0], /* No data */
88be860ca2SHiroki Sato };
89be860ca2SHiroki Sato }
90be860ca2SHiroki Sato
91be860ca2SHiroki Sato static ssize_t
fdgetc(struct fdctx * fdc,char * c)92be860ca2SHiroki Sato fdgetc(struct fdctx *fdc, char *c)
93be860ca2SHiroki Sato {
94be860ca2SHiroki Sato ssize_t nread;
95be860ca2SHiroki Sato
96be860ca2SHiroki Sato if (&fdc->buf[fdc->off] == fdc->ep) {
97be860ca2SHiroki Sato nread = read(fdc->fd, fdc->buf, fdc->buflen);
98be860ca2SHiroki Sato if (nread > 0) {
99be860ca2SHiroki Sato fdc->off = 0;
100be860ca2SHiroki Sato fdc->ep = fdc->buf + nread;
101be860ca2SHiroki Sato } else
102be860ca2SHiroki Sato return (nread);
103be860ca2SHiroki Sato }
104be860ca2SHiroki Sato *c = fdc->buf[fdc->off++];
105be860ca2SHiroki Sato
106be860ca2SHiroki Sato return (1);
107be860ca2SHiroki Sato }
108be860ca2SHiroki Sato
109be860ca2SHiroki Sato static void
fdctx_destroy(struct fdctx * fdc)110be860ca2SHiroki Sato fdctx_destroy(struct fdctx *fdc)
111be860ca2SHiroki Sato {
112b63d2d68SKyle Evans off_t residue;
113be860ca2SHiroki Sato
114be860ca2SHiroki Sato if (fdc->buflen > 1) {
115be860ca2SHiroki Sato /*
116be860ca2SHiroki Sato * Reposition the file offset. Here is the layout of buf:
117be860ca2SHiroki Sato *
118be860ca2SHiroki Sato * | off
119be860ca2SHiroki Sato * v
120be860ca2SHiroki Sato * |*****************|-------|
121be860ca2SHiroki Sato * buf ep buf+buflen
122be860ca2SHiroki Sato * |<- residue ->|
123be860ca2SHiroki Sato *
124be860ca2SHiroki Sato * off: current character
125be860ca2SHiroki Sato * ep: offset just after read(2)
126be860ca2SHiroki Sato * residue: length for reposition
127be860ca2SHiroki Sato */
128be860ca2SHiroki Sato residue = (fdc->ep - fdc->buf) - fdc->off;
129be860ca2SHiroki Sato if (residue > 0)
130be860ca2SHiroki Sato (void) lseek(fdc->fd, -residue, SEEK_CUR);
131be860ca2SHiroki Sato }
132be860ca2SHiroki Sato }
133be860ca2SHiroki Sato
1344b88c807SRodney W. Grimes /*
1358f0561ccSThomas Gellekum * The read builtin. The -r option causes backslashes to be treated like
1368f0561ccSThomas Gellekum * ordinary characters.
137b6748ec2SStefan Farfeleder *
138b6748ec2SStefan Farfeleder * Note that if IFS=' :' then read x y should work so that:
139b6748ec2SStefan Farfeleder * 'a b' x='a', y='b'
140b6748ec2SStefan Farfeleder * ' a b ' x='a', y='b'
141b6748ec2SStefan Farfeleder * ':b' x='', y='b'
142b6748ec2SStefan Farfeleder * ':' x='', y=''
143b6748ec2SStefan Farfeleder * '::' x='', y=''
144b6748ec2SStefan Farfeleder * ': :' x='', y=''
145b6748ec2SStefan Farfeleder * ':::' x='', y='::'
146b6748ec2SStefan Farfeleder * ':b c:' x='', y='b c:'
1474b88c807SRodney W. Grimes */
1484b88c807SRodney W. Grimes
149aa9caaf6SPeter Wemm int
readcmd(int argc __unused,char ** argv __unused)1505134c3f7SWarner Losh readcmd(int argc __unused, char **argv __unused)
151aa9caaf6SPeter Wemm {
1524b88c807SRodney W. Grimes char **ap;
1534b88c807SRodney W. Grimes int backslash;
1544b88c807SRodney W. Grimes char c;
1558f0561ccSThomas Gellekum int rflag;
1564b88c807SRodney W. Grimes char *prompt;
157384aedabSJilles Tjoelker const char *ifs;
1584b88c807SRodney W. Grimes char *p;
1594b88c807SRodney W. Grimes int startword;
1604b88c807SRodney W. Grimes int status;
1614b88c807SRodney W. Grimes int i;
162b6748ec2SStefan Farfeleder int is_ifs;
163b6748ec2SStefan Farfeleder int saveall = 0;
164f0688a48SJilles Tjoelker ptrdiff_t lastnonifs, lastnonifsws;
165afa53c8dSMike Smith struct timeval tv;
166afa53c8dSMike Smith char *tvptr;
167afa53c8dSMike Smith fd_set ifds;
168c4539460SJilles Tjoelker ssize_t nread;
169c4539460SJilles Tjoelker int sig;
170be860ca2SHiroki Sato struct fdctx fdctx;
1714b88c807SRodney W. Grimes
1728f0561ccSThomas Gellekum rflag = 0;
1734b88c807SRodney W. Grimes prompt = NULL;
174afa53c8dSMike Smith tv.tv_sec = -1;
175afa53c8dSMike Smith tv.tv_usec = 0;
1768f0561ccSThomas Gellekum while ((i = nextopt("erp:t:")) != '\0') {
177afa53c8dSMike Smith switch(i) {
178afa53c8dSMike Smith case 'p':
179f01e3d0cSMartin Cracauer prompt = shoptarg;
180afa53c8dSMike Smith break;
181afa53c8dSMike Smith case 'e':
1828f0561ccSThomas Gellekum break;
1838f0561ccSThomas Gellekum case 'r':
1848f0561ccSThomas Gellekum rflag = 1;
185afa53c8dSMike Smith break;
186afa53c8dSMike Smith case 't':
187f01e3d0cSMartin Cracauer tv.tv_sec = strtol(shoptarg, &tvptr, 0);
188f01e3d0cSMartin Cracauer if (tvptr == shoptarg)
189afa53c8dSMike Smith error("timeout value");
190afa53c8dSMike Smith switch(*tvptr) {
191afa53c8dSMike Smith case 0:
192afa53c8dSMike Smith case 's':
193afa53c8dSMike Smith break;
194afa53c8dSMike Smith case 'h':
195afa53c8dSMike Smith tv.tv_sec *= 60;
196afa53c8dSMike Smith /* FALLTHROUGH */
197afa53c8dSMike Smith case 'm':
198afa53c8dSMike Smith tv.tv_sec *= 60;
199afa53c8dSMike Smith break;
200afa53c8dSMike Smith default:
201afa53c8dSMike Smith error("timeout unit");
202afa53c8dSMike Smith }
203afa53c8dSMike Smith break;
204afa53c8dSMike Smith }
2054b88c807SRodney W. Grimes }
2064b88c807SRodney W. Grimes if (prompt && isatty(0)) {
2074b88c807SRodney W. Grimes out2str(prompt);
2084b88c807SRodney W. Grimes flushall();
2094b88c807SRodney W. Grimes }
2104b88c807SRodney W. Grimes if (*(ap = argptr) == NULL)
2114b88c807SRodney W. Grimes error("arg count");
2124b88c807SRodney W. Grimes if ((ifs = bltinlookup("IFS", 1)) == NULL)
21386d8da5dSStefan Farfeleder ifs = " \t\n";
214afa53c8dSMike Smith
215afa53c8dSMike Smith if (tv.tv_sec >= 0) {
216afa53c8dSMike Smith /*
217afa53c8dSMike Smith * Wait for something to become available.
218afa53c8dSMike Smith */
219afa53c8dSMike Smith FD_ZERO(&ifds);
220afa53c8dSMike Smith FD_SET(0, &ifds);
221afa53c8dSMike Smith status = select(1, &ifds, NULL, NULL, &tv);
222afa53c8dSMike Smith /*
223afa53c8dSMike Smith * If there's nothing ready, return an error.
224afa53c8dSMike Smith */
225c4539460SJilles Tjoelker if (status <= 0) {
226e31fb971SBryan Drewery while (*ap != NULL)
227e31fb971SBryan Drewery setvar(*ap++, "", 0);
228c4539460SJilles Tjoelker sig = pendingsig;
229c4539460SJilles Tjoelker return (128 + (sig != 0 ? sig : SIGALRM));
230c4539460SJilles Tjoelker }
231afa53c8dSMike Smith }
232afa53c8dSMike Smith
2334b88c807SRodney W. Grimes status = 0;
234b6748ec2SStefan Farfeleder startword = 2;
2354b88c807SRodney W. Grimes backslash = 0;
2364b88c807SRodney W. Grimes STARTSTACKSTR(p);
237f0688a48SJilles Tjoelker lastnonifs = lastnonifsws = -1;
238be860ca2SHiroki Sato fdctx_init(STDIN_FILENO, &fdctx);
2394b88c807SRodney W. Grimes for (;;) {
2404d0b267aSAdrian Chadd c = 0;
241be860ca2SHiroki Sato nread = fdgetc(&fdctx, &c);
242c4539460SJilles Tjoelker if (nread == -1) {
243c4539460SJilles Tjoelker if (errno == EINTR) {
244c4539460SJilles Tjoelker sig = pendingsig;
245c4539460SJilles Tjoelker if (sig == 0)
246c4539460SJilles Tjoelker continue;
247c4539460SJilles Tjoelker status = 128 + sig;
248c4539460SJilles Tjoelker break;
249c4539460SJilles Tjoelker }
250c4539460SJilles Tjoelker warning("read error: %s", strerror(errno));
251c4539460SJilles Tjoelker status = 2;
252c4539460SJilles Tjoelker break;
253c4539460SJilles Tjoelker } else if (nread != 1) {
2544b88c807SRodney W. Grimes status = 1;
2554b88c807SRodney W. Grimes break;
2564b88c807SRodney W. Grimes }
2574b88c807SRodney W. Grimes if (c == '\0')
2584b88c807SRodney W. Grimes continue;
2599d37e157SJilles Tjoelker CHECKSTRSPACE(1, p);
2604b88c807SRodney W. Grimes if (backslash) {
2614b88c807SRodney W. Grimes backslash = 0;
2624b6578dcSJilles Tjoelker if (c != '\n') {
263917fdfb1SJilles Tjoelker startword = 0;
264f0688a48SJilles Tjoelker lastnonifs = lastnonifsws = p - stackblock();
2659d37e157SJilles Tjoelker USTPUTC(c, p);
2664b6578dcSJilles Tjoelker }
2674b88c807SRodney W. Grimes continue;
2684b88c807SRodney W. Grimes }
2698f0561ccSThomas Gellekum if (!rflag && c == '\\') {
2704b88c807SRodney W. Grimes backslash++;
2714b88c807SRodney W. Grimes continue;
2724b88c807SRodney W. Grimes }
2734b88c807SRodney W. Grimes if (c == '\n')
2744b88c807SRodney W. Grimes break;
275b6748ec2SStefan Farfeleder if (strchr(ifs, c))
276b6748ec2SStefan Farfeleder is_ifs = strchr(" \t\n", c) ? 1 : 2;
277b6748ec2SStefan Farfeleder else
278b6748ec2SStefan Farfeleder is_ifs = 0;
279b6748ec2SStefan Farfeleder
280b6748ec2SStefan Farfeleder if (startword != 0) {
281b6748ec2SStefan Farfeleder if (is_ifs == 1) {
282b6748ec2SStefan Farfeleder /* Ignore leading IFS whitespace */
283b6748ec2SStefan Farfeleder if (saveall)
2849d37e157SJilles Tjoelker USTPUTC(c, p);
2854b88c807SRodney W. Grimes continue;
2864b88c807SRodney W. Grimes }
287b6748ec2SStefan Farfeleder if (is_ifs == 2 && startword == 1) {
288b6748ec2SStefan Farfeleder /* Only one non-whitespace IFS per word */
289b6748ec2SStefan Farfeleder startword = 2;
290f0688a48SJilles Tjoelker if (saveall) {
291f0688a48SJilles Tjoelker lastnonifsws = p - stackblock();
2929d37e157SJilles Tjoelker USTPUTC(c, p);
293f0688a48SJilles Tjoelker }
294b6748ec2SStefan Farfeleder continue;
295b6748ec2SStefan Farfeleder }
296b6748ec2SStefan Farfeleder }
297b6748ec2SStefan Farfeleder
298b6748ec2SStefan Farfeleder if (is_ifs == 0) {
299b6748ec2SStefan Farfeleder /* append this character to the current variable */
3004b88c807SRodney W. Grimes startword = 0;
301b6748ec2SStefan Farfeleder if (saveall)
302b6748ec2SStefan Farfeleder /* Not just a spare terminator */
303b6748ec2SStefan Farfeleder saveall++;
304f0688a48SJilles Tjoelker lastnonifs = lastnonifsws = p - stackblock();
3059d37e157SJilles Tjoelker USTPUTC(c, p);
306b6748ec2SStefan Farfeleder continue;
307b6748ec2SStefan Farfeleder }
308b6748ec2SStefan Farfeleder
309b6748ec2SStefan Farfeleder /* end of variable... */
310b6748ec2SStefan Farfeleder startword = is_ifs;
311b6748ec2SStefan Farfeleder
312b6748ec2SStefan Farfeleder if (ap[1] == NULL) {
313b6748ec2SStefan Farfeleder /* Last variable needs all IFS chars */
314b6748ec2SStefan Farfeleder saveall++;
315f0688a48SJilles Tjoelker if (is_ifs == 2)
316f0688a48SJilles Tjoelker lastnonifsws = p - stackblock();
3179d37e157SJilles Tjoelker USTPUTC(c, p);
318b6748ec2SStefan Farfeleder continue;
319b6748ec2SStefan Farfeleder }
320b6748ec2SStefan Farfeleder
3214b88c807SRodney W. Grimes STACKSTRNUL(p);
3224b88c807SRodney W. Grimes setvar(*ap, stackblock(), 0);
3234b88c807SRodney W. Grimes ap++;
3244b88c807SRodney W. Grimes STARTSTACKSTR(p);
325f0688a48SJilles Tjoelker lastnonifs = lastnonifsws = -1;
3264b88c807SRodney W. Grimes }
327be860ca2SHiroki Sato fdctx_destroy(&fdctx);
3284b88c807SRodney W. Grimes STACKSTRNUL(p);
329b6748ec2SStefan Farfeleder
330f0688a48SJilles Tjoelker /*
331f0688a48SJilles Tjoelker * Remove trailing IFS chars: always remove whitespace, don't remove
332f0688a48SJilles Tjoelker * non-whitespace unless it was naked
333f0688a48SJilles Tjoelker */
334f0688a48SJilles Tjoelker if (saveall <= 1)
335f0688a48SJilles Tjoelker lastnonifsws = lastnonifs;
336f0688a48SJilles Tjoelker stackblock()[lastnonifsws + 1] = '\0';
3374b88c807SRodney W. Grimes setvar(*ap, stackblock(), 0);
338b6748ec2SStefan Farfeleder
339b6748ec2SStefan Farfeleder /* Set any remaining args to "" */
3404b88c807SRodney W. Grimes while (*++ap != NULL)
341781bfb5aSJilles Tjoelker setvar(*ap, "", 0);
3424b88c807SRodney W. Grimes return status;
3434b88c807SRodney W. Grimes }
3444b88c807SRodney W. Grimes
3454b88c807SRodney W. Grimes
3464b88c807SRodney W. Grimes
347aa9caaf6SPeter Wemm int
umaskcmd(int argc __unused,char ** argv __unused)348384aedabSJilles Tjoelker umaskcmd(int argc __unused, char **argv __unused)
349aa9caaf6SPeter Wemm {
350aa9caaf6SPeter Wemm char *ap;
3514b88c807SRodney W. Grimes int mask;
3524b88c807SRodney W. Grimes int i;
353aa9caaf6SPeter Wemm int symbolic_mode = 0;
3544b88c807SRodney W. Grimes
355aa9caaf6SPeter Wemm while ((i = nextopt("S")) != '\0') {
356aa9caaf6SPeter Wemm symbolic_mode = 1;
357aa9caaf6SPeter Wemm }
358aa9caaf6SPeter Wemm
3594b88c807SRodney W. Grimes INTOFF;
3604b88c807SRodney W. Grimes mask = umask(0);
3614b88c807SRodney W. Grimes umask(mask);
3624b88c807SRodney W. Grimes INTON;
363aa9caaf6SPeter Wemm
364aa9caaf6SPeter Wemm if ((ap = *argptr) == NULL) {
365aa9caaf6SPeter Wemm if (symbolic_mode) {
366aa9caaf6SPeter Wemm char u[4], g[4], o[4];
367aa9caaf6SPeter Wemm
368aa9caaf6SPeter Wemm i = 0;
369aa9caaf6SPeter Wemm if ((mask & S_IRUSR) == 0)
370aa9caaf6SPeter Wemm u[i++] = 'r';
371aa9caaf6SPeter Wemm if ((mask & S_IWUSR) == 0)
372aa9caaf6SPeter Wemm u[i++] = 'w';
373aa9caaf6SPeter Wemm if ((mask & S_IXUSR) == 0)
374aa9caaf6SPeter Wemm u[i++] = 'x';
375aa9caaf6SPeter Wemm u[i] = '\0';
376aa9caaf6SPeter Wemm
377aa9caaf6SPeter Wemm i = 0;
378aa9caaf6SPeter Wemm if ((mask & S_IRGRP) == 0)
379aa9caaf6SPeter Wemm g[i++] = 'r';
380aa9caaf6SPeter Wemm if ((mask & S_IWGRP) == 0)
381aa9caaf6SPeter Wemm g[i++] = 'w';
382aa9caaf6SPeter Wemm if ((mask & S_IXGRP) == 0)
383aa9caaf6SPeter Wemm g[i++] = 'x';
384aa9caaf6SPeter Wemm g[i] = '\0';
385aa9caaf6SPeter Wemm
386aa9caaf6SPeter Wemm i = 0;
387aa9caaf6SPeter Wemm if ((mask & S_IROTH) == 0)
388aa9caaf6SPeter Wemm o[i++] = 'r';
389aa9caaf6SPeter Wemm if ((mask & S_IWOTH) == 0)
390aa9caaf6SPeter Wemm o[i++] = 'w';
391aa9caaf6SPeter Wemm if ((mask & S_IXOTH) == 0)
392aa9caaf6SPeter Wemm o[i++] = 'x';
393aa9caaf6SPeter Wemm o[i] = '\0';
394aa9caaf6SPeter Wemm
395aa9caaf6SPeter Wemm out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
3964b88c807SRodney W. Grimes } else {
397aa9caaf6SPeter Wemm out1fmt("%.4o\n", mask);
398aa9caaf6SPeter Wemm }
399aa9caaf6SPeter Wemm } else {
40058570ac4SJilles Tjoelker if (is_digit(*ap)) {
4014b88c807SRodney W. Grimes mask = 0;
4024b88c807SRodney W. Grimes do {
403aa9caaf6SPeter Wemm if (*ap >= '8' || *ap < '0')
404e4c880afSStefan Farfeleder error("Illegal number: %s", *argptr);
405aa9caaf6SPeter Wemm mask = (mask << 3) + (*ap - '0');
406aa9caaf6SPeter Wemm } while (*++ap != '\0');
4074b88c807SRodney W. Grimes umask(mask);
408aa9caaf6SPeter Wemm } else {
409aa9caaf6SPeter Wemm void *set;
410670528cdSStefan Farfeleder INTOFF;
41174136dc3SPedro F. Giffuni if ((set = setmode (ap)) == NULL)
412aa9caaf6SPeter Wemm error("Illegal number: %s", ap);
413aa9caaf6SPeter Wemm
414aa9caaf6SPeter Wemm mask = getmode (set, ~mask & 0777);
415aa9caaf6SPeter Wemm umask(~mask & 0777);
416a207266eSWarner Losh free(set);
417670528cdSStefan Farfeleder INTON;
418aa9caaf6SPeter Wemm }
4194b88c807SRodney W. Grimes }
4204b88c807SRodney W. Grimes return 0;
4214b88c807SRodney W. Grimes }
4227a2afe64SJoerg Wunsch
423aa9caaf6SPeter Wemm /*
424aa9caaf6SPeter Wemm * ulimit builtin
425aa9caaf6SPeter Wemm *
426aa9caaf6SPeter Wemm * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
427aa9caaf6SPeter Wemm * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
428aa9caaf6SPeter Wemm * ash by J.T. Conklin.
429aa9caaf6SPeter Wemm *
430aa9caaf6SPeter Wemm * Public domain.
431aa9caaf6SPeter Wemm */
4327a2afe64SJoerg Wunsch
433aa9caaf6SPeter Wemm struct limits {
434aa9caaf6SPeter Wemm const char *name;
43516992ff4SPeter Wemm const char *units;
436aa9caaf6SPeter Wemm int cmd;
437a9250603SJilles Tjoelker short factor; /* multiply by to get rlim_{cur,max} values */
438aa9caaf6SPeter Wemm char option;
4397a2afe64SJoerg Wunsch };
4407a2afe64SJoerg Wunsch
441aa9caaf6SPeter Wemm static const struct limits limits[] = {
442aa9caaf6SPeter Wemm #ifdef RLIMIT_CPU
44316992ff4SPeter Wemm { "cpu time", "seconds", RLIMIT_CPU, 1, 't' },
444aa9caaf6SPeter Wemm #endif
445aa9caaf6SPeter Wemm #ifdef RLIMIT_FSIZE
44616992ff4SPeter Wemm { "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' },
447aa9caaf6SPeter Wemm #endif
448aa9caaf6SPeter Wemm #ifdef RLIMIT_DATA
44916992ff4SPeter Wemm { "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' },
450aa9caaf6SPeter Wemm #endif
451aa9caaf6SPeter Wemm #ifdef RLIMIT_STACK
45216992ff4SPeter Wemm { "stack size", "kbytes", RLIMIT_STACK, 1024, 's' },
453aa9caaf6SPeter Wemm #endif
454aa9caaf6SPeter Wemm #ifdef RLIMIT_CORE
45516992ff4SPeter Wemm { "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' },
456aa9caaf6SPeter Wemm #endif
457aa9caaf6SPeter Wemm #ifdef RLIMIT_RSS
45816992ff4SPeter Wemm { "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' },
459aa9caaf6SPeter Wemm #endif
460aa9caaf6SPeter Wemm #ifdef RLIMIT_MEMLOCK
46116992ff4SPeter Wemm { "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' },
462aa9caaf6SPeter Wemm #endif
463aa9caaf6SPeter Wemm #ifdef RLIMIT_NPROC
46416992ff4SPeter Wemm { "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' },
465aa9caaf6SPeter Wemm #endif
466aa9caaf6SPeter Wemm #ifdef RLIMIT_NOFILE
46716992ff4SPeter Wemm { "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' },
468aa9caaf6SPeter Wemm #endif
469aa9caaf6SPeter Wemm #ifdef RLIMIT_VMEM
47016992ff4SPeter Wemm { "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' },
471aa9caaf6SPeter Wemm #endif
472aa9caaf6SPeter Wemm #ifdef RLIMIT_SWAP
47316992ff4SPeter Wemm { "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' },
474aa9caaf6SPeter Wemm #endif
4757cde774dSBrian Feldman #ifdef RLIMIT_SBSIZE
476535c8d93SJilles Tjoelker { "socket buffer size", "bytes", RLIMIT_SBSIZE, 1, 'b' },
4777cde774dSBrian Feldman #endif
478bc093719SEd Schouten #ifdef RLIMIT_NPTS
479bc093719SEd Schouten { "pseudo-terminals", (char *)0, RLIMIT_NPTS, 1, 'p' },
480bc093719SEd Schouten #endif
48185a0ddfdSKonstantin Belousov #ifdef RLIMIT_KQUEUES
48285a0ddfdSKonstantin Belousov { "kqueues", (char *)0, RLIMIT_KQUEUES, 1, 'k' },
48385a0ddfdSKonstantin Belousov #endif
4841bdbd705SKonstantin Belousov #ifdef RLIMIT_UMTXP
485535c8d93SJilles Tjoelker { "umtx shared locks", (char *)0, RLIMIT_UMTXP, 1, 'o' },
4861bdbd705SKonstantin Belousov #endif
487*5d92f20cSKonstantin Belousov #ifdef RLIMIT_PIPEBUF
488*5d92f20cSKonstantin Belousov { "pipebuf", (char *)0, RLIMIT_PIPEBUF, 1024, 'y' },
489*5d92f20cSKonstantin Belousov #endif
49016992ff4SPeter Wemm { (char *) 0, (char *)0, 0, 0, '\0' }
4917a2afe64SJoerg Wunsch };
4927a2afe64SJoerg Wunsch
4932ef146f1SJilles Tjoelker enum limithow { SOFT = 0x1, HARD = 0x2 };
4942ef146f1SJilles Tjoelker
4952ef146f1SJilles Tjoelker static void
printlimit(enum limithow how,const struct rlimit * limit,const struct limits * l)4962ef146f1SJilles Tjoelker printlimit(enum limithow how, const struct rlimit *limit,
4972ef146f1SJilles Tjoelker const struct limits *l)
4982ef146f1SJilles Tjoelker {
4992ef146f1SJilles Tjoelker rlim_t val = 0;
5002ef146f1SJilles Tjoelker
5012ef146f1SJilles Tjoelker if (how & SOFT)
5022ef146f1SJilles Tjoelker val = limit->rlim_cur;
5032ef146f1SJilles Tjoelker else if (how & HARD)
5042ef146f1SJilles Tjoelker val = limit->rlim_max;
5052ef146f1SJilles Tjoelker if (val == RLIM_INFINITY)
5062ef146f1SJilles Tjoelker out1str("unlimited\n");
5072ef146f1SJilles Tjoelker else
5082ef146f1SJilles Tjoelker {
5092ef146f1SJilles Tjoelker val /= l->factor;
5102ef146f1SJilles Tjoelker out1fmt("%jd\n", (intmax_t)val);
5112ef146f1SJilles Tjoelker }
5122ef146f1SJilles Tjoelker }
5132ef146f1SJilles Tjoelker
514aa9caaf6SPeter Wemm int
ulimitcmd(int argc __unused,char ** argv __unused)5155134c3f7SWarner Losh ulimitcmd(int argc __unused, char **argv __unused)
516aa9caaf6SPeter Wemm {
5170c1661b7SMaxime Henrion rlim_t val = 0;
5182ef146f1SJilles Tjoelker enum limithow how = SOFT | HARD;
519aa9caaf6SPeter Wemm const struct limits *l;
520aa9caaf6SPeter Wemm int set, all = 0;
521aa9caaf6SPeter Wemm int optc, what;
522aa9caaf6SPeter Wemm struct rlimit limit;
5237a2afe64SJoerg Wunsch
524aa9caaf6SPeter Wemm what = 'f';
525*5d92f20cSKonstantin Belousov while ((optc = nextopt("HSatfdsmcnuvlbpwkoy")) != '\0')
526aa9caaf6SPeter Wemm switch (optc) {
5277a2afe64SJoerg Wunsch case 'H':
528aa9caaf6SPeter Wemm how = HARD;
5297a2afe64SJoerg Wunsch break;
5307a2afe64SJoerg Wunsch case 'S':
531aa9caaf6SPeter Wemm how = SOFT;
5327a2afe64SJoerg Wunsch break;
5337a2afe64SJoerg Wunsch case 'a':
534aa9caaf6SPeter Wemm all = 1;
5357a2afe64SJoerg Wunsch break;
536aa9caaf6SPeter Wemm default:
537aa9caaf6SPeter Wemm what = optc;
5387a2afe64SJoerg Wunsch }
5397a2afe64SJoerg Wunsch
540aa9caaf6SPeter Wemm for (l = limits; l->name && l->option != what; l++)
541aa9caaf6SPeter Wemm ;
542aa9caaf6SPeter Wemm if (!l->name)
543abe2dc61STim J. Robbins error("internal error (%c)", what);
5447a2afe64SJoerg Wunsch
545aa9caaf6SPeter Wemm set = *argptr ? 1 : 0;
546aa9caaf6SPeter Wemm if (set) {
547aa9caaf6SPeter Wemm char *p = *argptr;
548aa9caaf6SPeter Wemm
549aa9caaf6SPeter Wemm if (all || argptr[1])
550abe2dc61STim J. Robbins error("too many arguments");
551aa9caaf6SPeter Wemm if (strcmp(p, "unlimited") == 0)
5527a2afe64SJoerg Wunsch val = RLIM_INFINITY;
5537a2afe64SJoerg Wunsch else {
5542d70c637SJilles Tjoelker char *end;
5552d70c637SJilles Tjoelker uintmax_t uval;
556aa9caaf6SPeter Wemm
5572d70c637SJilles Tjoelker if (*p < '0' || *p > '9')
558abe2dc61STim J. Robbins error("bad number");
5592d70c637SJilles Tjoelker errno = 0;
5602d70c637SJilles Tjoelker uval = strtoumax(p, &end, 10);
5612d70c637SJilles Tjoelker if (errno != 0 || *end != '\0')
5622d70c637SJilles Tjoelker error("bad number");
5632d70c637SJilles Tjoelker if (uval > UINTMAX_MAX / l->factor)
5642d70c637SJilles Tjoelker error("bad number");
5652d70c637SJilles Tjoelker uval *= l->factor;
5662d70c637SJilles Tjoelker val = (rlim_t)uval;
5672d70c637SJilles Tjoelker if (val < 0 || (uintmax_t)val != uval ||
5682d70c637SJilles Tjoelker val == RLIM_INFINITY)
5692d70c637SJilles Tjoelker error("bad number");
570aa9caaf6SPeter Wemm }
571aa9caaf6SPeter Wemm }
572aa9caaf6SPeter Wemm if (all) {
573aa9caaf6SPeter Wemm for (l = limits; l->name; l++) {
57416992ff4SPeter Wemm char optbuf[40];
57516992ff4SPeter Wemm if (getrlimit(l->cmd, &limit) < 0)
576abe2dc61STim J. Robbins error("can't get limit: %s", strerror(errno));
577aa9caaf6SPeter Wemm
57816992ff4SPeter Wemm if (l->units)
57916992ff4SPeter Wemm snprintf(optbuf, sizeof(optbuf),
5804e4e0959SPeter Wemm "(%s, -%c) ", l->units, l->option);
58116992ff4SPeter Wemm else
58216992ff4SPeter Wemm snprintf(optbuf, sizeof(optbuf),
5834e4e0959SPeter Wemm "(-%c) ", l->option);
5844e4e0959SPeter Wemm out1fmt("%-18s %18s ", l->name, optbuf);
5852ef146f1SJilles Tjoelker printlimit(how, &limit, l);
5867a2afe64SJoerg Wunsch }
5877a2afe64SJoerg Wunsch return 0;
5887a2afe64SJoerg Wunsch }
589aa9caaf6SPeter Wemm
59016992ff4SPeter Wemm if (getrlimit(l->cmd, &limit) < 0)
591abe2dc61STim J. Robbins error("can't get limit: %s", strerror(errno));
592aa9caaf6SPeter Wemm if (set) {
593aa9caaf6SPeter Wemm if (how & SOFT)
594aa9caaf6SPeter Wemm limit.rlim_cur = val;
595aa9caaf6SPeter Wemm if (how & HARD)
596aa9caaf6SPeter Wemm limit.rlim_max = val;
597aa9caaf6SPeter Wemm if (setrlimit(l->cmd, &limit) < 0)
598abe2dc61STim J. Robbins error("bad limit: %s", strerror(errno));
5992ef146f1SJilles Tjoelker } else
6002ef146f1SJilles Tjoelker printlimit(how, &limit, l);
601aa9caaf6SPeter Wemm return 0;
602aa9caaf6SPeter Wemm }
603