Commit | Line | Data |
---|---|---|
ecc449eb KB |
1 | /*- |
2 | * Copyright (c) 1980, 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
b79f4fa9 DF |
6 | */ |
7 | ||
35371dec | 8 | #ifndef lint |
ee397aec | 9 | static char sccsid[] = "@(#)func.c 5.27 (Berkeley) %G%"; |
a0996775 | 10 | #endif /* not lint */ |
d43c89f3 | 11 | |
b9c4f741 KB |
12 | #include <sys/types.h> |
13 | #include <sys/stat.h> | |
14 | #include <signal.h> | |
15 | #include <locale.h> | |
16 | #include <stdlib.h> | |
17 | #include <string.h> | |
18 | #include <unistd.h> | |
4df6491c CZ |
19 | #if __STDC__ |
20 | # include <stdarg.h> | |
21 | #else | |
22 | # include <varargs.h> | |
23 | #endif | |
24 | ||
4d7b2685 KB |
25 | #include "csh.h" |
26 | #include "extern.h" | |
b9c4f741 | 27 | #include "pathnames.h" |
d43c89f3 | 28 | |
6e37afca KB |
29 | extern char **environ; |
30 | ||
31 | static int zlast = -1; | |
0aec749d CZ |
32 | static void islogin __P((void)); |
33 | static void reexecute __P((struct command *)); | |
34 | static void preread __P((void)); | |
35 | static void doagain __P((void)); | |
36 | static int getword __P((Char *)); | |
37 | static int keyword __P((Char *)); | |
38 | static void Unsetenv __P((Char *)); | |
39 | static void toend __P((void)); | |
40 | static void xecho __P((int, Char **)); | |
d43c89f3 BJ |
41 | |
42 | struct biltins * | |
43 | isbfunc(t) | |
6e37afca | 44 | struct command *t; |
d43c89f3 | 45 | { |
6e37afca KB |
46 | register Char *cp = t->t_dcom[0]; |
47 | register struct biltins *bp, *bp1, *bp2; | |
48 | static struct biltins label = {"", dozip, 0, 0}; | |
49 | static struct biltins foregnd = {"%job", dofg1, 0, 0}; | |
50 | static struct biltins backgnd = {"%job &", dobg1, 0, 0}; | |
51 | ||
52 | if (lastchr(cp) == ':') { | |
53 | label.bname = short2str(cp); | |
54 | return (&label); | |
55 | } | |
56 | if (*cp == '%') { | |
57 | if (t->t_dflg & F_AMPERSAND) { | |
58 | t->t_dflg &= ~F_AMPERSAND; | |
59 | backgnd.bname = short2str(cp); | |
60 | return (&backgnd); | |
d43c89f3 | 61 | } |
6e37afca KB |
62 | foregnd.bname = short2str(cp); |
63 | return (&foregnd); | |
64 | } | |
65 | /* | |
66 | * Binary search Bp1 is the beginning of the current search range. Bp2 is | |
67 | * one past the end. | |
68 | */ | |
69 | for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { | |
70 | register i; | |
71 | ||
72 | bp = bp1 + ((bp2 - bp1) >> 1); | |
73 | if ((i = *cp - *bp->bname) == 0 && | |
74 | (i = Strcmp(cp, str2short(bp->bname))) == 0) | |
75 | return bp; | |
76 | if (i < 0) | |
77 | bp2 = bp; | |
78 | else | |
79 | bp1 = bp + 1; | |
80 | } | |
81 | return (0); | |
d43c89f3 BJ |
82 | } |
83 | ||
6e37afca | 84 | void |
d43c89f3 | 85 | func(t, bp) |
6e37afca KB |
86 | register struct command *t; |
87 | register struct biltins *bp; | |
d43c89f3 | 88 | { |
6e37afca KB |
89 | int i; |
90 | ||
91 | xechoit(t->t_dcom); | |
92 | setname(bp->bname); | |
93 | i = blklen(t->t_dcom) - 1; | |
94 | if (i < bp->minargs) | |
95 | stderror(ERR_NAME | ERR_TOOFEW); | |
96 | if (i > bp->maxargs) | |
97 | stderror(ERR_NAME | ERR_TOOMANY); | |
98 | (*bp->bfunct) (t->t_dcom, t); | |
d43c89f3 BJ |
99 | } |
100 | ||
6e37afca | 101 | void |
454c2aa3 CZ |
102 | /*ARGSUSED*/ |
103 | doonintr(v, t) | |
104 | Char **v; | |
105 | struct command *t; | |
d43c89f3 | 106 | { |
6e37afca KB |
107 | register Char *cp; |
108 | register Char *vv = v[1]; | |
109 | ||
110 | if (parintr == SIG_IGN) | |
111 | return; | |
112 | if (setintr && intty) | |
113 | stderror(ERR_NAME | ERR_TERMINAL); | |
114 | cp = gointr; | |
115 | gointr = 0; | |
116 | xfree((ptr_t) cp); | |
117 | if (vv == 0) { | |
118 | if (setintr) | |
119 | (void) sigblock(sigmask(SIGINT)); | |
120 | else | |
121 | (void) signal(SIGINT, SIG_DFL); | |
122 | gointr = 0; | |
123 | } | |
124 | else if (eq((vv = strip(vv)), STRminus)) { | |
125 | (void) signal(SIGINT, SIG_IGN); | |
126 | gointr = Strsave(STRminus); | |
127 | } | |
128 | else { | |
129 | gointr = Strsave(vv); | |
130 | (void) signal(SIGINT, pintr); | |
131 | } | |
d43c89f3 BJ |
132 | } |
133 | ||
6e37afca | 134 | void |
454c2aa3 CZ |
135 | /*ARGSUSED*/ |
136 | donohup(v, t) | |
137 | Char **v; | |
138 | struct command *t; | |
d43c89f3 | 139 | { |
6e37afca KB |
140 | if (intty) |
141 | stderror(ERR_NAME | ERR_TERMINAL); | |
142 | if (setintr == 0) { | |
143 | (void) signal(SIGHUP, SIG_IGN); | |
144 | } | |
d43c89f3 BJ |
145 | } |
146 | ||
6e37afca | 147 | void |
454c2aa3 CZ |
148 | /*ARGSUSED*/ |
149 | dozip(v, t) | |
150 | Char **v; | |
151 | struct command *t; | |
d43c89f3 | 152 | { |
6e37afca | 153 | ; |
d43c89f3 BJ |
154 | } |
155 | ||
6e37afca | 156 | void |
d43c89f3 BJ |
157 | prvars() |
158 | { | |
6e37afca | 159 | plist(&shvhed); |
d43c89f3 BJ |
160 | } |
161 | ||
6e37afca | 162 | void |
454c2aa3 CZ |
163 | /*ARGSUSED*/ |
164 | doalias(v, t) | |
165 | Char **v; | |
166 | struct command *t; | |
d43c89f3 | 167 | { |
6e37afca KB |
168 | register struct varent *vp; |
169 | register Char *p; | |
170 | ||
171 | v++; | |
172 | p = *v++; | |
173 | if (p == 0) | |
174 | plist(&aliases); | |
175 | else if (*v == 0) { | |
176 | vp = adrof1(strip(p), &aliases); | |
454c2aa3 CZ |
177 | if (vp) { |
178 | blkpr(cshout, vp->vec); | |
179 | fputc('\n', cshout); | |
180 | } | |
6e37afca KB |
181 | } |
182 | else { | |
183 | if (eq(p, STRalias) || eq(p, STRunalias)) { | |
184 | setname(short2str(p)); | |
185 | stderror(ERR_NAME | ERR_DANGER); | |
d43c89f3 | 186 | } |
6e37afca KB |
187 | set1(strip(p), saveblk(v), &aliases); |
188 | } | |
d43c89f3 BJ |
189 | } |
190 | ||
6e37afca | 191 | void |
454c2aa3 CZ |
192 | /*ARGSUSED*/ |
193 | unalias(v, t) | |
194 | Char **v; | |
195 | struct command *t; | |
d43c89f3 | 196 | { |
6e37afca | 197 | unset1(v, &aliases); |
d43c89f3 BJ |
198 | } |
199 | ||
6e37afca | 200 | void |
454c2aa3 CZ |
201 | /*ARGSUSED*/ |
202 | dologout(v, t) | |
203 | Char **v; | |
204 | struct command *t; | |
d43c89f3 | 205 | { |
6e37afca KB |
206 | islogin(); |
207 | goodbye(); | |
d43c89f3 BJ |
208 | } |
209 | ||
6e37afca | 210 | void |
454c2aa3 CZ |
211 | /*ARGSUSED*/ |
212 | dologin(v, t) | |
213 | Char **v; | |
214 | struct command *t; | |
d43c89f3 | 215 | { |
6e37afca KB |
216 | islogin(); |
217 | rechist(); | |
218 | (void) signal(SIGTERM, parterm); | |
0aec749d | 219 | (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL); |
6e37afca KB |
220 | untty(); |
221 | xexit(1); | |
d43c89f3 BJ |
222 | } |
223 | ||
6e37afca | 224 | static void |
d43c89f3 BJ |
225 | islogin() |
226 | { | |
6e37afca KB |
227 | if (chkstop == 0 && setintr) |
228 | panystop(0); | |
229 | if (loginsh) | |
230 | return; | |
231 | stderror(ERR_NOTLOGIN); | |
d43c89f3 BJ |
232 | } |
233 | ||
6e37afca | 234 | void |
d43c89f3 | 235 | doif(v, kp) |
6e37afca KB |
236 | Char **v; |
237 | struct command *kp; | |
d43c89f3 | 238 | { |
6e37afca KB |
239 | register int i; |
240 | register Char **vv; | |
241 | ||
242 | v++; | |
c96f7f99 | 243 | i = expr(&v); |
6e37afca KB |
244 | vv = v; |
245 | if (*vv == NULL) | |
246 | stderror(ERR_NAME | ERR_EMPTYIF); | |
247 | if (eq(*vv, STRthen)) { | |
248 | if (*++vv) | |
249 | stderror(ERR_NAME | ERR_IMPRTHEN); | |
250 | setname(short2str(STRthen)); | |
d43c89f3 | 251 | /* |
6e37afca KB |
252 | * If expression was zero, then scan to else, otherwise just fall into |
253 | * following code. | |
d43c89f3 | 254 | */ |
6e37afca | 255 | if (!i) |
0aec749d | 256 | search(T_IF, 0, NULL); |
6e37afca KB |
257 | return; |
258 | } | |
259 | /* | |
260 | * Simple command attached to this if. Left shift the node in this tree, | |
261 | * munging it so we can reexecute it. | |
262 | */ | |
263 | if (i) { | |
264 | lshift(kp->t_dcom, vv - kp->t_dcom); | |
265 | reexecute(kp); | |
266 | donefds(); | |
267 | } | |
d43c89f3 BJ |
268 | } |
269 | ||
270 | /* | |
271 | * Reexecute a command, being careful not | |
272 | * to redo i/o redirection, which is already set up. | |
273 | */ | |
6e37afca | 274 | static void |
d43c89f3 | 275 | reexecute(kp) |
6e37afca | 276 | register struct command *kp; |
d43c89f3 | 277 | { |
6e37afca KB |
278 | kp->t_dflg &= F_SAVE; |
279 | kp->t_dflg |= F_REPEAT; | |
280 | /* | |
281 | * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set | |
282 | * pgrp's as the jobs would then have no way to get the tty (we can't give | |
283 | * it to them, and our parent wouldn't know their pgrp, etc. | |
284 | */ | |
4d7b2685 | 285 | execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL); |
d43c89f3 BJ |
286 | } |
287 | ||
6e37afca | 288 | void |
454c2aa3 CZ |
289 | /*ARGSUSED*/ |
290 | doelse(v, t) | |
291 | Char **v; | |
292 | struct command *t; | |
d43c89f3 | 293 | { |
0aec749d | 294 | search(T_ELSE, 0, NULL); |
d43c89f3 BJ |
295 | } |
296 | ||
6e37afca | 297 | void |
454c2aa3 CZ |
298 | /*ARGSUSED*/ |
299 | dogoto(v, t) | |
300 | Char **v; | |
301 | struct command *t; | |
d43c89f3 | 302 | { |
6e37afca KB |
303 | register struct whyle *wp; |
304 | Char *lp; | |
305 | ||
306 | /* | |
307 | * While we still can, locate any unknown ends of existing loops. This | |
308 | * obscure code is the WORST result of the fact that we don't really parse. | |
309 | */ | |
310 | zlast = T_GOTO; | |
311 | for (wp = whyles; wp; wp = wp->w_next) | |
ee397aec | 312 | if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) { |
0aec749d | 313 | search(T_BREAK, 0, NULL); |
c4a58397 | 314 | btell(&wp->w_end); |
6e37afca KB |
315 | } |
316 | else | |
c4a58397 | 317 | bseek(&wp->w_end); |
6e37afca KB |
318 | search(T_GOTO, 0, lp = globone(v[1], G_ERROR)); |
319 | xfree((ptr_t) lp); | |
320 | /* | |
321 | * Eliminate loops which were exited. | |
322 | */ | |
323 | wfree(); | |
d43c89f3 BJ |
324 | } |
325 | ||
6e37afca | 326 | void |
454c2aa3 CZ |
327 | /*ARGSUSED*/ |
328 | doswitch(v, t) | |
329 | Char **v; | |
330 | struct command *t; | |
d43c89f3 | 331 | { |
6e37afca KB |
332 | register Char *cp, *lp; |
333 | ||
334 | v++; | |
335 | if (!*v || *(*v++) != '(') | |
336 | stderror(ERR_SYNTAX); | |
337 | cp = **v == ')' ? STRNULL : *v++; | |
338 | if (*(*v++) != ')') | |
339 | v--; | |
340 | if (*v) | |
341 | stderror(ERR_SYNTAX); | |
342 | search(T_SWITCH, 0, lp = globone(cp, G_ERROR)); | |
343 | xfree((ptr_t) lp); | |
d43c89f3 BJ |
344 | } |
345 | ||
6e37afca | 346 | void |
454c2aa3 CZ |
347 | /*ARGSUSED*/ |
348 | dobreak(v, t) | |
349 | Char **v; | |
350 | struct command *t; | |
d43c89f3 | 351 | { |
6e37afca KB |
352 | if (whyles) |
353 | toend(); | |
354 | else | |
355 | stderror(ERR_NAME | ERR_NOTWHILE); | |
d43c89f3 BJ |
356 | } |
357 | ||
6e37afca | 358 | void |
454c2aa3 CZ |
359 | /*ARGSUSED*/ |
360 | doexit(v, t) | |
361 | Char **v; | |
362 | struct command *t; | |
d43c89f3 | 363 | { |
6e37afca KB |
364 | if (chkstop == 0 && (intty || intact) && evalvec == 0) |
365 | panystop(0); | |
366 | /* | |
367 | * Don't DEMAND parentheses here either. | |
368 | */ | |
369 | v++; | |
370 | if (*v) { | |
c96f7f99 | 371 | set(STRstatus, putn(expr(&v))); |
6e37afca KB |
372 | if (*v) |
373 | stderror(ERR_NAME | ERR_EXPRESSION); | |
374 | } | |
375 | btoeof(); | |
376 | if (intty) | |
377 | (void) close(SHIN); | |
d43c89f3 BJ |
378 | } |
379 | ||
6e37afca | 380 | void |
454c2aa3 CZ |
381 | /*ARGSUSED*/ |
382 | doforeach(v, t) | |
383 | Char **v; | |
384 | struct command *t; | |
d43c89f3 | 385 | { |
6e37afca KB |
386 | register Char *cp, *sp; |
387 | register struct whyle *nwp; | |
388 | ||
389 | v++; | |
390 | sp = cp = strip(*v); | |
391 | if (!letter(*sp)) | |
392 | stderror(ERR_NAME | ERR_VARBEGIN); | |
393 | while (*cp && alnum(*cp)) | |
394 | cp++; | |
395 | if (*cp) | |
396 | stderror(ERR_NAME | ERR_VARALNUM); | |
397 | if ((cp - sp) > MAXVARLEN) | |
398 | stderror(ERR_NAME | ERR_VARTOOLONG); | |
399 | cp = *v++; | |
400 | if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') | |
401 | stderror(ERR_NAME | ERR_NOPAREN); | |
402 | v++; | |
403 | gflag = 0, tglob(v); | |
404 | v = globall(v); | |
405 | if (v == 0) | |
406 | stderror(ERR_NAME | ERR_NOMATCH); | |
407 | nwp = (struct whyle *) xcalloc(1, sizeof *nwp); | |
408 | nwp->w_fe = nwp->w_fe0 = v; | |
409 | gargv = 0; | |
c4a58397 | 410 | btell(&nwp->w_start); |
6e37afca KB |
411 | nwp->w_fename = Strsave(cp); |
412 | nwp->w_next = whyles; | |
ee397aec | 413 | nwp->w_end.type = F_SEEK; |
6e37afca KB |
414 | whyles = nwp; |
415 | /* | |
416 | * Pre-read the loop so as to be more comprehensible to a terminal user. | |
417 | */ | |
418 | zlast = T_FOREACH; | |
419 | if (intty) | |
420 | preread(); | |
421 | doagain(); | |
d43c89f3 BJ |
422 | } |
423 | ||
6e37afca | 424 | void |
454c2aa3 CZ |
425 | /*ARGSUSED*/ |
426 | dowhile(v, t) | |
427 | Char **v; | |
428 | struct command *t; | |
d43c89f3 | 429 | { |
6e37afca | 430 | register int status; |
c4a58397 | 431 | register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) && |
6e37afca KB |
432 | whyles->w_fename == 0; |
433 | ||
434 | v++; | |
435 | /* | |
436 | * Implement prereading here also, taking care not to evaluate the | |
437 | * expression before the loop has been read up from a terminal. | |
438 | */ | |
439 | if (intty && !again) | |
440 | status = !exp0(&v, 1); | |
441 | else | |
c96f7f99 | 442 | status = !expr(&v); |
6e37afca KB |
443 | if (*v) |
444 | stderror(ERR_NAME | ERR_EXPRESSION); | |
445 | if (!again) { | |
446 | register struct whyle *nwp = | |
447 | (struct whyle *) xcalloc(1, sizeof(*nwp)); | |
448 | ||
449 | nwp->w_start = lineloc; | |
ee397aec CZ |
450 | nwp->w_end.type = F_SEEK; |
451 | nwp->w_end.f_seek = 0; | |
6e37afca KB |
452 | nwp->w_next = whyles; |
453 | whyles = nwp; | |
454 | zlast = T_WHILE; | |
455 | if (intty) { | |
456 | /* | |
457 | * The tty preread | |
458 | */ | |
459 | preread(); | |
460 | doagain(); | |
461 | return; | |
d43c89f3 | 462 | } |
6e37afca KB |
463 | } |
464 | if (status) | |
465 | /* We ain't gonna loop no more, no more! */ | |
466 | toend(); | |
d43c89f3 BJ |
467 | } |
468 | ||
6e37afca | 469 | static void |
d43c89f3 BJ |
470 | preread() |
471 | { | |
c4a58397 | 472 | whyles->w_end.type = I_SEEK; |
6e37afca | 473 | if (setintr) |
b9c4f741 | 474 | (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); |
6e37afca | 475 | |
0aec749d | 476 | search(T_BREAK, 0, NULL); /* read the expression in */ |
6e37afca KB |
477 | if (setintr) |
478 | (void) sigblock(sigmask(SIGINT)); | |
c4a58397 | 479 | btell(&whyles->w_end); |
d43c89f3 BJ |
480 | } |
481 | ||
6e37afca | 482 | void |
454c2aa3 CZ |
483 | /*ARGSUSED*/ |
484 | doend(v, t) | |
485 | Char **v; | |
486 | struct command *t; | |
d43c89f3 | 487 | { |
6e37afca KB |
488 | if (!whyles) |
489 | stderror(ERR_NAME | ERR_NOTWHILE); | |
c4a58397 | 490 | btell(&whyles->w_end); |
6e37afca | 491 | doagain(); |
d43c89f3 BJ |
492 | } |
493 | ||
6e37afca | 494 | void |
454c2aa3 CZ |
495 | /*ARGSUSED*/ |
496 | docontin(v, t) | |
497 | Char **v; | |
498 | struct command *t; | |
d43c89f3 | 499 | { |
6e37afca KB |
500 | if (!whyles) |
501 | stderror(ERR_NAME | ERR_NOTWHILE); | |
502 | doagain(); | |
d43c89f3 BJ |
503 | } |
504 | ||
6e37afca | 505 | static void |
d43c89f3 BJ |
506 | doagain() |
507 | { | |
6e37afca KB |
508 | /* Repeating a while is simple */ |
509 | if (whyles->w_fename == 0) { | |
c4a58397 | 510 | bseek(&whyles->w_start); |
6e37afca KB |
511 | return; |
512 | } | |
513 | /* | |
514 | * The foreach variable list actually has a spurious word ")" at the end of | |
515 | * the w_fe list. Thus we are at the of the list if one word beyond this | |
516 | * is 0. | |
517 | */ | |
518 | if (!whyles->w_fe[1]) { | |
454c2aa3 | 519 | dobreak(NULL, NULL); |
6e37afca KB |
520 | return; |
521 | } | |
522 | set(whyles->w_fename, Strsave(*whyles->w_fe++)); | |
c4a58397 | 523 | bseek(&whyles->w_start); |
d43c89f3 BJ |
524 | } |
525 | ||
6e37afca | 526 | void |
d43c89f3 | 527 | dorepeat(v, kp) |
6e37afca KB |
528 | Char **v; |
529 | struct command *kp; | |
d43c89f3 | 530 | { |
6e37afca | 531 | register int i; |
b9c4f741 | 532 | register sigset_t omask = 0; |
6e37afca KB |
533 | |
534 | i = getn(v[1]); | |
535 | if (setintr) | |
536 | omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); | |
537 | lshift(v, 2); | |
538 | while (i > 0) { | |
d43c89f3 | 539 | if (setintr) |
6e37afca KB |
540 | (void) sigsetmask(omask); |
541 | reexecute(kp); | |
542 | --i; | |
543 | } | |
544 | donefds(); | |
545 | if (setintr) | |
546 | (void) sigsetmask(omask); | |
d43c89f3 BJ |
547 | } |
548 | ||
6e37afca | 549 | void |
454c2aa3 CZ |
550 | /*ARGSUSED*/ |
551 | doswbrk(v, t) | |
552 | Char **v; | |
553 | struct command *t; | |
d43c89f3 | 554 | { |
0aec749d | 555 | search(T_BRKSW, 0, NULL); |
d43c89f3 BJ |
556 | } |
557 | ||
6e37afca | 558 | int |
d43c89f3 | 559 | srchx(cp) |
6e37afca | 560 | register Char *cp; |
d43c89f3 | 561 | { |
6e37afca KB |
562 | register struct srch *sp, *sp1, *sp2; |
563 | register i; | |
564 | ||
565 | /* | |
566 | * Binary search Sp1 is the beginning of the current search range. Sp2 is | |
567 | * one past the end. | |
568 | */ | |
569 | for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { | |
570 | sp = sp1 + ((sp2 - sp1) >> 1); | |
571 | if ((i = *cp - *sp->s_name) == 0 && | |
572 | (i = Strcmp(cp, str2short(sp->s_name))) == 0) | |
573 | return sp->s_value; | |
574 | if (i < 0) | |
575 | sp2 = sp; | |
576 | else | |
577 | sp1 = sp + 1; | |
578 | } | |
579 | return (-1); | |
d43c89f3 BJ |
580 | } |
581 | ||
6e37afca KB |
582 | static Char Stype; |
583 | static Char *Sgoal; | |
d43c89f3 BJ |
584 | |
585 | /*VARARGS2*/ | |
6e37afca | 586 | void |
d43c89f3 | 587 | search(type, level, goal) |
6e37afca KB |
588 | int type; |
589 | register int level; | |
590 | Char *goal; | |
d43c89f3 | 591 | { |
6e37afca KB |
592 | Char wordbuf[BUFSIZ]; |
593 | register Char *aword = wordbuf; | |
594 | register Char *cp; | |
595 | ||
596 | Stype = type; | |
597 | Sgoal = goal; | |
c4a58397 CZ |
598 | if (type == T_GOTO) { |
599 | struct Ain a; | |
600 | a.type = F_SEEK; | |
601 | a.f_seek = 0; | |
602 | bseek(&a); | |
603 | } | |
6e37afca | 604 | do { |
c4a58397 | 605 | if (intty && fseekp == feobp && aret == F_SEEK) |
454c2aa3 | 606 | (void) fprintf(cshout, "? "), (void) fflush(cshout); |
6e37afca KB |
607 | aword[0] = 0; |
608 | (void) getword(aword); | |
609 | switch (srchx(aword)) { | |
d43c89f3 | 610 | |
6e37afca KB |
611 | case T_ELSE: |
612 | if (level == 0 && type == T_IF) | |
613 | return; | |
614 | break; | |
615 | ||
616 | case T_IF: | |
617 | while (getword(aword)) | |
618 | continue; | |
619 | if ((type == T_IF || type == T_ELSE) && | |
620 | eq(aword, STRthen)) | |
621 | level++; | |
622 | break; | |
623 | ||
624 | case T_ENDIF: | |
625 | if (type == T_IF || type == T_ELSE) | |
626 | level--; | |
627 | break; | |
628 | ||
629 | case T_FOREACH: | |
630 | case T_WHILE: | |
631 | if (type == T_BREAK) | |
632 | level++; | |
633 | break; | |
634 | ||
635 | case T_END: | |
636 | if (type == T_BREAK) | |
637 | level--; | |
638 | break; | |
639 | ||
640 | case T_SWITCH: | |
641 | if (type == T_SWITCH || type == T_BRKSW) | |
642 | level++; | |
643 | break; | |
644 | ||
645 | case T_ENDSW: | |
646 | if (type == T_SWITCH || type == T_BRKSW) | |
647 | level--; | |
648 | break; | |
649 | ||
650 | case T_LABEL: | |
651 | if (type == T_GOTO && getword(aword) && eq(aword, goal)) | |
652 | level = -1; | |
653 | break; | |
654 | ||
655 | default: | |
656 | if (type != T_GOTO && (type != T_SWITCH || level != 0)) | |
657 | break; | |
658 | if (lastchr(aword) != ':') | |
659 | break; | |
660 | aword[Strlen(aword) - 1] = 0; | |
661 | if (type == T_GOTO && eq(aword, goal) || | |
662 | type == T_SWITCH && eq(aword, STRdefault)) | |
663 | level = -1; | |
664 | break; | |
665 | ||
666 | case T_CASE: | |
667 | if (type != T_SWITCH || level != 0) | |
668 | break; | |
669 | (void) getword(aword); | |
670 | if (lastchr(aword) == ':') | |
671 | aword[Strlen(aword) - 1] = 0; | |
672 | cp = strip(Dfix1(aword)); | |
673 | if (Gmatch(goal, cp)) | |
674 | level = -1; | |
675 | xfree((ptr_t) cp); | |
676 | break; | |
677 | ||
678 | case T_DEFAULT: | |
679 | if (type == T_SWITCH && level == 0) | |
680 | level = -1; | |
681 | break; | |
682 | } | |
683 | (void) getword(NULL); | |
684 | } while (level >= 0); | |
d43c89f3 BJ |
685 | } |
686 | ||
6e37afca | 687 | static int |
d43c89f3 | 688 | getword(wp) |
6e37afca | 689 | register Char *wp; |
d43c89f3 | 690 | { |
6e37afca KB |
691 | register int found = 0; |
692 | register int c, d; | |
693 | int kwd = 0; | |
694 | Char *owp = wp; | |
6e37afca KB |
695 | |
696 | c = readc(1); | |
697 | d = 0; | |
698 | do { | |
699 | while (c == ' ' || c == '\t') | |
700 | c = readc(1); | |
701 | if (c == '#') | |
702 | do | |
703 | c = readc(1); | |
704 | while (c >= 0 && c != '\n'); | |
705 | if (c < 0) | |
706 | goto past; | |
707 | if (c == '\n') { | |
708 | if (wp) | |
709 | break; | |
710 | return (0); | |
711 | } | |
712 | unreadc(c); | |
713 | found = 1; | |
d43c89f3 | 714 | do { |
6e37afca KB |
715 | c = readc(1); |
716 | if (c == '\\' && (c = readc(1)) == '\n') | |
717 | c = ' '; | |
718 | if (c == '\'' || c == '"') | |
719 | if (d == 0) | |
720 | d = c; | |
721 | else if (d == c) | |
722 | d = 0; | |
723 | if (c < 0) | |
724 | goto past; | |
725 | if (wp) { | |
726 | *wp++ = c; | |
727 | *wp = 0; /* end the string b4 test */ | |
728 | } | |
729 | } while ((d || !(kwd = keyword(owp)) && c != ' ' | |
730 | && c != '\t') && c != '\n'); | |
731 | } while (wp == 0); | |
732 | ||
733 | /* | |
734 | * if we have read a keyword ( "if", "switch" or "while" ) then we do not | |
735 | * need to unreadc the look-ahead char | |
736 | */ | |
737 | if (!kwd) { | |
d43c89f3 BJ |
738 | unreadc(c); |
739 | if (found) | |
6e37afca KB |
740 | *--wp = 0; |
741 | } | |
742 | ||
743 | return (found); | |
d43c89f3 BJ |
744 | |
745 | past: | |
6e37afca | 746 | switch (Stype) { |
d43c89f3 | 747 | |
6e37afca KB |
748 | case T_IF: |
749 | stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); | |
d43c89f3 | 750 | |
6e37afca KB |
751 | case T_ELSE: |
752 | stderror(ERR_NAME | ERR_NOTFOUND, "endif"); | |
d43c89f3 | 753 | |
6e37afca KB |
754 | case T_BRKSW: |
755 | case T_SWITCH: | |
756 | stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); | |
d43c89f3 | 757 | |
6e37afca KB |
758 | case T_BREAK: |
759 | stderror(ERR_NAME | ERR_NOTFOUND, "end"); | |
d43c89f3 | 760 | |
6e37afca KB |
761 | case T_GOTO: |
762 | setname(short2str(Sgoal)); | |
763 | stderror(ERR_NAME | ERR_NOTFOUND, "label"); | |
764 | } | |
765 | /* NOTREACHED */ | |
766 | return (0); | |
d43c89f3 BJ |
767 | } |
768 | ||
6e37afca KB |
769 | /* |
770 | * keyword(wp) determines if wp is one of the built-n functions if, | |
771 | * switch or while. It seems that when an if statement looks like | |
772 | * "if(" then getword above sucks in the '(' and so the search routine | |
773 | * never finds what it is scanning for. Rather than rewrite doword, I hack | |
774 | * in a test to see if the string forms a keyword. Then doword stops | |
775 | * and returns the word "if" -strike | |
776 | */ | |
777 | ||
778 | static int | |
779 | keyword(wp) | |
780 | Char *wp; | |
d43c89f3 | 781 | { |
6e37afca KB |
782 | static Char STRif[] = {'i', 'f', '\0'}; |
783 | static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'}; | |
784 | static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'}; | |
d43c89f3 | 785 | |
6e37afca KB |
786 | if (!wp) |
787 | return (0); | |
788 | ||
789 | if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0) | |
790 | || (Strcmp(wp, STRswitch) == 0)) | |
791 | return (1); | |
792 | ||
793 | return (0); | |
794 | } | |
795 | ||
796 | static void | |
797 | toend() | |
798 | { | |
ee397aec | 799 | if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) { |
6e37afca | 800 | search(T_BREAK, 0, NULL); |
c4a58397 CZ |
801 | btell(&whyles->w_end); |
802 | whyles->w_end.f_seek--; | |
6e37afca KB |
803 | } |
804 | else | |
c4a58397 | 805 | bseek(&whyles->w_end); |
6e37afca | 806 | wfree(); |
d43c89f3 BJ |
807 | } |
808 | ||
6e37afca | 809 | void |
d43c89f3 BJ |
810 | wfree() |
811 | { | |
c4a58397 CZ |
812 | struct Ain o; |
813 | struct whyle *nwp; | |
814 | btell(&o); | |
815 | ||
816 | if (o.type != F_SEEK) | |
817 | return; | |
6e37afca | 818 | |
c4a58397 | 819 | for (; whyles; whyles = nwp) { |
6e37afca | 820 | register struct whyle *wp = whyles; |
c4a58397 | 821 | nwp = wp->w_next; |
ee397aec CZ |
822 | if (wp->w_start.type != F_SEEK || wp->w_end.type != F_SEEK) |
823 | break; | |
c4a58397 CZ |
824 | if (o.f_seek >= wp->w_start.f_seek && |
825 | (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) | |
6e37afca KB |
826 | break; |
827 | if (wp->w_fe0) | |
828 | blkfree(wp->w_fe0); | |
829 | if (wp->w_fename) | |
830 | xfree((ptr_t) wp->w_fename); | |
831 | xfree((ptr_t) wp); | |
6e37afca | 832 | } |
d43c89f3 BJ |
833 | } |
834 | ||
6e37afca | 835 | void |
454c2aa3 CZ |
836 | /*ARGSUSED*/ |
837 | doecho(v, t) | |
838 | Char **v; | |
839 | struct command *t; | |
d43c89f3 | 840 | { |
6e37afca | 841 | xecho(' ', v); |
d43c89f3 BJ |
842 | } |
843 | ||
6e37afca | 844 | void |
454c2aa3 CZ |
845 | /*ARGSUSED*/ |
846 | doglob(v, t) | |
847 | Char **v; | |
848 | struct command *t; | |
d43c89f3 | 849 | { |
6e37afca | 850 | xecho(0, v); |
454c2aa3 | 851 | (void) fflush(cshout); |
d43c89f3 BJ |
852 | } |
853 | ||
6e37afca KB |
854 | static void |
855 | xecho(sep, v) | |
0aec749d | 856 | int sep; |
6e37afca | 857 | register Char **v; |
d43c89f3 | 858 | { |
6e37afca KB |
859 | register Char *cp; |
860 | int nonl = 0; | |
861 | ||
862 | if (setintr) | |
b9c4f741 | 863 | (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); |
6e37afca KB |
864 | v++; |
865 | if (*v == 0) | |
866 | return; | |
867 | gflag = 0, tglob(v); | |
868 | if (gflag) { | |
869 | v = globall(v); | |
870 | if (v == 0) | |
871 | stderror(ERR_NAME | ERR_NOMATCH); | |
872 | } | |
873 | else { | |
874 | v = gargv = saveblk(v); | |
875 | trim(v); | |
876 | } | |
877 | if (sep == ' ' && *v && eq(*v, STRmn)) | |
878 | nonl++, v++; | |
879 | while (cp = *v++) { | |
880 | register int c; | |
881 | ||
882 | while (c = *cp++) | |
454c2aa3 | 883 | (void) fputc(c | QUOTE, cshout); |
d43c89f3 | 884 | |
6e37afca | 885 | if (*v) |
454c2aa3 | 886 | (void) fputc(sep | QUOTE, cshout); |
6e37afca KB |
887 | } |
888 | if (sep && nonl == 0) | |
454c2aa3 | 889 | (void) fputc('\n', cshout); |
6e37afca | 890 | else |
454c2aa3 | 891 | (void) fflush(cshout); |
6e37afca KB |
892 | if (setintr) |
893 | (void) sigblock(sigmask(SIGINT)); | |
894 | if (gargv) | |
895 | blkfree(gargv), gargv = 0; | |
d43c89f3 BJ |
896 | } |
897 | ||
6e37afca | 898 | void |
454c2aa3 CZ |
899 | /*ARGSUSED*/ |
900 | dosetenv(v, t) | |
901 | Char **v; | |
902 | struct command *t; | |
d43c89f3 | 903 | { |
6e37afca | 904 | Char *vp, *lp; |
d43c89f3 | 905 | |
6e37afca KB |
906 | v++; |
907 | if ((vp = *v++) == 0) { | |
908 | register Char **ep; | |
c349da0d | 909 | |
6e37afca | 910 | if (setintr) |
b9c4f741 | 911 | (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); |
6e37afca | 912 | for (ep = STR_environ; *ep; ep++) |
454c2aa3 | 913 | (void) fprintf(cshout, "%s\n", short2str(*ep)); |
6e37afca KB |
914 | return; |
915 | } | |
916 | if ((lp = *v++) == 0) | |
917 | lp = STRNULL; | |
43fa56b8 | 918 | Setenv(vp, lp = globone(lp, G_APPEND)); |
6e37afca KB |
919 | if (eq(vp, STRPATH)) { |
920 | importpath(lp); | |
454c2aa3 | 921 | dohash(NULL, NULL); |
6e37afca KB |
922 | } |
923 | else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) { | |
924 | #ifdef NLS | |
925 | int k; | |
926 | ||
927 | (void) setlocale(LC_ALL, ""); | |
928 | for (k = 0200; k <= 0377 && !Isprint(k); k++); | |
929 | AsciiOnly = k > 0377; | |
930 | #else | |
931 | AsciiOnly = 0; | |
932 | #endif /* NLS */ | |
933 | } | |
934 | xfree((ptr_t) lp); | |
d43c89f3 BJ |
935 | } |
936 | ||
6e37afca | 937 | void |
454c2aa3 CZ |
938 | /*ARGSUSED*/ |
939 | dounsetenv(v, t) | |
940 | Char **v; | |
941 | struct command *t; | |
d43c89f3 | 942 | { |
6e37afca KB |
943 | Char **ep, *p, *n; |
944 | int i, maxi; | |
945 | static Char *name = NULL; | |
946 | ||
947 | if (name) | |
948 | xfree((ptr_t) name); | |
949 | /* | |
950 | * Find the longest environment variable | |
951 | */ | |
952 | for (maxi = 0, ep = STR_environ; *ep; ep++) { | |
953 | for (i = 0, p = *ep; *p && *p != '='; p++, i++); | |
954 | if (i > maxi) | |
955 | maxi = i; | |
956 | } | |
957 | ||
958 | name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char)); | |
959 | ||
2ce74acc CZ |
960 | while (++v && *v) |
961 | for (maxi = 1; maxi;) | |
962 | for (maxi = 0, ep = STR_environ; *ep; ep++) { | |
963 | for (n = name, p = *ep; *p && *p != '='; *n++ = *p++); | |
964 | *n = '\0'; | |
965 | if (!Gmatch(name, *v)) | |
966 | continue; | |
967 | maxi = 1; | |
968 | if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) { | |
6e37afca | 969 | #ifdef NLS |
2ce74acc | 970 | int k; |
6e37afca | 971 | |
2ce74acc CZ |
972 | (void) setlocale(LC_ALL, ""); |
973 | for (k = 0200; k <= 0377 && !Isprint(k); k++); | |
974 | AsciiOnly = k > 0377; | |
6e37afca | 975 | #else |
2ce74acc CZ |
976 | AsciiOnly = getenv("LANG") == NULL && |
977 | getenv("LC_CTYPE") == NULL; | |
6e37afca | 978 | #endif /* NLS */ |
2ce74acc CZ |
979 | } |
980 | /* | |
981 | * Delete name, and start again cause the environment changes | |
982 | */ | |
983 | Unsetenv(name); | |
984 | break; | |
6e37afca | 985 | } |
f52b9180 CZ |
986 | xfree((ptr_t) name); |
987 | name = NULL; | |
d43c89f3 BJ |
988 | } |
989 | ||
6e37afca KB |
990 | void |
991 | Setenv(name, val) | |
992 | Char *name, *val; | |
d43c89f3 | 993 | { |
6e37afca KB |
994 | register Char **ep = STR_environ; |
995 | register Char *cp, *dp; | |
996 | Char *blk[2]; | |
997 | Char **oep = ep; | |
998 | ||
999 | ||
1000 | for (; *ep; ep++) { | |
1001 | for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) | |
1002 | continue; | |
1003 | if (*cp != 0 || *dp != '=') | |
1004 | continue; | |
1005 | cp = Strspl(STRequal, val); | |
1006 | xfree((ptr_t) * ep); | |
1007 | *ep = strip(Strspl(name, cp)); | |
1008 | xfree((ptr_t) cp); | |
1009 | blkfree((Char **) environ); | |
1010 | environ = short2blk(STR_environ); | |
1011 | return; | |
1012 | } | |
1013 | cp = Strspl(name, STRequal); | |
1014 | blk[0] = strip(Strspl(cp, val)); | |
1015 | xfree((ptr_t) cp); | |
1016 | blk[1] = 0; | |
1017 | STR_environ = blkspl(STR_environ, blk); | |
1018 | blkfree((Char **) environ); | |
1019 | environ = short2blk(STR_environ); | |
1020 | xfree((ptr_t) oep); | |
d43c89f3 BJ |
1021 | } |
1022 | ||
6e37afca KB |
1023 | static void |
1024 | Unsetenv(name) | |
1025 | Char *name; | |
d43c89f3 | 1026 | { |
6e37afca KB |
1027 | register Char **ep = STR_environ; |
1028 | register Char *cp, *dp; | |
1029 | Char **oep = ep; | |
1030 | ||
1031 | for (; *ep; ep++) { | |
1032 | for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) | |
1033 | continue; | |
1034 | if (*cp != 0 || *dp != '=') | |
1035 | continue; | |
1036 | cp = *ep; | |
1037 | *ep = 0; | |
1038 | STR_environ = blkspl(STR_environ, ep + 1); | |
1039 | environ = short2blk(STR_environ); | |
1040 | *ep = cp; | |
1041 | xfree((ptr_t) cp); | |
1042 | xfree((ptr_t) oep); | |
1043 | return; | |
1044 | } | |
d43c89f3 BJ |
1045 | } |
1046 | ||
6e37afca | 1047 | void |
454c2aa3 CZ |
1048 | /*ARGSUSED*/ |
1049 | doumask(v, t) | |
1050 | Char **v; | |
1051 | struct command *t; | |
d43c89f3 | 1052 | { |
6e37afca KB |
1053 | register Char *cp = v[1]; |
1054 | register int i; | |
d43c89f3 | 1055 | |
6e37afca KB |
1056 | if (cp == 0) { |
1057 | i = umask(0); | |
35371dec | 1058 | (void) umask(i); |
454c2aa3 | 1059 | (void) fprintf(cshout, "%o\n", i); |
6e37afca KB |
1060 | return; |
1061 | } | |
1062 | i = 0; | |
1063 | while (Isdigit(*cp) && *cp != '8' && *cp != '9') | |
1064 | i = i * 8 + *cp++ - '0'; | |
1065 | if (*cp || i < 0 || i > 0777) | |
1066 | stderror(ERR_NAME | ERR_MASK); | |
1067 | (void) umask(i); | |
d43c89f3 BJ |
1068 | } |
1069 | ||
6e37afca KB |
1070 | typedef int RLIM_TYPE; |
1071 | ||
1072 | static struct limits { | |
1073 | int limconst; | |
1074 | char *limname; | |
1075 | int limdiv; | |
1076 | char *limscale; | |
1077 | } limits[] = { | |
1078 | RLIMIT_CPU, "cputime", 1, "seconds", | |
1079 | RLIMIT_FSIZE, "filesize", 1024, "kbytes", | |
1080 | RLIMIT_DATA, "datasize", 1024, "kbytes", | |
1081 | RLIMIT_STACK, "stacksize", 1024, "kbytes", | |
1082 | RLIMIT_CORE, "coredumpsize", 1024, "kbytes", | |
1083 | RLIMIT_RSS, "memoryuse", 1024, "kbytes", | |
0aec749d CZ |
1084 | RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes", |
1085 | RLIMIT_NPROC, "maxproc", 1, "", | |
1086 | RLIMIT_OFILE, "openfiles", 1, "", | |
1087 | -1, NULL, 0, NULL | |
d43c89f3 BJ |
1088 | }; |
1089 | ||
6e37afca KB |
1090 | static struct limits *findlim(); |
1091 | static RLIM_TYPE getval(); | |
1092 | static void limtail(); | |
1093 | static void plim(); | |
1094 | static int setlim(); | |
1095 | ||
1096 | static struct limits * | |
d43c89f3 | 1097 | findlim(cp) |
6e37afca | 1098 | Char *cp; |
d43c89f3 | 1099 | { |
6e37afca KB |
1100 | register struct limits *lp, *res; |
1101 | ||
1102 | res = (struct limits *) NULL; | |
1103 | for (lp = limits; lp->limconst >= 0; lp++) | |
1104 | if (prefix(cp, str2short(lp->limname))) { | |
1105 | if (res) | |
1106 | stderror(ERR_NAME | ERR_AMBIG); | |
1107 | res = lp; | |
1108 | } | |
1109 | if (res) | |
1110 | return (res); | |
1111 | stderror(ERR_NAME | ERR_LIMIT); | |
1112 | /* NOTREACHED */ | |
1113 | return (0); | |
d43c89f3 BJ |
1114 | } |
1115 | ||
6e37afca | 1116 | void |
454c2aa3 CZ |
1117 | /*ARGSUSED*/ |
1118 | dolimit(v, t) | |
1119 | Char **v; | |
1120 | struct command *t; | |
d43c89f3 | 1121 | { |
6e37afca KB |
1122 | register struct limits *lp; |
1123 | register RLIM_TYPE limit; | |
1124 | char hard = 0; | |
d43c89f3 | 1125 | |
6e37afca KB |
1126 | v++; |
1127 | if (*v && eq(*v, STRmh)) { | |
1128 | hard = 1; | |
d43c89f3 | 1129 | v++; |
6e37afca KB |
1130 | } |
1131 | if (*v == 0) { | |
1132 | for (lp = limits; lp->limconst >= 0; lp++) | |
1133 | plim(lp, hard); | |
1134 | return; | |
1135 | } | |
1136 | lp = findlim(v[0]); | |
1137 | if (v[1] == 0) { | |
1138 | plim(lp, hard); | |
1139 | return; | |
1140 | } | |
1141 | limit = getval(lp, v + 1); | |
1142 | if (setlim(lp, hard, limit) < 0) | |
1143 | stderror(ERR_SILENT); | |
d43c89f3 BJ |
1144 | } |
1145 | ||
6e37afca | 1146 | static RLIM_TYPE |
d43c89f3 | 1147 | getval(lp, v) |
6e37afca KB |
1148 | register struct limits *lp; |
1149 | Char **v; | |
d43c89f3 | 1150 | { |
6e37afca KB |
1151 | register float f; |
1152 | double atof(); | |
1153 | Char *cp = *v++; | |
d43c89f3 | 1154 | |
6e37afca | 1155 | f = atof(short2str(cp)); |
d43c89f3 | 1156 | |
6e37afca KB |
1157 | while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') |
1158 | cp++; | |
1159 | if (*cp == 0) { | |
1160 | if (*v == 0) | |
1161 | return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv)); | |
1162 | cp = *v; | |
1163 | } | |
1164 | switch (*cp) { | |
1165 | case ':': | |
1166 | if (lp->limconst != RLIMIT_CPU) | |
1167 | goto badscal; | |
1168 | return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1)))); | |
1169 | case 'h': | |
1170 | if (lp->limconst != RLIMIT_CPU) | |
1171 | goto badscal; | |
1172 | limtail(cp, "hours"); | |
1173 | f *= 3600.0; | |
1174 | break; | |
1175 | case 'm': | |
1176 | if (lp->limconst == RLIMIT_CPU) { | |
1177 | limtail(cp, "minutes"); | |
1178 | f *= 60.0; | |
1179 | break; | |
d43c89f3 | 1180 | } |
6e37afca KB |
1181 | *cp = 'm'; |
1182 | limtail(cp, "megabytes"); | |
1183 | f *= 1024.0 * 1024.0; | |
1184 | break; | |
1185 | case 's': | |
1186 | if (lp->limconst != RLIMIT_CPU) | |
1187 | goto badscal; | |
1188 | limtail(cp, "seconds"); | |
1189 | break; | |
1190 | case 'M': | |
1191 | if (lp->limconst == RLIMIT_CPU) | |
1192 | goto badscal; | |
1193 | *cp = 'm'; | |
1194 | limtail(cp, "megabytes"); | |
1195 | f *= 1024.0 * 1024.0; | |
1196 | break; | |
1197 | case 'k': | |
1198 | if (lp->limconst == RLIMIT_CPU) | |
1199 | goto badscal; | |
1200 | limtail(cp, "kbytes"); | |
1201 | f *= 1024.0; | |
1202 | break; | |
1203 | case 'u': | |
1204 | limtail(cp, "unlimited"); | |
1205 | return (RLIM_INFINITY); | |
1206 | default: | |
1207 | badscal: | |
1208 | stderror(ERR_NAME | ERR_SCALEF); | |
1209 | } | |
c4a58397 CZ |
1210 | if ((f + 0.5) >= (float) 0x7fffffff || (f + 0.5) < (float) 0x80000000) |
1211 | stderror(ERR_NAME | ERR_SCALEF); | |
6e37afca | 1212 | return ((RLIM_TYPE) (f + 0.5)); |
d43c89f3 BJ |
1213 | } |
1214 | ||
6e37afca KB |
1215 | static void |
1216 | limtail(cp, str) | |
1217 | Char *cp; | |
1218 | char *str; | |
d43c89f3 | 1219 | { |
6e37afca KB |
1220 | while (*cp && *cp == *str) |
1221 | cp++, str++; | |
1222 | if (*cp) | |
1223 | stderror(ERR_BADSCALE, str); | |
d43c89f3 BJ |
1224 | } |
1225 | ||
6e37afca KB |
1226 | |
1227 | /*ARGSUSED*/ | |
1228 | static void | |
f74ac01c | 1229 | plim(lp, hard) |
6e37afca KB |
1230 | register struct limits *lp; |
1231 | Char hard; | |
d43c89f3 | 1232 | { |
6e37afca KB |
1233 | struct rlimit rlim; |
1234 | RLIM_TYPE limit; | |
1235 | ||
454c2aa3 | 1236 | (void) fprintf(cshout, "%s \t", lp->limname); |
6e37afca KB |
1237 | |
1238 | (void) getrlimit(lp->limconst, &rlim); | |
1239 | limit = hard ? rlim.rlim_max : rlim.rlim_cur; | |
1240 | ||
1241 | if (limit == RLIM_INFINITY) | |
454c2aa3 | 1242 | (void) fprintf(cshout, "unlimited"); |
6e37afca KB |
1243 | else if (lp->limconst == RLIMIT_CPU) |
1244 | psecs((long) limit); | |
1245 | else | |
454c2aa3 CZ |
1246 | (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv), |
1247 | lp->limscale); | |
1248 | (void) fputc('\n', cshout); | |
d43c89f3 BJ |
1249 | } |
1250 | ||
6e37afca | 1251 | void |
454c2aa3 CZ |
1252 | /*ARGSUSED*/ |
1253 | dounlimit(v, t) | |
1254 | Char **v; | |
1255 | struct command *t; | |
d43c89f3 | 1256 | { |
6e37afca KB |
1257 | register struct limits *lp; |
1258 | int lerr = 0; | |
1259 | Char hard = 0; | |
d43c89f3 | 1260 | |
6e37afca KB |
1261 | v++; |
1262 | if (*v && eq(*v, STRmh)) { | |
1263 | hard = 1; | |
d43c89f3 | 1264 | v++; |
6e37afca KB |
1265 | } |
1266 | if (*v == 0) { | |
1267 | for (lp = limits; lp->limconst >= 0; lp++) | |
1268 | if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) | |
1269 | lerr++; | |
1270 | if (lerr) | |
1271 | stderror(ERR_SILENT); | |
1272 | return; | |
1273 | } | |
1274 | while (*v) { | |
1275 | lp = findlim(*v++); | |
1276 | if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) | |
1277 | stderror(ERR_SILENT); | |
1278 | } | |
d43c89f3 BJ |
1279 | } |
1280 | ||
6e37afca | 1281 | static int |
f74ac01c | 1282 | setlim(lp, hard, limit) |
6e37afca KB |
1283 | register struct limits *lp; |
1284 | Char hard; | |
1285 | RLIM_TYPE limit; | |
d43c89f3 | 1286 | { |
6e37afca KB |
1287 | struct rlimit rlim; |
1288 | ||
1289 | (void) getrlimit(lp->limconst, &rlim); | |
1290 | ||
1291 | if (hard) | |
1292 | rlim.rlim_max = limit; | |
1293 | else if (limit == RLIM_INFINITY && geteuid() != 0) | |
1294 | rlim.rlim_cur = rlim.rlim_max; | |
1295 | else | |
1296 | rlim.rlim_cur = limit; | |
1297 | ||
1298 | if (setrlimit(lp->limconst, &rlim) < 0) { | |
454c2aa3 CZ |
1299 | (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname, |
1300 | limit == RLIM_INFINITY ? "remove" : "set", | |
1301 | hard ? " hard" : ""); | |
6e37afca KB |
1302 | return (-1); |
1303 | } | |
1304 | return (0); | |
d43c89f3 BJ |
1305 | } |
1306 | ||
6e37afca | 1307 | void |
454c2aa3 CZ |
1308 | /*ARGSUSED*/ |
1309 | dosuspend(v, t) | |
1310 | Char **v; | |
1311 | struct command *t; | |
d43c89f3 | 1312 | { |
6e37afca KB |
1313 | int ctpgrp; |
1314 | ||
1315 | void (*old) (); | |
1316 | ||
1317 | if (loginsh) | |
1318 | stderror(ERR_SUSPLOG); | |
1319 | untty(); | |
1320 | ||
1321 | old = signal(SIGTSTP, SIG_DFL); | |
1322 | (void) kill(0, SIGTSTP); | |
1323 | /* the shell stops here */ | |
1324 | (void) signal(SIGTSTP, old); | |
1325 | ||
1326 | if (tpgrp != -1) { | |
6e37afca | 1327 | ctpgrp = tcgetpgrp(FSHTTY); |
454c2aa3 | 1328 | while (ctpgrp != opgrp) { |
6e37afca KB |
1329 | old = signal(SIGTTIN, SIG_DFL); |
1330 | (void) kill(0, SIGTTIN); | |
1331 | (void) signal(SIGTTIN, old); | |
d43c89f3 | 1332 | } |
6e37afca KB |
1333 | (void) setpgid(0, shpgrp); |
1334 | (void) tcsetpgrp(FSHTTY, shpgrp); | |
1335 | } | |
d43c89f3 BJ |
1336 | } |
1337 | ||
6e37afca KB |
1338 | /* This is the dreaded EVAL built-in. |
1339 | * If you don't fiddle with file descriptors, and reset didfds, | |
1340 | * this command will either ignore redirection inside or outside | |
1341 | * its aguments, e.g. eval "date >x" vs. eval "date" >x | |
1342 | * The stuff here seems to work, but I did it by trial and error rather | |
1343 | * than really knowing what was going on. If tpgrp is zero, we are | |
1344 | * probably a background eval, e.g. "eval date &", and we want to | |
1345 | * make sure that any processes we start stay in our pgrp. | |
1346 | * This is also the case for "time eval date" -- stay in same pgrp. | |
1347 | * Otherwise, under stty tostop, processes will stop in the wrong | |
1348 | * pgrp, with no way for the shell to get them going again. -IAN! | |
1349 | */ | |
454c2aa3 | 1350 | static Char **gv = NULL; |
6e37afca | 1351 | void |
454c2aa3 CZ |
1352 | /*ARGSUSED*/ |
1353 | doeval(v, t) | |
1354 | Char **v; | |
1355 | struct command *t; | |
d43c89f3 | 1356 | { |
6e37afca KB |
1357 | Char **oevalvec; |
1358 | Char *oevalp; | |
1359 | int odidfds; | |
1360 | jmp_buf osetexit; | |
1361 | int my_reenter; | |
454c2aa3 | 1362 | Char **savegv = gv; |
6e37afca KB |
1363 | int saveIN; |
1364 | int saveOUT; | |
454c2aa3 | 1365 | int saveERR; |
6e37afca KB |
1366 | int oSHIN; |
1367 | int oSHOUT; | |
454c2aa3 | 1368 | int oSHERR; |
6e37afca KB |
1369 | |
1370 | oevalvec = evalvec; | |
1371 | oevalp = evalp; | |
1372 | odidfds = didfds; | |
1373 | oSHIN = SHIN; | |
1374 | oSHOUT = SHOUT; | |
454c2aa3 | 1375 | oSHERR = SHERR; |
6e37afca KB |
1376 | |
1377 | v++; | |
1378 | if (*v == 0) | |
1379 | return; | |
1380 | gflag = 0, tglob(v); | |
1381 | if (gflag) { | |
1382 | gv = v = globall(v); | |
1383 | gargv = 0; | |
1384 | if (v == 0) | |
1385 | stderror(ERR_NOMATCH); | |
1386 | v = copyblk(v); | |
1387 | } | |
1388 | else { | |
0aec749d | 1389 | gv = NULL; |
6e37afca KB |
1390 | v = copyblk(v); |
1391 | trim(v); | |
1392 | } | |
1393 | ||
1394 | saveIN = dcopy(SHIN, -1); | |
1395 | saveOUT = dcopy(SHOUT, -1); | |
454c2aa3 | 1396 | saveERR = dcopy(SHERR, -1); |
6e37afca KB |
1397 | |
1398 | getexit(osetexit); | |
1399 | ||
1400 | if ((my_reenter = setexit()) == 0) { | |
1401 | evalvec = v; | |
1402 | evalp = 0; | |
1403 | SHIN = dcopy(0, -1); | |
1404 | SHOUT = dcopy(1, -1); | |
454c2aa3 | 1405 | SHERR = dcopy(2, -1); |
6e37afca KB |
1406 | didfds = 0; |
1407 | process(0); | |
1408 | } | |
1409 | ||
1410 | evalvec = oevalvec; | |
1411 | evalp = oevalp; | |
1412 | doneinp = 0; | |
1413 | didfds = odidfds; | |
1414 | (void) close(SHIN); | |
1415 | (void) close(SHOUT); | |
454c2aa3 | 1416 | (void) close(SHERR); |
6e37afca KB |
1417 | SHIN = dmove(saveIN, oSHIN); |
1418 | SHOUT = dmove(saveOUT, oSHOUT); | |
454c2aa3 | 1419 | SHERR = dmove(saveERR, oSHERR); |
6e37afca | 1420 | if (gv) |
454c2aa3 | 1421 | blkfree(gv), gv = NULL; |
6e37afca | 1422 | resexit(osetexit); |
454c2aa3 | 1423 | gv = savegv; |
6e37afca KB |
1424 | if (my_reenter) |
1425 | stderror(ERR_SILENT); | |
d43c89f3 | 1426 | } |
17b1f379 CZ |
1427 | |
1428 | void | |
1429 | /*ARGSUSED*/ | |
1430 | doprintf(v, t) | |
1431 | Char **v; | |
1432 | struct command *t; | |
1433 | { | |
1434 | char **c; | |
1435 | extern int progprintf __P((int, char **)); | |
1436 | int ret; | |
1437 | ||
1438 | ret = progprintf(blklen(v), c = short2blk(v)); | |
1439 | ||
1440 | blkfree((Char **) c); | |
1441 | if (ret) | |
1442 | stderror(ERR_SILENT); | |
1443 | } | |
1444 |