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