1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * %sccs.include.redist.c%
9 */
10
11 #ifndef lint
12 static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 05/04/95";
13 #endif /* not lint */
14
15 /*
16 * Miscelaneous builtins.
17 */
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <sys/resource.h>
23 #include <unistd.h>
24 #include <ctype.h>
25
26 #include "shell.h"
27 #include "options.h"
28 #include "var.h"
29 #include "output.h"
30 #include "memalloc.h"
31 #include "error.h"
32 #include "mystring.h"
33
34 #undef eflag
35
36 extern char **argptr; /* argument list for builtin command */
37
38
39 /*
40 * The read builtin. The -e option causes backslashes to escape the
41 * following character.
42 *
43 * This uses unbuffered input, which may be avoidable in some cases.
44 */
45
46 int
readcmd(argc,argv)47 readcmd(argc, argv)
48 int argc;
49 char **argv;
50 {
51 char **ap;
52 int backslash;
53 char c;
54 int eflag;
55 char *prompt;
56 char *ifs;
57 char *p;
58 int startword;
59 int status;
60 int i;
61
62 eflag = 0;
63 prompt = NULL;
64 while ((i = nextopt("ep:")) != '\0') {
65 if (i == 'p')
66 prompt = optarg;
67 else
68 eflag = 1;
69 }
70 if (prompt && isatty(0)) {
71 out2str(prompt);
72 flushall();
73 }
74 if (*(ap = argptr) == NULL)
75 error("arg count");
76 if ((ifs = bltinlookup("IFS", 1)) == NULL)
77 ifs = nullstr;
78 status = 0;
79 startword = 1;
80 backslash = 0;
81 STARTSTACKSTR(p);
82 for (;;) {
83 if (read(0, &c, 1) != 1) {
84 status = 1;
85 break;
86 }
87 if (c == '\0')
88 continue;
89 if (backslash) {
90 backslash = 0;
91 if (c != '\n')
92 STPUTC(c, p);
93 continue;
94 }
95 if (eflag && c == '\\') {
96 backslash++;
97 continue;
98 }
99 if (c == '\n')
100 break;
101 if (startword && *ifs == ' ' && strchr(ifs, c)) {
102 continue;
103 }
104 startword = 0;
105 if (backslash && c == '\\') {
106 if (read(0, &c, 1) != 1) {
107 status = 1;
108 break;
109 }
110 STPUTC(c, p);
111 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
112 STACKSTRNUL(p);
113 setvar(*ap, stackblock(), 0);
114 ap++;
115 startword = 1;
116 STARTSTACKSTR(p);
117 } else {
118 STPUTC(c, p);
119 }
120 }
121 STACKSTRNUL(p);
122 setvar(*ap, stackblock(), 0);
123 while (*++ap != NULL)
124 setvar(*ap, nullstr, 0);
125 return status;
126 }
127
128
129
130 int
umaskcmd(argc,argv)131 umaskcmd(argc, argv)
132 int argc;
133 char **argv;
134 {
135 char *ap;
136 int mask;
137 int i;
138 int symbolic_mode = 0;
139
140 while ((i = nextopt("S")) != '\0') {
141 symbolic_mode = 1;
142 }
143
144 INTOFF;
145 mask = umask(0);
146 umask(mask);
147 INTON;
148
149 if ((ap = *argptr) == NULL) {
150 if (symbolic_mode) {
151 char u[4], g[4], o[4];
152
153 i = 0;
154 if ((mask & S_IRUSR) == 0)
155 u[i++] = 'r';
156 if ((mask & S_IWUSR) == 0)
157 u[i++] = 'w';
158 if ((mask & S_IXUSR) == 0)
159 u[i++] = 'x';
160 u[i] = '\0';
161
162 i = 0;
163 if ((mask & S_IRGRP) == 0)
164 g[i++] = 'r';
165 if ((mask & S_IWGRP) == 0)
166 g[i++] = 'w';
167 if ((mask & S_IXGRP) == 0)
168 g[i++] = 'x';
169 g[i] = '\0';
170
171 i = 0;
172 if ((mask & S_IROTH) == 0)
173 o[i++] = 'r';
174 if ((mask & S_IWOTH) == 0)
175 o[i++] = 'w';
176 if ((mask & S_IXOTH) == 0)
177 o[i++] = 'x';
178 o[i] = '\0';
179
180 out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
181 } else {
182 out1fmt("%.4o\n", mask);
183 }
184 } else {
185 if (isdigit(*ap)) {
186 mask = 0;
187 do {
188 if (*ap >= '8' || *ap < '0')
189 error("Illegal number: %s", argv[1]);
190 mask = (mask << 3) + (*ap - '0');
191 } while (*++ap != '\0');
192 umask(mask);
193 } else {
194 void *set;
195 if ((set = setmode (ap)) == 0)
196 error("Illegal number: %s", ap);
197
198 mask = getmode (set, ~mask & 0777);
199 umask(~mask & 0777);
200 }
201 }
202 return 0;
203 }
204
205 /*
206 * ulimit builtin
207 *
208 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
209 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
210 * ash by J.T. Conklin.
211 *
212 * Public domain.
213 */
214
215 struct limits {
216 const char *name;
217 int cmd;
218 int factor; /* multiply by to get rlim_{cur,max} values */
219 char option;
220 };
221
222 static const struct limits limits[] = {
223 #ifdef RLIMIT_CPU
224 { "time(seconds)", RLIMIT_CPU, 1, 't' },
225 #endif
226 #ifdef RLIMIT_FSIZE
227 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
228 #endif
229 #ifdef RLIMIT_DATA
230 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
231 #endif
232 #ifdef RLIMIT_STACK
233 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
234 #endif
235 #ifdef RLIMIT_CORE
236 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
237 #endif
238 #ifdef RLIMIT_RSS
239 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
240 #endif
241 #ifdef RLIMIT_MEMLOCK
242 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
243 #endif
244 #ifdef RLIMIT_NPROC
245 { "process(processes)", RLIMIT_NPROC, 1, 'p' },
246 #endif
247 #ifdef RLIMIT_NOFILE
248 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
249 #endif
250 #ifdef RLIMIT_VMEM
251 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
252 #endif
253 #ifdef RLIMIT_SWAP
254 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
255 #endif
256 { (char *) 0, 0, 0, '\0' }
257 };
258
259 int
ulimitcmd(argc,argv)260 ulimitcmd(argc, argv)
261 int argc;
262 char **argv;
263 {
264 register int c;
265 quad_t val;
266 enum { SOFT = 0x1, HARD = 0x2 }
267 how = SOFT | HARD;
268 const struct limits *l;
269 int set, all = 0;
270 int optc, what;
271 struct rlimit limit;
272
273 what = 'f';
274 while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
275 switch (optc) {
276 case 'H':
277 how = HARD;
278 break;
279 case 'S':
280 how = SOFT;
281 break;
282 case 'a':
283 all = 1;
284 break;
285 default:
286 what = optc;
287 }
288
289 for (l = limits; l->name && l->option != what; l++)
290 ;
291 if (!l->name)
292 error("ulimit: internal error (%c)\n", what);
293
294 set = *argptr ? 1 : 0;
295 if (set) {
296 char *p = *argptr;
297
298 if (all || argptr[1])
299 error("ulimit: too many arguments\n");
300 if (strcmp(p, "unlimited") == 0)
301 val = RLIM_INFINITY;
302 else {
303 val = (quad_t) 0;
304
305 while ((c = *p++) >= '0' && c <= '9')
306 {
307 val = (val * 10) + (long)(c - '0');
308 if (val < (quad_t) 0)
309 break;
310 }
311 if (c)
312 error("ulimit: bad number\n");
313 val *= l->factor;
314 }
315 }
316 if (all) {
317 for (l = limits; l->name; l++) {
318 getrlimit(l->cmd, &limit);
319 if (how & SOFT)
320 val = limit.rlim_cur;
321 else if (how & HARD)
322 val = limit.rlim_max;
323
324 out1fmt("%-20s ", l->name);
325 if (val == RLIM_INFINITY)
326 out1fmt("unlimited\n");
327 else
328 {
329 val /= l->factor;
330 out1fmt("%ld\n", (long) val);
331 }
332 }
333 return 0;
334 }
335
336 getrlimit(l->cmd, &limit);
337 if (set) {
338 if (how & SOFT)
339 limit.rlim_cur = val;
340 if (how & HARD)
341 limit.rlim_max = val;
342 if (setrlimit(l->cmd, &limit) < 0)
343 error("ulimit: bad limit\n");
344 } else {
345 if (how & SOFT)
346 val = limit.rlim_cur;
347 else if (how & HARD)
348 val = limit.rlim_max;
349 }
350
351 if (!set) {
352 if (val == RLIM_INFINITY)
353 out1fmt("unlimited\n");
354 else
355 {
356 val /= l->factor;
357 out1fmt("%ld\n", (long) val);
358 }
359 }
360 return 0;
361 }
362