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