Loop freeing was busted
[unix-history] / usr / src / bin / csh / func.c
CommitLineData
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 9static 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
29extern char **environ;
30
31static int zlast = -1;
0aec749d
CZ
32static void islogin __P((void));
33static void reexecute __P((struct command *));
34static void preread __P((void));
35static void doagain __P((void));
099eec43 36static void search __P((int, int, Char *));
0aec749d
CZ
37static int getword __P((Char *));
38static int keyword __P((Char *));
0aec749d
CZ
39static void toend __P((void));
40static void xecho __P((int, Char **));
099eec43 41static void Unsetenv __P((Char *));
d43c89f3
BJ
42
43struct biltins *
44isbfunc(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 85void
d43c89f3 86func(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 102void
454c2aa3
CZ
103/*ARGSUSED*/
104doonintr(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 135void
454c2aa3
CZ
136/*ARGSUSED*/
137donohup(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 148void
454c2aa3
CZ
149/*ARGSUSED*/
150dozip(v, t)
151 Char **v;
152 struct command *t;
d43c89f3 153{
6e37afca 154 ;
d43c89f3
BJ
155}
156
6e37afca 157void
d43c89f3
BJ
158prvars()
159{
6e37afca 160 plist(&shvhed);
d43c89f3
BJ
161}
162
6e37afca 163void
454c2aa3
CZ
164/*ARGSUSED*/
165doalias(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 192void
454c2aa3
CZ
193/*ARGSUSED*/
194unalias(v, t)
195 Char **v;
196 struct command *t;
d43c89f3 197{
6e37afca 198 unset1(v, &aliases);
d43c89f3
BJ
199}
200
6e37afca 201void
454c2aa3
CZ
202/*ARGSUSED*/
203dologout(v, t)
204 Char **v;
205 struct command *t;
d43c89f3 206{
6e37afca
KB
207 islogin();
208 goodbye();
d43c89f3
BJ
209}
210
6e37afca 211void
454c2aa3
CZ
212/*ARGSUSED*/
213dologin(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 225static void
d43c89f3
BJ
226islogin()
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 235void
d43c89f3 236doif(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 275static void
d43c89f3 276reexecute(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 289void
454c2aa3
CZ
290/*ARGSUSED*/
291doelse(v, t)
292 Char **v;
293 struct command *t;
d43c89f3 294{
0aec749d 295 search(T_ELSE, 0, NULL);
d43c89f3
BJ
296}
297
6e37afca 298void
454c2aa3
CZ
299/*ARGSUSED*/
300dogoto(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
310void
311gotolab(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 334void
454c2aa3
CZ
335/*ARGSUSED*/
336doswitch(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 354void
454c2aa3
CZ
355/*ARGSUSED*/
356dobreak(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 366void
454c2aa3
CZ
367/*ARGSUSED*/
368doexit(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 388void
454c2aa3
CZ
389/*ARGSUSED*/
390doforeach(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 432void
454c2aa3
CZ
433/*ARGSUSED*/
434dowhile(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 477static void
d43c89f3
BJ
478preread()
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 490void
454c2aa3
CZ
491/*ARGSUSED*/
492doend(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 502void
454c2aa3
CZ
503/*ARGSUSED*/
504docontin(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 513static void
d43c89f3
BJ
514doagain()
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 534void
d43c89f3 535dorepeat(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 557void
454c2aa3
CZ
558/*ARGSUSED*/
559doswbrk(v, t)
560 Char **v;
561 struct command *t;
d43c89f3 562{
0aec749d 563 search(T_BRKSW, 0, NULL);
d43c89f3
BJ
564}
565
6e37afca 566int
d43c89f3 567srchx(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
590static Char Stype;
591static Char *Sgoal;
d43c89f3
BJ
592
593/*VARARGS2*/
6e37afca 594void
d43c89f3 595search(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 695static int
d43c89f3 696getword(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
753past:
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
786static int
787keyword(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
804static void
805toend()
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 817void
d43c89f3
BJ
818wfree()
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 854void
454c2aa3
CZ
855/*ARGSUSED*/
856doecho(v, t)
857 Char **v;
858 struct command *t;
d43c89f3 859{
6e37afca 860 xecho(' ', v);
d43c89f3
BJ
861}
862
6e37afca 863void
454c2aa3
CZ
864/*ARGSUSED*/
865doglob(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
873static void
874xecho(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 917void
454c2aa3
CZ
918/*ARGSUSED*/
919dosetenv(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 957void
454c2aa3
CZ
958/*ARGSUSED*/
959dounsetenv(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
1013void
1014Setenv(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
1046static void
1047Unsetenv(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 1070void
454c2aa3
CZ
1071/*ARGSUSED*/
1072doumask(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
1093typedef int RLIM_TYPE;
1094
1095static 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
1113static struct limits *findlim();
1114static RLIM_TYPE getval();
1115static void limtail();
1116static void plim();
1117static int setlim();
1118
1119static struct limits *
d43c89f3 1120findlim(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 1139void
454c2aa3
CZ
1140/*ARGSUSED*/
1141dolimit(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 1169static RLIM_TYPE
d43c89f3 1170getval(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:
1230badscal:
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
1238static void
1239limtail(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*/
1251static void
f74ac01c 1252plim(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 1274void
454c2aa3
CZ
1275/*ARGSUSED*/
1276dounlimit(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 1304static int
f74ac01c 1305setlim(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 1330void
454c2aa3
CZ
1331/*ARGSUSED*/
1332dosuspend(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 1373static Char **gv = NULL;
6e37afca 1374void
454c2aa3
CZ
1375/*ARGSUSED*/
1376doeval(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
1451void
1452/*ARGSUSED*/
1453doprintf(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}