1/* 2 * init.c - main loop and initialization routines 3 * 4 * This file is part of zsh, the Z shell. 5 * 6 * Copyright (c) 1992-1997 Paul Falstad 7 * All rights reserved. 8 * 9 * Permission is hereby granted, without written agreement and without 10 * license or royalty fees, to use, copy, modify, and distribute this 11 * software and to distribute modified versions of this software for any 12 * purpose, provided that the above copyright notice and the following 13 * two paragraphs appear in all copies of this software. 14 * 15 * In no event shall Paul Falstad or the Zsh Development Group be liable 16 * to any party for direct, indirect, special, incidental, or consequential 17 * damages arising out of the use of this software and its documentation, 18 * even if Paul Falstad and the Zsh Development Group have been advised of 19 * the possibility of such damage. 20 * 21 * Paul Falstad and the Zsh Development Group specifically disclaim any 22 * warranties, including, but not limited to, the implied warranties of 23 * merchantability and fitness for a particular purpose. The software 24 * provided hereunder is on an "as is" basis, and Paul Falstad and the 25 * Zsh Development Group have no obligation to provide maintenance, 26 * support, updates, enhancements, or modifications. 27 * 28 */ 29 30#include "zsh.mdh" 31 32#include "zshpaths.h" 33#include "zshxmods.h" 34 35#include "init.pro" 36 37#include "version.h" 38 39/**/ 40int noexitct = 0; 41 42/* buffer for $_ and its length */ 43 44/**/ 45char *zunderscore; 46 47/**/ 48int underscorelen, underscoreused; 49 50/* what level of sourcing we are at */ 51 52/**/ 53int sourcelevel; 54 55/* the shell tty fd */ 56 57/**/ 58mod_export int SHTTY; 59 60/* the FILE attached to the shell tty */ 61 62/**/ 63mod_export FILE *shout; 64 65/* termcap strings */ 66 67/**/ 68mod_export char *tcstr[TC_COUNT]; 69 70/* lengths of each termcap string */ 71 72/**/ 73mod_export int tclen[TC_COUNT]; 74 75/* Values of the li, co and am entries */ 76 77/**/ 78int tclines, tccolumns; 79/**/ 80mod_export int hasam, hasxn, hasye; 81 82/* Value of the Co (max_colors) entry: may not be set */ 83 84/**/ 85mod_export int tccolours; 86 87/* SIGCHLD mask */ 88 89/**/ 90mod_export sigset_t sigchld_mask; 91 92/**/ 93mod_export struct hookdef zshhooks[] = { 94 HOOKDEF("exit", NULL, HOOKF_ALL), 95 HOOKDEF("before_trap", NULL, HOOKF_ALL), 96 HOOKDEF("after_trap", NULL, HOOKF_ALL), 97}; 98 99/* keep executing lists until EOF found */ 100 101/**/ 102enum loop_return 103loop(int toplevel, int justonce) 104{ 105 Eprog prog; 106 int err, non_empty = 0; 107 108 pushheap(); 109 if (!toplevel) 110 lexsave(); 111 for (;;) { 112 freeheap(); 113 if (stophist == 3) /* re-entry via preprompt() */ 114 hend(NULL); 115 hbegin(1); /* init history mech */ 116 if (isset(SHINSTDIN)) { 117 setblock_stdin(); 118 if (interact && toplevel) { 119 int hstop = stophist; 120 stophist = 3; 121 preprompt(); 122 if (stophist != 3) 123 hbegin(1); 124 else 125 stophist = hstop; 126 errflag = 0; 127 } 128 } 129 use_exit_printed = 0; 130 intr(); /* interrupts on */ 131 lexinit(); /* initialize lexical state */ 132 if (!(prog = parse_event())) { /* if we couldn't parse a list */ 133 hend(NULL); 134 if ((tok == ENDINPUT && !errflag) || 135 (tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) || 136 justonce) 137 break; 138 if (exit_pending) { 139 /* 140 * Something down there (a ZLE function?) decided 141 * to exit when there was stuff to clear up. 142 * Handle that now. 143 */ 144 stopmsg = 1; 145 zexit(exit_pending >> 1, 0); 146 } 147 if (tok == LEXERR && !lastval) 148 lastval = 1; 149 continue; 150 } 151 if (hend(prog)) { 152 enum lextok toksav = tok; 153 154 non_empty = 1; 155 if (toplevel && 156 (getshfunc("preexec") || 157 paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) { 158 LinkList args; 159 char *cmdstr; 160 161 /* 162 * As we're about to freeheap() or popheap() 163 * anyway, there's no gain in using permanent 164 * storage here. 165 */ 166 args = newlinklist(); 167 addlinknode(args, "preexec"); 168 /* If curline got dumped from the history, we don't know 169 * what the user typed. */ 170 if (hist_ring && curline.histnum == curhist) 171 addlinknode(args, hist_ring->node.nam); 172 else 173 addlinknode(args, ""); 174 addlinknode(args, dupstring(getjobtext(prog, NULL))); 175 addlinknode(args, cmdstr = getpermtext(prog, NULL, 0)); 176 177 callhookfunc("preexec", args, 1, NULL); 178 179 /* The only permanent storage is from getpermtext() */ 180 zsfree(cmdstr); 181 errflag = 0; 182 } 183 if (stopmsg) /* unset 'you have stopped jobs' flag */ 184 stopmsg--; 185 execode(prog, 0, 0, toplevel ? "toplevel" : "file"); 186 tok = toksav; 187 if (toplevel) 188 noexitct = 0; 189 } 190 if (ferror(stderr)) { 191 zerr("write error"); 192 clearerr(stderr); 193 } 194 if (subsh) /* how'd we get this far in a subshell? */ 195 exit(lastval); 196 if (((!interact || sourcelevel) && errflag) || retflag) 197 break; 198 if (isset(SINGLECOMMAND) && toplevel) { 199 if (sigtrapped[SIGEXIT]) 200 dotrap(SIGEXIT); 201 exit(lastval); 202 } 203 if (justonce) 204 break; 205 } 206 err = errflag; 207 if (!toplevel) 208 lexrestore(); 209 popheap(); 210 211 if (err) 212 return LOOP_ERROR; 213 if (!non_empty) 214 return LOOP_EMPTY; 215 return LOOP_OK; 216} 217 218/* Shared among parseargs(), parseopts(), init_io(), and init_misc() */ 219static char *cmd; 220static int restricted; 221 222/**/ 223static void 224parseargs(char **argv, char **runscript) 225{ 226 char **x; 227 LinkList paramlist; 228 229 argzero = *argv++; 230 SHIN = 0; 231 232 /* There's a bit of trickery with opts[INTERACTIVE] here. It starts * 233 * at a value of 2 (instead of 1) or 0. If it is explicitly set on * 234 * the command line, it goes to 1 or 0. If input is coming from * 235 * somewhere that normally makes the shell non-interactive, we do * 236 * "opts[INTERACTIVE] &= 1", so that only a *default* on state will * 237 * be changed. At the end of the function, a value of 2 gets * 238 * changed to 1. */ 239 opts[INTERACTIVE] = isatty(0) ? 2 : 0; 240 /* 241 * MONITOR is similar: we initialise it to 2, and if it's 242 * still 2 at the end, we set it to the value of INTERACTIVE. 243 */ 244 opts[MONITOR] = 2; /* may be unset in init_io() */ 245 opts[HASHDIRS] = 2; /* same relationship to INTERACTIVE */ 246 opts[SHINSTDIN] = 0; 247 opts[SINGLECOMMAND] = 0; 248 249 if (parseopts(NULL, &argv, opts, &cmd, NULL)) 250 exit(1); 251 252 paramlist = znewlinklist(); 253 if (*argv) { 254 if (unset(SHINSTDIN)) { 255 if (cmd) 256 argzero = *argv; 257 else 258 *runscript = *argv; 259 opts[INTERACTIVE] &= 1; 260 argv++; 261 } 262 while (*argv) 263 zaddlinknode(paramlist, ztrdup(*argv++)); 264 } else if (!cmd) 265 opts[SHINSTDIN] = 1; 266 if(isset(SINGLECOMMAND)) 267 opts[INTERACTIVE] &= 1; 268 opts[INTERACTIVE] = !!opts[INTERACTIVE]; 269 if (opts[MONITOR] == 2) 270 opts[MONITOR] = opts[INTERACTIVE]; 271 if (opts[HASHDIRS] == 2) 272 opts[HASHDIRS] = opts[INTERACTIVE]; 273 pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *)); 274 275 while ((*x++ = (char *)getlinknode(paramlist))); 276 free(paramlist); 277 argzero = ztrdup(argzero); 278} 279 280/* Insert into list in order of pointer value */ 281 282/**/ 283static void 284parseopts_insert(LinkList optlist, char *base, int optno) 285{ 286 LinkNode node; 287 void *ptr = base + (optno < 0 ? -optno : optno); 288 289 for (node = firstnode(optlist); node; incnode(node)) { 290 if (ptr < getdata(node)) { 291 insertlinknode(optlist, prevnode(node), ptr); 292 return; 293 } 294 } 295 296 addlinknode(optlist, ptr); 297} 298 299/* 300 * Parse shell options. 301 * If nam is not NULL, this is called from a command; don't 302 * exit on failure. 303 * 304 * If optlist is not NULL, it used to form a list of pointers 305 * into new_opts indicating which options have been changed. 306 */ 307 308/**/ 309mod_export int 310parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp, 311 LinkList optlist) 312{ 313 int optionbreak = 0; 314 int action, optno; 315 char **argv = *argvp; 316 317 *cmdp = 0; 318#define WARN_OPTION(F, S) \ 319 do { \ 320 if (nam) \ 321 zwarnnam(nam, F, S); \ 322 else \ 323 zerr(F, S); \ 324 } while (0) 325#define LAST_OPTION(N) \ 326 do { \ 327 if (nam) { \ 328 if (*argv) \ 329 argv++; \ 330 goto doneargv; \ 331 } else exit(N); \ 332 } while(0) 333 334 /* loop through command line options (begins with "-" or "+") */ 335 while (!optionbreak && *argv && (**argv == '-' || **argv == '+')) { 336 char *args = *argv; 337 action = (**argv == '-'); 338 if (!argv[0][1]) 339 *argv = "--"; 340 while (*++*argv) { 341 if (**argv == '-') { 342 if(!argv[0][1]) { 343 /* The pseudo-option `--' signifies the end of options. */ 344 argv++; 345 goto doneoptions; 346 } 347 if(*argv != args+1 || **argv != '-') 348 goto badoptionstring; 349 /* GNU-style long options */ 350 ++*argv; 351 if (!strcmp(*argv, "version")) { 352 printf("zsh %s (%s-%s-%s)\n", 353 ZSH_VERSION, MACHTYPE, VENDOR, OSTYPE); 354 LAST_OPTION(0); 355 } 356 if (!strcmp(*argv, "help")) { 357 printhelp(); 358 LAST_OPTION(0); 359 } 360 /* `-' characters are allowed in long options */ 361 for(args = *argv; *args; args++) 362 if(*args == '-') 363 *args = '_'; 364 goto longoptions; 365 } 366 367 if (unset(SHOPTIONLETTERS) && **argv == 'b') { 368 /* -b ends options at the end of this argument */ 369 optionbreak = 1; 370 } else if (**argv == 'c') { 371 /* -c command */ 372 *cmdp = *argv; 373 new_opts[INTERACTIVE] &= 1; 374 scriptname = scriptfilename = ztrdup("zsh"); 375 } else if (**argv == 'o') { 376 if (!*++*argv) 377 argv++; 378 if (!*argv) { 379 WARN_OPTION("string expected after -o", NULL); 380 return 1; 381 } 382 longoptions: 383 if (!(optno = optlookup(*argv))) { 384 WARN_OPTION("no such option: %s", *argv); 385 return 1; 386 } else if (optno == RESTRICTED && !nam) { 387 restricted = action; 388 } else if ((optno == EMACSMODE || optno == VIMODE) && nam) { 389 WARN_OPTION("can't change option: %s", *argv); 390 } else { 391 if (dosetopt(optno, action, !nam, new_opts) && nam) { 392 WARN_OPTION("can't change option: %s", *argv); 393 } else if (optlist) { 394 parseopts_insert(optlist, new_opts, optno); 395 } 396 } 397 break; 398 } else if (isspace(STOUC(**argv))) { 399 /* zsh's typtab not yet set, have to use ctype */ 400 while (*++*argv) 401 if (!isspace(STOUC(**argv))) { 402 badoptionstring: 403 WARN_OPTION("bad option string: '%s'", args); 404 return 1; 405 } 406 break; 407 } else { 408 if (!(optno = optlookupc(**argv))) { 409 WARN_OPTION("bad option: -%c", **argv); 410 return 1; 411 } else if (optno == RESTRICTED && !nam) { 412 restricted = action; 413 } else if ((optno == EMACSMODE || optno == VIMODE) && nam) { 414 WARN_OPTION("can't change option: %s", *argv); 415 } else { 416 if (dosetopt(optno, action, !nam, new_opts) && nam) { 417 WARN_OPTION("can't change option: -%c", **argv); 418 } else if (optlist) { 419 parseopts_insert(optlist, new_opts, optno); 420 } 421 } 422 } 423 } 424 argv++; 425 } 426 doneoptions: 427 if (*cmdp) { 428 if (!*argv) { 429 WARN_OPTION("string expected after -%s", *cmdp); 430 return 1; 431 } 432 *cmdp = *argv++; 433 } 434 doneargv: 435 *argvp = argv; 436 return 0; 437} 438 439/**/ 440static void 441printhelp(void) 442{ 443 printf("Usage: %s [<options>] [<argument> ...]\n", argzero); 444 printf("\nSpecial options:\n"); 445 printf(" --help show this message, then exit\n"); 446 printf(" --version show zsh version number, then exit\n"); 447 if(unset(SHOPTIONLETTERS)) 448 printf(" -b end option processing, like --\n"); 449 printf(" -c take first argument as a command to execute\n"); 450 printf(" -o OPTION set an option by name (see below)\n"); 451 printf("\nNormal options are named. An option may be turned on by\n"); 452 printf("`-o OPTION', `--OPTION', `+o no_OPTION' or `+-no-OPTION'. An\n"); 453 printf("option may be turned off by `-o no_OPTION', `--no-OPTION',\n"); 454 printf("`+o OPTION' or `+-OPTION'. Options are listed below only in\n"); 455 printf("`--OPTION' or `--no-OPTION' form.\n"); 456 printoptionlist(); 457} 458 459/**/ 460mod_export void 461init_io(void) 462{ 463 static char outbuf[BUFSIZ], errbuf[BUFSIZ]; 464 465#ifdef RSH_BUG_WORKAROUND 466 int i; 467#endif 468 469/* stdout, stderr fully buffered */ 470#ifdef _IOFBF 471 setvbuf(stdout, outbuf, _IOFBF, BUFSIZ); 472 setvbuf(stderr, errbuf, _IOFBF, BUFSIZ); 473#else 474 setbuffer(stdout, outbuf, BUFSIZ); 475 setbuffer(stderr, errbuf, BUFSIZ); 476#endif 477 478/* This works around a bug in some versions of in.rshd. * 479 * Currently this is not defined by default. */ 480#ifdef RSH_BUG_WORKAROUND 481 if (cmd) { 482 for (i = 3; i < 10; i++) 483 close(i); 484 } 485#endif 486 487 if (shout) { 488 /* 489 * Check if shout was set to stderr, if so don't close it. 490 * We do this if we are interactive but don't have a 491 * terminal. 492 */ 493 if (shout != stderr) 494 fclose(shout); 495 shout = 0; 496 } 497 if (SHTTY != -1) { 498 zclose(SHTTY); 499 SHTTY = -1; 500 } 501 502 /* Send xtrace output to stderr -- see execcmd() */ 503 xtrerr = stderr; 504 505 /* Make sure the tty is opened read/write. */ 506 if (isatty(0)) { 507 zsfree(ttystrname); 508 if ((ttystrname = ztrdup(ttyname(0)))) { 509 SHTTY = movefd(open(ttystrname, O_RDWR | O_NOCTTY)); 510#ifdef TIOCNXCL 511 /* 512 * See if the terminal claims to be busy. If so, and fd 0 513 * is a terminal, try and set non-exclusive use for that. 514 * This is something to do with Solaris over-cleverness. 515 */ 516 if (SHTTY == -1 && errno == EBUSY) 517 ioctl(0, TIOCNXCL, 0); 518#endif 519 } 520 /* 521 * xterm, rxvt and probably all terminal emulators except 522 * dtterm on Solaris 2.6 & 7 have a bug. Applications are 523 * unable to open /dev/tty or /dev/pts/<terminal number here> 524 * because something in Sun's STREAMS modules doesn't like 525 * it. The open() call fails with EBUSY which is not even 526 * listed as a possibility in the open(2) man page. So we'll 527 * try to outsmart The Company. -- <dave@srce.hr> 528 * 529 * Presumably there's no harm trying this on any OS, given that 530 * isatty(0) worked but opening the tty didn't. Possibly we won't 531 * get the tty read/write, but it's the best we can do -- pws 532 * 533 * Try both stdin and stdout before trying /dev/tty. -- Bart 534 */ 535#if defined(HAVE_FCNTL_H) && defined(F_GETFL) 536#define rdwrtty(fd) ((fcntl(fd, F_GETFL, 0) & O_RDWR) == O_RDWR) 537#else 538#define rdwrtty(fd) 1 539#endif 540 if (SHTTY == -1 && rdwrtty(0)) { 541 SHTTY = movefd(dup(0)); 542 } 543 } 544 if (SHTTY == -1 && isatty(1) && rdwrtty(1) && 545 (SHTTY = movefd(dup(1))) != -1) { 546 zsfree(ttystrname); 547 ttystrname = ztrdup(ttyname(1)); 548 } 549 if (SHTTY == -1 && 550 (SHTTY = movefd(open("/dev/tty", O_RDWR | O_NOCTTY))) != -1) { 551 zsfree(ttystrname); 552 ttystrname = ztrdup(ttyname(SHTTY)); 553 } 554 if (SHTTY == -1) { 555 zsfree(ttystrname); 556 ttystrname = ztrdup(""); 557 } else { 558#ifdef FD_CLOEXEC 559 long fdflags = fcntl(SHTTY, F_GETFD, 0); 560 if (fdflags != (long)-1) { 561 fdflags |= FD_CLOEXEC; 562 fcntl(SHTTY, F_SETFD, fdflags); 563 } 564#endif 565 if (!ttystrname) 566 ttystrname = ztrdup("/dev/tty"); 567 } 568 569 /* We will only use zle if shell is interactive, * 570 * SHTTY != -1, and shout != 0 */ 571 if (interact) { 572 init_shout(); 573 if(!SHTTY || !shout) 574 opts[USEZLE] = 0; 575 } else 576 opts[USEZLE] = 0; 577 578#ifdef JOB_CONTROL 579 /* If interactive, make sure the shell is in the foreground and is the 580 * process group leader. 581 */ 582 mypid = (zlong)getpid(); 583 if (opts[MONITOR] && (SHTTY != -1)) { 584 origpgrp = GETPGRP(); 585 acquire_pgrp(); /* might also clear opts[MONITOR] */ 586 } else 587 opts[MONITOR] = 0; 588#else 589 opts[MONITOR] = 0; 590#endif 591} 592 593/**/ 594mod_export void 595init_shout(void) 596{ 597 static char shoutbuf[BUFSIZ]; 598#if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC) 599 int ldisc; 600#endif 601 602 if (SHTTY == -1) 603 { 604 /* Since we're interative, it's nice to have somewhere to write. */ 605 shout = stderr; 606 return; 607 } 608 609#if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC) 610 ldisc = NTTYDISC; 611 ioctl(SHTTY, TIOCSETD, (char *)&ldisc); 612#endif 613 614 /* Associate terminal file descriptor with a FILE pointer */ 615 shout = fdopen(SHTTY, "w"); 616#ifdef _IOFBF 617 setvbuf(shout, shoutbuf, _IOFBF, BUFSIZ); 618#endif 619 620 gettyinfo(&shttyinfo); /* get tty state */ 621#if defined(__sgi) 622 if (shttyinfo.tio.c_cc[VSWTCH] <= 0) /* hack for irises */ 623 shttyinfo.tio.c_cc[VSWTCH] = CSWTCH; 624#endif 625} 626 627/* names of the termcap strings we want */ 628 629static char *tccapnams[TC_COUNT] = { 630 "cl", "le", "LE", "nd", "RI", "up", "UP", "do", 631 "DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta", 632 "md", "so", "us", "me", "se", "ue", "ch", 633 "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB" 634}; 635 636/**/ 637mod_export char * 638tccap_get_name(int cap) 639{ 640 if (cap >= TC_COUNT) { 641#ifdef DEBUG 642 dputs("name of invalid capability %d requested", cap); 643#endif 644 return ""; 645 } 646 return tccapnams[cap]; 647} 648 649/* Initialise termcap */ 650 651/**/ 652mod_export int 653init_term(void) 654{ 655#ifndef TGETENT_ACCEPTS_NULL 656 static char termbuf[2048]; /* the termcap buffer */ 657#endif 658 659 if (!*term) { 660 termflags |= TERM_UNKNOWN; 661 return 0; 662 } 663 664 /* unset zle if using zsh under emacs */ 665 if (!strcmp(term, "emacs")) 666 opts[USEZLE] = 0; 667 668#ifdef TGETENT_ACCEPTS_NULL 669 /* If possible, we let tgetent allocate its own termcap buffer */ 670 if (tgetent(NULL, term) != TGETENT_SUCCESS) 671#else 672 if (tgetent(termbuf, term) != TGETENT_SUCCESS) 673#endif 674 { 675 if (isset(INTERACTIVE)) 676 zerr("can't find terminal definition for %s", term); 677 errflag = 0; 678 termflags |= TERM_BAD; 679 return 0; 680 } else { 681 char tbuf[1024], *pp; 682 int t0; 683 684 termflags &= ~TERM_BAD; 685 termflags &= ~TERM_UNKNOWN; 686 for (t0 = 0; t0 != TC_COUNT; t0++) { 687 pp = tbuf; 688 zsfree(tcstr[t0]); 689 /* AIX tgetstr() ignores second argument */ 690 if (!(pp = tgetstr(tccapnams[t0], &pp))) 691 tcstr[t0] = NULL, tclen[t0] = 0; 692 else { 693 tclen[t0] = strlen(pp); 694 tcstr[t0] = (char *) zalloc(tclen[t0] + 1); 695 memcpy(tcstr[t0], pp, tclen[t0] + 1); 696 } 697 } 698 699 /* check whether terminal has automargin (wraparound) capability */ 700 hasam = tgetflag("am"); 701 hasxn = tgetflag("xn"); /* also check for newline wraparound glitch */ 702 hasye = tgetflag("YE"); /* print in last column does carriage return */ 703 704 tclines = tgetnum("li"); 705 tccolumns = tgetnum("co"); 706 tccolours = tgetnum("Co"); 707 708 /* if there's no termcap entry for cursor up, use single line mode: * 709 * this is flagged by termflags which is examined in zle_refresh.c * 710 */ 711 if (tccan(TCUP)) 712 termflags &= ~TERM_NOUP; 713 else { 714 zsfree(tcstr[TCUP]); 715 tcstr[TCUP] = NULL; 716 termflags |= TERM_NOUP; 717 } 718 719 /* most termcaps don't define "bc" because they use \b. */ 720 if (!tccan(TCBACKSPACE)) { 721 zsfree(tcstr[TCBACKSPACE]); 722 tcstr[TCBACKSPACE] = ztrdup("\b"); 723 tclen[TCBACKSPACE] = 1; 724 } 725 726 /* if there's no termcap entry for cursor left, use backspace. */ 727 if (!tccan(TCLEFT)) { 728 zsfree(tcstr[TCLEFT]); 729 tcstr[TCLEFT] = ztrdup(tcstr[TCBACKSPACE]); 730 tclen[TCLEFT] = tclen[TCBACKSPACE]; 731 } 732 733 if (tccan(TCSAVECURSOR) && !tccan(TCRESTRCURSOR)) { 734 tclen[TCSAVECURSOR] = 0; 735 zsfree(tcstr[TCSAVECURSOR]); 736 tcstr[TCSAVECURSOR] = NULL; 737 } 738 739 /* if the termcap entry for down is \n, don't use it. */ 740 if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n') { 741 tclen[TCDOWN] = 0; 742 zsfree(tcstr[TCDOWN]); 743 tcstr[TCDOWN] = NULL; 744 } 745 746 /* if there's no termcap entry for clear, use ^L. */ 747 if (!tccan(TCCLEARSCREEN)) { 748 zsfree(tcstr[TCCLEARSCREEN]); 749 tcstr[TCCLEARSCREEN] = ztrdup("\14"); 750 tclen[TCCLEARSCREEN] = 1; 751 } 752#if 0 /* This might work, but there may be more to it */ 753 rprompt_indent = (hasye || !tccan(TCLEFT)) ? 1 : 0; 754#endif 755 } 756 return 1; 757} 758 759/* Initialize lots of global variables and hash tables */ 760 761/**/ 762void 763setupvals(void) 764{ 765#ifdef USE_GETPWUID 766 struct passwd *pswd; 767#endif 768 struct timezone dummy_tz; 769 char *ptr; 770 int i, j; 771#if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined (ADDITIONAL_FPATH) 772 char **fpathptr; 773# if defined(FPATH_DIR) && defined(FPATH_SUBDIRS) 774 char *fpath_subdirs[] = FPATH_SUBDIRS; 775# endif 776# if defined(ADDITIONAL_FPATH) 777 char *more_fndirs[] = ADDITIONAL_FPATH; 778 int more_fndirs_len; 779# endif 780# ifdef SITEFPATH_DIR 781 int fpathlen = 1; 782# else 783 int fpathlen = 0; 784# endif 785#endif 786 int close_fds[10], tmppipe[2]; 787 788 /* 789 * Workaround a problem with NIS (in one guise or another) which 790 * grabs file descriptors and keeps them for future reference. 791 * We don't want these to be in the range where the user can 792 * open fd's, i.e. 0 to 9 inclusive. So we make sure all 793 * fd's in that range are in use. 794 */ 795 memset(close_fds, 0, 10*sizeof(int)); 796 if (pipe(tmppipe) == 0) { 797 /* 798 * Strategy: Make sure we have at least fd 0 open (hence 799 * the pipe). From then on, keep dup'ing until we are 800 * up to 9. If we go over the top, close immediately, else 801 * mark for later closure. 802 */ 803 i = -1; /* max fd we have checked */ 804 while (i < 9) { 805 /* j is current fd */ 806 if (i < tmppipe[0]) 807 j = tmppipe[0]; 808 else if (i < tmppipe[1]) 809 j = tmppipe[1]; 810 else { 811 j = dup(0); 812 if (j == -1) 813 break; 814 } 815 if (j < 10) 816 close_fds[j] = 1; 817 else 818 close(j); 819 if (i < j) 820 i = j; 821 } 822 if (i < tmppipe[0]) 823 close(tmppipe[0]); 824 if (i < tmppipe[1]) 825 close(tmppipe[1]); 826 } 827 828 (void)addhookdefs(NULL, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks)); 829 830 init_eprog(); 831 832 zero_mnumber.type = MN_INTEGER; 833 zero_mnumber.u.l = 0; 834 835 noeval = 0; 836 curhist = 0; 837 histsiz = DEFAULT_HISTSIZE; 838 inithist(); 839 840 cmdstack = (unsigned char *) zalloc(CMDSTACKSZ); 841 cmdsp = 0; 842 843 bangchar = '!'; 844 hashchar = '#'; 845 hatchar = '^'; 846 termflags = TERM_UNKNOWN; 847 curjob = prevjob = coprocin = coprocout = -1; 848 gettimeofday(&shtimer, &dummy_tz); /* init $SECONDS */ 849 srand((unsigned int)(shtimer.tv_sec + shtimer.tv_usec)); /* seed $RANDOM */ 850 851 /* Set default path */ 852 path = (char **) zalloc(sizeof(*path) * 5); 853 path[0] = ztrdup("/bin"); 854 path[1] = ztrdup("/usr/bin"); 855 path[2] = ztrdup("/usr/ucb"); 856 path[3] = ztrdup("/usr/local/bin"); 857 path[4] = NULL; 858 859 cdpath = mkarray(NULL); 860 manpath = mkarray(NULL); 861 fignore = mkarray(NULL); 862 863#if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined(ADDITIONAL_FPATH) 864# ifdef FPATH_DIR 865# ifdef FPATH_SUBDIRS 866 fpathlen += sizeof(fpath_subdirs)/sizeof(char *); 867# else 868 fpathlen++; 869# endif 870# endif 871# if defined(ADDITIONAL_FPATH) 872 more_fndirs_len = sizeof(more_fndirs)/sizeof(char *); 873 fpathlen += more_fndirs_len; 874# endif 875 fpath = fpathptr = (char **)zalloc((fpathlen+1)*sizeof(char *)); 876# ifdef SITEFPATH_DIR 877 *fpathptr++ = ztrdup(SITEFPATH_DIR); 878 fpathlen--; 879# endif 880# if defined(ADDITIONAL_FPATH) 881 for (j = 0; j < more_fndirs_len; j++) 882 *fpathptr++ = ztrdup(more_fndirs[j]); 883# endif 884# ifdef FPATH_DIR 885# ifdef FPATH_SUBDIRS 886# ifdef ADDITIONAL_FPATH 887 for (j = more_fndirs_len; j < fpathlen; j++) 888 *fpathptr++ = tricat(FPATH_DIR, "/", fpath_subdirs[j - more_fndirs_len]); 889# else 890 for (j = 0; j < fpathlen; j++) 891 *fpathptr++ = tricat(FPATH_DIR, "/", fpath_subdirs[j]); 892#endif 893# else 894 *fpathptr++ = ztrdup(FPATH_DIR); 895# endif 896# endif 897 *fpathptr = NULL; 898#else 899 fpath = mkarray(NULL); 900#endif 901 902 mailpath = mkarray(NULL); 903 watch = mkarray(NULL); 904 psvar = mkarray(NULL); 905 module_path = mkarray(ztrdup(MODULE_DIR)); 906 modulestab = newmoduletable(17, "modules"); 907 linkedmodules = znewlinklist(); 908 909 /* Set default prompts */ 910 if(unset(INTERACTIVE)) { 911 prompt = ztrdup(""); 912 prompt2 = ztrdup(""); 913 } else if (EMULATION(EMULATE_KSH|EMULATE_SH)) { 914 prompt = ztrdup(privasserted() ? "# " : "$ "); 915 prompt2 = ztrdup("> "); 916 } else { 917 prompt = ztrdup("%m%# "); 918 prompt2 = ztrdup("%_> "); 919 } 920 prompt3 = ztrdup("?# "); 921 prompt4 = EMULATION(EMULATE_KSH|EMULATE_SH) 922 ? ztrdup("+ ") : ztrdup("+%N:%i> "); 923 sprompt = ztrdup("zsh: correct '%R' to '%r' [nyae]? "); 924 925 ifs = EMULATION(EMULATE_KSH|EMULATE_SH) ? 926 ztrdup(DEFAULT_IFS_SH) : ztrdup(DEFAULT_IFS); 927 wordchars = ztrdup(DEFAULT_WORDCHARS); 928 postedit = ztrdup(""); 929 zunderscore = (char *) zalloc(underscorelen = 32); 930 underscoreused = 1; 931 *zunderscore = '\0'; 932 933 zoptarg = ztrdup(""); 934 zoptind = 1; 935 936 ppid = (zlong) getppid(); 937 mypid = (zlong) getpid(); 938 term = ztrdup(""); 939 940 nullcmd = ztrdup("cat"); 941 readnullcmd = ztrdup(DEFAULT_READNULLCMD); 942 943 /* We cache the uid so we know when to * 944 * recheck the info for `USERNAME' */ 945 cached_uid = getuid(); 946 947 /* Get password entry and set info for `USERNAME' */ 948#ifdef USE_GETPWUID 949 if ((pswd = getpwuid(cached_uid))) { 950 if (EMULATION(EMULATE_ZSH)) 951 home = metafy(pswd->pw_dir, -1, META_DUP); 952 cached_username = ztrdup(pswd->pw_name); 953 } 954 else 955#endif /* USE_GETPWUID */ 956 { 957 if (EMULATION(EMULATE_ZSH)) 958 home = ztrdup("/"); 959 cached_username = ztrdup(""); 960 } 961 962 /* 963 * Try a cheap test to see if we can initialize `PWD' from `HOME'. 964 * In non-native emulations HOME must come from the environment; 965 * we're not allowed to set it locally. 966 */ 967 if (EMULATION(EMULATE_ZSH)) 968 ptr = home; 969 else 970 ptr = zgetenv("HOME"); 971 if (ptr && ispwd(ptr)) 972 pwd = ztrdup(ptr); 973 else if ((ptr = zgetenv("PWD")) && (strlen(ptr) < PATH_MAX) && 974 (ptr = metafy(ptr, -1, META_STATIC), ispwd(ptr))) 975 pwd = ztrdup(ptr); 976 else { 977 pwd = NULL; 978 pwd = metafy(zgetcwd(), -1, META_DUP); 979 } 980 981 oldpwd = ztrdup(pwd); /* initialize `OLDPWD' = `PWD' */ 982 983 inittyptab(); /* initialize the ztypes table */ 984 initlextabs(); /* initialize lexing tables */ 985 986 createreswdtable(); /* create hash table for reserved words */ 987 createaliastables(); /* create hash tables for aliases */ 988 createcmdnamtable(); /* create hash table for external commands */ 989 createshfunctable(); /* create hash table for shell functions */ 990 createbuiltintable(); /* create hash table for builtin commands */ 991 createnameddirtable(); /* create hash table for named directories */ 992 createparamtable(); /* create parameter hash table */ 993 994 condtab = NULL; 995 wrappers = NULL; 996 997#ifdef TIOCGWINSZ 998 adjustwinsize(0); 999#else 1000 /* columns and lines are normally zero, unless something different * 1001 * was inhereted from the environment. If either of them are zero * 1002 * the setiparam calls below set them to the defaults from termcap */ 1003 setiparam("COLUMNS", zterm_columns); 1004 setiparam("LINES", zterm_lines); 1005#endif 1006 { 1007 /* Import from environment, overrides init_term() */ 1008 struct value vbuf; 1009 char *name = "ZLE_RPROMPT_INDENT"; 1010 if (getvalue(&vbuf, &name, 1) && !(vbuf.flags & PM_UNSET)) 1011 rprompt_indent = getintvalue(&vbuf); 1012 else 1013 rprompt_indent = 1; 1014 } 1015 1016#ifdef HAVE_GETRLIMIT 1017 for (i = 0; i != RLIM_NLIMITS; i++) { 1018 getrlimit(i, current_limits + i); 1019 limits[i] = current_limits[i]; 1020 } 1021#endif 1022 1023 breaks = loops = 0; 1024 lastmailcheck = time(NULL); 1025 locallevel = sourcelevel = 0; 1026 sfcontext = SFC_NONE; 1027 trap_return = 0; 1028 trap_state = TRAP_STATE_INACTIVE; 1029 noerrexit = -1; 1030 nohistsave = 1; 1031 dirstack = znewlinklist(); 1032 bufstack = znewlinklist(); 1033 hsubl = hsubr = NULL; 1034 lastpid = 0; 1035 lastpid_status = -1L; 1036 1037 get_usage(); 1038 1039 /* Close the file descriptors we opened to block off 0 to 9 */ 1040 for (i = 0; i < 10; i++) 1041 if (close_fds[i]) 1042 close(i); 1043 1044 /* Colour sequences for outputting colours in prompts and zle */ 1045 set_default_colour_sequences(); 1046} 1047 1048/* 1049 * Setup shell input, opening any script file (runscript, may be NULL). 1050 * This is deferred until we have a path to search, in case 1051 * PATHSCRIPT is set for sh-compatible behaviour. 1052 */ 1053static void 1054setupshin(char *runscript) 1055{ 1056 if (runscript) { 1057 char *funmeta, *sfname = NULL; 1058 struct stat st; 1059 1060 funmeta = unmeta(runscript); 1061 /* 1062 * Always search the current directory first. 1063 */ 1064 if (access(funmeta, F_OK) == 0 && 1065 stat(funmeta, &st) >= 0 && 1066 !S_ISDIR(st.st_mode)) 1067 sfname = runscript; 1068 else if (isset(PATHSCRIPT) && !strchr(runscript, '/')) { 1069 /* 1070 * With the PATHSCRIPT option, search the path if no 1071 * path was given in the script name. 1072 */ 1073 funmeta = pathprog(runscript, &sfname); 1074 } 1075 if (!sfname || 1076 (SHIN = movefd(open(funmeta, O_RDONLY | O_NOCTTY))) 1077 == -1) { 1078 zerr("can't open input file: %s", runscript); 1079 exit(127); 1080 } 1081 scriptfilename = sfname; 1082 zsfree(argzero); /* ztrdup'd in parseargs */ 1083 argzero = runscript; 1084 } 1085 /* 1086 * We only initialise line numbering once there is a script to 1087 * read commands from. 1088 */ 1089 lineno = 1; 1090 /* 1091 * Finish setting up SHIN and its relatives. 1092 */ 1093 bshin = SHIN ? fdopen(SHIN, "r") : stdin; 1094 if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) { 1095#ifdef _IONBF 1096 setvbuf(stdin, NULL, _IONBF, 0); 1097#else 1098 setlinebuf(stdin); 1099#endif 1100 } 1101} 1102 1103/* Initialize signal handling */ 1104 1105/**/ 1106void 1107init_signals(void) 1108{ 1109 if (interact) { 1110 int i; 1111 signal_setmask(signal_mask(0)); 1112 for (i=0; i<NSIG; ++i) 1113 signal_default(i); 1114 } 1115 sigchld_mask = signal_mask(SIGCHLD); 1116 1117 intr(); 1118 1119#ifndef QDEBUG 1120 signal_ignore(SIGQUIT); 1121#endif 1122 1123 if (signal_ignore(SIGHUP) == SIG_IGN) 1124 opts[HUP] = 0; 1125 else 1126 install_handler(SIGHUP); 1127 install_handler(SIGCHLD); 1128#ifdef SIGWINCH 1129 install_handler(SIGWINCH); 1130 winch_block(); /* See utils.c:preprompt() */ 1131#endif 1132 if (interact) { 1133 install_handler(SIGALRM); 1134 signal_ignore(SIGTERM); 1135 } 1136 if (jobbing) { 1137 signal_ignore(SIGTTOU); 1138 signal_ignore(SIGTSTP); 1139 signal_ignore(SIGTTIN); 1140 } 1141} 1142 1143/* Source the init scripts. If called as "ksh" or "sh" * 1144 * then we source the standard sh/ksh scripts instead of * 1145 * the standard zsh scripts */ 1146 1147/**/ 1148void 1149run_init_scripts(void) 1150{ 1151 noerrexit = -1; 1152 1153 if (EMULATION(EMULATE_KSH|EMULATE_SH)) { 1154 if (islogin) 1155 source("/etc/profile"); 1156 if (unset(PRIVILEGED)) { 1157 char *s = getsparam("ENV"); 1158 if (islogin) 1159 sourcehome(".profile"); 1160 noerrs = 2; 1161 if (s && !parsestr(s)) { 1162 singsub(&s); 1163 noerrs = 0; 1164 source(s); 1165 } 1166 noerrs = 0; 1167 } else 1168 source("/etc/suid_profile"); 1169 } else { 1170#ifdef GLOBAL_ZSHENV 1171 source(GLOBAL_ZSHENV); 1172#endif 1173 1174 if (isset(RCS) && unset(PRIVILEGED)) 1175 { 1176 if (isset(INTERACTIVE)) { 1177 /* 1178 * Always attempt to load the newuser module to perform 1179 * checks for new zsh users. Don't care if we can't load it. 1180 */ 1181 if (!load_module("zsh/newuser", NULL, 1)) { 1182 /* Unload it immediately. */ 1183 unload_named_module("zsh/newuser", "zsh", 1); 1184 } 1185 } 1186 1187 sourcehome(".zshenv"); 1188 } 1189 if (islogin) { 1190#ifdef GLOBAL_ZPROFILE 1191 if (isset(RCS) && isset(GLOBALRCS)) 1192 source(GLOBAL_ZPROFILE); 1193#endif 1194 if (isset(RCS) && unset(PRIVILEGED)) 1195 sourcehome(".zprofile"); 1196 } 1197 if (interact) { 1198#ifdef GLOBAL_ZSHRC 1199 if (isset(RCS) && isset(GLOBALRCS)) 1200 source(GLOBAL_ZSHRC); 1201#endif 1202 if (isset(RCS) && unset(PRIVILEGED)) 1203 sourcehome(".zshrc"); 1204 } 1205 if (islogin) { 1206#ifdef GLOBAL_ZLOGIN 1207 if (isset(RCS) && isset(GLOBALRCS)) 1208 source(GLOBAL_ZLOGIN); 1209#endif 1210 if (isset(RCS) && unset(PRIVILEGED)) 1211 sourcehome(".zlogin"); 1212 } 1213 } 1214 noerrexit = 0; 1215 nohistsave = 0; 1216} 1217 1218/* Miscellaneous initializations that happen after init scripts are run */ 1219 1220/**/ 1221void 1222init_misc(void) 1223{ 1224#ifndef RESTRICTED_R 1225 if ( restricted ) 1226#else 1227 if (*zsh_name == 'r' || restricted) 1228#endif 1229 dosetopt(RESTRICTED, 1, 0, opts); 1230 if (cmd) { 1231 if (SHIN >= 10) 1232 fclose(bshin); 1233 SHIN = movefd(open("/dev/null", O_RDONLY | O_NOCTTY)); 1234 bshin = fdopen(SHIN, "r"); 1235 execstring(cmd, 0, 1, "cmdarg"); 1236 stopmsg = 1; 1237 zexit(lastval, 0); 1238 } 1239 1240 if (interact && isset(RCS)) 1241 readhistfile(NULL, 0, HFILE_USE_OPTIONS); 1242} 1243 1244/* 1245 * source a file 1246 * Returns one of the SOURCE_* enum values. 1247 */ 1248 1249/**/ 1250mod_export enum source_return 1251source(char *s) 1252{ 1253 Eprog prog; 1254 int tempfd = -1, fd, cj; 1255 zlong oldlineno; 1256 int oldshst, osubsh, oloops; 1257 FILE *obshin; 1258 char *old_scriptname = scriptname, *us; 1259 char *old_scriptfilename = scriptfilename; 1260 unsigned char *ocs; 1261 int ocsp; 1262 int otrap_return = trap_return, otrap_state = trap_state; 1263 struct funcstack fstack; 1264 enum source_return ret = SOURCE_OK; 1265 1266 if (!s || 1267 (!(prog = try_source_file((us = unmeta(s)))) && 1268 (tempfd = movefd(open(us, O_RDONLY | O_NOCTTY))) == -1)) { 1269 return SOURCE_NOT_FOUND; 1270 } 1271 1272 /* save the current shell state */ 1273 fd = SHIN; /* store the shell input fd */ 1274 obshin = bshin; /* store file handle for buffered shell input */ 1275 osubsh = subsh; /* store whether we are in a subshell */ 1276 cj = thisjob; /* store our current job number */ 1277 oldlineno = lineno; /* store our current lineno */ 1278 oloops = loops; /* stored the # of nested loops we are in */ 1279 oldshst = opts[SHINSTDIN]; /* store current value of this option */ 1280 ocs = cmdstack; 1281 ocsp = cmdsp; 1282 cmdstack = (unsigned char *) zalloc(CMDSTACKSZ); 1283 cmdsp = 0; 1284 1285 if (!prog) { 1286 SHIN = tempfd; 1287 bshin = fdopen(SHIN, "r"); 1288 } 1289 subsh = 0; 1290 lineno = 1; 1291 loops = 0; 1292 dosetopt(SHINSTDIN, 0, 1, opts); 1293 scriptname = s; 1294 scriptfilename = s; 1295 1296 if (isset(SOURCETRACE)) { 1297 printprompt4(); 1298 fprintf(xtrerr ? xtrerr : stderr, "<sourcetrace>\n"); 1299 } 1300 1301 /* 1302 * The special return behaviour of traps shouldn't 1303 * trigger in files sourced from traps; the return 1304 * is just a return from the file. 1305 */ 1306 trap_state = TRAP_STATE_INACTIVE; 1307 1308 sourcelevel++; 1309 1310 fstack.name = scriptfilename; 1311 fstack.caller = funcstack ? funcstack->name : 1312 dupstring(old_scriptfilename ? old_scriptfilename : "zsh"); 1313 fstack.flineno = 0; 1314 fstack.lineno = oldlineno; 1315 fstack.filename = scriptfilename; 1316 fstack.prev = funcstack; 1317 fstack.tp = FS_SOURCE; 1318 funcstack = &fstack; 1319 1320 if (prog) { 1321 pushheap(); 1322 errflag = 0; 1323 execode(prog, 1, 0, "filecode"); 1324 popheap(); 1325 if (errflag) 1326 ret = SOURCE_ERROR; 1327 } else { 1328 /* loop through the file to be sourced */ 1329 switch (loop(0, 0)) 1330 { 1331 case LOOP_OK: 1332 /* nothing to do but compilers like a complete enum */ 1333 break; 1334 1335 case LOOP_EMPTY: 1336 /* Empty code resets status */ 1337 lastval = 0; 1338 break; 1339 1340 case LOOP_ERROR: 1341 ret = SOURCE_ERROR; 1342 break; 1343 } 1344 } 1345 funcstack = funcstack->prev; 1346 sourcelevel--; 1347 1348 trap_state = otrap_state; 1349 trap_return = otrap_return; 1350 1351 /* restore the current shell state */ 1352 if (prog) 1353 freeeprog(prog); 1354 else { 1355 fclose(bshin); 1356 fdtable[SHIN] = FDT_UNUSED; 1357 SHIN = fd; /* the shell input fd */ 1358 bshin = obshin; /* file handle for buffered shell input */ 1359 } 1360 subsh = osubsh; /* whether we are in a subshell */ 1361 thisjob = cj; /* current job number */ 1362 lineno = oldlineno; /* our current lineno */ 1363 loops = oloops; /* the # of nested loops we are in */ 1364 dosetopt(SHINSTDIN, oldshst, 1, opts); /* SHINSTDIN option */ 1365 errflag = 0; 1366 if (!exit_pending) 1367 retflag = 0; 1368 scriptname = old_scriptname; 1369 scriptfilename = old_scriptfilename; 1370 free(cmdstack); 1371 cmdstack = ocs; 1372 cmdsp = ocsp; 1373 1374 return ret; 1375} 1376 1377/* Try to source a file in the home directory */ 1378 1379/**/ 1380void 1381sourcehome(char *s) 1382{ 1383 char *h; 1384 1385 queue_signals(); 1386 if (EMULATION(EMULATE_SH|EMULATE_KSH) || !(h = getsparam("ZDOTDIR"))) { 1387 h = home; 1388 if (!h) 1389 return; 1390 } 1391 1392 { 1393 /* Let source() complain if path is too long */ 1394 VARARR(char, buf, strlen(h) + strlen(s) + 2); 1395 sprintf(buf, "%s/%s", h, s); 1396 unqueue_signals(); 1397 source(buf); 1398 } 1399} 1400 1401/**/ 1402void 1403init_bltinmods(void) 1404{ 1405 1406#include "bltinmods.list" 1407 1408 (void)load_module("zsh/main", NULL, 0); 1409} 1410 1411/**/ 1412mod_export void 1413noop_function(void) 1414{ 1415 /* do nothing */ 1416} 1417 1418/**/ 1419mod_export void 1420noop_function_int(UNUSED(int nothing)) 1421{ 1422 /* do nothing */ 1423} 1424 1425/* 1426 * ZLE entry point pointer. 1427 * No other source file needs to know which modules are linked in. 1428 */ 1429/**/ 1430mod_export ZleEntryPoint zle_entry_ptr; 1431 1432/* 1433 * State of loading of zle. 1434 * 0 = Not loaded, not attempted. 1435 * 1 = Loaded successfully 1436 * 2 = Failed to load. 1437 */ 1438/**/ 1439mod_export int zle_load_state; 1440 1441/**/ 1442mod_export char * 1443zleentry(VA_ALIST1(int cmd)) 1444VA_DCL 1445{ 1446 char *ret = NULL; 1447 va_list ap; 1448 VA_DEF_ARG(int cmd); 1449 1450 VA_START(ap, cmd); 1451 VA_GET_ARG(ap, cmd, int); 1452 1453#if defined(LINKED_XMOD_zshQszle) || defined(UNLINKED_XMOD_zshQszle) 1454 /* autoload */ 1455 switch (zle_load_state) { 1456 case 0: 1457 /* 1458 * Some commands don't require us to load ZLE. 1459 * These also have no fallback. 1460 */ 1461 if (cmd != ZLE_CMD_TRASH && cmd != ZLE_CMD_RESET_PROMPT && 1462 cmd != ZLE_CMD_REFRESH) 1463 { 1464 if (load_module("zsh/zle", NULL, 0) != 1) { 1465 (void)load_module("zsh/compctl", NULL, 0); 1466 ret = zle_entry_ptr(cmd, ap); 1467 /* Don't execute fallback code */ 1468 cmd = -1; 1469 } else { 1470 zle_load_state = 2; 1471 /* Execute fallback code below */ 1472 } 1473 } 1474 break; 1475 1476 case 1: 1477 ret = zle_entry_ptr(cmd, ap); 1478 /* Don't execute fallback code */ 1479 cmd = -1; 1480 break; 1481 1482 case 2: 1483 /* Execute fallback code */ 1484 break; 1485 } 1486#endif 1487 1488 switch (cmd) { 1489 /* 1490 * Only the read command really needs a fallback if zle 1491 * is not available. ZLE_CMD_GET_LINE has traditionally 1492 * had local code in bufferwords() to do this, but that' 1493 * probably only because bufferwords() is part of completion 1494 * and so everything to do with it is horribly complicated. 1495 */ 1496 case ZLE_CMD_READ: 1497 { 1498 char *pptbuf, **lp; 1499 int pptlen; 1500 1501 lp = va_arg(ap, char **); 1502 1503 pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL, 1504 NULL), 1505 &pptlen); 1506 write_loop(2, pptbuf, pptlen); 1507 free(pptbuf); 1508 1509 ret = shingetline(); 1510 break; 1511 } 1512 1513 case ZLE_CMD_GET_LINE: 1514 { 1515 int *ll, *cs; 1516 1517 ll = va_arg(ap, int *); 1518 cs = va_arg(ap, int *); 1519 *ll = *cs = 0; 1520 ret = ztrdup(""); 1521 break; 1522 } 1523 } 1524 1525 va_end(ap); 1526 return ret; 1527} 1528 1529/* compctl entry point pointers. Similar to the ZLE ones. */ 1530 1531/**/ 1532mod_export CompctlReadFn compctlreadptr = fallback_compctlread; 1533 1534/**/ 1535mod_export int 1536fallback_compctlread(char *name, UNUSED(char **args), UNUSED(Options ops), UNUSED(char *reply)) 1537{ 1538 zwarnnam(name, "option valid only in functions called from completion"); 1539 return 1; 1540} 1541 1542/* 1543 * Used by zle to indicate it has already printed a "use 'exit' to exit" 1544 * message. 1545 */ 1546/**/ 1547mod_export int use_exit_printed; 1548 1549/* 1550 * This is real main entry point. This has to be mod_export'ed 1551 * so zsh.exe can found it on Cygwin 1552 */ 1553 1554/**/ 1555mod_export int 1556zsh_main(int argc, char **argv) 1557{ 1558 char **t, *runscript = NULL; 1559 int t0; 1560#ifdef USE_LOCALE 1561 setlocale(LC_ALL, ""); 1562#endif 1563 1564 if (argc < 1) { 1565 argzero = "zsh"; 1566 zerr("too few arguments", NULL, 0); 1567 exit(1); 1568 } 1569 1570 init_jobs(argv, environ); 1571 1572 /* 1573 * Provisionally set up the type table to allow metafication. 1574 * This will be done properly when we have decided if we are 1575 * interactive 1576 */ 1577 typtab['\0'] |= IMETA; 1578 typtab[STOUC(Meta) ] |= IMETA; 1579 typtab[STOUC(Marker)] |= IMETA; 1580 for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++) 1581 typtab[t0] |= ITOK | IMETA; 1582 1583 for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++); 1584 1585 zsh_name = argv[0]; 1586 do { 1587 char *arg0 = zsh_name; 1588 if (!(zsh_name = strrchr(arg0, '/'))) 1589 zsh_name = arg0; 1590 else 1591 zsh_name++; 1592 if (*zsh_name == '-') 1593 zsh_name++; 1594 if (strcmp(zsh_name, "su") == 0) { 1595 char *sh = zgetenv("SHELL"); 1596 if (sh && *sh && arg0 != sh) 1597 zsh_name = sh; 1598 else 1599 break; 1600 } else 1601 break; 1602 } while (zsh_name); 1603 1604 fdtable_size = zopenmax(); 1605 fdtable = zshcalloc(fdtable_size*sizeof(*fdtable)); 1606 fdtable[0] = fdtable[1] = fdtable[2] = FDT_EXTERNAL; 1607 1608 createoptiontable(); 1609 emulate(zsh_name, 1, &emulation, opts); /* initialises most options */ 1610 opts[LOGINSHELL] = (**argv == '-'); 1611 opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid()); 1612 opts[USEZLE] = 1; /* may be unset in init_io() */ 1613 /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */ 1614 parseargs(argv, &runscript); 1615 1616 SHTTY = -1; 1617 init_io(); 1618 setupvals(); 1619 1620 init_signals(); 1621 init_bltinmods(); 1622 init_builtins(); 1623 run_init_scripts(); 1624 setupshin(runscript); 1625 init_misc(); 1626 1627 for (;;) { 1628 /* 1629 * See if we can free up some of jobtab. 1630 * We only do this at top level, because if we are 1631 * executing stuff we may refer to them by job pointer. 1632 */ 1633 int errexit = 0; 1634 maybeshrinkjobtab(); 1635 1636 do { 1637 /* Reset return from top level which gets us back here */ 1638 retflag = 0; 1639 loop(1,0); 1640 if (errflag && !interact && !isset(CONTINUEONERROR)) { 1641 errexit = 1; 1642 break; 1643 } 1644 } while (tok != ENDINPUT && (tok != LEXERR || isset(SHINSTDIN))); 1645 if (tok == LEXERR || errexit) { 1646 /* Make sure a fatal error exits with non-zero status */ 1647 if (!lastval) 1648 lastval = 1; 1649 stopmsg = 1; 1650 zexit(lastval, 0); 1651 } 1652 if (!(isset(IGNOREEOF) && interact)) { 1653#if 0 1654 if (interact) 1655 fputs(islogin ? "logout\n" : "exit\n", shout); 1656#endif 1657 zexit(lastval, 0); 1658 continue; 1659 } 1660 noexitct++; 1661 if (noexitct >= 10) { 1662 stopmsg = 1; 1663 zexit(lastval, 0); 1664 } 1665 /* 1666 * Don't print the message if it was already handled by 1667 * zle, since that makes special arrangements to keep 1668 * the display tidy. 1669 */ 1670 if (!use_exit_printed) 1671 zerrnam("zsh", (!islogin) ? "use 'exit' to exit." 1672 : "use 'logout' to logout."); 1673 } 1674} 1675