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 |
c4a58397 | 9 | static char sccsid[] = "@(#)func.c 5.24 (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++; | |
243 | i = exp(&v); | |
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) | |
c4a58397 | 312 | if (wp->w_end.type == I_SEEK) { |
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) { | |
371 | set(STRstatus, putn(exp(&v))); | |
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; | |
413 | whyles = nwp; | |
414 | /* | |
415 | * Pre-read the loop so as to be more comprehensible to a terminal user. | |
416 | */ | |
417 | zlast = T_FOREACH; | |
418 | if (intty) | |
419 | preread(); | |
420 | doagain(); | |
d43c89f3 BJ |
421 | } |
422 | ||
6e37afca | 423 | void |
454c2aa3 CZ |
424 | /*ARGSUSED*/ |
425 | dowhile(v, t) | |
426 | Char **v; | |
427 | struct command *t; | |
d43c89f3 | 428 | { |
6e37afca | 429 | register int status; |
c4a58397 | 430 | register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) && |
6e37afca KB |
431 | whyles->w_fename == 0; |
432 | ||
433 | v++; | |
434 | /* | |
435 | * Implement prereading here also, taking care not to evaluate the | |
436 | * expression before the loop has been read up from a terminal. | |
437 | */ | |
438 | if (intty && !again) | |
439 | status = !exp0(&v, 1); | |
440 | else | |
441 | status = !exp(&v); | |
442 | if (*v) | |
443 | stderror(ERR_NAME | ERR_EXPRESSION); | |
444 | if (!again) { | |
445 | register struct whyle *nwp = | |
446 | (struct whyle *) xcalloc(1, sizeof(*nwp)); | |
447 | ||
448 | nwp->w_start = lineloc; | |
c4a58397 | 449 | nwp->w_end.type = I_SEEK; |
6e37afca KB |
450 | nwp->w_next = whyles; |
451 | whyles = nwp; | |
452 | zlast = T_WHILE; | |
453 | if (intty) { | |
454 | /* | |
455 | * The tty preread | |
456 | */ | |
457 | preread(); | |
458 | doagain(); | |
459 | return; | |
d43c89f3 | 460 | } |
6e37afca KB |
461 | } |
462 | if (status) | |
463 | /* We ain't gonna loop no more, no more! */ | |
464 | toend(); | |
d43c89f3 BJ |
465 | } |
466 | ||
6e37afca | 467 | static void |
d43c89f3 BJ |
468 | preread() |
469 | { | |
c4a58397 | 470 | whyles->w_end.type = I_SEEK; |
6e37afca | 471 | if (setintr) |
b9c4f741 | 472 | (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); |
6e37afca | 473 | |
0aec749d | 474 | search(T_BREAK, 0, NULL); /* read the expression in */ |
6e37afca KB |
475 | if (setintr) |
476 | (void) sigblock(sigmask(SIGINT)); | |
c4a58397 | 477 | btell(&whyles->w_end); |
d43c89f3 BJ |
478 | } |
479 | ||
6e37afca | 480 | void |
454c2aa3 CZ |
481 | /*ARGSUSED*/ |
482 | doend(v, t) | |
483 | Char **v; | |
484 | struct command *t; | |
d43c89f3 | 485 | { |
6e37afca KB |
486 | if (!whyles) |
487 | stderror(ERR_NAME | ERR_NOTWHILE); | |
c4a58397 | 488 | btell(&whyles->w_end); |
6e37afca | 489 | doagain(); |
d43c89f3 BJ |
490 | } |
491 | ||
6e37afca | 492 | void |
454c2aa3 CZ |
493 | /*ARGSUSED*/ |
494 | docontin(v, t) | |
495 | Char **v; | |
496 | struct command *t; | |
d43c89f3 | 497 | { |
6e37afca KB |
498 | if (!whyles) |
499 | stderror(ERR_NAME | ERR_NOTWHILE); | |
500 | doagain(); | |
d43c89f3 BJ |
501 | } |
502 | ||
6e37afca | 503 | static void |
d43c89f3 BJ |
504 | doagain() |
505 | { | |
6e37afca KB |
506 | /* Repeating a while is simple */ |
507 | if (whyles->w_fename == 0) { | |
c4a58397 | 508 | bseek(&whyles->w_start); |
6e37afca KB |
509 | return; |
510 | } | |
511 | /* | |
512 | * The foreach variable list actually has a spurious word ")" at the end of | |
513 | * the w_fe list. Thus we are at the of the list if one word beyond this | |
514 | * is 0. | |
515 | */ | |
516 | if (!whyles->w_fe[1]) { | |
454c2aa3 | 517 | dobreak(NULL, NULL); |
6e37afca KB |
518 | return; |
519 | } | |
520 | set(whyles->w_fename, Strsave(*whyles->w_fe++)); | |
c4a58397 | 521 | bseek(&whyles->w_start); |
d43c89f3 BJ |
522 | } |
523 | ||
6e37afca | 524 | void |
d43c89f3 | 525 | dorepeat(v, kp) |
6e37afca KB |
526 | Char **v; |
527 | struct command *kp; | |
d43c89f3 | 528 | { |
6e37afca | 529 | register int i; |
b9c4f741 | 530 | register sigset_t omask = 0; |
6e37afca KB |
531 | |
532 | i = getn(v[1]); | |
533 | if (setintr) | |
534 | omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); | |
535 | lshift(v, 2); | |
536 | while (i > 0) { | |
d43c89f3 | 537 | if (setintr) |
6e37afca KB |
538 | (void) sigsetmask(omask); |
539 | reexecute(kp); | |
540 | --i; | |
541 | } | |
542 | donefds(); | |
543 | if (setintr) | |
544 | (void) sigsetmask(omask); | |
d43c89f3 BJ |
545 | } |
546 | ||
6e37afca | 547 | void |
454c2aa3 CZ |
548 | /*ARGSUSED*/ |
549 | doswbrk(v, t) | |
550 | Char **v; | |
551 | struct command *t; | |
d43c89f3 | 552 | { |
0aec749d | 553 | search(T_BRKSW, 0, NULL); |
d43c89f3 BJ |
554 | } |
555 | ||
6e37afca | 556 | int |
d43c89f3 | 557 | srchx(cp) |
6e37afca | 558 | register Char *cp; |
d43c89f3 | 559 | { |
6e37afca KB |
560 | register struct srch *sp, *sp1, *sp2; |
561 | register i; | |
562 | ||
563 | /* | |
564 | * Binary search Sp1 is the beginning of the current search range. Sp2 is | |
565 | * one past the end. | |
566 | */ | |
567 | for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { | |
568 | sp = sp1 + ((sp2 - sp1) >> 1); | |
569 | if ((i = *cp - *sp->s_name) == 0 && | |
570 | (i = Strcmp(cp, str2short(sp->s_name))) == 0) | |
571 | return sp->s_value; | |
572 | if (i < 0) | |
573 | sp2 = sp; | |
574 | else | |
575 | sp1 = sp + 1; | |
576 | } | |
577 | return (-1); | |
d43c89f3 BJ |
578 | } |
579 | ||
6e37afca KB |
580 | static Char Stype; |
581 | static Char *Sgoal; | |
d43c89f3 BJ |
582 | |
583 | /*VARARGS2*/ | |
6e37afca | 584 | void |
d43c89f3 | 585 | search(type, level, goal) |
6e37afca KB |
586 | int type; |
587 | register int level; | |
588 | Char *goal; | |
d43c89f3 | 589 | { |
6e37afca KB |
590 | Char wordbuf[BUFSIZ]; |
591 | register Char *aword = wordbuf; | |
592 | register Char *cp; | |
593 | ||
594 | Stype = type; | |
595 | Sgoal = goal; | |
c4a58397 CZ |
596 | if (type == T_GOTO) { |
597 | struct Ain a; | |
598 | a.type = F_SEEK; | |
599 | a.f_seek = 0; | |
600 | bseek(&a); | |
601 | } | |
6e37afca | 602 | do { |
c4a58397 | 603 | if (intty && fseekp == feobp && aret == F_SEEK) |
454c2aa3 | 604 | (void) fprintf(cshout, "? "), (void) fflush(cshout); |
6e37afca KB |
605 | aword[0] = 0; |
606 | (void) getword(aword); | |
607 | switch (srchx(aword)) { | |
d43c89f3 | 608 | |
6e37afca KB |
609 | case T_ELSE: |
610 | if (level == 0 && type == T_IF) | |
611 | return; | |
612 | break; | |
613 | ||
614 | case T_IF: | |
615 | while (getword(aword)) | |
616 | continue; | |
617 | if ((type == T_IF || type == T_ELSE) && | |
618 | eq(aword, STRthen)) | |
619 | level++; | |
620 | break; | |
621 | ||
622 | case T_ENDIF: | |
623 | if (type == T_IF || type == T_ELSE) | |
624 | level--; | |
625 | break; | |
626 | ||
627 | case T_FOREACH: | |
628 | case T_WHILE: | |
629 | if (type == T_BREAK) | |
630 | level++; | |
631 | break; | |
632 | ||
633 | case T_END: | |
634 | if (type == T_BREAK) | |
635 | level--; | |
636 | break; | |
637 | ||
638 | case T_SWITCH: | |
639 | if (type == T_SWITCH || type == T_BRKSW) | |
640 | level++; | |
641 | break; | |
642 | ||
643 | case T_ENDSW: | |
644 | if (type == T_SWITCH || type == T_BRKSW) | |
645 | level--; | |
646 | break; | |
647 | ||
648 | case T_LABEL: | |
649 | if (type == T_GOTO && getword(aword) && eq(aword, goal)) | |
650 | level = -1; | |
651 | break; | |
652 | ||
653 | default: | |
654 | if (type != T_GOTO && (type != T_SWITCH || level != 0)) | |
655 | break; | |
656 | if (lastchr(aword) != ':') | |
657 | break; | |
658 | aword[Strlen(aword) - 1] = 0; | |
659 | if (type == T_GOTO && eq(aword, goal) || | |
660 | type == T_SWITCH && eq(aword, STRdefault)) | |
661 | level = -1; | |
662 | break; | |
663 | ||
664 | case T_CASE: | |
665 | if (type != T_SWITCH || level != 0) | |
666 | break; | |
667 | (void) getword(aword); | |
668 | if (lastchr(aword) == ':') | |
669 | aword[Strlen(aword) - 1] = 0; | |
670 | cp = strip(Dfix1(aword)); | |
671 | if (Gmatch(goal, cp)) | |
672 | level = -1; | |
673 | xfree((ptr_t) cp); | |
674 | break; | |
675 | ||
676 | case T_DEFAULT: | |
677 | if (type == T_SWITCH && level == 0) | |
678 | level = -1; | |
679 | break; | |
680 | } | |
681 | (void) getword(NULL); | |
682 | } while (level >= 0); | |
d43c89f3 BJ |
683 | } |
684 | ||
6e37afca | 685 | static int |
d43c89f3 | 686 | getword(wp) |
6e37afca | 687 | register Char *wp; |
d43c89f3 | 688 | { |
6e37afca KB |
689 | register int found = 0; |
690 | register int c, d; | |
691 | int kwd = 0; | |
692 | Char *owp = wp; | |
6e37afca KB |
693 | |
694 | c = readc(1); | |
695 | d = 0; | |
696 | do { | |
697 | while (c == ' ' || c == '\t') | |
698 | c = readc(1); | |
699 | if (c == '#') | |
700 | do | |
701 | c = readc(1); | |
702 | while (c >= 0 && c != '\n'); | |
703 | if (c < 0) | |
704 | goto past; | |
705 | if (c == '\n') { | |
706 | if (wp) | |
707 | break; | |
708 | return (0); | |
709 | } | |
710 | unreadc(c); | |
711 | found = 1; | |
d43c89f3 | 712 | do { |
6e37afca KB |
713 | c = readc(1); |
714 | if (c == '\\' && (c = readc(1)) == '\n') | |
715 | c = ' '; | |
716 | if (c == '\'' || c == '"') | |
717 | if (d == 0) | |
718 | d = c; | |
719 | else if (d == c) | |
720 | d = 0; | |
721 | if (c < 0) | |
722 | goto past; | |
723 | if (wp) { | |
724 | *wp++ = c; | |
725 | *wp = 0; /* end the string b4 test */ | |
726 | } | |
727 | } while ((d || !(kwd = keyword(owp)) && c != ' ' | |
728 | && c != '\t') && c != '\n'); | |
729 | } while (wp == 0); | |
730 | ||
731 | /* | |
732 | * if we have read a keyword ( "if", "switch" or "while" ) then we do not | |
733 | * need to unreadc the look-ahead char | |
734 | */ | |
735 | if (!kwd) { | |
d43c89f3 BJ |
736 | unreadc(c); |
737 | if (found) | |
6e37afca KB |
738 | *--wp = 0; |
739 | } | |
740 | ||
741 | return (found); | |
d43c89f3 BJ |
742 | |
743 | past: | |
6e37afca | 744 | switch (Stype) { |
d43c89f3 | 745 | |
6e37afca KB |
746 | case T_IF: |
747 | stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); | |
d43c89f3 | 748 | |
6e37afca KB |
749 | case T_ELSE: |
750 | stderror(ERR_NAME | ERR_NOTFOUND, "endif"); | |
d43c89f3 | 751 | |
6e37afca KB |
752 | case T_BRKSW: |
753 | case T_SWITCH: | |
754 | stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); | |
d43c89f3 | 755 | |
6e37afca KB |
756 | case T_BREAK: |
757 | stderror(ERR_NAME | ERR_NOTFOUND, "end"); | |
d43c89f3 | 758 | |
6e37afca KB |
759 | case T_GOTO: |
760 | setname(short2str(Sgoal)); | |
761 | stderror(ERR_NAME | ERR_NOTFOUND, "label"); | |
762 | } | |
763 | /* NOTREACHED */ | |
764 | return (0); | |
d43c89f3 BJ |
765 | } |
766 | ||
6e37afca KB |
767 | /* |
768 | * keyword(wp) determines if wp is one of the built-n functions if, | |
769 | * switch or while. It seems that when an if statement looks like | |
770 | * "if(" then getword above sucks in the '(' and so the search routine | |
771 | * never finds what it is scanning for. Rather than rewrite doword, I hack | |
772 | * in a test to see if the string forms a keyword. Then doword stops | |
773 | * and returns the word "if" -strike | |
774 | */ | |
775 | ||
776 | static int | |
777 | keyword(wp) | |
778 | Char *wp; | |
d43c89f3 | 779 | { |
6e37afca KB |
780 | static Char STRif[] = {'i', 'f', '\0'}; |
781 | static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'}; | |
782 | static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'}; | |
d43c89f3 | 783 | |
6e37afca KB |
784 | if (!wp) |
785 | return (0); | |
786 | ||
787 | if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0) | |
788 | || (Strcmp(wp, STRswitch) == 0)) | |
789 | return (1); | |
790 | ||
791 | return (0); | |
792 | } | |
793 | ||
794 | static void | |
795 | toend() | |
796 | { | |
c4a58397 | 797 | if (whyles->w_end.type == I_SEEK) { |
6e37afca | 798 | search(T_BREAK, 0, NULL); |
c4a58397 CZ |
799 | btell(&whyles->w_end); |
800 | whyles->w_end.f_seek--; | |
6e37afca KB |
801 | } |
802 | else | |
c4a58397 | 803 | bseek(&whyles->w_end); |
6e37afca | 804 | wfree(); |
d43c89f3 BJ |
805 | } |
806 | ||
6e37afca | 807 | void |
d43c89f3 BJ |
808 | wfree() |
809 | { | |
c4a58397 CZ |
810 | struct Ain o; |
811 | struct whyle *nwp; | |
812 | btell(&o); | |
813 | ||
814 | if (o.type != F_SEEK) | |
815 | return; | |
6e37afca | 816 | |
c4a58397 | 817 | for (; whyles; whyles = nwp) { |
6e37afca | 818 | register struct whyle *wp = whyles; |
c4a58397 CZ |
819 | nwp = wp->w_next; |
820 | if (wp->w_start.type != F_SEEK || wp->w_end.type != F_SEEK) | |
821 | continue; | |
6e37afca | 822 | |
c4a58397 CZ |
823 | if (o.f_seek >= wp->w_start.f_seek && |
824 | (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) | |
6e37afca KB |
825 | break; |
826 | if (wp->w_fe0) | |
827 | blkfree(wp->w_fe0); | |
828 | if (wp->w_fename) | |
829 | xfree((ptr_t) wp->w_fename); | |
830 | xfree((ptr_t) wp); | |
6e37afca | 831 | } |
d43c89f3 BJ |
832 | } |
833 | ||
6e37afca | 834 | void |
454c2aa3 CZ |
835 | /*ARGSUSED*/ |
836 | doecho(v, t) | |
837 | Char **v; | |
838 | struct command *t; | |
d43c89f3 | 839 | { |
6e37afca | 840 | xecho(' ', v); |
d43c89f3 BJ |
841 | } |
842 | ||
6e37afca | 843 | void |
454c2aa3 CZ |
844 | /*ARGSUSED*/ |
845 | doglob(v, t) | |
846 | Char **v; | |
847 | struct command *t; | |
d43c89f3 | 848 | { |
6e37afca | 849 | xecho(0, v); |
454c2aa3 | 850 | (void) fflush(cshout); |
d43c89f3 BJ |
851 | } |
852 | ||
6e37afca KB |
853 | static void |
854 | xecho(sep, v) | |
0aec749d | 855 | int sep; |
6e37afca | 856 | register Char **v; |
d43c89f3 | 857 | { |
6e37afca KB |
858 | register Char *cp; |
859 | int nonl = 0; | |
860 | ||
861 | if (setintr) | |
b9c4f741 | 862 | (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); |
6e37afca KB |
863 | v++; |
864 | if (*v == 0) | |
865 | return; | |
866 | gflag = 0, tglob(v); | |
867 | if (gflag) { | |
868 | v = globall(v); | |
869 | if (v == 0) | |
870 | stderror(ERR_NAME | ERR_NOMATCH); | |
871 | } | |
872 | else { | |
873 | v = gargv = saveblk(v); | |
874 | trim(v); | |
875 | } | |
876 | if (sep == ' ' && *v && eq(*v, STRmn)) | |
877 | nonl++, v++; | |
878 | while (cp = *v++) { | |
879 | register int c; | |
880 | ||
881 | while (c = *cp++) | |
454c2aa3 | 882 | (void) fputc(c | QUOTE, cshout); |
d43c89f3 | 883 | |
6e37afca | 884 | if (*v) |
454c2aa3 | 885 | (void) fputc(sep | QUOTE, cshout); |
6e37afca KB |
886 | } |
887 | if (sep && nonl == 0) | |
454c2aa3 | 888 | (void) fputc('\n', cshout); |
6e37afca | 889 | else |
454c2aa3 | 890 | (void) fflush(cshout); |
6e37afca KB |
891 | if (setintr) |
892 | (void) sigblock(sigmask(SIGINT)); | |
893 | if (gargv) | |
894 | blkfree(gargv), gargv = 0; | |
d43c89f3 BJ |
895 | } |
896 | ||
6e37afca | 897 | void |
454c2aa3 CZ |
898 | /*ARGSUSED*/ |
899 | dosetenv(v, t) | |
900 | Char **v; | |
901 | struct command *t; | |
d43c89f3 | 902 | { |
6e37afca | 903 | Char *vp, *lp; |
d43c89f3 | 904 | |
6e37afca KB |
905 | v++; |
906 | if ((vp = *v++) == 0) { | |
907 | register Char **ep; | |
c349da0d | 908 | |
6e37afca | 909 | if (setintr) |
b9c4f741 | 910 | (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); |
6e37afca | 911 | for (ep = STR_environ; *ep; ep++) |
454c2aa3 | 912 | (void) fprintf(cshout, "%s\n", short2str(*ep)); |
6e37afca KB |
913 | return; |
914 | } | |
915 | if ((lp = *v++) == 0) | |
916 | lp = STRNULL; | |
43fa56b8 | 917 | Setenv(vp, lp = globone(lp, G_APPEND)); |
6e37afca KB |
918 | if (eq(vp, STRPATH)) { |
919 | importpath(lp); | |
454c2aa3 | 920 | dohash(NULL, NULL); |
6e37afca KB |
921 | } |
922 | else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) { | |
923 | #ifdef NLS | |
924 | int k; | |
925 | ||
926 | (void) setlocale(LC_ALL, ""); | |
927 | for (k = 0200; k <= 0377 && !Isprint(k); k++); | |
928 | AsciiOnly = k > 0377; | |
929 | #else | |
930 | AsciiOnly = 0; | |
931 | #endif /* NLS */ | |
932 | } | |
933 | xfree((ptr_t) lp); | |
d43c89f3 BJ |
934 | } |
935 | ||
6e37afca | 936 | void |
454c2aa3 CZ |
937 | /*ARGSUSED*/ |
938 | dounsetenv(v, t) | |
939 | Char **v; | |
940 | struct command *t; | |
d43c89f3 | 941 | { |
6e37afca KB |
942 | Char **ep, *p, *n; |
943 | int i, maxi; | |
944 | static Char *name = NULL; | |
945 | ||
946 | if (name) | |
947 | xfree((ptr_t) name); | |
948 | /* | |
949 | * Find the longest environment variable | |
950 | */ | |
951 | for (maxi = 0, ep = STR_environ; *ep; ep++) { | |
952 | for (i = 0, p = *ep; *p && *p != '='; p++, i++); | |
953 | if (i > maxi) | |
954 | maxi = i; | |
955 | } | |
956 | ||
957 | name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char)); | |
958 | ||
2ce74acc CZ |
959 | while (++v && *v) |
960 | for (maxi = 1; maxi;) | |
961 | for (maxi = 0, ep = STR_environ; *ep; ep++) { | |
962 | for (n = name, p = *ep; *p && *p != '='; *n++ = *p++); | |
963 | *n = '\0'; | |
964 | if (!Gmatch(name, *v)) | |
965 | continue; | |
966 | maxi = 1; | |
967 | if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) { | |
6e37afca | 968 | #ifdef NLS |
2ce74acc | 969 | int k; |
6e37afca | 970 | |
2ce74acc CZ |
971 | (void) setlocale(LC_ALL, ""); |
972 | for (k = 0200; k <= 0377 && !Isprint(k); k++); | |
973 | AsciiOnly = k > 0377; | |
6e37afca | 974 | #else |
2ce74acc CZ |
975 | AsciiOnly = getenv("LANG") == NULL && |
976 | getenv("LC_CTYPE") == NULL; | |
6e37afca | 977 | #endif /* NLS */ |
2ce74acc CZ |
978 | } |
979 | /* | |
980 | * Delete name, and start again cause the environment changes | |
981 | */ | |
982 | Unsetenv(name); | |
983 | break; | |
6e37afca | 984 | } |
6e37afca | 985 | xfree((ptr_t) name), name = NULL; |
d43c89f3 BJ |
986 | } |
987 | ||
6e37afca KB |
988 | void |
989 | Setenv(name, val) | |
990 | Char *name, *val; | |
d43c89f3 | 991 | { |
6e37afca KB |
992 | register Char **ep = STR_environ; |
993 | register Char *cp, *dp; | |
994 | Char *blk[2]; | |
995 | Char **oep = ep; | |
996 | ||
997 | ||
998 | for (; *ep; ep++) { | |
999 | for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) | |
1000 | continue; | |
1001 | if (*cp != 0 || *dp != '=') | |
1002 | continue; | |
1003 | cp = Strspl(STRequal, val); | |
1004 | xfree((ptr_t) * ep); | |
1005 | *ep = strip(Strspl(name, cp)); | |
1006 | xfree((ptr_t) cp); | |
1007 | blkfree((Char **) environ); | |
1008 | environ = short2blk(STR_environ); | |
1009 | return; | |
1010 | } | |
1011 | cp = Strspl(name, STRequal); | |
1012 | blk[0] = strip(Strspl(cp, val)); | |
1013 | xfree((ptr_t) cp); | |
1014 | blk[1] = 0; | |
1015 | STR_environ = blkspl(STR_environ, blk); | |
1016 | blkfree((Char **) environ); | |
1017 | environ = short2blk(STR_environ); | |
1018 | xfree((ptr_t) oep); | |
d43c89f3 BJ |
1019 | } |
1020 | ||
6e37afca KB |
1021 | static void |
1022 | Unsetenv(name) | |
1023 | Char *name; | |
d43c89f3 | 1024 | { |
6e37afca KB |
1025 | register Char **ep = STR_environ; |
1026 | register Char *cp, *dp; | |
1027 | Char **oep = ep; | |
1028 | ||
1029 | for (; *ep; ep++) { | |
1030 | for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) | |
1031 | continue; | |
1032 | if (*cp != 0 || *dp != '=') | |
1033 | continue; | |
1034 | cp = *ep; | |
1035 | *ep = 0; | |
1036 | STR_environ = blkspl(STR_environ, ep + 1); | |
1037 | environ = short2blk(STR_environ); | |
1038 | *ep = cp; | |
1039 | xfree((ptr_t) cp); | |
1040 | xfree((ptr_t) oep); | |
1041 | return; | |
1042 | } | |
d43c89f3 BJ |
1043 | } |
1044 | ||
6e37afca | 1045 | void |
454c2aa3 CZ |
1046 | /*ARGSUSED*/ |
1047 | doumask(v, t) | |
1048 | Char **v; | |
1049 | struct command *t; | |
d43c89f3 | 1050 | { |
6e37afca KB |
1051 | register Char *cp = v[1]; |
1052 | register int i; | |
d43c89f3 | 1053 | |
6e37afca KB |
1054 | if (cp == 0) { |
1055 | i = umask(0); | |
35371dec | 1056 | (void) umask(i); |
454c2aa3 | 1057 | (void) fprintf(cshout, "%o\n", i); |
6e37afca KB |
1058 | return; |
1059 | } | |
1060 | i = 0; | |
1061 | while (Isdigit(*cp) && *cp != '8' && *cp != '9') | |
1062 | i = i * 8 + *cp++ - '0'; | |
1063 | if (*cp || i < 0 || i > 0777) | |
1064 | stderror(ERR_NAME | ERR_MASK); | |
1065 | (void) umask(i); | |
d43c89f3 BJ |
1066 | } |
1067 | ||
6e37afca KB |
1068 | typedef int RLIM_TYPE; |
1069 | ||
1070 | static struct limits { | |
1071 | int limconst; | |
1072 | char *limname; | |
1073 | int limdiv; | |
1074 | char *limscale; | |
1075 | } limits[] = { | |
1076 | RLIMIT_CPU, "cputime", 1, "seconds", | |
1077 | RLIMIT_FSIZE, "filesize", 1024, "kbytes", | |
1078 | RLIMIT_DATA, "datasize", 1024, "kbytes", | |
1079 | RLIMIT_STACK, "stacksize", 1024, "kbytes", | |
1080 | RLIMIT_CORE, "coredumpsize", 1024, "kbytes", | |
1081 | RLIMIT_RSS, "memoryuse", 1024, "kbytes", | |
0aec749d CZ |
1082 | RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes", |
1083 | RLIMIT_NPROC, "maxproc", 1, "", | |
1084 | RLIMIT_OFILE, "openfiles", 1, "", | |
1085 | -1, NULL, 0, NULL | |
d43c89f3 BJ |
1086 | }; |
1087 | ||
6e37afca KB |
1088 | static struct limits *findlim(); |
1089 | static RLIM_TYPE getval(); | |
1090 | static void limtail(); | |
1091 | static void plim(); | |
1092 | static int setlim(); | |
1093 | ||
1094 | static struct limits * | |
d43c89f3 | 1095 | findlim(cp) |
6e37afca | 1096 | Char *cp; |
d43c89f3 | 1097 | { |
6e37afca KB |
1098 | register struct limits *lp, *res; |
1099 | ||
1100 | res = (struct limits *) NULL; | |
1101 | for (lp = limits; lp->limconst >= 0; lp++) | |
1102 | if (prefix(cp, str2short(lp->limname))) { | |
1103 | if (res) | |
1104 | stderror(ERR_NAME | ERR_AMBIG); | |
1105 | res = lp; | |
1106 | } | |
1107 | if (res) | |
1108 | return (res); | |
1109 | stderror(ERR_NAME | ERR_LIMIT); | |
1110 | /* NOTREACHED */ | |
1111 | return (0); | |
d43c89f3 BJ |
1112 | } |
1113 | ||
6e37afca | 1114 | void |
454c2aa3 CZ |
1115 | /*ARGSUSED*/ |
1116 | dolimit(v, t) | |
1117 | Char **v; | |
1118 | struct command *t; | |
d43c89f3 | 1119 | { |
6e37afca KB |
1120 | register struct limits *lp; |
1121 | register RLIM_TYPE limit; | |
1122 | char hard = 0; | |
d43c89f3 | 1123 | |
6e37afca KB |
1124 | v++; |
1125 | if (*v && eq(*v, STRmh)) { | |
1126 | hard = 1; | |
d43c89f3 | 1127 | v++; |
6e37afca KB |
1128 | } |
1129 | if (*v == 0) { | |
1130 | for (lp = limits; lp->limconst >= 0; lp++) | |
1131 | plim(lp, hard); | |
1132 | return; | |
1133 | } | |
1134 | lp = findlim(v[0]); | |
1135 | if (v[1] == 0) { | |
1136 | plim(lp, hard); | |
1137 | return; | |
1138 | } | |
1139 | limit = getval(lp, v + 1); | |
1140 | if (setlim(lp, hard, limit) < 0) | |
1141 | stderror(ERR_SILENT); | |
d43c89f3 BJ |
1142 | } |
1143 | ||
6e37afca | 1144 | static RLIM_TYPE |
d43c89f3 | 1145 | getval(lp, v) |
6e37afca KB |
1146 | register struct limits *lp; |
1147 | Char **v; | |
d43c89f3 | 1148 | { |
6e37afca KB |
1149 | register float f; |
1150 | double atof(); | |
1151 | Char *cp = *v++; | |
d43c89f3 | 1152 | |
6e37afca | 1153 | f = atof(short2str(cp)); |
d43c89f3 | 1154 | |
6e37afca KB |
1155 | while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') |
1156 | cp++; | |
1157 | if (*cp == 0) { | |
1158 | if (*v == 0) | |
1159 | return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv)); | |
1160 | cp = *v; | |
1161 | } | |
1162 | switch (*cp) { | |
1163 | case ':': | |
1164 | if (lp->limconst != RLIMIT_CPU) | |
1165 | goto badscal; | |
1166 | return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1)))); | |
1167 | case 'h': | |
1168 | if (lp->limconst != RLIMIT_CPU) | |
1169 | goto badscal; | |
1170 | limtail(cp, "hours"); | |
1171 | f *= 3600.0; | |
1172 | break; | |
1173 | case 'm': | |
1174 | if (lp->limconst == RLIMIT_CPU) { | |
1175 | limtail(cp, "minutes"); | |
1176 | f *= 60.0; | |
1177 | break; | |
d43c89f3 | 1178 | } |
6e37afca KB |
1179 | *cp = 'm'; |
1180 | limtail(cp, "megabytes"); | |
1181 | f *= 1024.0 * 1024.0; | |
1182 | break; | |
1183 | case 's': | |
1184 | if (lp->limconst != RLIMIT_CPU) | |
1185 | goto badscal; | |
1186 | limtail(cp, "seconds"); | |
1187 | break; | |
1188 | case 'M': | |
1189 | if (lp->limconst == RLIMIT_CPU) | |
1190 | goto badscal; | |
1191 | *cp = 'm'; | |
1192 | limtail(cp, "megabytes"); | |
1193 | f *= 1024.0 * 1024.0; | |
1194 | break; | |
1195 | case 'k': | |
1196 | if (lp->limconst == RLIMIT_CPU) | |
1197 | goto badscal; | |
1198 | limtail(cp, "kbytes"); | |
1199 | f *= 1024.0; | |
1200 | break; | |
1201 | case 'u': | |
1202 | limtail(cp, "unlimited"); | |
1203 | return (RLIM_INFINITY); | |
1204 | default: | |
1205 | badscal: | |
1206 | stderror(ERR_NAME | ERR_SCALEF); | |
1207 | } | |
c4a58397 CZ |
1208 | if ((f + 0.5) >= (float) 0x7fffffff || (f + 0.5) < (float) 0x80000000) |
1209 | stderror(ERR_NAME | ERR_SCALEF); | |
6e37afca | 1210 | return ((RLIM_TYPE) (f + 0.5)); |
d43c89f3 BJ |
1211 | } |
1212 | ||
6e37afca KB |
1213 | static void |
1214 | limtail(cp, str) | |
1215 | Char *cp; | |
1216 | char *str; | |
d43c89f3 | 1217 | { |
6e37afca KB |
1218 | while (*cp && *cp == *str) |
1219 | cp++, str++; | |
1220 | if (*cp) | |
1221 | stderror(ERR_BADSCALE, str); | |
d43c89f3 BJ |
1222 | } |
1223 | ||
6e37afca KB |
1224 | |
1225 | /*ARGSUSED*/ | |
1226 | static void | |
f74ac01c | 1227 | plim(lp, hard) |
6e37afca KB |
1228 | register struct limits *lp; |
1229 | Char hard; | |
d43c89f3 | 1230 | { |
6e37afca KB |
1231 | struct rlimit rlim; |
1232 | RLIM_TYPE limit; | |
1233 | ||
454c2aa3 | 1234 | (void) fprintf(cshout, "%s \t", lp->limname); |
6e37afca KB |
1235 | |
1236 | (void) getrlimit(lp->limconst, &rlim); | |
1237 | limit = hard ? rlim.rlim_max : rlim.rlim_cur; | |
1238 | ||
1239 | if (limit == RLIM_INFINITY) | |
454c2aa3 | 1240 | (void) fprintf(cshout, "unlimited"); |
6e37afca KB |
1241 | else if (lp->limconst == RLIMIT_CPU) |
1242 | psecs((long) limit); | |
1243 | else | |
454c2aa3 CZ |
1244 | (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv), |
1245 | lp->limscale); | |
1246 | (void) fputc('\n', cshout); | |
d43c89f3 BJ |
1247 | } |
1248 | ||
6e37afca | 1249 | void |
454c2aa3 CZ |
1250 | /*ARGSUSED*/ |
1251 | dounlimit(v, t) | |
1252 | Char **v; | |
1253 | struct command *t; | |
d43c89f3 | 1254 | { |
6e37afca KB |
1255 | register struct limits *lp; |
1256 | int lerr = 0; | |
1257 | Char hard = 0; | |
d43c89f3 | 1258 | |
6e37afca KB |
1259 | v++; |
1260 | if (*v && eq(*v, STRmh)) { | |
1261 | hard = 1; | |
d43c89f3 | 1262 | v++; |
6e37afca KB |
1263 | } |
1264 | if (*v == 0) { | |
1265 | for (lp = limits; lp->limconst >= 0; lp++) | |
1266 | if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) | |
1267 | lerr++; | |
1268 | if (lerr) | |
1269 | stderror(ERR_SILENT); | |
1270 | return; | |
1271 | } | |
1272 | while (*v) { | |
1273 | lp = findlim(*v++); | |
1274 | if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) | |
1275 | stderror(ERR_SILENT); | |
1276 | } | |
d43c89f3 BJ |
1277 | } |
1278 | ||
6e37afca | 1279 | static int |
f74ac01c | 1280 | setlim(lp, hard, limit) |
6e37afca KB |
1281 | register struct limits *lp; |
1282 | Char hard; | |
1283 | RLIM_TYPE limit; | |
d43c89f3 | 1284 | { |
6e37afca KB |
1285 | struct rlimit rlim; |
1286 | ||
1287 | (void) getrlimit(lp->limconst, &rlim); | |
1288 | ||
1289 | if (hard) | |
1290 | rlim.rlim_max = limit; | |
1291 | else if (limit == RLIM_INFINITY && geteuid() != 0) | |
1292 | rlim.rlim_cur = rlim.rlim_max; | |
1293 | else | |
1294 | rlim.rlim_cur = limit; | |
1295 | ||
1296 | if (setrlimit(lp->limconst, &rlim) < 0) { | |
454c2aa3 CZ |
1297 | (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname, |
1298 | limit == RLIM_INFINITY ? "remove" : "set", | |
1299 | hard ? " hard" : ""); | |
6e37afca KB |
1300 | return (-1); |
1301 | } | |
1302 | return (0); | |
d43c89f3 BJ |
1303 | } |
1304 | ||
6e37afca | 1305 | void |
454c2aa3 CZ |
1306 | /*ARGSUSED*/ |
1307 | dosuspend(v, t) | |
1308 | Char **v; | |
1309 | struct command *t; | |
d43c89f3 | 1310 | { |
6e37afca KB |
1311 | int ctpgrp; |
1312 | ||
1313 | void (*old) (); | |
1314 | ||
1315 | if (loginsh) | |
1316 | stderror(ERR_SUSPLOG); | |
1317 | untty(); | |
1318 | ||
1319 | old = signal(SIGTSTP, SIG_DFL); | |
1320 | (void) kill(0, SIGTSTP); | |
1321 | /* the shell stops here */ | |
1322 | (void) signal(SIGTSTP, old); | |
1323 | ||
1324 | if (tpgrp != -1) { | |
6e37afca | 1325 | ctpgrp = tcgetpgrp(FSHTTY); |
454c2aa3 | 1326 | while (ctpgrp != opgrp) { |
6e37afca KB |
1327 | old = signal(SIGTTIN, SIG_DFL); |
1328 | (void) kill(0, SIGTTIN); | |
1329 | (void) signal(SIGTTIN, old); | |
d43c89f3 | 1330 | } |
6e37afca KB |
1331 | (void) setpgid(0, shpgrp); |
1332 | (void) tcsetpgrp(FSHTTY, shpgrp); | |
1333 | } | |
d43c89f3 BJ |
1334 | } |
1335 | ||
6e37afca KB |
1336 | /* This is the dreaded EVAL built-in. |
1337 | * If you don't fiddle with file descriptors, and reset didfds, | |
1338 | * this command will either ignore redirection inside or outside | |
1339 | * its aguments, e.g. eval "date >x" vs. eval "date" >x | |
1340 | * The stuff here seems to work, but I did it by trial and error rather | |
1341 | * than really knowing what was going on. If tpgrp is zero, we are | |
1342 | * probably a background eval, e.g. "eval date &", and we want to | |
1343 | * make sure that any processes we start stay in our pgrp. | |
1344 | * This is also the case for "time eval date" -- stay in same pgrp. | |
1345 | * Otherwise, under stty tostop, processes will stop in the wrong | |
1346 | * pgrp, with no way for the shell to get them going again. -IAN! | |
1347 | */ | |
454c2aa3 | 1348 | static Char **gv = NULL; |
6e37afca | 1349 | void |
454c2aa3 CZ |
1350 | /*ARGSUSED*/ |
1351 | doeval(v, t) | |
1352 | Char **v; | |
1353 | struct command *t; | |
d43c89f3 | 1354 | { |
6e37afca KB |
1355 | Char **oevalvec; |
1356 | Char *oevalp; | |
1357 | int odidfds; | |
1358 | jmp_buf osetexit; | |
1359 | int my_reenter; | |
454c2aa3 | 1360 | Char **savegv = gv; |
6e37afca KB |
1361 | int saveIN; |
1362 | int saveOUT; | |
454c2aa3 | 1363 | int saveERR; |
6e37afca KB |
1364 | int oSHIN; |
1365 | int oSHOUT; | |
454c2aa3 | 1366 | int oSHERR; |
6e37afca KB |
1367 | |
1368 | oevalvec = evalvec; | |
1369 | oevalp = evalp; | |
1370 | odidfds = didfds; | |
1371 | oSHIN = SHIN; | |
1372 | oSHOUT = SHOUT; | |
454c2aa3 | 1373 | oSHERR = SHERR; |
6e37afca KB |
1374 | |
1375 | v++; | |
1376 | if (*v == 0) | |
1377 | return; | |
1378 | gflag = 0, tglob(v); | |
1379 | if (gflag) { | |
1380 | gv = v = globall(v); | |
1381 | gargv = 0; | |
1382 | if (v == 0) | |
1383 | stderror(ERR_NOMATCH); | |
1384 | v = copyblk(v); | |
1385 | } | |
1386 | else { | |
0aec749d | 1387 | gv = NULL; |
6e37afca KB |
1388 | v = copyblk(v); |
1389 | trim(v); | |
1390 | } | |
1391 | ||
1392 | saveIN = dcopy(SHIN, -1); | |
1393 | saveOUT = dcopy(SHOUT, -1); | |
454c2aa3 | 1394 | saveERR = dcopy(SHERR, -1); |
6e37afca KB |
1395 | |
1396 | getexit(osetexit); | |
1397 | ||
1398 | if ((my_reenter = setexit()) == 0) { | |
1399 | evalvec = v; | |
1400 | evalp = 0; | |
1401 | SHIN = dcopy(0, -1); | |
1402 | SHOUT = dcopy(1, -1); | |
454c2aa3 | 1403 | SHERR = dcopy(2, -1); |
6e37afca KB |
1404 | didfds = 0; |
1405 | process(0); | |
1406 | } | |
1407 | ||
1408 | evalvec = oevalvec; | |
1409 | evalp = oevalp; | |
1410 | doneinp = 0; | |
1411 | didfds = odidfds; | |
1412 | (void) close(SHIN); | |
1413 | (void) close(SHOUT); | |
454c2aa3 | 1414 | (void) close(SHERR); |
6e37afca KB |
1415 | SHIN = dmove(saveIN, oSHIN); |
1416 | SHOUT = dmove(saveOUT, oSHOUT); | |
454c2aa3 | 1417 | SHERR = dmove(saveERR, oSHERR); |
6e37afca | 1418 | if (gv) |
454c2aa3 | 1419 | blkfree(gv), gv = NULL; |
6e37afca | 1420 | resexit(osetexit); |
454c2aa3 | 1421 | gv = savegv; |
6e37afca KB |
1422 | if (my_reenter) |
1423 | stderror(ERR_SILENT); | |
d43c89f3 | 1424 | } |
17b1f379 CZ |
1425 | |
1426 | void | |
1427 | /*ARGSUSED*/ | |
1428 | doprintf(v, t) | |
1429 | Char **v; | |
1430 | struct command *t; | |
1431 | { | |
1432 | char **c; | |
1433 | extern int progprintf __P((int, char **)); | |
1434 | int ret; | |
1435 | ||
1436 | ret = progprintf(blklen(v), c = short2blk(v)); | |
1437 | ||
1438 | blkfree((Char **) c); | |
1439 | if (ret) | |
1440 | stderror(ERR_SILENT); | |
1441 | } | |
1442 |