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 * 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 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*/ 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*/ 153 dozip(v, t) 154 Char **v; 155 struct command *t; 156 { 157 ; 158 } 159 160 void 161 prvars() 162 { 163 plist(&shvhed); 164 } 165 166 void 167 /*ARGSUSED*/ 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*/ 197 unalias(v, t) 198 Char **v; 199 struct command *t; 200 { 201 unset1(v, &aliases); 202 } 203 204 void 205 /*ARGSUSED*/ 206 dologout(v, t) 207 Char **v; 208 struct command *t; 209 { 210 islogin(); 211 goodbye(); 212 } 213 214 void 215 /*ARGSUSED*/ 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 229 islogin() 230 { 231 if (chkstop == 0 && setintr) 232 panystop(0); 233 if (loginsh) 234 return; 235 stderror(ERR_NOTLOGIN); 236 } 237 238 void 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 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*/ 294 doelse(v, t) 295 Char **v; 296 struct command *t; 297 { 298 search(T_ELSE, 0, NULL); 299 } 300 301 void 302 /*ARGSUSED*/ 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 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*/ 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*/ 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*/ 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*/ 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*/ 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 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*/ 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*/ 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 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 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*/ 570 doswbrk(v, t) 571 Char **v; 572 struct command *t; 573 { 574 search(T_BRKSW, 0, NULL); 575 } 576 577 int 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 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 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 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 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 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*/ 867 doecho(v, t) 868 Char **v; 869 struct command *t; 870 { 871 xecho(' ', v); 872 } 873 874 void 875 /*ARGSUSED*/ 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 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*/ 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*/ 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 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 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*/ 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 * 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*/ 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 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 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 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*/ 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 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*/ 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*/ 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*/ 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