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.14 (Berkeley) 04/04/91"; 10 #endif /* not lint */ 11 12 #include "sh.h" 13 #include <sys/ioctl.h> 14 #include "pathnames.h" 15 16 /* 17 * C shell 18 */ 19 20 struct biltins * 21 isbfunc(t) 22 struct command *t; 23 { 24 register char *cp = t->t_dcom[0]; 25 register struct biltins *bp, *bp1, *bp2; 26 int dolabel(), dofg1(), dobg1(); 27 static struct biltins label = { "", dolabel, 0, 0 }; 28 static struct biltins foregnd = { "%job", dofg1, 0, 0 }; 29 static struct biltins backgnd = { "%job &", dobg1, 0, 0 }; 30 31 if (lastchr(cp) == ':') { 32 label.bname = cp; 33 return (&label); 34 } 35 if (*cp == '%') { 36 if (t->t_dflg & F_AMPERSAND) { 37 t->t_dflg &= ~F_AMPERSAND; 38 backgnd.bname = cp; 39 return (&backgnd); 40 } 41 foregnd.bname = cp; 42 return (&foregnd); 43 } 44 /* 45 * Binary search 46 * Bp1 is the beginning of the current search range. 47 * Bp2 is one past the end. 48 */ 49 for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { 50 register i; 51 52 bp = bp1 + (bp2 - bp1 >> 1); 53 if ((i = *cp - *bp->bname) == 0 && 54 (i = strcmp(cp, bp->bname)) == 0) 55 return bp; 56 if (i < 0) 57 bp2 = bp; 58 else 59 bp1 = bp + 1; 60 } 61 return (0); 62 } 63 64 func(t, bp) 65 register struct command *t; 66 register struct biltins *bp; 67 { 68 int i; 69 70 xechoit(t->t_dcom); 71 setname(bp->bname); 72 i = blklen(t->t_dcom) - 1; 73 if (i < bp->minargs) 74 bferr("Too few arguments"); 75 if (i > bp->maxargs) 76 bferr("Too many arguments"); 77 (*bp->bfunct)(t->t_dcom, t); 78 } 79 80 dolabel() 81 { 82 83 } 84 85 doonintr(v) 86 char **v; 87 { 88 register char *cp; 89 register char *vv = v[1]; 90 91 if (parintr == SIG_IGN) 92 return; 93 if (setintr && intty) 94 bferr("Can't from terminal"); 95 cp = gointr, gointr = 0, xfree(cp); 96 if (vv == 0) { 97 if (setintr) 98 (void) sigblock(sigmask(SIGINT)); 99 else 100 (void) signal(SIGINT, SIG_DFL); 101 gointr = 0; 102 } else if (eq((vv = strip(vv)), "-")) { 103 (void) signal(SIGINT, SIG_IGN); 104 gointr = "-"; 105 } else { 106 gointr = savestr(vv); 107 (void) signal(SIGINT, pintr); 108 } 109 } 110 111 donohup() 112 { 113 114 if (intty) 115 bferr("Can't from terminal"); 116 if (setintr == 0) { 117 (void) signal(SIGHUP, SIG_IGN); 118 #ifdef CC 119 submit(getpid()); 120 #endif 121 } 122 } 123 124 dozip() 125 { 126 127 ; 128 } 129 130 prvars() 131 { 132 133 plist(&shvhed); 134 } 135 136 doalias(v) 137 register char **v; 138 { 139 register struct varent *vp; 140 register char *p; 141 142 v++; 143 p = *v++; 144 if (p == 0) 145 plist(&aliases); 146 else if (*v == 0) { 147 vp = adrof1(strip(p), &aliases); 148 if (vp) 149 blkpr(vp->vec), printf("\n"); 150 } else { 151 if (eq(p, "alias") || eq(p, "unalias")) { 152 setname(p); 153 bferr("Too dangerous to alias that"); 154 } 155 set1(strip(p), saveblk(v), &aliases); 156 } 157 } 158 159 unalias(v) 160 char **v; 161 { 162 163 unset1(v, &aliases); 164 } 165 166 dologout() 167 { 168 169 islogin(); 170 goodbye(); 171 } 172 173 dologin(v) 174 char **v; 175 { 176 177 islogin(); 178 rechist(); 179 (void) signal(SIGTERM, parterm); 180 execl(_PATH_LOGIN, "login", v[1], 0); 181 untty(); 182 exit(1); 183 } 184 185 islogin() 186 { 187 188 if (chkstop == 0 && setintr) 189 panystop(0); 190 if (loginsh) 191 return; 192 error("Not login shell"); 193 } 194 195 doif(v, kp) 196 char **v; 197 struct command *kp; 198 { 199 register int i; 200 register char **vv; 201 202 v++; 203 i = exp(&v); 204 vv = v; 205 if (*vv == NOSTR) 206 bferr("Empty if"); 207 if (eq(*vv, "then")) { 208 if (*++vv) 209 bferr("Improper then"); 210 setname("then"); 211 /* 212 * If expression was zero, then scan to else, 213 * otherwise just fall into following code. 214 */ 215 if (!i) 216 search(T_IF, 0); 217 return; 218 } 219 /* 220 * Simple command attached to this if. 221 * Left shift the node in this tree, munging it 222 * so we can reexecute it. 223 */ 224 if (i) { 225 lshift(kp->t_dcom, vv - kp->t_dcom); 226 reexecute(kp); 227 donefds(); 228 } 229 } 230 231 /* 232 * Reexecute a command, being careful not 233 * to redo i/o redirection, which is already set up. 234 */ 235 reexecute(kp) 236 register struct command *kp; 237 { 238 239 kp->t_dflg &= F_SAVE; 240 kp->t_dflg |= F_REPEAT; 241 /* 242 * If tty is still ours to arbitrate, arbitrate it; 243 * otherwise dont even set pgrp's as the jobs would 244 * then have no way to get the tty (we can't give it 245 * to them, and our parent wouldn't know their pgrp, etc. 246 */ 247 execute(kp, tpgrp > 0 ? tpgrp : -1); 248 } 249 250 doelse() 251 { 252 253 search(T_ELSE, 0); 254 } 255 256 dogoto(v) 257 char **v; 258 { 259 register struct whyle *wp; 260 char *lp; 261 262 /* 263 * While we still can, locate any unknown ends of existing loops. 264 * This obscure code is the WORST result of the fact that we 265 * don't really parse. 266 */ 267 for (wp = whyles; wp; wp = wp->w_next) 268 if (wp->w_end == 0) { 269 search(T_BREAK, 0); 270 wp->w_end = btell(); 271 } else 272 bseek(wp->w_end); 273 search(T_GOTO, 0, lp = globone(v[1])); 274 xfree(lp); 275 /* 276 * Eliminate loops which were exited. 277 */ 278 wfree(); 279 } 280 281 doswitch(v) 282 register char **v; 283 { 284 register char *cp, *lp; 285 286 v++; 287 if (!*v || *(*v++) != '(') 288 goto syntax; 289 cp = **v == ')' ? "" : *v++; 290 if (*(*v++) != ')') 291 v--; 292 if (*v) 293 syntax: 294 error("Syntax error"); 295 search(T_SWITCH, 0, lp = globone(cp)); 296 xfree(lp); 297 } 298 299 dobreak() 300 { 301 302 if (whyles) 303 toend(); 304 else 305 bferr("Not in while/foreach"); 306 } 307 308 doexit(v) 309 char **v; 310 { 311 312 if (chkstop == 0) 313 panystop(0); 314 /* 315 * Don't DEMAND parentheses here either. 316 */ 317 v++; 318 if (*v) { 319 set("status", putn(exp(&v))); 320 if (*v) 321 bferr("Expression syntax"); 322 } 323 btoeof(); 324 if (intty) 325 (void) close(SHIN); 326 } 327 328 doforeach(v) 329 register char **v; 330 { 331 register char *cp; 332 register struct whyle *nwp; 333 334 v++; 335 cp = strip(*v); 336 while (*cp && letter(*cp)) 337 cp++; 338 if (*cp || strlen(*v) >= 20) 339 bferr("Invalid variable"); 340 cp = *v++; 341 if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') 342 bferr("Words not ()'ed"); 343 v++; 344 gflag = 0, tglob(v); 345 v = globall(v); 346 if (v == 0) 347 bferr("No match"); 348 nwp = (struct whyle *) calloc(1, sizeof *nwp); 349 nwp->w_fe = nwp->w_fe0 = v; gargv = 0; 350 nwp->w_start = btell(); 351 nwp->w_fename = savestr(cp); 352 nwp->w_next = whyles; 353 whyles = nwp; 354 /* 355 * Pre-read the loop so as to be more 356 * comprehensible to a terminal user. 357 */ 358 if (intty) 359 preread(); 360 doagain(); 361 } 362 363 dowhile(v) 364 char **v; 365 { 366 register int status; 367 register bool again = whyles != 0 && whyles->w_start == lineloc && 368 whyles->w_fename == 0; 369 370 v++; 371 /* 372 * Implement prereading here also, taking care not to 373 * evaluate the expression before the loop has been read up 374 * from a terminal. 375 */ 376 if (intty && !again) 377 status = !exp0(&v, 1); 378 else 379 status = !exp(&v); 380 if (*v) 381 bferr("Expression syntax"); 382 if (!again) { 383 register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp)); 384 385 nwp->w_start = lineloc; 386 nwp->w_end = 0; 387 nwp->w_next = whyles; 388 whyles = nwp; 389 if (intty) { 390 /* 391 * The tty preread 392 */ 393 preread(); 394 doagain(); 395 return; 396 } 397 } 398 if (status) 399 /* We ain't gonna loop no more, no more! */ 400 toend(); 401 } 402 403 preread() 404 { 405 406 whyles->w_end = -1; 407 if (setintr) 408 (void) sigsetmask(sigblock(0L) & ~sigmask(SIGINT)); 409 search(T_BREAK, 0); 410 if (setintr) 411 (void) sigblock(sigmask(SIGINT)); 412 whyles->w_end = btell(); 413 } 414 415 doend() 416 { 417 418 if (!whyles) 419 bferr("Not in while/foreach"); 420 whyles->w_end = btell(); 421 doagain(); 422 } 423 424 docontin() 425 { 426 427 if (!whyles) 428 bferr("Not in while/foreach"); 429 doagain(); 430 } 431 432 doagain() 433 { 434 435 /* Repeating a while is simple */ 436 if (whyles->w_fename == 0) { 437 bseek(whyles->w_start); 438 return; 439 } 440 /* 441 * The foreach variable list actually has a spurious word 442 * ")" at the end of the w_fe list. Thus we are at the 443 * of the list if one word beyond this is 0. 444 */ 445 if (!whyles->w_fe[1]) { 446 dobreak(); 447 return; 448 } 449 set(whyles->w_fename, savestr(*whyles->w_fe++)); 450 bseek(whyles->w_start); 451 } 452 453 dorepeat(v, kp) 454 char **v; 455 struct command *kp; 456 { 457 register int i; 458 register long omask; 459 460 i = getn(v[1]); 461 if (setintr) 462 omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 463 lshift(v, 2); 464 while (i > 0) { 465 if (setintr) 466 (void) sigsetmask(omask); 467 reexecute(kp); 468 --i; 469 } 470 donefds(); 471 if (setintr) 472 (void) sigsetmask(omask); 473 } 474 475 doswbrk() 476 { 477 478 search(T_BRKSW, 0); 479 } 480 481 srchx(cp) 482 register char *cp; 483 { 484 register struct srch *sp, *sp1, *sp2; 485 register i; 486 487 /* 488 * Binary search 489 * Sp1 is the beginning of the current search range. 490 * Sp2 is one past the end. 491 */ 492 for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { 493 sp = sp1 + (sp2 - sp1 >> 1); 494 if ((i = *cp - *sp->s_name) == 0 && 495 (i = strcmp(cp, sp->s_name)) == 0) 496 return sp->s_value; 497 if (i < 0) 498 sp2 = sp; 499 else 500 sp1 = sp + 1; 501 } 502 return (-1); 503 } 504 505 char Stype; 506 char *Sgoal; 507 508 /*VARARGS2*/ 509 search(type, level, goal) 510 int type; 511 register int level; 512 char *goal; 513 { 514 char wordbuf[BUFSIZ]; 515 register char *aword = wordbuf; 516 register char *cp; 517 518 Stype = type; Sgoal = goal; 519 if (type == T_GOTO) 520 bseek((off_t)0); 521 do { 522 if (intty && fseekp == feobp) 523 printf("? "), flush(); 524 aword[0] = 0; 525 (void) getword(aword); 526 switch (srchx(aword)) { 527 528 case T_ELSE: 529 if (level == 0 && type == T_IF) 530 return; 531 break; 532 533 case T_IF: 534 while (getword(aword)) 535 continue; 536 if ((type == T_IF || type == T_ELSE) && 537 eq(aword, "then")) 538 level++; 539 break; 540 541 case T_ENDIF: 542 if (type == T_IF || type == T_ELSE) 543 level--; 544 break; 545 546 case T_FOREACH: 547 case T_WHILE: 548 if (type == T_BREAK) 549 level++; 550 break; 551 552 case T_END: 553 if (type == T_BREAK) 554 level--; 555 break; 556 557 case T_SWITCH: 558 if (type == T_SWITCH || type == T_BRKSW) 559 level++; 560 break; 561 562 case T_ENDSW: 563 if (type == T_SWITCH || type == T_BRKSW) 564 level--; 565 break; 566 567 case T_LABEL: 568 if (type == T_GOTO && getword(aword) && eq(aword, goal)) 569 level = -1; 570 break; 571 572 default: 573 if (type != T_GOTO && (type != T_SWITCH || level != 0)) 574 break; 575 if (lastchr(aword) != ':') 576 break; 577 aword[strlen(aword) - 1] = 0; 578 if (type == T_GOTO && eq(aword, goal) || 579 type == T_SWITCH && eq(aword, "default")) 580 level = -1; 581 break; 582 583 case T_CASE: 584 if (type != T_SWITCH || level != 0) 585 break; 586 (void) getword(aword); 587 if (lastchr(aword) == ':') 588 aword[strlen(aword) - 1] = 0; 589 cp = strip(Dfix1(aword)); 590 if (Gmatch(goal, cp)) 591 level = -1; 592 xfree(cp); 593 break; 594 595 case T_DEFAULT: 596 if (type == T_SWITCH && level == 0) 597 level = -1; 598 break; 599 } 600 (void) getword(NOSTR); 601 } while (level >= 0); 602 } 603 604 getword(wp) 605 register char *wp; 606 { 607 register int found = 0; 608 register int c, d; 609 610 c = readc(1); 611 d = 0; 612 do { 613 while (c == ' ' || c == '\t') 614 c = readc(1); 615 if (c == '#') 616 do 617 c = readc(1); 618 while (c >= 0 && c != '\n'); 619 if (c < 0) 620 goto past; 621 if (c == '\n') { 622 if (wp) 623 break; 624 return (0); 625 } 626 unreadc(c); 627 found = 1; 628 do { 629 c = readc(1); 630 if (c == '\\' && (c = readc(1)) == '\n') 631 c = ' '; 632 if (c == '\'' || c == '"') 633 if (d == 0) 634 d = c; 635 else if (d == c) 636 d = 0; 637 if (c < 0) 638 goto past; 639 if (wp) 640 *wp++ = c; 641 } while ((d || c != ' ' && c != '\t') && c != '\n'); 642 } while (wp == 0); 643 unreadc(c); 644 if (found) 645 *--wp = 0; 646 return (found); 647 648 past: 649 switch (Stype) { 650 651 case T_IF: 652 bferr("then/endif not found"); 653 654 case T_ELSE: 655 bferr("endif not found"); 656 657 case T_BRKSW: 658 case T_SWITCH: 659 bferr("endsw not found"); 660 661 case T_BREAK: 662 bferr("end not found"); 663 664 case T_GOTO: 665 setname(Sgoal); 666 bferr("label not found"); 667 } 668 /*NOTREACHED*/ 669 } 670 671 toend() 672 { 673 674 if (whyles->w_end == 0) { 675 search(T_BREAK, 0); 676 whyles->w_end = btell() - 1; 677 } else 678 bseek(whyles->w_end); 679 wfree(); 680 } 681 682 wfree() 683 { 684 long o = btell(); 685 686 while (whyles) { 687 register struct whyle *wp = whyles; 688 register struct whyle *nwp = wp->w_next; 689 690 if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) 691 break; 692 if (wp->w_fe0) 693 blkfree(wp->w_fe0); 694 if (wp->w_fename) 695 xfree(wp->w_fename); 696 xfree((char *)wp); 697 whyles = nwp; 698 } 699 } 700 701 doecho(v) 702 char **v; 703 { 704 705 echo(' ', v); 706 } 707 708 doglob(v) 709 char **v; 710 { 711 712 echo(0, v); 713 flush(); 714 } 715 716 echo(sep, v) 717 char sep; 718 register char **v; 719 { 720 register char *cp; 721 int nonl = 0; 722 723 if (setintr) 724 (void) sigsetmask(sigblock(0L) & ~sigmask(SIGINT)); 725 v++; 726 if (*v == 0) 727 return; 728 gflag = 0, tglob(v); 729 if (gflag) { 730 v = globall(v); 731 if (v == 0) 732 bferr("No match"); 733 } else 734 trim(v); 735 if (sep == ' ' && *v && !strcmp(*v, "-n")) 736 nonl++, v++; 737 while (cp = *v++) { 738 register int c; 739 740 while (c = *cp++) 741 cshputchar(c | QUOTE); 742 if (*v) 743 cshputchar(sep | QUOTE); 744 } 745 if (sep && nonl == 0) 746 cshputchar('\n'); 747 else 748 flush(); 749 if (setintr) 750 (void) sigblock(sigmask(SIGINT)); 751 if (gargv) 752 blkfree(gargv), gargv = 0; 753 } 754 755 char **environ; 756 757 dosetenv(v) 758 register char **v; 759 { 760 char *vp, *lp; 761 762 v++; 763 if ((vp = *v++) == 0) { 764 register char **ep; 765 766 if (setintr) 767 (void) sigsetmask(sigblock(0L) & ~ sigmask(SIGINT)); 768 for (ep = environ; *ep; ep++) 769 printf("%s\n", *ep); 770 return; 771 } 772 if ((lp = *v++) == 0) 773 lp = ""; 774 setenv(vp, lp = globone(lp)); 775 if (eq(vp, "PATH")) { 776 importpath(lp); 777 dohash(); 778 } 779 xfree(lp); 780 } 781 782 dounsetenv(v) 783 register char **v; 784 { 785 786 v++; 787 do 788 unsetenv(*v++); 789 while (*v); 790 } 791 792 setenv(name, val) 793 char *name, *val; 794 { 795 register char **ep = environ; 796 register char *cp, *dp; 797 char *blk[2], **oep = ep; 798 799 for (; *ep; ep++) { 800 for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 801 continue; 802 if (*cp != 0 || *dp != '=') 803 continue; 804 cp = strspl("=", val); 805 xfree(*ep); 806 *ep = strspl(name, cp); 807 xfree(cp); 808 trim(ep); 809 return; 810 } 811 blk[0] = strspl(name, "="); blk[1] = 0; 812 environ = blkspl(environ, blk); 813 xfree((char *)oep); 814 setenv(name, val); 815 } 816 817 unsetenv(name) 818 char *name; 819 { 820 register char **ep = environ; 821 register char *cp, *dp; 822 char **oep = ep; 823 824 for (; *ep; ep++) { 825 for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 826 continue; 827 if (*cp != 0 || *dp != '=') 828 continue; 829 cp = *ep; 830 *ep = 0; 831 environ = blkspl(environ, ep+1); 832 *ep = cp; 833 xfree(cp); 834 xfree((char *)oep); 835 return; 836 } 837 } 838 839 doumask(v) 840 register char **v; 841 { 842 register char *cp = v[1]; 843 register int i; 844 845 if (cp == 0) { 846 i = umask(0); 847 (void) umask(i); 848 printf("%o\n", i); 849 return; 850 } 851 i = 0; 852 while (digit(*cp) && *cp != '8' && *cp != '9') 853 i = i * 8 + *cp++ - '0'; 854 if (*cp || i < 0 || i > 0777) 855 bferr("Improper mask"); 856 (void) umask(i); 857 } 858 859 860 struct limits { 861 int limconst; 862 char *limname; 863 int limdiv; 864 char *limscale; 865 } limits[] = { 866 RLIMIT_CPU, "cputime", 1, "seconds", 867 RLIMIT_FSIZE, "filesize", 1024, "kbytes", 868 RLIMIT_DATA, "datasize", 1024, "kbytes", 869 RLIMIT_STACK, "stacksize", 1024, "kbytes", 870 RLIMIT_CORE, "coredumpsize", 1024, "kbytes", 871 RLIMIT_RSS, "memoryuse", 1024, "kbytes", 872 -1, 0, 873 }; 874 875 struct limits * 876 findlim(cp) 877 char *cp; 878 { 879 register struct limits *lp, *res; 880 881 res = 0; 882 for (lp = limits; lp->limconst >= 0; lp++) 883 if (prefix(cp, lp->limname)) { 884 if (res) 885 bferr("Ambiguous"); 886 res = lp; 887 } 888 if (res) 889 return (res); 890 bferr("No such limit"); 891 /*NOTREACHED*/ 892 } 893 894 dolimit(v) 895 register char **v; 896 { 897 register struct limits *lp; 898 register int limit; 899 char hard = 0; 900 901 v++; 902 if (*v && eq(*v, "-h")) { 903 hard = 1; 904 v++; 905 } 906 if (*v == 0) { 907 for (lp = limits; lp->limconst >= 0; lp++) 908 plim(lp, hard); 909 return; 910 } 911 lp = findlim(v[0]); 912 if (v[1] == 0) { 913 plim(lp, hard); 914 return; 915 } 916 limit = getval(lp, v+1); 917 if (setlim(lp, hard, limit) < 0) 918 error(NOSTR); 919 } 920 921 getval(lp, v) 922 register struct limits *lp; 923 char **v; 924 { 925 register float f; 926 double atof(); 927 char *cp = *v++; 928 929 f = atof(cp); 930 while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 931 cp++; 932 if (*cp == 0) { 933 if (*v == 0) 934 return ((int)(f+0.5) * lp->limdiv); 935 cp = *v; 936 } 937 switch (*cp) { 938 939 case ':': 940 if (lp->limconst != RLIMIT_CPU) 941 goto badscal; 942 return ((int)(f * 60.0 + atof(cp+1))); 943 944 case 'h': 945 if (lp->limconst != RLIMIT_CPU) 946 goto badscal; 947 limtail(cp, "hours"); 948 f *= 3600.; 949 break; 950 951 case 'm': 952 if (lp->limconst == RLIMIT_CPU) { 953 limtail(cp, "minutes"); 954 f *= 60.; 955 break; 956 } 957 case 'M': 958 if (lp->limconst == RLIMIT_CPU) 959 goto badscal; 960 *cp = 'm'; 961 limtail(cp, "megabytes"); 962 f *= 1024.*1024.; 963 break; 964 965 case 's': 966 if (lp->limconst != RLIMIT_CPU) 967 goto badscal; 968 limtail(cp, "seconds"); 969 break; 970 971 case 'k': 972 if (lp->limconst == RLIMIT_CPU) 973 goto badscal; 974 limtail(cp, "kbytes"); 975 f *= 1024; 976 break; 977 978 case 'u': 979 limtail(cp, "unlimited"); 980 return (RLIM_INFINITY); 981 982 default: 983 badscal: 984 bferr("Improper or unknown scale factor"); 985 } 986 return ((int)(f+0.5)); 987 } 988 989 limtail(cp, str0) 990 char *cp, *str0; 991 { 992 register char *str = str0; 993 994 while (*cp && *cp == *str) 995 cp++, str++; 996 if (*cp) 997 error("Bad scaling; did you mean ``%s''?", str0); 998 } 999 1000 plim(lp, hard) 1001 register struct limits *lp; 1002 char hard; 1003 { 1004 struct rlimit rlim; 1005 int limit; 1006 1007 printf("%s \t", lp->limname); 1008 (void) getrlimit(lp->limconst, &rlim); 1009 limit = hard ? rlim.rlim_max : rlim.rlim_cur; 1010 if (limit == RLIM_INFINITY) 1011 printf("unlimited"); 1012 else if (lp->limconst == RLIMIT_CPU) 1013 psecs((long)limit); 1014 else 1015 printf("%d %s", limit / lp->limdiv, lp->limscale); 1016 printf("\n"); 1017 } 1018 1019 dounlimit(v) 1020 register char **v; 1021 { 1022 register struct limits *lp; 1023 int err = 0; 1024 char hard = 0; 1025 1026 v++; 1027 if (*v && eq(*v, "-h")) { 1028 hard = 1; 1029 v++; 1030 } 1031 if (*v == 0) { 1032 for (lp = limits; lp->limconst >= 0; lp++) 1033 if (setlim(lp, hard, (int)RLIM_INFINITY) < 0) 1034 err++; 1035 if (err) 1036 error(NOSTR); 1037 return; 1038 } 1039 while (*v) { 1040 lp = findlim(*v++); 1041 if (setlim(lp, hard, (int)RLIM_INFINITY) < 0) 1042 error(NOSTR); 1043 } 1044 } 1045 1046 setlim(lp, hard, limit) 1047 register struct limits *lp; 1048 char hard; 1049 { 1050 struct rlimit rlim; 1051 1052 (void) getrlimit(lp->limconst, &rlim); 1053 if (hard) 1054 rlim.rlim_max = limit; 1055 else if (limit == RLIM_INFINITY && geteuid() != 0) 1056 rlim.rlim_cur = rlim.rlim_max; 1057 else 1058 rlim.rlim_cur = limit; 1059 if (setrlimit(lp->limconst, &rlim) < 0) { 1060 printf("%s: %s: Can't %s%s limit\n", bname, lp->limname, 1061 limit == RLIM_INFINITY ? "remove" : "set", 1062 hard ? " hard" : ""); 1063 return (-1); 1064 } 1065 return (0); 1066 } 1067 1068 dosuspend() 1069 { 1070 sig_t old; 1071 int ldisc, ctpgrp; 1072 1073 if (loginsh) 1074 error("Can't suspend a login shell (yet)"); 1075 untty(); 1076 old = signal(SIGTSTP, SIG_DFL); 1077 (void) kill(0, SIGTSTP); 1078 /* the shell stops here */ 1079 (void) signal(SIGTSTP, old); 1080 if (tpgrp != -1) { 1081 retry: 1082 (void) ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp); 1083 if (ctpgrp != opgrp) { 1084 old = signal(SIGTTIN, SIG_DFL); 1085 (void) kill(0, SIGTTIN); 1086 (void) signal(SIGTTIN, old); 1087 goto retry; 1088 } 1089 (void) setpgrp(0, shpgrp); 1090 (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&shpgrp); 1091 } 1092 } 1093 1094 doeval(v) 1095 char **v; 1096 { 1097 char **oevalvec = evalvec; 1098 char *oevalp = evalp; 1099 jmp_buf osetexit; 1100 int reenter; 1101 char **gv = 0; 1102 1103 v++; 1104 if (*v == 0) 1105 return; 1106 gflag = 0, tglob(v); 1107 if (gflag) { 1108 gv = v = globall(v); 1109 gargv = 0; 1110 if (v == 0) 1111 error("No match"); 1112 v = copyblk(v); 1113 } else 1114 trim(v); 1115 getexit(osetexit); 1116 reenter = 0; 1117 (void)setjmp(reslab); 1118 reenter++; 1119 if (reenter == 1) { 1120 evalvec = v; 1121 evalp = 0; 1122 process(0); 1123 } 1124 evalvec = oevalvec; 1125 evalp = oevalp; 1126 doneinp = 0; 1127 if (gv) 1128 blkfree(gv); 1129 resexit(osetexit); 1130 if (reenter >= 2) 1131 error(NOSTR); 1132 } 1133