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