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