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