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