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