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