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