1 /*- 2 * Copyright (c) 1980, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)func.c 5.38 (Berkeley) 12/01/92"; 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 * 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 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*/ 104 doonintr(v, t) 105 Char **v; 106 struct command *t; 107 { 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 } 133 } 134 135 void 136 /*ARGSUSED*/ 137 donohup(v, t) 138 Char **v; 139 struct command *t; 140 { 141 if (intty) 142 stderror(ERR_NAME | ERR_TERMINAL); 143 if (setintr == 0) { 144 (void) signal(SIGHUP, SIG_IGN); 145 } 146 } 147 148 void 149 /*ARGSUSED*/ 150 dozip(v, t) 151 Char **v; 152 struct command *t; 153 { 154 ; 155 } 156 157 void 158 prvars() 159 { 160 plist(&shvhed); 161 } 162 163 void 164 /*ARGSUSED*/ 165 doalias(v, t) 166 Char **v; 167 struct command *t; 168 { 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); 178 if (vp) { 179 blkpr(cshout, vp->vec); 180 fputc('\n', cshout); 181 } 182 } 183 else { 184 if (eq(p, STRalias) || eq(p, STRunalias)) { 185 setname(vis_str(p)); 186 stderror(ERR_NAME | ERR_DANGER); 187 } 188 set1(strip(p), saveblk(v), &aliases); 189 } 190 } 191 192 void 193 /*ARGSUSED*/ 194 unalias(v, t) 195 Char **v; 196 struct command *t; 197 { 198 unset1(v, &aliases); 199 } 200 201 void 202 /*ARGSUSED*/ 203 dologout(v, t) 204 Char **v; 205 struct command *t; 206 { 207 islogin(); 208 goodbye(); 209 } 210 211 void 212 /*ARGSUSED*/ 213 dologin(v, t) 214 Char **v; 215 struct command *t; 216 { 217 islogin(); 218 rechist(); 219 (void) signal(SIGTERM, parterm); 220 (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL); 221 untty(); 222 xexit(1); 223 } 224 225 static void 226 islogin() 227 { 228 if (chkstop == 0 && setintr) 229 panystop(0); 230 if (loginsh) 231 return; 232 stderror(ERR_NOTLOGIN); 233 } 234 235 void 236 doif(v, kp) 237 Char **v; 238 struct command *kp; 239 { 240 register int i; 241 register Char **vv; 242 243 v++; 244 i = expr(&v); 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(vis_str(STRthen)); 252 /* 253 * If expression was zero, then scan to else, otherwise just fall into 254 * following code. 255 */ 256 if (!i) 257 search(T_IF, 0, NULL); 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 } 269 } 270 271 /* 272 * Reexecute a command, being careful not 273 * to redo i/o redirection, which is already set up. 274 */ 275 static void 276 reexecute(kp) 277 register struct command *kp; 278 { 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 */ 286 execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL); 287 } 288 289 void 290 /*ARGSUSED*/ 291 doelse(v, t) 292 Char **v; 293 struct command *t; 294 { 295 search(T_ELSE, 0, NULL); 296 } 297 298 void 299 /*ARGSUSED*/ 300 dogoto(v, t) 301 Char **v; 302 struct command *t; 303 { 304 Char *lp; 305 306 gotolab(lp = globone(v[1], G_ERROR)); 307 xfree((ptr_t) lp); 308 } 309 310 void 311 gotolab(lab) 312 Char *lab; 313 { 314 register struct whyle *wp; 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) 321 if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) { 322 search(T_BREAK, 0, NULL); 323 btell(&wp->w_end); 324 } 325 else 326 bseek(&wp->w_end); 327 search(T_GOTO, 0, lab); 328 /* 329 * Eliminate loops which were exited. 330 */ 331 wfree(); 332 } 333 334 void 335 /*ARGSUSED*/ 336 doswitch(v, t) 337 Char **v; 338 struct command *t; 339 { 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); 352 } 353 354 void 355 /*ARGSUSED*/ 356 dobreak(v, t) 357 Char **v; 358 struct command *t; 359 { 360 if (whyles) 361 toend(); 362 else 363 stderror(ERR_NAME | ERR_NOTWHILE); 364 } 365 366 void 367 /*ARGSUSED*/ 368 doexit(v, t) 369 Char **v; 370 struct command *t; 371 { 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) { 379 set(STRstatus, putn(expr(&v))); 380 if (*v) 381 stderror(ERR_NAME | ERR_EXPRESSION); 382 } 383 btoeof(); 384 if (intty) 385 (void) close(SHIN); 386 } 387 388 void 389 /*ARGSUSED*/ 390 doforeach(v, t) 391 Char **v; 392 struct command *t; 393 { 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; 418 btell(&nwp->w_start); 419 nwp->w_fename = Strsave(cp); 420 nwp->w_next = whyles; 421 nwp->w_end.type = F_SEEK; 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(); 430 } 431 432 void 433 /*ARGSUSED*/ 434 dowhile(v, t) 435 Char **v; 436 struct command *t; 437 { 438 register int status; 439 register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) && 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 450 status = !expr(&v); 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; 458 nwp->w_end.type = F_SEEK; 459 nwp->w_end.f_seek = 0; 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; 470 } 471 } 472 if (status) 473 /* We ain't gonna loop no more, no more! */ 474 toend(); 475 } 476 477 static void 478 preread() 479 { 480 whyles->w_end.type = I_SEEK; 481 if (setintr) 482 (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 483 484 search(T_BREAK, 0, NULL); /* read the expression in */ 485 if (setintr) 486 (void) sigblock(sigmask(SIGINT)); 487 btell(&whyles->w_end); 488 } 489 490 void 491 /*ARGSUSED*/ 492 doend(v, t) 493 Char **v; 494 struct command *t; 495 { 496 if (!whyles) 497 stderror(ERR_NAME | ERR_NOTWHILE); 498 btell(&whyles->w_end); 499 doagain(); 500 } 501 502 void 503 /*ARGSUSED*/ 504 docontin(v, t) 505 Char **v; 506 struct command *t; 507 { 508 if (!whyles) 509 stderror(ERR_NAME | ERR_NOTWHILE); 510 doagain(); 511 } 512 513 static void 514 doagain() 515 { 516 /* Repeating a while is simple */ 517 if (whyles->w_fename == 0) { 518 bseek(&whyles->w_start); 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]) { 527 dobreak(NULL, NULL); 528 return; 529 } 530 set(whyles->w_fename, Strsave(*whyles->w_fe++)); 531 bseek(&whyles->w_start); 532 } 533 534 void 535 dorepeat(v, kp) 536 Char **v; 537 struct command *kp; 538 { 539 register int i; 540 register sigset_t omask = 0; 541 542 i = getn(v[1]); 543 if (setintr) 544 omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 545 lshift(v, 2); 546 while (i > 0) { 547 if (setintr) 548 (void) sigsetmask(omask); 549 reexecute(kp); 550 --i; 551 } 552 donefds(); 553 if (setintr) 554 (void) sigsetmask(omask); 555 } 556 557 void 558 /*ARGSUSED*/ 559 doswbrk(v, t) 560 Char **v; 561 struct command *t; 562 { 563 search(T_BRKSW, 0, NULL); 564 } 565 566 int 567 srchx(cp) 568 register Char *cp; 569 { 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); 588 } 589 590 static Char Stype; 591 static Char *Sgoal; 592 593 /*VARARGS2*/ 594 static void 595 search(type, level, goal) 596 int type; 597 register int level; 598 Char *goal; 599 { 600 Char wordbuf[BUFSIZ]; 601 register Char *aword = wordbuf; 602 register Char *cp; 603 604 Stype = type; 605 Sgoal = goal; 606 if (type == T_GOTO) { 607 struct Ain a; 608 a.type = F_SEEK; 609 a.f_seek = 0; 610 bseek(&a); 611 } 612 do { 613 if (intty && fseekp == feobp && aret == F_SEEK) 614 (void) fprintf(cshout, "? "), (void) fflush(cshout); 615 aword[0] = 0; 616 (void) getword(aword); 617 switch (srchx(aword)) { 618 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); 693 } 694 695 static int 696 getword(wp) 697 register Char *wp; 698 { 699 register int found = 0; 700 register int c, d; 701 int kwd = 0; 702 Char *owp = wp; 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; 722 do { 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) { 746 unreadc(c); 747 if (found) 748 *--wp = 0; 749 } 750 751 return (found); 752 753 past: 754 switch (Stype) { 755 756 case T_IF: 757 stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); 758 759 case T_ELSE: 760 stderror(ERR_NAME | ERR_NOTFOUND, "endif"); 761 762 case T_BRKSW: 763 case T_SWITCH: 764 stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); 765 766 case T_BREAK: 767 stderror(ERR_NAME | ERR_NOTFOUND, "end"); 768 769 case T_GOTO: 770 setname(vis_str(Sgoal)); 771 stderror(ERR_NAME | ERR_NOTFOUND, "label"); 772 } 773 /* NOTREACHED */ 774 return (0); 775 } 776 777 /* 778 * keyword(wp) determines if wp is one of the built-n functions if, 779 * switch or while. It seems that when an if statement looks like 780 * "if(" then getword above sucks in the '(' and so the search routine 781 * never finds what it is scanning for. Rather than rewrite doword, I hack 782 * in a test to see if the string forms a keyword. Then doword stops 783 * and returns the word "if" -strike 784 */ 785 786 static int 787 keyword(wp) 788 Char *wp; 789 { 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'}; 793 794 if (!wp) 795 return (0); 796 797 if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0) 798 || (Strcmp(wp, STRswitch) == 0)) 799 return (1); 800 801 return (0); 802 } 803 804 static void 805 toend() 806 { 807 if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) { 808 search(T_BREAK, 0, NULL); 809 btell(&whyles->w_end); 810 whyles->w_end.f_seek--; 811 } 812 else 813 bseek(&whyles->w_end); 814 wfree(); 815 } 816 817 void 818 wfree() 819 { 820 struct Ain o; 821 struct whyle *nwp; 822 823 btell(&o); 824 825 for (; whyles; whyles = nwp) { 826 register struct whyle *wp = whyles; 827 nwp = wp->w_next; 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 } 844 } 845 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); 851 } 852 } 853 854 void 855 /*ARGSUSED*/ 856 doecho(v, t) 857 Char **v; 858 struct command *t; 859 { 860 xecho(' ', v); 861 } 862 863 void 864 /*ARGSUSED*/ 865 doglob(v, t) 866 Char **v; 867 struct command *t; 868 { 869 xecho(0, v); 870 (void) fflush(cshout); 871 } 872 873 static void 874 xecho(sep, v) 875 int sep; 876 register Char **v; 877 { 878 register Char *cp; 879 int nonl = 0; 880 881 if (setintr) 882 (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 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++) 902 (void) vis_fputc(c | QUOTE, cshout); 903 904 if (*v) 905 (void) vis_fputc(sep | QUOTE, cshout); 906 } 907 if (sep && nonl == 0) 908 (void) fputc('\n', cshout); 909 else 910 (void) fflush(cshout); 911 if (setintr) 912 (void) sigblock(sigmask(SIGINT)); 913 if (gargv) 914 blkfree(gargv), gargv = 0; 915 } 916 917 void 918 /*ARGSUSED*/ 919 dosetenv(v, t) 920 Char **v; 921 struct command *t; 922 { 923 Char *vp, *lp; 924 925 v++; 926 if ((vp = *v++) == 0) { 927 register Char **ep; 928 929 if (setintr) 930 (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 931 for (ep = STR_environ; *ep; ep++) 932 (void) fprintf(cshout, "%s\n", vis_str(*ep)); 933 return; 934 } 935 if ((lp = *v++) == 0) 936 lp = STRNULL; 937 Setenv(vp, lp = globone(lp, G_APPEND)); 938 if (eq(vp, STRPATH)) { 939 importpath(lp); 940 dohash(NULL, NULL); 941 } 942 else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) { 943 #ifdef NLS 944 int k; 945 946 (void) setlocale(LC_ALL, ""); 947 for (k = 0200; k <= 0377 && !Isprint(k); k++) 948 continue; 949 AsciiOnly = k > 0377; 950 #else 951 AsciiOnly = 0; 952 #endif /* NLS */ 953 } 954 xfree((ptr_t) lp); 955 } 956 957 void 958 /*ARGSUSED*/ 959 dounsetenv(v, t) 960 Char **v; 961 struct command *t; 962 { 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++) { 973 for (i = 0, p = *ep; *p && *p != '='; p++, i++) 974 continue; 975 if (i > maxi) 976 maxi = i; 977 } 978 979 name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char)); 980 981 while (++v && *v) 982 for (maxi = 1; maxi;) 983 for (maxi = 0, ep = STR_environ; *ep; ep++) { 984 for (n = name, p = *ep; *p && *p != '='; *n++ = *p++) 985 continue; 986 *n = '\0'; 987 if (!Gmatch(name, *v)) 988 continue; 989 maxi = 1; 990 if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) { 991 #ifdef NLS 992 int k; 993 994 (void) setlocale(LC_ALL, ""); 995 for (k = 0200; k <= 0377 && !Isprint(k); k++) 996 continue; 997 AsciiOnly = k > 0377; 998 #else 999 AsciiOnly = getenv("LANG") == NULL && 1000 getenv("LC_CTYPE") == NULL; 1001 #endif /* NLS */ 1002 } 1003 /* 1004 * Delete name, and start again cause the environment changes 1005 */ 1006 Unsetenv(name); 1007 break; 1008 } 1009 xfree((ptr_t) name); 1010 name = NULL; 1011 } 1012 1013 void 1014 Setenv(name, val) 1015 Char *name, *val; 1016 { 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); 1044 } 1045 1046 static void 1047 Unsetenv(name) 1048 Char *name; 1049 { 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 } 1068 } 1069 1070 void 1071 /*ARGSUSED*/ 1072 doumask(v, t) 1073 Char **v; 1074 struct command *t; 1075 { 1076 register Char *cp = v[1]; 1077 register int i; 1078 1079 if (cp == 0) { 1080 i = umask(0); 1081 (void) umask(i); 1082 (void) fprintf(cshout, "%o\n", i); 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); 1091 } 1092 1093 typedef quad_t RLIM_TYPE; 1094 1095 static struct limits { 1096 int limconst; 1097 char *limname; 1098 int limdiv; 1099 char *limscale; 1100 } limits[] = { 1101 RLIMIT_CPU, "cputime", 1, "seconds", 1102 RLIMIT_FSIZE, "filesize", 1024, "kbytes", 1103 RLIMIT_DATA, "datasize", 1024, "kbytes", 1104 RLIMIT_STACK, "stacksize", 1024, "kbytes", 1105 RLIMIT_CORE, "coredumpsize", 1024, "kbytes", 1106 RLIMIT_RSS, "memoryuse", 1024, "kbytes", 1107 RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes", 1108 RLIMIT_NPROC, "maxproc", 1, "", 1109 RLIMIT_NOFILE, "openfiles", 1, "", 1110 -1, NULL, 0, NULL 1111 }; 1112 1113 static struct limits *findlim(); 1114 static RLIM_TYPE getval(); 1115 static void limtail(); 1116 static void plim(); 1117 static int setlim(); 1118 1119 static struct limits * 1120 findlim(cp) 1121 Char *cp; 1122 { 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); 1137 } 1138 1139 void 1140 /*ARGSUSED*/ 1141 dolimit(v, t) 1142 Char **v; 1143 struct command *t; 1144 { 1145 register struct limits *lp; 1146 register RLIM_TYPE limit; 1147 char hard = 0; 1148 1149 v++; 1150 if (*v && eq(*v, STRmh)) { 1151 hard = 1; 1152 v++; 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); 1167 } 1168 1169 static RLIM_TYPE 1170 getval(lp, v) 1171 register struct limits *lp; 1172 Char **v; 1173 { 1174 register float f; 1175 double atof(); 1176 Char *cp = *v++; 1177 1178 f = atof(short2str(cp)); 1179 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; 1203 } 1204 *cp = 'm'; 1205 limtail(cp, "megabytes"); 1206 f *= 1024.0 * 1024.0; 1207 break; 1208 case 's': 1209 if (lp->limconst != RLIMIT_CPU) 1210 goto badscal; 1211 limtail(cp, "seconds"); 1212 break; 1213 case 'M': 1214 if (lp->limconst == RLIMIT_CPU) 1215 goto badscal; 1216 *cp = 'm'; 1217 limtail(cp, "megabytes"); 1218 f *= 1024.0 * 1024.0; 1219 break; 1220 case 'k': 1221 if (lp->limconst == RLIMIT_CPU) 1222 goto badscal; 1223 limtail(cp, "kbytes"); 1224 f *= 1024.0; 1225 break; 1226 case 'u': 1227 limtail(cp, "unlimited"); 1228 return (RLIM_INFINITY); 1229 default: 1230 badscal: 1231 stderror(ERR_NAME | ERR_SCALEF); 1232 } 1233 f += 0.5; 1234 if (f > (float) RLIM_INFINITY) 1235 return RLIM_INFINITY; 1236 else 1237 return ((RLIM_TYPE) f); 1238 } 1239 1240 static void 1241 limtail(cp, str) 1242 Char *cp; 1243 char *str; 1244 { 1245 while (*cp && *cp == *str) 1246 cp++, str++; 1247 if (*cp) 1248 stderror(ERR_BADSCALE, str); 1249 } 1250 1251 1252 /*ARGSUSED*/ 1253 static void 1254 plim(lp, hard) 1255 register struct limits *lp; 1256 Char hard; 1257 { 1258 struct rlimit rlim; 1259 RLIM_TYPE limit; 1260 1261 (void) fprintf(cshout, "%s \t", lp->limname); 1262 1263 (void) getrlimit(lp->limconst, &rlim); 1264 limit = hard ? rlim.rlim_max : rlim.rlim_cur; 1265 1266 if (limit == RLIM_INFINITY) 1267 (void) fprintf(cshout, "unlimited"); 1268 else if (lp->limconst == RLIMIT_CPU) 1269 psecs((long) limit); 1270 else 1271 (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv), 1272 lp->limscale); 1273 (void) fputc('\n', cshout); 1274 } 1275 1276 void 1277 /*ARGSUSED*/ 1278 dounlimit(v, t) 1279 Char **v; 1280 struct command *t; 1281 { 1282 register struct limits *lp; 1283 int lerr = 0; 1284 Char hard = 0; 1285 1286 v++; 1287 if (*v && eq(*v, STRmh)) { 1288 hard = 1; 1289 v++; 1290 } 1291 if (*v == 0) { 1292 for (lp = limits; lp->limconst >= 0; lp++) 1293 if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 1294 lerr++; 1295 if (lerr) 1296 stderror(ERR_SILENT); 1297 return; 1298 } 1299 while (*v) { 1300 lp = findlim(*v++); 1301 if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 1302 stderror(ERR_SILENT); 1303 } 1304 } 1305 1306 static int 1307 setlim(lp, hard, limit) 1308 register struct limits *lp; 1309 Char hard; 1310 RLIM_TYPE limit; 1311 { 1312 struct rlimit rlim; 1313 1314 (void) getrlimit(lp->limconst, &rlim); 1315 1316 if (hard) 1317 rlim.rlim_max = limit; 1318 else if (limit == RLIM_INFINITY && geteuid() != 0) 1319 rlim.rlim_cur = rlim.rlim_max; 1320 else 1321 rlim.rlim_cur = limit; 1322 1323 if (setrlimit(lp->limconst, &rlim) < 0) { 1324 (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname, 1325 limit == RLIM_INFINITY ? "remove" : "set", 1326 hard ? " hard" : ""); 1327 return (-1); 1328 } 1329 return (0); 1330 } 1331 1332 void 1333 /*ARGSUSED*/ 1334 dosuspend(v, t) 1335 Char **v; 1336 struct command *t; 1337 { 1338 int ctpgrp; 1339 1340 void (*old) (); 1341 1342 if (loginsh) 1343 stderror(ERR_SUSPLOG); 1344 untty(); 1345 1346 old = signal(SIGTSTP, SIG_DFL); 1347 (void) kill(0, SIGTSTP); 1348 /* the shell stops here */ 1349 (void) signal(SIGTSTP, old); 1350 1351 if (tpgrp != -1) { 1352 ctpgrp = tcgetpgrp(FSHTTY); 1353 while (ctpgrp != opgrp) { 1354 old = signal(SIGTTIN, SIG_DFL); 1355 (void) kill(0, SIGTTIN); 1356 (void) signal(SIGTTIN, old); 1357 } 1358 (void) setpgid(0, shpgrp); 1359 (void) tcsetpgrp(FSHTTY, shpgrp); 1360 } 1361 } 1362 1363 /* This is the dreaded EVAL built-in. 1364 * If you don't fiddle with file descriptors, and reset didfds, 1365 * this command will either ignore redirection inside or outside 1366 * its aguments, e.g. eval "date >x" vs. eval "date" >x 1367 * The stuff here seems to work, but I did it by trial and error rather 1368 * than really knowing what was going on. If tpgrp is zero, we are 1369 * probably a background eval, e.g. "eval date &", and we want to 1370 * make sure that any processes we start stay in our pgrp. 1371 * This is also the case for "time eval date" -- stay in same pgrp. 1372 * Otherwise, under stty tostop, processes will stop in the wrong 1373 * pgrp, with no way for the shell to get them going again. -IAN! 1374 */ 1375 static Char **gv = NULL; 1376 void 1377 /*ARGSUSED*/ 1378 doeval(v, t) 1379 Char **v; 1380 struct command *t; 1381 { 1382 Char **oevalvec; 1383 Char *oevalp; 1384 int odidfds; 1385 jmp_buf osetexit; 1386 int my_reenter; 1387 Char **savegv = gv; 1388 int saveIN; 1389 int saveOUT; 1390 int saveERR; 1391 int oSHIN; 1392 int oSHOUT; 1393 int oSHERR; 1394 1395 oevalvec = evalvec; 1396 oevalp = evalp; 1397 odidfds = didfds; 1398 oSHIN = SHIN; 1399 oSHOUT = SHOUT; 1400 oSHERR = SHERR; 1401 1402 v++; 1403 if (*v == 0) 1404 return; 1405 gflag = 0, tglob(v); 1406 if (gflag) { 1407 gv = v = globall(v); 1408 gargv = 0; 1409 if (v == 0) 1410 stderror(ERR_NOMATCH); 1411 v = copyblk(v); 1412 } 1413 else { 1414 gv = NULL; 1415 v = copyblk(v); 1416 trim(v); 1417 } 1418 1419 saveIN = dcopy(SHIN, -1); 1420 saveOUT = dcopy(SHOUT, -1); 1421 saveERR = dcopy(SHERR, -1); 1422 1423 getexit(osetexit); 1424 1425 if ((my_reenter = setexit()) == 0) { 1426 evalvec = v; 1427 evalp = 0; 1428 SHIN = dcopy(0, -1); 1429 SHOUT = dcopy(1, -1); 1430 SHERR = dcopy(2, -1); 1431 didfds = 0; 1432 process(0); 1433 } 1434 1435 evalvec = oevalvec; 1436 evalp = oevalp; 1437 doneinp = 0; 1438 didfds = odidfds; 1439 (void) close(SHIN); 1440 (void) close(SHOUT); 1441 (void) close(SHERR); 1442 SHIN = dmove(saveIN, oSHIN); 1443 SHOUT = dmove(saveOUT, oSHOUT); 1444 SHERR = dmove(saveERR, oSHERR); 1445 if (gv) 1446 blkfree(gv), gv = NULL; 1447 resexit(osetexit); 1448 gv = savegv; 1449 if (my_reenter) 1450 stderror(ERR_SILENT); 1451 } 1452 1453 void 1454 /*ARGSUSED*/ 1455 doprintf(v, t) 1456 Char **v; 1457 struct command *t; 1458 { 1459 char **c; 1460 extern int progprintf __P((int, char **)); 1461 int ret; 1462 1463 ret = progprintf(blklen(v), c = short2blk(v)); 1464 (void) fflush(cshout); 1465 (void) fflush(csherr); 1466 1467 blkfree((Char **) c); 1468 if (ret) 1469 stderror(ERR_SILENT); 1470 } 1471