1 /* $Header: /src/pub/tcsh/sh.func.c,v 3.111 2004/05/13 15:23:39 christos Exp $ */ 2 /* 3 * sh.func.c: csh builtin functions 4 */ 5 /*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 #include "sh.h" 34 35 RCSID("$Id: sh.func.c,v 3.111 2004/05/13 15:23:39 christos Exp $") 36 37 #include "ed.h" 38 #include "tw.h" 39 #include "tc.h" 40 #ifdef WINNT_NATIVE 41 #include "nt.const.h" 42 #endif /* WINNT_NATIVE */ 43 44 /* 45 * C shell 46 */ 47 extern int just_signaled; 48 extern char **environ; 49 50 extern bool MapsAreInited; 51 extern bool NLSMapsAreInited; 52 extern bool NoNLSRebind; 53 extern bool GotTermCaps; 54 55 static int zlast = -1; 56 57 static void islogin __P((void)); 58 static void preread __P((void)); 59 static void doagain __P((void)); 60 static char *isrchx __P((int)); 61 static void search __P((int, int, Char *)); 62 static int getword __P((Char *)); 63 static void toend __P((void)); 64 static void xecho __P((int, Char **)); 65 static bool islocale_var __P((Char *)); 66 static void wpfree __P((struct whyle *)); 67 68 struct biltins * 69 isbfunc(t) 70 struct command *t; 71 { 72 register Char *cp = t->t_dcom[0]; 73 register struct biltins *bp, *bp1, *bp2; 74 static struct biltins label = {"", dozip, 0, 0}; 75 static struct biltins foregnd = {"%job", dofg1, 0, 0}; 76 static struct biltins backgnd = {"%job &", dobg1, 0, 0}; 77 78 /* 79 * We never match a builtin that has quoted the first 80 * character; this has been the traditional way to escape 81 * builtin commands. 82 */ 83 if (*cp & QUOTE) 84 return NULL; 85 86 if (*cp != ':' && lastchr(cp) == ':') { 87 label.bname = short2str(cp); 88 return (&label); 89 } 90 if (*cp == '%') { 91 if (t->t_dflg & F_AMPERSAND) { 92 t->t_dflg &= ~F_AMPERSAND; 93 backgnd.bname = short2str(cp); 94 return (&backgnd); 95 } 96 foregnd.bname = short2str(cp); 97 return (&foregnd); 98 } 99 #ifdef WARP 100 /* 101 * This is a perhaps kludgy way to determine if the warp builtin is to be 102 * acknowledged or not. If checkwarp() fails, then we are to assume that 103 * the warp command is invalid, and carry on as we would handle any other 104 * non-builtin command. -- JDK 2/4/88 105 */ 106 if (eq(STRwarp, cp) && !checkwarp()) { 107 return (0); /* this builtin disabled */ 108 } 109 #endif /* WARP */ 110 /* 111 * Binary search Bp1 is the beginning of the current search range. Bp2 is 112 * one past the end. 113 */ 114 for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { 115 int i; 116 117 bp = bp1 + ((bp2 - bp1) >> 1); 118 if ((i = ((char) *cp) - *bp->bname) == 0 && 119 (i = StrQcmp(cp, str2short(bp->bname))) == 0) 120 return bp; 121 if (i < 0) 122 bp2 = bp; 123 else 124 bp1 = bp + 1; 125 } 126 #ifdef WINNT_NATIVE 127 return nt_check_additional_builtins(cp); 128 #endif /*WINNT_NATIVE*/ 129 return (0); 130 } 131 132 void 133 func(t, bp) 134 register struct command *t; 135 register struct biltins *bp; 136 { 137 int i; 138 139 xechoit(t->t_dcom); 140 setname(bp->bname); 141 i = blklen(t->t_dcom) - 1; 142 if (i < bp->minargs) 143 stderror(ERR_NAME | ERR_TOOFEW); 144 if (i > bp->maxargs) 145 stderror(ERR_NAME | ERR_TOOMANY); 146 (*bp->bfunct) (t->t_dcom, t); 147 } 148 149 /*ARGSUSED*/ 150 void 151 doonintr(v, c) 152 Char **v; 153 struct command *c; 154 { 155 register Char *cp; 156 register Char *vv = v[1]; 157 158 USE(c); 159 if (parintr == SIG_IGN) 160 return; 161 if (setintr && intty) 162 stderror(ERR_NAME | ERR_TERMINAL); 163 cp = gointr; 164 gointr = 0; 165 xfree((ptr_t) cp); 166 if (vv == 0) { 167 #ifdef BSDSIGS 168 if (setintr) { 169 (void) sigblock(sigmask(SIGINT)); 170 (void) signal(SIGINT, pintr); 171 } 172 else 173 (void) signal(SIGINT, SIG_DFL); 174 #else /* !BSDSIGS */ 175 if (setintr) { 176 (void) sighold(SIGINT); 177 (void) sigset(SIGINT, pintr); 178 } 179 else 180 (void) sigset(SIGINT, SIG_DFL); 181 #endif /* BSDSIGS */ 182 gointr = 0; 183 } 184 else if (eq((vv = strip(vv)), STRminus)) { 185 #ifdef BSDSIGS 186 (void) signal(SIGINT, SIG_IGN); 187 #else /* !BSDSIGS */ 188 (void) sigset(SIGINT, SIG_IGN); 189 #endif /* BSDSIGS */ 190 gointr = Strsave(STRminus); 191 } 192 else { 193 gointr = Strsave(vv); 194 #ifdef BSDSIGS 195 (void) signal(SIGINT, pintr); 196 #else /* !BSDSIGS */ 197 (void) sigset(SIGINT, pintr); 198 #endif /* BSDSIGS */ 199 } 200 } 201 202 /*ARGSUSED*/ 203 void 204 donohup(v, c) 205 Char **v; 206 struct command *c; 207 { 208 USE(c); 209 USE(v); 210 if (intty) 211 stderror(ERR_NAME | ERR_TERMINAL); 212 if (setintr == 0) { 213 (void) signal(SIGHUP, SIG_IGN); 214 #ifdef CC 215 submit(getpid()); 216 #endif /* CC */ 217 } 218 } 219 220 /*ARGSUSED*/ 221 void 222 dohup(v, c) 223 Char **v; 224 struct command *c; 225 { 226 USE(c); 227 USE(v); 228 if (intty) 229 stderror(ERR_NAME | ERR_TERMINAL); 230 if (setintr == 0) 231 (void) signal(SIGHUP, SIG_DFL); 232 } 233 234 235 /*ARGSUSED*/ 236 void 237 dozip(v, c) 238 Char **v; 239 struct command *c; 240 { 241 USE(c); 242 USE(v); 243 } 244 245 /*ARGSUSED*/ 246 void 247 dofiletest(v, c) 248 Char **v; 249 struct command *c; 250 { 251 Char **fileptr, *ftest, *res; 252 253 if (*(ftest = *++v) != '-') 254 stderror(ERR_NAME | ERR_FILEINQ); 255 ++v; 256 257 gflag = 0; 258 tglob(v); 259 if (gflag) { 260 v = globall(v); 261 if (v == 0) 262 stderror(ERR_NAME | ERR_NOMATCH); 263 } 264 else 265 v = gargv = saveblk(v); 266 trim(v); 267 268 while (*(fileptr = v++) != '\0') { 269 xprintf("%S", res = filetest(ftest, &fileptr, 0)); 270 xfree((ptr_t) res); 271 if (*v) 272 xprintf(" "); 273 } 274 xprintf("\n"); 275 276 if (gargv) { 277 blkfree(gargv); 278 gargv = 0; 279 } 280 } 281 282 void 283 prvars() 284 { 285 plist(&shvhed, VAR_ALL); 286 } 287 288 /*ARGSUSED*/ 289 void 290 doalias(v, c) 291 register Char **v; 292 struct command *c; 293 { 294 register struct varent *vp; 295 register Char *p; 296 297 USE(c); 298 v++; 299 p = *v++; 300 if (p == 0) 301 plist(&aliases, VAR_ALL); 302 else if (*v == 0) { 303 vp = adrof1(strip(p), &aliases); 304 if (vp && vp->vec) 305 blkpr(vp->vec), xputchar('\n'); 306 } 307 else { 308 if (eq(p, STRalias) || eq(p, STRunalias)) { 309 setname(short2str(p)); 310 stderror(ERR_NAME | ERR_DANGER); 311 } 312 set1(strip(p), saveblk(v), &aliases, VAR_READWRITE); 313 tw_cmd_free(); 314 } 315 } 316 317 /*ARGSUSED*/ 318 void 319 unalias(v, c) 320 Char **v; 321 struct command *c; 322 { 323 USE(c); 324 unset1(v, &aliases); 325 tw_cmd_free(); 326 } 327 328 /*ARGSUSED*/ 329 void 330 dologout(v, c) 331 Char **v; 332 struct command *c; 333 { 334 USE(c); 335 USE(v); 336 islogin(); 337 goodbye(NULL, NULL); 338 } 339 340 /*ARGSUSED*/ 341 void 342 dologin(v, c) 343 Char **v; 344 struct command *c; 345 { 346 #ifdef WINNT_NATIVE 347 USE(c); 348 USE(v); 349 #else /* !WINNT_NATIVE */ 350 char **p = short2blk(v); 351 USE(c); 352 islogin(); 353 rechist(NULL, adrof(STRsavehist) != NULL); 354 (void) signal(SIGTERM, parterm); 355 (void) execv(_PATH_BIN_LOGIN, p); 356 (void) execv(_PATH_USRBIN_LOGIN, p); 357 blkfree((Char **) p); 358 untty(); 359 xexit(1); 360 #endif /* !WINNT_NATIVE */ 361 } 362 363 364 #ifdef NEWGRP 365 /*ARGSUSED*/ 366 void 367 donewgrp(v, c) 368 Char **v; 369 struct command *c; 370 { 371 char **p; 372 if (chkstop == 0 && setintr) 373 panystop(0); 374 (void) signal(SIGTERM, parterm); 375 p = short2blk(v); 376 /* 377 * From Beto Appleton (beto@aixwiz.austin.ibm.com) 378 * Newgrp can take 2 arguments... 379 */ 380 (void) execv(_PATH_BIN_NEWGRP, p); 381 (void) execv(_PATH_USRBIN_NEWGRP, p); 382 blkfree((Char **) p); 383 untty(); 384 xexit(1); 385 } 386 #endif /* NEWGRP */ 387 388 static void 389 islogin() 390 { 391 if (chkstop == 0 && setintr) 392 panystop(0); 393 if (loginsh) 394 return; 395 stderror(ERR_NOTLOGIN); 396 } 397 398 void 399 doif(v, kp) 400 Char **v; 401 struct command *kp; 402 { 403 register int i; 404 register Char **vv; 405 406 v++; 407 i = expr(&v); 408 vv = v; 409 if (*vv == NULL) 410 stderror(ERR_NAME | ERR_EMPTYIF); 411 if (eq(*vv, STRthen)) { 412 if (*++vv) 413 stderror(ERR_NAME | ERR_IMPRTHEN); 414 setname(short2str(STRthen)); 415 /* 416 * If expression was zero, then scan to else , otherwise just fall into 417 * following code. 418 */ 419 if (!i) 420 search(TC_IF, 0, NULL); 421 return; 422 } 423 /* 424 * Simple command attached to this if. Left shift the node in this tree, 425 * munging it so we can reexecute it. 426 */ 427 if (i) { 428 lshift(kp->t_dcom, vv - kp->t_dcom); 429 reexecute(kp); 430 donefds(); 431 } 432 } 433 434 /* 435 * Reexecute a command, being careful not 436 * to redo i/o redirection, which is already set up. 437 */ 438 void 439 reexecute(kp) 440 register struct command *kp; 441 { 442 kp->t_dflg &= F_SAVE; 443 kp->t_dflg |= F_REPEAT; 444 /* 445 * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set 446 * pgrp's as the jobs would then have no way to get the tty (we can't give 447 * it to them, and our parent wouldn't know their pgrp, etc. 448 */ 449 execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL, TRUE); 450 } 451 452 /*ARGSUSED*/ 453 void 454 doelse (v, c) 455 Char **v; 456 struct command *c; 457 { 458 USE(c); 459 USE(v); 460 search(TC_ELSE, 0, NULL); 461 } 462 463 /*ARGSUSED*/ 464 void 465 dogoto(v, c) 466 Char **v; 467 struct command *c; 468 { 469 Char *lp; 470 471 USE(c); 472 gotolab(lp = globone(v[1], G_ERROR)); 473 xfree((ptr_t) lp); 474 } 475 476 void 477 gotolab(lab) 478 Char *lab; 479 { 480 register struct whyle *wp; 481 /* 482 * While we still can, locate any unknown ends of existing loops. This 483 * obscure code is the WORST result of the fact that we don't really parse. 484 */ 485 zlast = TC_GOTO; 486 for (wp = whyles; wp; wp = wp->w_next) 487 if (wp->w_end.type == TCSH_F_SEEK && wp->w_end.f_seek == 0) { 488 search(TC_BREAK, 0, NULL); 489 btell(&wp->w_end); 490 } 491 else { 492 bseek(&wp->w_end); 493 } 494 search(TC_GOTO, 0, lab); 495 /* 496 * Eliminate loops which were exited. 497 */ 498 wfree(); 499 } 500 501 /*ARGSUSED*/ 502 void 503 doswitch(v, c) 504 register Char **v; 505 struct command *c; 506 { 507 register Char *cp, *lp; 508 509 USE(c); 510 v++; 511 if (!*v || *(*v++) != '(') 512 stderror(ERR_SYNTAX); 513 cp = **v == ')' ? STRNULL : *v++; 514 if (*(*v++) != ')') 515 v--; 516 if (*v) 517 stderror(ERR_SYNTAX); 518 search(TC_SWITCH, 0, lp = globone(cp, G_ERROR)); 519 xfree((ptr_t) lp); 520 } 521 522 /*ARGSUSED*/ 523 void 524 dobreak(v, c) 525 Char **v; 526 struct command *c; 527 { 528 USE(v); 529 USE(c); 530 if (whyles) 531 toend(); 532 else 533 stderror(ERR_NAME | ERR_NOTWHILE); 534 } 535 536 /*ARGSUSED*/ 537 void 538 doexit(v, c) 539 Char **v; 540 struct command *c; 541 { 542 USE(c); 543 544 if (chkstop == 0 && (intty || intact) && evalvec == 0) 545 panystop(0); 546 /* 547 * Don't DEMAND parentheses here either. 548 */ 549 v++; 550 if (*v) { 551 set(STRstatus, putn(expr(&v)), VAR_READWRITE); 552 if (*v) 553 stderror(ERR_NAME | ERR_EXPRESSION); 554 } 555 btoeof(); 556 #if 0 557 if (intty) 558 #endif 559 /* Always close, why only on ttys? */ 560 (void) close(SHIN); 561 } 562 563 /*ARGSUSED*/ 564 void 565 doforeach(v, c) 566 register Char **v; 567 struct command *c; 568 { 569 register Char *cp, *sp; 570 register struct whyle *nwp; 571 572 USE(c); 573 v++; 574 sp = cp = strip(*v); 575 if (!letter(*sp)) 576 stderror(ERR_NAME | ERR_VARBEGIN); 577 while (*cp && alnum(*cp)) 578 cp++; 579 if (*cp) 580 stderror(ERR_NAME | ERR_VARALNUM); 581 if ((cp - sp) > MAXVARLEN) 582 stderror(ERR_NAME | ERR_VARTOOLONG); 583 cp = *v++; 584 if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') 585 stderror(ERR_NAME | ERR_NOPAREN); 586 v++; 587 gflag = 0, tglob(v); 588 if (gflag) { 589 v = globall(v); 590 if (v == 0) 591 stderror(ERR_NAME | ERR_NOMATCH); 592 } 593 else { 594 v = gargv = saveblk(v); 595 trim(v); 596 } 597 nwp = (struct whyle *) xcalloc(1, sizeof *nwp); 598 nwp->w_fe = nwp->w_fe0 = v; 599 gargv = 0; 600 btell(&nwp->w_start); 601 nwp->w_fename = Strsave(cp); 602 nwp->w_next = whyles; 603 nwp->w_end.type = TCSH_F_SEEK; 604 whyles = nwp; 605 /* 606 * Pre-read the loop so as to be more comprehensible to a terminal user. 607 */ 608 zlast = TC_FOREACH; 609 if (intty) 610 preread(); 611 doagain(); 612 } 613 614 /*ARGSUSED*/ 615 void 616 dowhile(v, c) 617 Char **v; 618 struct command *c; 619 { 620 register int status; 621 register bool again = whyles != 0 && 622 SEEKEQ(&whyles->w_start, &lineloc) && 623 whyles->w_fename == 0; 624 625 USE(c); 626 v++; 627 /* 628 * Implement prereading here also, taking care not to evaluate the 629 * expression before the loop has been read up from a terminal. 630 */ 631 if (intty && !again) 632 status = !exp0(&v, 1); 633 else 634 status = !expr(&v); 635 if (*v) 636 stderror(ERR_NAME | ERR_EXPRESSION); 637 if (!again) { 638 register struct whyle *nwp = 639 (struct whyle *) xcalloc(1, sizeof(*nwp)); 640 641 nwp->w_start = lineloc; 642 nwp->w_end.type = TCSH_F_SEEK; 643 nwp->w_end.f_seek = 0; 644 nwp->w_next = whyles; 645 whyles = nwp; 646 zlast = TC_WHILE; 647 if (intty) { 648 /* 649 * The tty preread 650 */ 651 preread(); 652 doagain(); 653 return; 654 } 655 } 656 if (status) 657 /* We ain't gonna loop no more, no more! */ 658 toend(); 659 } 660 661 static void 662 preread() 663 { 664 whyles->w_end.type = TCSH_I_SEEK; 665 if (setintr) 666 #ifdef BSDSIGS 667 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 668 #else /* !BSDSIGS */ 669 (void) sigrelse (SIGINT); 670 #endif /* BSDSIGS */ 671 search(TC_BREAK, 0, NULL); /* read the expression in */ 672 if (setintr) 673 #ifdef BSDSIGS 674 (void) sigblock(sigmask(SIGINT)); 675 #else /* !BSDSIGS */ 676 (void) sighold(SIGINT); 677 #endif /* BSDSIGS */ 678 btell(&whyles->w_end); 679 } 680 681 /*ARGSUSED*/ 682 void 683 doend(v, c) 684 Char **v; 685 struct command *c; 686 { 687 USE(v); 688 USE(c); 689 if (!whyles) 690 stderror(ERR_NAME | ERR_NOTWHILE); 691 btell(&whyles->w_end); 692 doagain(); 693 } 694 695 /*ARGSUSED*/ 696 void 697 docontin(v, c) 698 Char **v; 699 struct command *c; 700 { 701 USE(v); 702 USE(c); 703 if (!whyles) 704 stderror(ERR_NAME | ERR_NOTWHILE); 705 doagain(); 706 } 707 708 static void 709 doagain() 710 { 711 /* Repeating a while is simple */ 712 if (whyles->w_fename == 0) { 713 bseek(&whyles->w_start); 714 return; 715 } 716 /* 717 * The foreach variable list actually has a spurious word ")" at the end of 718 * the w_fe list. Thus we are at the of the list if one word beyond this 719 * is 0. 720 */ 721 if (!whyles->w_fe[1]) { 722 dobreak(NULL, NULL); 723 return; 724 } 725 set(whyles->w_fename, quote(Strsave(*whyles->w_fe++)), VAR_READWRITE); 726 bseek(&whyles->w_start); 727 } 728 729 void 730 dorepeat(v, kp) 731 Char **v; 732 struct command *kp; 733 { 734 int i = 1; 735 736 #ifdef BSDSIGS 737 register sigmask_t omask = 0; 738 #endif /* BSDSIGS */ 739 740 do { 741 i *= getn(v[1]); 742 lshift(v, 2); 743 } while (v[0] != NULL && Strcmp(v[0], STRrepeat) == 0); 744 745 if (setintr) 746 #ifdef BSDSIGS 747 omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 748 #else /* !BSDSIGS */ 749 (void) sighold(SIGINT); 750 #endif /* BSDSIGS */ 751 while (i > 0) { 752 if (setintr) 753 #ifdef BSDSIGS 754 (void) sigsetmask(omask); 755 #else /* !BSDSIGS */ 756 (void) sigrelse (SIGINT); 757 #endif /* BSDSIGS */ 758 reexecute(kp); 759 --i; 760 } 761 donefds(); 762 if (setintr) 763 #ifdef BSDSIGS 764 (void) sigsetmask(omask); 765 #else /* !BSDSIGS */ 766 (void) sigrelse (SIGINT); 767 #endif /* BSDSIGS */ 768 } 769 770 /*ARGSUSED*/ 771 void 772 doswbrk(v, c) 773 Char **v; 774 struct command *c; 775 { 776 USE(v); 777 USE(c); 778 search(TC_BRKSW, 0, NULL); 779 } 780 781 int 782 srchx(cp) 783 Char *cp; 784 { 785 struct srch *sp, *sp1, *sp2; 786 int i; 787 788 /* 789 * Ignore keywords inside heredocs 790 */ 791 if (inheredoc) 792 return -1; 793 794 /* 795 * Binary search Sp1 is the beginning of the current search range. Sp2 is 796 * one past the end. 797 */ 798 for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { 799 sp = sp1 + ((sp2 - sp1) >> 1); 800 if ((i = *cp - *sp->s_name) == 0 && 801 (i = Strcmp(cp, str2short(sp->s_name))) == 0) 802 return sp->s_value; 803 if (i < 0) 804 sp2 = sp; 805 else 806 sp1 = sp + 1; 807 } 808 return (-1); 809 } 810 811 static char * 812 isrchx(n) 813 register int n; 814 { 815 register struct srch *sp, *sp2; 816 817 for (sp = srchn, sp2 = srchn + nsrchn; sp < sp2; sp++) 818 if (sp->s_value == n) 819 return (sp->s_name); 820 return (""); 821 } 822 823 824 static Char Stype; 825 static Char *Sgoal; 826 827 static void 828 search(type, level, goal) 829 int type; 830 register int level; 831 Char *goal; 832 { 833 Char wordbuf[BUFSIZE]; 834 register Char *aword = wordbuf; 835 register Char *cp; 836 struct whyle *wp; 837 int wlevel = 0; 838 839 Stype = (Char) type; 840 Sgoal = goal; 841 if (type == TC_GOTO) { 842 struct Ain a; 843 a.type = TCSH_F_SEEK; 844 a.f_seek = 0; 845 bseek(&a); 846 } 847 do { 848 if (intty && fseekp == feobp && aret == TCSH_F_SEEK) 849 printprompt(1, isrchx(type == TC_BREAK ? zlast : type)); 850 /* xprintf("? "), flush(); */ 851 aword[0] = 0; 852 (void) getword(aword); 853 switch (srchx(aword)) { 854 855 case TC_ELSE: 856 if (level == 0 && type == TC_IF) 857 return; 858 break; 859 860 case TC_IF: 861 while (getword(aword)) 862 continue; 863 if ((type == TC_IF || type == TC_ELSE) && 864 eq(aword, STRthen)) 865 level++; 866 break; 867 868 case TC_ENDIF: 869 if (type == TC_IF || type == TC_ELSE) 870 level--; 871 break; 872 873 case TC_FOREACH: 874 case TC_WHILE: 875 wlevel++; 876 if (type == TC_BREAK) 877 level++; 878 break; 879 880 case TC_END: 881 if (type == TC_BRKSW) { 882 if (wlevel == 0) { 883 wp = whyles; 884 if (wp) { 885 whyles = wp->w_next; 886 wpfree(wp); 887 } 888 } 889 } 890 if (type == TC_BREAK) 891 level--; 892 wlevel--; 893 break; 894 895 case TC_SWITCH: 896 if (type == TC_SWITCH || type == TC_BRKSW) 897 level++; 898 break; 899 900 case TC_ENDSW: 901 if (type == TC_SWITCH || type == TC_BRKSW) 902 level--; 903 break; 904 905 case TC_LABEL: 906 if (type == TC_GOTO && getword(aword) && eq(aword, goal)) 907 level = -1; 908 break; 909 910 default: 911 if (type != TC_GOTO && (type != TC_SWITCH || level != 0)) 912 break; 913 if (lastchr(aword) != ':') 914 break; 915 aword[Strlen(aword) - 1] = 0; 916 if ((type == TC_GOTO && eq(aword, goal)) || 917 (type == TC_SWITCH && eq(aword, STRdefault))) 918 level = -1; 919 break; 920 921 case TC_CASE: 922 if (type != TC_SWITCH || level != 0) 923 break; 924 (void) getword(aword); 925 if (lastchr(aword) == ':') 926 aword[Strlen(aword) - 1] = 0; 927 cp = strip(Dfix1(aword)); 928 if (Gmatch(goal, cp)) 929 level = -1; 930 xfree((ptr_t) cp); 931 break; 932 933 case TC_DEFAULT: 934 if (type == TC_SWITCH && level == 0) 935 level = -1; 936 break; 937 } 938 (void) getword(NULL); 939 } while (level >= 0); 940 } 941 942 static int 943 getword(wp) 944 register Char *wp; 945 { 946 int found = 0, first; 947 int c, d; 948 949 c = readc(1); 950 d = 0; 951 do { 952 while (c == ' ' || c == '\t') 953 c = readc(1); 954 if (c == '#') 955 do 956 c = readc(1); 957 while (c >= 0 && c != '\n'); 958 if (c < 0) 959 goto past; 960 if (c == '\n') { 961 if (wp) 962 break; 963 return (0); 964 } 965 unreadc(c); 966 found = 1; 967 first = 1; 968 do { 969 c = readc(1); 970 if (c == '\\' && (c = readc(1)) == '\n') 971 c = ' '; 972 if (c == '\'' || c == '"') { 973 if (d == 0) 974 d = c; 975 else if (d == c) 976 d = 0; 977 } 978 if (c < 0) 979 goto past; 980 if (wp) { 981 *wp++ = (Char) c; 982 *wp = '\0'; 983 } 984 if (!first && !d && c == '(') { 985 if (wp) { 986 unreadc(c); 987 *--wp = '\0'; 988 return found; 989 } 990 else 991 break; 992 } 993 first = 0; 994 } while ((d || (c != ' ' && c != '\t')) && c != '\n'); 995 } while (wp == 0); 996 997 unreadc(c); 998 if (found) 999 *--wp = '\0'; 1000 1001 return (found); 1002 1003 past: 1004 switch (Stype) { 1005 1006 case TC_IF: 1007 stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); 1008 break; 1009 1010 case TC_ELSE: 1011 stderror(ERR_NAME | ERR_NOTFOUND, "endif"); 1012 break; 1013 1014 case TC_BRKSW: 1015 case TC_SWITCH: 1016 stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); 1017 break; 1018 1019 case TC_BREAK: 1020 stderror(ERR_NAME | ERR_NOTFOUND, "end"); 1021 break; 1022 1023 case TC_GOTO: 1024 setname(short2str(Sgoal)); 1025 stderror(ERR_NAME | ERR_NOTFOUND, "label"); 1026 break; 1027 1028 default: 1029 break; 1030 } 1031 /* NOTREACHED */ 1032 return (0); 1033 } 1034 1035 static void 1036 toend() 1037 { 1038 if (whyles->w_end.type == TCSH_F_SEEK && whyles->w_end.f_seek == 0) { 1039 search(TC_BREAK, 0, NULL); 1040 btell(&whyles->w_end); 1041 whyles->w_end.f_seek--; 1042 } 1043 else { 1044 bseek(&whyles->w_end); 1045 } 1046 wfree(); 1047 } 1048 1049 static void 1050 wpfree(wp) 1051 struct whyle *wp; 1052 { 1053 if (wp->w_fe0) 1054 blkfree(wp->w_fe0); 1055 if (wp->w_fename) 1056 xfree((ptr_t) wp->w_fename); 1057 xfree((ptr_t) wp); 1058 } 1059 1060 void 1061 wfree() 1062 { 1063 struct Ain o; 1064 struct whyle *nwp; 1065 #ifdef lint 1066 nwp = NULL; /* sun lint is dumb! */ 1067 #endif 1068 1069 #ifdef FDEBUG 1070 static char foo[] = "IAFE"; 1071 #endif /* FDEBUG */ 1072 1073 btell(&o); 1074 1075 #ifdef FDEBUG 1076 xprintf("o->type %c o->a_seek %d o->f_seek %d\n", 1077 foo[o.type + 1], o.a_seek, o.f_seek); 1078 #endif /* FDEBUG */ 1079 1080 for (; whyles; whyles = nwp) { 1081 register struct whyle *wp = whyles; 1082 nwp = wp->w_next; 1083 1084 #ifdef FDEBUG 1085 xprintf("start->type %c start->a_seek %d start->f_seek %d\n", 1086 foo[wp->w_start.type+1], 1087 wp->w_start.a_seek, wp->w_start.f_seek); 1088 xprintf("end->type %c end->a_seek %d end->f_seek %d\n", 1089 foo[wp->w_end.type + 1], wp->w_end.a_seek, wp->w_end.f_seek); 1090 #endif /* FDEBUG */ 1091 1092 /* 1093 * XXX: We free loops that have different seek types. 1094 */ 1095 if (wp->w_end.type != TCSH_I_SEEK && wp->w_start.type == wp->w_end.type && 1096 wp->w_start.type == o.type) { 1097 if (wp->w_end.type == TCSH_F_SEEK) { 1098 if (o.f_seek >= wp->w_start.f_seek && 1099 (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) 1100 break; 1101 } 1102 else { 1103 if (o.a_seek >= wp->w_start.a_seek && 1104 (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek)) 1105 break; 1106 } 1107 } 1108 1109 wpfree(wp); 1110 } 1111 } 1112 1113 /*ARGSUSED*/ 1114 void 1115 doecho(v, c) 1116 Char **v; 1117 struct command *c; 1118 { 1119 USE(c); 1120 xecho(' ', v); 1121 } 1122 1123 /*ARGSUSED*/ 1124 void 1125 doglob(v, c) 1126 Char **v; 1127 struct command *c; 1128 { 1129 USE(c); 1130 xecho(0, v); 1131 flush(); 1132 } 1133 1134 static void 1135 xecho(sep, v) 1136 int sep; 1137 register Char **v; 1138 { 1139 register Char *cp; 1140 int nonl = 0; 1141 #ifdef ECHO_STYLE 1142 int echo_style = ECHO_STYLE; 1143 #else /* !ECHO_STYLE */ 1144 # if SYSVREL > 0 1145 int echo_style = SYSV_ECHO; 1146 # else /* SYSVREL == 0 */ 1147 int echo_style = BSD_ECHO; 1148 # endif /* SYSVREL */ 1149 #endif /* ECHO_STYLE */ 1150 struct varent *vp; 1151 1152 if ((vp = adrof(STRecho_style)) != NULL && vp->vec != NULL && 1153 vp->vec[0] != NULL) { 1154 if (Strcmp(vp->vec[0], STRbsd) == 0) 1155 echo_style = BSD_ECHO; 1156 else if (Strcmp(vp->vec[0], STRsysv) == 0) 1157 echo_style = SYSV_ECHO; 1158 else if (Strcmp(vp->vec[0], STRboth) == 0) 1159 echo_style = BOTH_ECHO; 1160 else if (Strcmp(vp->vec[0], STRnone) == 0) 1161 echo_style = NONE_ECHO; 1162 } 1163 1164 if (setintr) 1165 #ifdef BSDSIGS 1166 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 1167 #else /* !BSDSIGS */ 1168 (void) sigrelse (SIGINT); 1169 #endif /* BSDSIGS */ 1170 v++; 1171 if (*v == 0) 1172 goto done; 1173 gflag = 0, tglob(v); 1174 if (gflag) { 1175 v = globall(v); 1176 if (v == 0) 1177 stderror(ERR_NAME | ERR_NOMATCH); 1178 } 1179 else { 1180 v = gargv = saveblk(v); 1181 trim(v); 1182 } 1183 1184 if ((echo_style & BSD_ECHO) != 0 && sep == ' ' && *v && eq(*v, STRmn)) 1185 nonl++, v++; 1186 1187 while ((cp = *v++) != 0) { 1188 register int c; 1189 1190 while ((c = *cp++) != 0) { 1191 if ((echo_style & SYSV_ECHO) != 0 && c == '\\') { 1192 switch (c = *cp++) { 1193 case 'a': 1194 c = '\a'; 1195 break; 1196 case 'b': 1197 c = '\b'; 1198 break; 1199 case 'c': 1200 nonl = 1; 1201 goto done; 1202 case 'e': 1203 #if 0 /* Windows does not understand \e */ 1204 c = '\e'; 1205 #else 1206 c = '\033'; 1207 #endif 1208 break; 1209 case 'f': 1210 c = '\f'; 1211 break; 1212 case 'n': 1213 c = '\n'; 1214 break; 1215 case 'r': 1216 c = '\r'; 1217 break; 1218 case 't': 1219 c = '\t'; 1220 break; 1221 case 'v': 1222 c = '\v'; 1223 break; 1224 case '\\': 1225 c = '\\'; 1226 break; 1227 case '0': 1228 c = 0; 1229 if (*cp >= '0' && *cp < '8') 1230 c = c * 8 + *cp++ - '0'; 1231 if (*cp >= '0' && *cp < '8') 1232 c = c * 8 + *cp++ - '0'; 1233 if (*cp >= '0' && *cp < '8') 1234 c = c * 8 + *cp++ - '0'; 1235 break; 1236 case '\0': 1237 c = '\\'; 1238 cp--; 1239 break; 1240 default: 1241 xputchar('\\' | QUOTE); 1242 break; 1243 } 1244 } 1245 xputchar(c | QUOTE); 1246 1247 } 1248 if (*v) 1249 xputchar(sep | QUOTE); 1250 } 1251 done: 1252 if (sep && nonl == 0) 1253 xputchar('\n'); 1254 else 1255 flush(); 1256 if (setintr) 1257 #ifdef BSDSIGS 1258 (void) sigblock(sigmask(SIGINT)); 1259 #else /* !BSDSIGS */ 1260 (void) sighold(SIGINT); 1261 #endif /* BSDSIGS */ 1262 if (gargv) 1263 blkfree(gargv), gargv = 0; 1264 } 1265 1266 /* check whether an environment variable should invoke 'set_locale()' */ 1267 static bool 1268 islocale_var(var) 1269 Char *var; 1270 { 1271 static Char *locale_vars[] = { 1272 STRLANG, STRLC_ALL, STRLC_CTYPE, STRLC_NUMERIC, 1273 STRLC_TIME, STRLC_COLLATE, STRLC_MESSAGES, STRLC_MONETARY, 0 1274 }; 1275 register Char **v; 1276 1277 for (v = locale_vars; *v; ++v) 1278 if (eq(var, *v)) 1279 return 1; 1280 return 0; 1281 } 1282 1283 /*ARGSUSED*/ 1284 void 1285 doprintenv(v, c) 1286 register Char **v; 1287 struct command *c; 1288 { 1289 Char *e; 1290 extern bool output_raw; 1291 extern bool xlate_cr; 1292 1293 USE(c); 1294 if (setintr) 1295 #ifdef BSDSIGS 1296 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 1297 #else /* !BSDSIGS */ 1298 (void) sigrelse (SIGINT); 1299 #endif /* BSDSIGS */ 1300 1301 v++; 1302 if (*v == 0) { 1303 register Char **ep; 1304 1305 xlate_cr = 1; 1306 for (ep = STR_environ; *ep; ep++) 1307 xprintf("%S\n", *ep); 1308 xlate_cr = 0; 1309 } 1310 else if ((e = tgetenv(*v)) != NULL) { 1311 output_raw = 1; 1312 xprintf("%S\n", e); 1313 output_raw = 0; 1314 } 1315 else 1316 set(STRstatus, Strsave(STR1), VAR_READWRITE); 1317 } 1318 1319 /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things 1320 (and anything else with a modern compiler) */ 1321 1322 /*ARGSUSED*/ 1323 void 1324 dosetenv(v, c) 1325 register Char **v; 1326 struct command *c; 1327 { 1328 Char *vp, *lp; 1329 1330 USE(c); 1331 if (*++v == 0) { 1332 doprintenv(--v, 0); 1333 return; 1334 } 1335 1336 vp = *v++; 1337 1338 lp = vp; 1339 1340 for (; *lp != '\0' ; lp++) { 1341 if (*lp == '=') 1342 stderror(ERR_NAME | ERR_SYNTAX); 1343 } 1344 if ((lp = *v++) == 0) 1345 lp = STRNULL; 1346 1347 tsetenv(vp, lp = globone(lp, G_APPEND)); 1348 if (eq(vp, STRKPATH)) { 1349 importpath(lp); 1350 dohash(NULL, NULL); 1351 xfree((ptr_t) lp); 1352 return; 1353 } 1354 1355 #ifdef apollo 1356 if (eq(vp, STRSYSTYPE)) { 1357 dohash(NULL, NULL); 1358 xfree((ptr_t) lp); 1359 return; 1360 } 1361 #endif /* apollo */ 1362 1363 /* dspkanji/dspmbyte autosetting */ 1364 /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ 1365 #if defined(DSPMBYTE) 1366 if(eq(vp, STRLANG) && !adrof(CHECK_MBYTEVAR)) { 1367 autoset_dspmbyte(lp); 1368 } 1369 #endif 1370 1371 if (islocale_var(vp)) { 1372 #ifdef NLS 1373 int k; 1374 1375 # ifdef SETLOCALEBUG 1376 dont_free = 1; 1377 # endif /* SETLOCALEBUG */ 1378 (void) setlocale(LC_ALL, ""); 1379 # ifdef LC_COLLATE 1380 (void) setlocale(LC_COLLATE, ""); 1381 # endif 1382 # ifdef NLS_CATALOGS 1383 # ifdef LC_MESSAGES 1384 (void) setlocale(LC_MESSAGES, ""); 1385 # endif /* LC_MESSAGES */ 1386 (void) catclose(catd); 1387 nlsinit(); 1388 # endif /* NLS_CATALOGS */ 1389 # ifdef LC_CTYPE 1390 (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ 1391 # endif /* LC_CTYPE */ 1392 # ifdef SETLOCALEBUG 1393 dont_free = 0; 1394 # endif /* SETLOCALEBUG */ 1395 # ifdef STRCOLLBUG 1396 fix_strcoll_bug(); 1397 # endif /* STRCOLLBUG */ 1398 tw_cmd_free(); /* since the collation sequence has changed */ 1399 for (k = 0200; k <= 0377 && !Isprint(k); k++) 1400 continue; 1401 AsciiOnly = k > 0377; 1402 #else /* !NLS */ 1403 AsciiOnly = 0; 1404 #endif /* NLS */ 1405 NLSMapsAreInited = 0; 1406 ed_Init(); 1407 if (MapsAreInited && !NLSMapsAreInited) 1408 ed_InitNLSMaps(); 1409 xfree((ptr_t) lp); 1410 return; 1411 } 1412 1413 #ifdef NLS_CATALOGS 1414 if (eq(vp, STRNLSPATH)) { 1415 (void) catclose(catd); 1416 nlsinit(); 1417 } 1418 #endif 1419 1420 if (eq(vp, STRNOREBIND)) { 1421 NoNLSRebind = 1; 1422 MapsAreInited = 0; 1423 NLSMapsAreInited = 0; 1424 ed_InitMaps(); 1425 xfree((ptr_t) lp); 1426 return; 1427 } 1428 #ifdef WINNT_NATIVE 1429 if (eq(vp, STRtcshlang)) { 1430 nlsinit(); 1431 xfree((ptr_t) lp); 1432 return; 1433 } 1434 #endif /* WINNT_NATIVE */ 1435 if (eq(vp, STRKTERM)) { 1436 char *t; 1437 set(STRterm, quote(lp), VAR_READWRITE); /* lp memory used here */ 1438 t = short2str(lp); 1439 if (noediting && strcmp(t, "unknown") != 0 && strcmp(t,"dumb") != 0) { 1440 editing = 1; 1441 noediting = 0; 1442 set(STRedit, Strsave(STRNULL), VAR_READWRITE); 1443 } 1444 GotTermCaps = 0; 1445 ed_Init(); 1446 return; 1447 } 1448 1449 if (eq(vp, STRKHOME)) { 1450 /* 1451 * convert to canonical pathname (possibly resolving symlinks) 1452 */ 1453 lp = dcanon(lp, lp); 1454 set(STRhome, quote(lp), VAR_READWRITE); /* cp memory used here */ 1455 1456 /* fix directory stack for new tilde home */ 1457 dtilde(); 1458 return; 1459 } 1460 1461 if (eq(vp, STRKSHLVL)) { 1462 /* lp memory used here */ 1463 set(STRshlvl, quote(lp), VAR_READWRITE); 1464 return; 1465 } 1466 1467 if (eq(vp, STRKUSER)) { 1468 set(STRuser, quote(lp), VAR_READWRITE); /* lp memory used here */ 1469 return; 1470 } 1471 1472 if (eq(vp, STRKGROUP)) { 1473 set(STRgroup, quote(lp), VAR_READWRITE); /* lp memory used here */ 1474 return; 1475 } 1476 1477 #ifdef COLOR_LS_F 1478 if (eq(vp, STRLS_COLORS)) { 1479 parseLS_COLORS(lp); 1480 return; 1481 } 1482 #endif /* COLOR_LS_F */ 1483 1484 #ifdef SIG_WINDOW 1485 /* 1486 * Load/Update $LINES $COLUMNS 1487 */ 1488 if ((eq(lp, STRNULL) && (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) || 1489 eq(vp, STRTERMCAP)) { 1490 xfree((ptr_t) lp); 1491 check_window_size(1); 1492 return; 1493 } 1494 1495 /* 1496 * Change the size to the one directed by $LINES and $COLUMNS 1497 */ 1498 if (eq(vp, STRLINES) || eq(vp, STRCOLUMNS)) { 1499 #if 0 1500 GotTermCaps = 0; 1501 #endif 1502 xfree((ptr_t) lp); 1503 ed_Init(); 1504 return; 1505 } 1506 #endif /* SIG_WINDOW */ 1507 xfree((ptr_t) lp); 1508 } 1509 1510 /*ARGSUSED*/ 1511 void 1512 dounsetenv(v, c) 1513 register Char **v; 1514 struct command *c; 1515 { 1516 Char **ep, *p, *n; 1517 int i, maxi; 1518 static Char *name = NULL; 1519 1520 USE(c); 1521 if (name) 1522 xfree((ptr_t) name); 1523 /* 1524 * Find the longest environment variable 1525 */ 1526 for (maxi = 0, ep = STR_environ; *ep; ep++) { 1527 for (i = 0, p = *ep; *p && *p != '='; p++, i++) 1528 continue; 1529 if (i > maxi) 1530 maxi = i; 1531 } 1532 1533 name = (Char *) xmalloc((size_t) ((maxi + 1) * sizeof(Char))); 1534 1535 while (++v && *v) 1536 for (maxi = 1; maxi;) 1537 for (maxi = 0, ep = STR_environ; *ep; ep++) { 1538 for (n = name, p = *ep; *p && *p != '='; *n++ = *p++) 1539 continue; 1540 *n = '\0'; 1541 if (!Gmatch(name, *v)) 1542 continue; 1543 maxi = 1; 1544 1545 /* Unset the name. This wasn't being done until 1546 * later but most of the stuff following won't 1547 * work (particularly the setlocale() and getenv() 1548 * stuff) as intended until the name is actually 1549 * removed. (sg) 1550 */ 1551 Unsetenv(name); 1552 1553 if (eq(name, STRNOREBIND)) { 1554 NoNLSRebind = 0; 1555 MapsAreInited = 0; 1556 NLSMapsAreInited = 0; 1557 ed_InitMaps(); 1558 } 1559 #ifdef apollo 1560 else if (eq(name, STRSYSTYPE)) 1561 dohash(NULL, NULL); 1562 #endif /* apollo */ 1563 else if (islocale_var(name)) { 1564 #ifdef NLS 1565 int k; 1566 1567 # ifdef SETLOCALEBUG 1568 dont_free = 1; 1569 # endif /* SETLOCALEBUG */ 1570 (void) setlocale(LC_ALL, ""); 1571 # ifdef LC_COLLATE 1572 (void) setlocale(LC_COLLATE, ""); 1573 # endif 1574 # ifdef NLS_CATALOGS 1575 # ifdef LC_MESSAGES 1576 (void) setlocale(LC_MESSAGES, ""); 1577 # endif /* LC_MESSAGES */ 1578 (void) catclose(catd); 1579 nlsinit(); 1580 # endif /* NLS_CATALOGS */ 1581 # ifdef LC_CTYPE 1582 (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ 1583 # endif /* LC_CTYPE */ 1584 # ifdef SETLOCALEBUG 1585 dont_free = 0; 1586 # endif /* SETLOCALEBUG */ 1587 # ifdef STRCOLLBUG 1588 fix_strcoll_bug(); 1589 # endif /* STRCOLLBUG */ 1590 tw_cmd_free();/* since the collation sequence has changed */ 1591 for (k = 0200; k <= 0377 && !Isprint(k); k++) 1592 continue; 1593 AsciiOnly = k > 0377; 1594 #else /* !NLS */ 1595 AsciiOnly = getenv("LANG") == NULL && 1596 getenv("LC_CTYPE") == NULL; 1597 #endif /* NLS */ 1598 NLSMapsAreInited = 0; 1599 ed_Init(); 1600 if (MapsAreInited && !NLSMapsAreInited) 1601 ed_InitNLSMaps(); 1602 1603 } 1604 #ifdef WINNT_NATIVE 1605 else if (eq(name,(STRtcshlang))) { 1606 nls_dll_unload(); 1607 nlsinit(); 1608 } 1609 #endif /* WINNT_NATIVE */ 1610 #ifdef COLOR_LS_F 1611 else if (eq(name, STRLS_COLORS)) 1612 parseLS_COLORS(n); 1613 #endif /* COLOR_LS_F */ 1614 #ifdef NLS_CATALOGS 1615 else if (eq(name, STRNLSPATH)) { 1616 (void) catclose(catd); 1617 nlsinit(); 1618 } 1619 #endif 1620 /* 1621 * start again cause the environment changes 1622 */ 1623 break; 1624 } 1625 xfree((ptr_t) name); name = NULL; 1626 } 1627 1628 void 1629 tsetenv(name, val) 1630 Char *name, *val; 1631 { 1632 #ifdef SETENV_IN_LIB 1633 /* 1634 * XXX: This does not work right, since tcsh cannot track changes to 1635 * the environment this way. (the builtin setenv without arguments does 1636 * not print the right stuff neither does unsetenv). This was for Mach, 1637 * it is not needed anymore. 1638 */ 1639 #undef setenv 1640 char nameBuf[BUFSIZE]; 1641 char *cname = short2str(name); 1642 1643 if (cname == NULL) 1644 return; 1645 (void) strcpy(nameBuf, cname); 1646 setenv(nameBuf, short2str(val), 1); 1647 #else /* !SETENV_IN_LIB */ 1648 register Char **ep = STR_environ; 1649 register Char *cp, *dp; 1650 Char *blk[2]; 1651 Char **oep = ep; 1652 1653 #ifdef WINNT_NATIVE 1654 nt_set_env(name,val); 1655 #endif /* WINNT_NATIVE */ 1656 for (; *ep; ep++) { 1657 #ifdef WINNT_NATIVE 1658 for (cp = name, dp = *ep; *cp && Tolower(*cp & TRIM) == Tolower(*dp); 1659 cp++, dp++) 1660 #else 1661 for (cp = name, dp = *ep; *cp && (*cp & TRIM) == *dp; cp++, dp++) 1662 #endif /* WINNT_NATIVE */ 1663 continue; 1664 if (*cp != 0 || *dp != '=') 1665 continue; 1666 cp = Strspl(STRequal, val); 1667 xfree((ptr_t) * ep); 1668 *ep = strip(Strspl(name, cp)); 1669 xfree((ptr_t) cp); 1670 blkfree((Char **) environ); 1671 environ = short2blk(STR_environ); 1672 return; 1673 } 1674 cp = Strspl(name, STRequal); 1675 blk[0] = strip(Strspl(cp, val)); 1676 xfree((ptr_t) cp); 1677 blk[1] = 0; 1678 STR_environ = blkspl(STR_environ, blk); 1679 blkfree((Char **) environ); 1680 environ = short2blk(STR_environ); 1681 xfree((ptr_t) oep); 1682 #endif /* SETENV_IN_LIB */ 1683 } 1684 1685 void 1686 Unsetenv(name) 1687 Char *name; 1688 { 1689 register Char **ep = STR_environ; 1690 register Char *cp, *dp; 1691 Char **oep = ep; 1692 1693 #ifdef WINNT_NATIVE 1694 nt_set_env(name,NULL); 1695 #endif /*WINNT_NATIVE */ 1696 for (; *ep; ep++) { 1697 for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 1698 continue; 1699 if (*cp != 0 || *dp != '=') 1700 continue; 1701 cp = *ep; 1702 *ep = 0; 1703 STR_environ = blkspl(STR_environ, ep + 1); 1704 blkfree((Char **) environ); 1705 environ = short2blk(STR_environ); 1706 *ep = cp; 1707 xfree((ptr_t) cp); 1708 xfree((ptr_t) oep); 1709 return; 1710 } 1711 } 1712 1713 /*ARGSUSED*/ 1714 void 1715 doumask(v, c) 1716 register Char **v; 1717 struct command *c; 1718 { 1719 register Char *cp = v[1]; 1720 register int i; 1721 1722 USE(c); 1723 if (cp == 0) { 1724 i = (int)umask(0); 1725 (void) umask(i); 1726 xprintf("%o\n", i); 1727 return; 1728 } 1729 i = 0; 1730 while (Isdigit(*cp) && *cp != '8' && *cp != '9') 1731 i = i * 8 + *cp++ - '0'; 1732 if (*cp || i < 0 || i > 0777) 1733 stderror(ERR_NAME | ERR_MASK); 1734 (void) umask(i); 1735 } 1736 1737 #ifndef HAVENOLIMIT 1738 # ifndef BSDLIMIT 1739 typedef long RLIM_TYPE; 1740 # ifndef RLIM_INFINITY 1741 # if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY) 1742 extern RLIM_TYPE ulimit(); 1743 # endif /* ! _MINIX && !__clipper__ */ 1744 # define RLIM_INFINITY 0x003fffff 1745 # define RLIMIT_FSIZE 1 1746 # endif /* RLIM_INFINITY */ 1747 # ifdef aiws 1748 # define toset(a) (((a) == 3) ? 1004 : (a) + 1) 1749 # define RLIMIT_DATA 3 1750 # define RLIMIT_STACK 1005 1751 # else /* aiws */ 1752 # define toset(a) ((a) + 1) 1753 # endif /* aiws */ 1754 # else /* BSDLIMIT */ 1755 # if (defined(BSD4_4) || defined(__linux__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__) 1756 typedef rlim_t RLIM_TYPE; 1757 # else 1758 # if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3) 1759 typedef rlim_t RLIM_TYPE; 1760 # else 1761 # if defined(_SX) 1762 typedef long long RLIM_TYPE; 1763 # else /* !_SX */ 1764 typedef unsigned long RLIM_TYPE; 1765 # endif /* _SX */ 1766 # endif /* SOLARIS2 || (sgi && SYSVREL > 3) */ 1767 # endif /* BSD4_4 && !__386BSD__ */ 1768 # endif /* BSDLIMIT */ 1769 1770 # if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT) 1771 /* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */ 1772 /* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */ 1773 # ifndef RLIMIT_CPU 1774 # define RLIMIT_CPU 0 1775 # define RLIMIT_FSIZE 1 1776 # define RLIMIT_DATA 2 1777 # define RLIMIT_STACK 3 1778 # define RLIMIT_CORE 4 1779 # define RLIMIT_RSS 5 1780 # define RLIMIT_NOFILE 6 1781 # endif /* RLIMIT_CPU */ 1782 # ifndef RLIM_INFINITY 1783 # define RLIM_INFINITY 0x7fffffff 1784 # endif /* RLIM_INFINITY */ 1785 /* 1786 * old versions of HP/UX counted limits in 512 bytes 1787 */ 1788 # ifndef SIGRTMIN 1789 # define FILESIZE512 1790 # endif /* SIGRTMIN */ 1791 # endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */ 1792 1793 # if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX) 1794 /* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */ 1795 /* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */ 1796 /* than include both and get warnings, we define the extra SVR4 limits here. */ 1797 /* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */ 1798 /* RLIMIT_VMEM based on it? */ 1799 # ifndef RLIMIT_VMEM 1800 # define RLIMIT_VMEM 6 1801 # endif 1802 # ifndef RLIMIT_AS 1803 # define RLIMIT_AS RLIMIT_VMEM 1804 # endif 1805 # endif /* SYSVREL > 3 && BSDLIMIT */ 1806 1807 # if defined(__linux__) && defined(RLIMIT_AS) && !defined(RLIMIT_VMEM) 1808 # define RLIMIT_VMEM RLIMIT_AS 1809 # endif 1810 1811 struct limits limits[] = 1812 { 1813 # ifdef RLIMIT_CPU 1814 { RLIMIT_CPU, "cputime", 1, "seconds" }, 1815 # endif /* RLIMIT_CPU */ 1816 1817 # ifdef RLIMIT_FSIZE 1818 # ifndef aiws 1819 { RLIMIT_FSIZE, "filesize", 1024, "kbytes" }, 1820 # else 1821 { RLIMIT_FSIZE, "filesize", 512, "blocks" }, 1822 # endif /* aiws */ 1823 # endif /* RLIMIT_FSIZE */ 1824 1825 # ifdef RLIMIT_DATA 1826 { RLIMIT_DATA, "datasize", 1024, "kbytes" }, 1827 # endif /* RLIMIT_DATA */ 1828 1829 # ifdef RLIMIT_STACK 1830 # ifndef aiws 1831 { RLIMIT_STACK, "stacksize", 1024, "kbytes" }, 1832 # else 1833 { RLIMIT_STACK, "stacksize", 1024 * 1024, "kbytes"}, 1834 # endif /* aiws */ 1835 # endif /* RLIMIT_STACK */ 1836 1837 # ifdef RLIMIT_CORE 1838 { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" }, 1839 # endif /* RLIMIT_CORE */ 1840 1841 # ifdef RLIMIT_RSS 1842 { RLIMIT_RSS, "memoryuse", 1024, "kbytes" }, 1843 # endif /* RLIMIT_RSS */ 1844 1845 # ifdef RLIMIT_UMEM 1846 { RLIMIT_UMEM, "memoryuse", 1024, "kbytes" }, 1847 # endif /* RLIMIT_UMEM */ 1848 1849 # ifdef RLIMIT_VMEM 1850 { RLIMIT_VMEM, "vmemoryuse", 1024, "kbytes" }, 1851 # endif /* RLIMIT_VMEM */ 1852 1853 # ifdef RLIMIT_NOFILE 1854 { RLIMIT_NOFILE, "descriptors", 1, "" }, 1855 # endif /* RLIMIT_NOFILE */ 1856 1857 # ifdef RLIMIT_CONCUR 1858 { RLIMIT_CONCUR, "concurrency", 1, "thread(s)" }, 1859 # endif /* RLIMIT_CONCUR */ 1860 1861 # ifdef RLIMIT_MEMLOCK 1862 { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" }, 1863 # endif /* RLIMIT_MEMLOCK */ 1864 1865 # ifdef RLIMIT_NPROC 1866 { RLIMIT_NPROC, "maxproc", 1, "" }, 1867 # endif /* RLIMIT_NPROC */ 1868 1869 # if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE) 1870 { RLIMIT_OFILE, "openfiles", 1, "" }, 1871 # endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */ 1872 1873 # ifdef RLIMIT_SBSIZE 1874 { RLIMIT_SBSIZE, "sbsize", 1, "" }, 1875 # endif /* RLIMIT_SBSIZE */ 1876 1877 { -1, NULL, 0, NULL } 1878 }; 1879 1880 static struct limits *findlim __P((Char *)); 1881 static RLIM_TYPE getval __P((struct limits *, Char **)); 1882 static void limtail __P((Char *, char*)); 1883 static void plim __P((struct limits *, int)); 1884 static int setlim __P((struct limits *, int, RLIM_TYPE)); 1885 1886 #ifdef convex 1887 static RLIM_TYPE 1888 restrict_limit(value) 1889 double value; 1890 { 1891 /* 1892 * is f too large to cope with? return the maximum or minimum int 1893 */ 1894 if (value > (double) INT_MAX) 1895 return (RLIM_TYPE) INT_MAX; 1896 else if (value < (double) INT_MIN) 1897 return (RLIM_TYPE) INT_MIN; 1898 else 1899 return (RLIM_TYPE) value; 1900 } 1901 #else /* !convex */ 1902 # define restrict_limit(x) ((RLIM_TYPE) (x)) 1903 #endif /* convex */ 1904 1905 1906 static struct limits * 1907 findlim(cp) 1908 Char *cp; 1909 { 1910 register struct limits *lp, *res; 1911 1912 res = (struct limits *) NULL; 1913 for (lp = limits; lp->limconst >= 0; lp++) 1914 if (prefix(cp, str2short(lp->limname))) { 1915 if (res) 1916 stderror(ERR_NAME | ERR_AMBIG); 1917 res = lp; 1918 } 1919 if (res) 1920 return (res); 1921 stderror(ERR_NAME | ERR_LIMIT); 1922 /* NOTREACHED */ 1923 return (0); 1924 } 1925 1926 /*ARGSUSED*/ 1927 void 1928 dolimit(v, c) 1929 register Char **v; 1930 struct command *c; 1931 { 1932 register struct limits *lp; 1933 register RLIM_TYPE limit; 1934 int hard = 0; 1935 1936 USE(c); 1937 v++; 1938 if (*v && eq(*v, STRmh)) { 1939 hard = 1; 1940 v++; 1941 } 1942 if (*v == 0) { 1943 for (lp = limits; lp->limconst >= 0; lp++) 1944 plim(lp, hard); 1945 return; 1946 } 1947 lp = findlim(v[0]); 1948 if (v[1] == 0) { 1949 plim(lp, hard); 1950 return; 1951 } 1952 limit = getval(lp, v + 1); 1953 if (setlim(lp, hard, limit) < 0) 1954 stderror(ERR_SILENT); 1955 } 1956 1957 static RLIM_TYPE 1958 getval(lp, v) 1959 register struct limits *lp; 1960 Char **v; 1961 { 1962 register float f; 1963 #ifndef atof /* This can be a macro on linux */ 1964 extern double atof __P((const char *)); 1965 #endif /* atof */ 1966 Char *cp = *v++; 1967 1968 f = atof(short2str(cp)); 1969 1970 # ifdef convex 1971 /* 1972 * is f too large to cope with. limit f to minint, maxint - X-6768 by 1973 * strike 1974 */ 1975 if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) { 1976 stderror(ERR_NAME | ERR_TOOLARGE); 1977 } 1978 # endif /* convex */ 1979 1980 while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 1981 cp++; 1982 if (*cp == 0) { 1983 if (*v == 0) 1984 return restrict_limit((f * lp->limdiv) + 0.5); 1985 cp = *v; 1986 } 1987 switch (*cp) { 1988 # ifdef RLIMIT_CPU 1989 case ':': 1990 if (lp->limconst != RLIMIT_CPU) 1991 goto badscal; 1992 return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f * 60.0 + atof(short2str(cp + 1)))); 1993 case 'h': 1994 if (lp->limconst != RLIMIT_CPU) 1995 goto badscal; 1996 limtail(cp, "hours"); 1997 f *= 3600.0; 1998 break; 1999 case 'm': 2000 if (lp->limconst == RLIMIT_CPU) { 2001 limtail(cp, "minutes"); 2002 f *= 60.0; 2003 break; 2004 } 2005 *cp = 'm'; 2006 limtail(cp, "megabytes"); 2007 f *= 1024.0 * 1024.0; 2008 break; 2009 case 's': 2010 if (lp->limconst != RLIMIT_CPU) 2011 goto badscal; 2012 limtail(cp, "seconds"); 2013 break; 2014 # endif /* RLIMIT_CPU */ 2015 case 'M': 2016 # ifdef RLIMIT_CPU 2017 if (lp->limconst == RLIMIT_CPU) 2018 goto badscal; 2019 # endif /* RLIMIT_CPU */ 2020 *cp = 'm'; 2021 limtail(cp, "megabytes"); 2022 f *= 1024.0 * 1024.0; 2023 break; 2024 case 'k': 2025 # ifdef RLIMIT_CPU 2026 if (lp->limconst == RLIMIT_CPU) 2027 goto badscal; 2028 # endif /* RLIMIT_CPU */ 2029 limtail(cp, "kbytes"); 2030 f *= 1024.0; 2031 break; 2032 case 'b': 2033 # ifdef RLIMIT_CPU 2034 if (lp->limconst == RLIMIT_CPU) 2035 goto badscal; 2036 # endif /* RLIMIT_CPU */ 2037 limtail(cp, "blocks"); 2038 f *= 512.0; 2039 break; 2040 case 'u': 2041 limtail(cp, "unlimited"); 2042 return ((RLIM_TYPE) RLIM_INFINITY); 2043 default: 2044 # ifdef RLIMIT_CPU 2045 badscal: 2046 # endif /* RLIMIT_CPU */ 2047 stderror(ERR_NAME | ERR_SCALEF); 2048 } 2049 # ifdef convex 2050 return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5)); 2051 # else 2052 f += 0.5; 2053 if (f > (float) RLIM_INFINITY) 2054 return ((RLIM_TYPE) RLIM_INFINITY); 2055 else 2056 return ((RLIM_TYPE) f); 2057 # endif /* convex */ 2058 } 2059 2060 static void 2061 limtail(cp, str) 2062 Char *cp; 2063 char *str; 2064 { 2065 char *sp; 2066 2067 sp = str; 2068 while (*cp && *cp == *str) 2069 cp++, str++; 2070 if (*cp) 2071 stderror(ERR_BADSCALE, sp); 2072 } 2073 2074 2075 /*ARGSUSED*/ 2076 static void 2077 plim(lp, hard) 2078 register struct limits *lp; 2079 int hard; 2080 { 2081 # ifdef BSDLIMIT 2082 struct rlimit rlim; 2083 # endif /* BSDLIMIT */ 2084 RLIM_TYPE limit; 2085 int div = lp->limdiv; 2086 2087 xprintf("%-13.13s", lp->limname); 2088 2089 # ifndef BSDLIMIT 2090 limit = ulimit(lp->limconst, 0); 2091 # ifdef aiws 2092 if (lp->limconst == RLIMIT_DATA) 2093 limit -= 0x20000000; 2094 # endif /* aiws */ 2095 # else /* BSDLIMIT */ 2096 (void) getrlimit(lp->limconst, &rlim); 2097 limit = hard ? rlim.rlim_max : rlim.rlim_cur; 2098 # endif /* BSDLIMIT */ 2099 2100 # if !defined(BSDLIMIT) || defined(FILESIZE512) 2101 /* 2102 * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024 2103 * blocks. Note we cannot pre-multiply cause we might overflow (A/UX) 2104 */ 2105 if (lp->limconst == RLIMIT_FSIZE) { 2106 if (limit >= (RLIM_INFINITY / 512)) 2107 limit = RLIM_INFINITY; 2108 else 2109 div = (div == 1024 ? 2 : 1); 2110 } 2111 # endif /* !BSDLIMIT || FILESIZE512 */ 2112 2113 if (limit == RLIM_INFINITY) 2114 xprintf("unlimited"); 2115 else 2116 # ifdef RLIMIT_CPU 2117 if (lp->limconst == RLIMIT_CPU) 2118 psecs((long) limit); 2119 else 2120 # endif /* RLIMIT_CPU */ 2121 xprintf("%ld %s", (long) (limit / div), lp->limscale); 2122 xputchar('\n'); 2123 } 2124 2125 /*ARGSUSED*/ 2126 void 2127 dounlimit(v, c) 2128 register Char **v; 2129 struct command *c; 2130 { 2131 register struct limits *lp; 2132 int lerr = 0; 2133 int hard = 0; 2134 int force = 0; 2135 2136 USE(c); 2137 while (*++v && **v == '-') { 2138 Char *vp = *v; 2139 while (*++vp) 2140 switch (*vp) { 2141 case 'f': 2142 force = 1; 2143 break; 2144 case 'h': 2145 hard = 1; 2146 break; 2147 default: 2148 stderror(ERR_ULIMUS); 2149 break; 2150 } 2151 } 2152 2153 if (*v == 0) { 2154 for (lp = limits; lp->limconst >= 0; lp++) 2155 if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 2156 lerr++; 2157 if (!force && lerr) 2158 stderror(ERR_SILENT); 2159 return; 2160 } 2161 while (*v) { 2162 lp = findlim(*v++); 2163 if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0 && !force) 2164 stderror(ERR_SILENT); 2165 } 2166 } 2167 2168 static int 2169 setlim(lp, hard, limit) 2170 register struct limits *lp; 2171 int hard; 2172 RLIM_TYPE limit; 2173 { 2174 # ifdef BSDLIMIT 2175 struct rlimit rlim; 2176 2177 (void) getrlimit(lp->limconst, &rlim); 2178 2179 # ifdef FILESIZE512 2180 /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */ 2181 if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) 2182 limit /= 512; 2183 # endif /* FILESIZE512 */ 2184 if (hard) 2185 rlim.rlim_max = limit; 2186 else if (limit == RLIM_INFINITY && euid != 0) 2187 rlim.rlim_cur = rlim.rlim_max; 2188 else 2189 rlim.rlim_cur = limit; 2190 2191 if (rlim.rlim_cur > rlim.rlim_max) 2192 rlim.rlim_max = rlim.rlim_cur; 2193 2194 if (setrlimit(lp->limconst, &rlim) < 0) { 2195 # else /* BSDLIMIT */ 2196 if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) 2197 limit /= 512; 2198 # ifdef aiws 2199 if (lp->limconst == RLIMIT_DATA) 2200 limit += 0x20000000; 2201 # endif /* aiws */ 2202 if (ulimit(toset(lp->limconst), limit) < 0) { 2203 # endif /* BSDLIMIT */ 2204 xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname, 2205 lp->limname, limit == RLIM_INFINITY ? CGETS(15, 2, "remove") : 2206 CGETS(15, 3, "set"), hard ? CGETS(14, 4, " hard") : "", 2207 strerror(errno)); 2208 return (-1); 2209 } 2210 return (0); 2211 } 2212 2213 #endif /* !HAVENOLIMIT */ 2214 2215 /*ARGSUSED*/ 2216 void 2217 dosuspend(v, c) 2218 Char **v; 2219 struct command *c; 2220 { 2221 #ifdef BSDJOBS 2222 int ctpgrp; 2223 2224 signalfun_t old; 2225 #endif /* BSDJOBS */ 2226 2227 USE(c); 2228 USE(v); 2229 2230 if (loginsh) 2231 stderror(ERR_SUSPLOG); 2232 untty(); 2233 2234 #ifdef BSDJOBS 2235 old = signal(SIGTSTP, SIG_DFL); 2236 (void) kill(0, SIGTSTP); 2237 /* the shell stops here */ 2238 (void) signal(SIGTSTP, old); 2239 #else /* !BSDJOBS */ 2240 stderror(ERR_JOBCONTROL); 2241 #endif /* BSDJOBS */ 2242 2243 #ifdef BSDJOBS 2244 if (tpgrp != -1) { 2245 retry: 2246 ctpgrp = tcgetpgrp(FSHTTY); 2247 if (ctpgrp == -1) 2248 stderror(ERR_SYSTEM, "tcgetpgrp", strerror(errno)); 2249 if (ctpgrp != opgrp) { 2250 old = signal(SIGTTIN, SIG_DFL); 2251 (void) kill(0, SIGTTIN); 2252 (void) signal(SIGTTIN, old); 2253 goto retry; 2254 } 2255 (void) setpgid(0, shpgrp); 2256 (void) tcsetpgrp(FSHTTY, shpgrp); 2257 } 2258 #endif /* BSDJOBS */ 2259 (void) setdisc(FSHTTY); 2260 } 2261 2262 /* This is the dreaded EVAL built-in. 2263 * If you don't fiddle with file descriptors, and reset didfds, 2264 * this command will either ignore redirection inside or outside 2265 * its arguments, e.g. eval "date >x" vs. eval "date" >x 2266 * The stuff here seems to work, but I did it by trial and error rather 2267 * than really knowing what was going on. If tpgrp is zero, we are 2268 * probably a background eval, e.g. "eval date &", and we want to 2269 * make sure that any processes we start stay in our pgrp. 2270 * This is also the case for "time eval date" -- stay in same pgrp. 2271 * Otherwise, under stty tostop, processes will stop in the wrong 2272 * pgrp, with no way for the shell to get them going again. -IAN! 2273 */ 2274 2275 static Char **gv = NULL, **gav = NULL; 2276 2277 /*ARGSUSED*/ 2278 void 2279 doeval(v, c) 2280 Char **v; 2281 struct command *c; 2282 { 2283 Char **oevalvec; 2284 Char *oevalp; 2285 int odidfds; 2286 #ifndef CLOSE_ON_EXEC 2287 int odidcch; 2288 #endif /* CLOSE_ON_EXEC */ 2289 jmp_buf_t osetexit; 2290 int my_reenter; 2291 Char **savegv; 2292 int saveIN, saveOUT, saveDIAG; 2293 int oSHIN, oSHOUT, oSHDIAG; 2294 2295 USE(c); 2296 oevalvec = evalvec; 2297 oevalp = evalp; 2298 odidfds = didfds; 2299 #ifndef CLOSE_ON_EXEC 2300 odidcch = didcch; 2301 #endif /* CLOSE_ON_EXEC */ 2302 oSHIN = SHIN; 2303 oSHOUT = SHOUT; 2304 oSHDIAG = SHDIAG; 2305 2306 savegv = gv; 2307 gav = v; 2308 2309 gav++; 2310 if (*gav == 0) 2311 return; 2312 gflag = 0, tglob(gav); 2313 if (gflag) { 2314 gv = gav = globall(gav); 2315 gargv = 0; 2316 if (gav == 0) 2317 stderror(ERR_NOMATCH); 2318 gav = copyblk(gav); 2319 } 2320 else { 2321 gv = NULL; 2322 gav = copyblk(gav); 2323 trim(gav); 2324 } 2325 2326 saveIN = dcopy(SHIN, -1); 2327 saveOUT = dcopy(SHOUT, -1); 2328 saveDIAG = dcopy(SHDIAG, -1); 2329 2330 getexit(osetexit); 2331 2332 /* PWP: setjmp/longjmp bugfix for optimizing compilers */ 2333 #ifdef cray 2334 my_reenter = 1; /* assume non-zero return val */ 2335 if (setexit() == 0) { 2336 my_reenter = 0; /* Oh well, we were wrong */ 2337 #else /* !cray */ 2338 if ((my_reenter = setexit()) == 0) { 2339 #endif /* cray */ 2340 evalvec = gav; 2341 evalp = 0; 2342 SHIN = dcopy(0, -1); 2343 SHOUT = dcopy(1, -1); 2344 SHDIAG = dcopy(2, -1); 2345 #ifndef CLOSE_ON_EXEC 2346 didcch = 0; 2347 #endif /* CLOSE_ON_EXEC */ 2348 didfds = 0; 2349 process(0); 2350 } 2351 2352 evalvec = oevalvec; 2353 evalp = oevalp; 2354 doneinp = 0; 2355 #ifndef CLOSE_ON_EXEC 2356 didcch = odidcch; 2357 #endif /* CLOSE_ON_EXEC */ 2358 didfds = odidfds; 2359 (void) close(SHIN); 2360 (void) close(SHOUT); 2361 (void) close(SHDIAG); 2362 SHIN = dmove(saveIN, oSHIN); 2363 SHOUT = dmove(saveOUT, oSHOUT); 2364 SHDIAG = dmove(saveDIAG, oSHDIAG); 2365 2366 if (gv) 2367 blkfree(gv); 2368 2369 gv = savegv; 2370 resexit(osetexit); 2371 if (my_reenter) 2372 stderror(ERR_SILENT); 2373 } 2374 2375 /*************************************************************************/ 2376 /* print list of builtin commands */ 2377 2378 /*ARGSUSED*/ 2379 void 2380 dobuiltins(v, c) 2381 Char **v; 2382 struct command *c; 2383 { 2384 /* would use print_by_column() in tw.parse.c but that assumes 2385 * we have an array of Char * to pass.. (sg) 2386 */ 2387 extern int Tty_raw_mode; 2388 extern int TermH; /* from the editor routines */ 2389 extern int lbuffed; /* from sh.print.c */ 2390 2391 register struct biltins *b; 2392 register int row, col, columns, rows; 2393 unsigned int w, maxwidth; 2394 2395 USE(c); 2396 USE(v); 2397 lbuffed = 0; /* turn off line buffering */ 2398 2399 /* find widest string */ 2400 for (maxwidth = 0, b = bfunc; b < &bfunc[nbfunc]; ++b) 2401 maxwidth = max(maxwidth, strlen(b->bname)); 2402 ++maxwidth; /* for space */ 2403 2404 columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */ 2405 if (!columns) 2406 columns = 1; 2407 rows = (nbfunc + (columns - 1)) / columns; 2408 2409 for (b = bfunc, row = 0; row < rows; row++) { 2410 for (col = 0; col < columns; col++) { 2411 if (b < &bfunc[nbfunc]) { 2412 w = strlen(b->bname); 2413 xprintf("%s", b->bname); 2414 if (col < (columns - 1)) /* Not last column? */ 2415 for (; w < maxwidth; w++) 2416 xputchar(' '); 2417 ++b; 2418 } 2419 } 2420 if (row < (rows - 1)) { 2421 if (Tty_raw_mode) 2422 xputchar('\r'); 2423 xputchar('\n'); 2424 } 2425 } 2426 #ifdef WINNT_NATIVE 2427 nt_print_builtins(maxwidth); 2428 #else 2429 if (Tty_raw_mode) 2430 xputchar('\r'); 2431 xputchar('\n'); 2432 #endif /* WINNT_NATIVE */ 2433 2434 lbuffed = 1; /* turn back on line buffering */ 2435 flush(); 2436 } 2437 2438 void 2439 nlsinit() 2440 { 2441 #ifdef NLS_CATALOGS 2442 char catalog[ 256 ] = { 't', 'c', 's', 'h', '\0' }; 2443 2444 if (adrof(STRcatalog) != NULL) 2445 xsnprintf((char *)catalog, sizeof(catalog), "tcsh.%s", 2446 short2str(varval(STRcatalog))); 2447 catd = catopen(catalog, MCLoadBySet); 2448 #endif /* NLS_CATALOGS */ 2449 #ifdef WINNT_NATIVE 2450 nls_dll_init(); 2451 #endif /* WINNT_NATIVE */ 2452 errinit(); /* init the errorlist in correct locale */ 2453 mesginit(); /* init the messages for signals */ 2454 dateinit(); /* init the messages for dates */ 2455 editinit(); /* init the editor messages */ 2456 terminit(); /* init the termcap messages */ 2457 } 2458