void singsub(char **s) { LinkList foo; foo = newlinklist(); addlinknode(foo, *s); prefork(foo, 4); if (errflag) return; *s = (char *) ugetnode(foo); DPUTS(nonempty(foo), "BUG: singsub() produced more than one word!"); }
static void scancompcmd(HashNode hn, UNUSED(int flags)) { int l; Thingy t = (Thingy) hn; if(strpfx(namedcmdstr, t->nam)) { addlinknode(namedcmdll, t->nam); l = pfxlen(peekfirst(namedcmdll), t->nam); if (l < namedcmdambig) namedcmdambig = l; } }
static void cond_subst(char **strp, int glob_ok) { if (glob_ok && checkglobqual(*strp, strlen(*strp), 1, NULL)) { LinkList args = newlinklist(); addlinknode(args, *strp); prefork(args, 0, NULL); while (!errflag && args && nonempty(args) && has_token((char *)peekfirst(args))) zglob(args, firstnode(args), 0); *strp = sepjoin(hlinklist2array(args, 0), NULL, 1); } else singsub(strp); }
int multsub(char **s, char ***a, int *isarr, char *sep) { LinkList foo; int l; char **r, **p; foo = newlinklist(); addlinknode(foo, *s); prefork(foo, 0); if (errflag) { if (isarr) *isarr = 0; return 0; } if ((l = countlinknodes(foo)) > 1) { p = r = ncalloc((l + 1) * sizeof(char*)); while (nonempty(foo)) *p++ = (char *)ugetnode(foo); *p = NULL; if (a) { *a = r; *isarr = 1; return 0; } *s = sepjoin(r, NULL); return 0; } if (l) *s = (char *) ugetnode(foo); else *s = dupstring(""); if (isarr) *isarr = 0; return !l; }
mod_export void iremovesuffix(ZLE_INT_T c, int keep) { if (suffixfunc) { Shfunc shfunc = getshfunc(suffixfunc); if (shfunc) { LinkList args = newlinklist(); char buf[20]; int osc = sfcontext; int wasmeta = (zlemetaline != 0); if (wasmeta) { /* * The suffix removal function runs as a normal * ZLE function, not a completion function, so * the line should be unmetafied if this was * called from completion. (It may not be since * we may decide to remove the suffix later.) */ unmetafy_line(); } sprintf(buf, "%d", suffixfunclen); addlinknode(args, suffixfunc); addlinknode(args, buf); startparamscope(); makezleparams(0); sfcontext = SFC_COMPLETE; doshfunc(shfunc, args, 1); sfcontext = osc; endparamscope(); if (wasmeta) metafy_line(); } zsfree(suffixfunc); suffixfunc = NULL; } else { int sl = 0, flags = 0; struct suffixset *ss; if (c == NO_INSERT_CHAR) { sl = suffixnoinsrem ? suffixlen : 0; } else { ZLE_CHAR_T ch = c; /* * Search for a match for ch in the suffix list. * We stop if we encounter a match in a positive or negative * list, using the suffix length specified or zero respectively. * If we reached the end and passed through a negative * list, we use the suffix length for that, else zero. * This would break if it were possible to have negative * sets with different suffix length: that's not supposed * to happen. */ int negsuflen = 0, found = 0; for (ss = suffixlist; ss; ss = ss->next) { switch (ss->tp) { case SUFTYP_POSSTR: if (ZS_memchr(ss->chars, ch, ss->lenstr)) { sl = ss->lensuf; found = 1; } break; case SUFTYP_NEGSTR: if (ZS_memchr(ss->chars, ch, ss->lenstr)) { sl = 0; found = 1; } else { negsuflen = ss->lensuf; } break; case SUFTYP_POSRNG: if (ss->chars[0] <= ch && ch <= ss->chars[1]) { sl = ss->lensuf; found = 1; } break; case SUFTYP_NEGRNG: if (ss->chars[0] <= ch && ch <= ss->chars[1]) { sl = 0; found = 1; } else { negsuflen = ss->lensuf; } break; } if (found) { flags = ss->flags; break; } } if (!found) sl = negsuflen; } if (sl) { /* must be shifting wide character lengths */ backdel(sl, CUT_RAW); if (flags & SUFFLAGS_SPACE) { /* Add a space and advance over it */ spaceinline(1); if (zlemetaline) { zlemetaline[zlemetacs++] = ' '; } else { zleline[zlecs++] = ZWC(' '); } } if (!keep) invalidatelist(); } } fixsuffix(); }
int execfor(Estate state, int do_exec) { Wordcode end, loop; wordcode code = state->pc[-1]; int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0; int last = 0; char *name, *str, *cond = NULL, *advance = NULL; zlong val = 0; LinkList vars = NULL, args = NULL; int old_simple_pline = simple_pline; /* See comments in execwhile() */ simple_pline = 1; end = state->pc + WC_FOR_SKIP(code); if (iscond) { str = dupstring(ecgetstr(state, EC_NODUP, NULL)); singsub(&str); if (isset(XTRACE)) { char *str2 = dupstring(str); untokenize(str2); printprompt4(); fprintf(xtrerr, "%s\n", str2); fflush(xtrerr); } if (!errflag) { matheval(str); } if (errflag) { state->pc = end; simple_pline = old_simple_pline; return 1; } cond = ecgetstr(state, EC_NODUP, &ctok); advance = ecgetstr(state, EC_NODUP, &atok); } else { vars = ecgetlist(state, *state->pc++, EC_NODUP, NULL); if (WC_FOR_TYPE(code) == WC_FOR_LIST) { int htok = 0; if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) { state->pc = end; simple_pline = old_simple_pline; return 0; } if (htok) { execsubst(args); if (errflag) { state->pc = end; simple_pline = old_simple_pline; return 1; } } } else { char **x; args = newlinklist(); for (x = pparams; *x; x++) addlinknode(args, dupstring(*x)); } } if (!args || empty(args)) lastval = 0; loops++; pushheap(); cmdpush(CS_FOR); loop = state->pc; while (!last) { if (iscond) { if (ctok) { str = dupstring(cond); singsub(&str); } else str = cond; if (!errflag) { while (iblank(*str)) str++; if (*str) { if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s\n", str); fflush(xtrerr); } val = mathevali(str); } else val = 1; } if (errflag) { if (breaks) breaks--; lastval = 1; break; } if (!val) break; } else { LinkNode node; int count = 0; for (node = firstnode(vars); node; incnode(node)) { name = (char *)getdata(node); if (!args || !(str = (char *) ugetnode(args))) { if (count) { str = ""; last = 1; } else break; } if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s=%s\n", name, str); fflush(xtrerr); } setsparam(name, ztrdup(str)); count++; } if (!count) break; } state->pc = loop; execlist(state, 1, do_exec && args && empty(args)); if (breaks) { breaks--; if (breaks || !contflag) break; contflag = 0; } if (retflag) break; if (iscond && !errflag) { if (atok) { str = dupstring(advance); singsub(&str); } else str = advance; if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s\n", str); fflush(xtrerr); } if (!errflag) matheval(str); } if (errflag) { if (breaks) breaks--; lastval = 1; break; } freeheap(); } popheap(); cmdpop(); loops--; simple_pline = old_simple_pline; state->pc = end; return lastval; }
int execselect(Estate state, UNUSED(int do_exec)) { Wordcode end, loop; wordcode code = state->pc[-1]; char *str, *s, *name; LinkNode n; int i, usezle; FILE *inp; size_t more; LinkList args; int old_simple_pline = simple_pline; /* See comments in execwhile() */ simple_pline = 1; end = state->pc + WC_FOR_SKIP(code); name = ecgetstr(state, EC_NODUP, NULL); if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) { char **x; args = newlinklist(); for (x = pparams; *x; x++) addlinknode(args, dupstring(*x)); } else { int htok = 0; if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) { state->pc = end; simple_pline = old_simple_pline; return 0; } if (htok) { execsubst(args); if (errflag) { state->pc = end; simple_pline = old_simple_pline; return 1; } } } if (!args || empty(args)) { state->pc = end; simple_pline = old_simple_pline; return 0; } loops++; pushheap(); cmdpush(CS_SELECT); usezle = interact && SHTTY != -1 && isset(USEZLE); inp = fdopen(dup(usezle ? SHTTY : 0), "r"); more = selectlist(args, 0); loop = state->pc; for (;;) { for (;;) { if (empty(bufstack)) { if (usezle) { int oef = errflag; isfirstln = 1; str = zleentry(ZLE_CMD_READ, &prompt3, NULL, 0, ZLCON_SELECT); if (errflag) str = NULL; /* Keep any user interrupt error status */ errflag = oef | (errflag & ERRFLAG_INT); } else { str = promptexpand(prompt3, 0, NULL, NULL, NULL); zputs(str, stderr); free(str); fflush(stderr); str = fgets(zhalloc(256), 256, inp); } } else str = (char *)getlinknode(bufstack); if (!str && !errflag) setsparam("REPLY", ztrdup("")); /* EOF (user pressed Ctrl+D) */ if (!str || errflag) { if (breaks) breaks--; fprintf(stderr, "\n"); fflush(stderr); goto done; } if ((s = strchr(str, '\n'))) *s = '\0'; if (*str) break; more = selectlist(args, more); } setsparam("REPLY", ztrdup(str)); i = atoi(str); if (!i) str = ""; else { for (i--, n = firstnode(args); n && i; incnode(n), i--); if (n) str = (char *) getdata(n); else str = ""; } setsparam(name, ztrdup(str)); state->pc = loop; execlist(state, 1, 0); freeheap(); if (breaks) { breaks--; if (breaks || !contflag) break; contflag = 0; } if (retflag || errflag) break; } done: cmdpop(); popheap(); fclose(inp); loops--; simple_pline = old_simple_pline; state->pc = end; return lastval; }
enum loop_return loop(int toplevel, int justonce) { Eprog prog; int err, non_empty = 0; queue_signals(); pushheap(); if (!toplevel) zcontext_save(); for (;;) { freeheap(); if (stophist == 3) /* re-entry via preprompt() */ hend(NULL); hbegin(1); /* init history mech */ if (isset(SHINSTDIN)) { setblock_stdin(); if (interact && toplevel) { int hstop = stophist; stophist = 3; /* * Reset all errors including the interrupt error status * immediately, so preprompt runs regardless of what * just happened. We'll reset again below as a * precaution to ensure we get back to the command line * no matter what. */ errflag = 0; preprompt(); if (stophist != 3) hbegin(1); else stophist = hstop; /* * Reset all errors, including user interupts. * This is what allows ^C in an interactive shell * to return us to the command line. */ errflag = 0; } } use_exit_printed = 0; intr(); /* interrupts on */ lexinit(); /* initialize lexical state */ if (!(prog = parse_event(ENDINPUT))) { /* if we couldn't parse a list */ hend(NULL); if ((tok == ENDINPUT && !errflag) || (tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) || justonce) break; if (exit_pending) { /* * Something down there (a ZLE function?) decided * to exit when there was stuff to clear up. * Handle that now. */ stopmsg = 1; zexit(exit_pending >> 1, 0); } if (tok == LEXERR && !lastval) lastval = 1; continue; } if (hend(prog)) { enum lextok toksav = tok; non_empty = 1; if (toplevel && (getshfunc("preexec") || paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) { LinkList args; char *cmdstr; /* * As we're about to freeheap() or popheap() * anyway, there's no gain in using permanent * storage here. */ args = newlinklist(); addlinknode(args, "preexec"); /* If curline got dumped from the history, we don't know * what the user typed. */ if (hist_ring && curline.histnum == curhist) addlinknode(args, hist_ring->node.nam); else addlinknode(args, ""); addlinknode(args, dupstring(getjobtext(prog, NULL))); addlinknode(args, cmdstr = getpermtext(prog, NULL, 0)); callhookfunc("preexec", args, 1, NULL); /* The only permanent storage is from getpermtext() */ zsfree(cmdstr); /* * Note this does *not* remove a user interrupt error * condition, even though we're at the top level loop: * that would be inconsistent with the case where * we didn't execute a preexec function. This is * an implementation detail that an interrupting user * does't care about. */ errflag &= ~ERRFLAG_ERROR; } if (stopmsg) /* unset 'you have stopped jobs' flag */ stopmsg--; execode(prog, 0, 0, toplevel ? "toplevel" : "file"); tok = toksav; if (toplevel) noexitct = 0; } if (ferror(stderr)) { zerr("write error"); clearerr(stderr); } if (subsh) /* how'd we get this far in a subshell? */ exit(lastval); if (((!interact || sourcelevel) && errflag) || retflag) break; if (isset(SINGLECOMMAND) && toplevel) { dont_queue_signals(); if (sigtrapped[SIGEXIT]) dotrap(SIGEXIT); exit(lastval); } if (justonce) break; }
int execzlefunc(Thingy func, char **args, int set_bindk) { int r = 0, ret = 0, remetafy = 0; Widget w; Thingy save_bindk = bindk; if (set_bindk) bindk = func; if (zlemetaline) { unmetafy_line(); remetafy = 1; } if(func->flags & DISABLED) { /* this thingy is not the name of a widget */ char *nm = nicedup(func->nam, 0); char *msg = tricat("No such widget `", nm, "'"); zsfree(nm); showmsg(msg); zsfree(msg); ret = 1; } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) { int wflags = w->flags; /* * The rule is that "zle -N" widgets suppress EOF warnings. When * a "zle -N" widget invokes "zle another-widget" we pass through * this code again, but with actual arguments rather than with the * zlenoargs placeholder. */ if (keybuf[0] == eofchar && !keybuf[1] && args == zlenoargs && !zlell && isfirstln && (zlereadflags & ZLRF_IGNOREEOF)) { showmsg((!islogin) ? "zsh: use 'exit' to exit." : "zsh: use 'logout' to logout."); use_exit_printed = 1; eofsent = 1; ret = 1; } else { if(!(wflags & ZLE_KEEPSUFFIX)) removesuffix(); if(!(wflags & ZLE_MENUCMP)) { fixsuffix(); invalidatelist(); } if (wflags & ZLE_LINEMOVE) vilinerange = 1; if(!(wflags & ZLE_LASTCOL)) lastcol = -1; if (wflags & WIDGET_NCOMP) { int atcurhist = histline == curhist; compwidget = w; ret = completecall(args); if (atcurhist) histline = curhist; } else if (!w->u.fn) { handlefeep(zlenoargs); } else { queue_signals(); ret = w->u.fn(args); unqueue_signals(); } if (!(wflags & ZLE_NOTCOMMAND)) lastcmd = wflags; } r = 1; } else { Shfunc shf = (Shfunc) shfunctab->getnode(shfunctab, w->u.fnnam); if (!shf) { /* the shell function doesn't exist */ char *nm = nicedup(w->u.fnnam, 0); char *msg = tricat("No such shell function `", nm, "'"); zsfree(nm); showmsg(msg); zsfree(msg); ret = 1; } else { int osc = sfcontext, osi = movefd(0); int oxt = isset(XTRACE); LinkList largs = NULL; if (*args) { largs = newlinklist(); addlinknode(largs, dupstring(w->u.fnnam)); while (*args) addlinknode(largs, dupstring(*args++)); } startparamscope(); makezleparams(0); sfcontext = SFC_WIDGET; opts[XTRACE] = 0; ret = doshfunc(shf, largs, 1); opts[XTRACE] = oxt; sfcontext = osc; endparamscope(); lastcmd = w->flags; w->flags = 0; r = 1; redup(osi, 0); } } if (r) { unrefthingy(lbindk); refthingy(func); lbindk = func; } if (set_bindk) bindk = save_bindk; /* * Goodness knows where the user's left us; make sure * it's not on a combining character that won't be displayed * directly. */ CCRIGHT(); if (remetafy) metafy_line(); return ret; }
static mnumber callmathfunc(char *o) { MathFunc f; char *a, *n; static mnumber dummy; n = a = dupstring(o); while (*a != '(') a++; *a++ = '\0'; a[strlen(a) - 1] = '\0'; if ((f = getmathfunc(n, 1))) { if (f->flags & MFF_STR) { return f->sfunc(n, a, f->funcid); } else { int argc = 0; mnumber *argv = NULL, *q, marg; LinkList l = newlinklist(); LinkNode node; if (f->flags & MFF_USERFUNC) { /* first argument is function name: always use mathfunc */ addlinknode(l, n); } while (iblank(*a)) a++; while (*a) { if (*a) { argc++; if (f->flags & MFF_USERFUNC) { /* need to pass strings */ char *str; marg = mathevall(a, MPREC_ARG, &a); if (marg.type & MN_FLOAT) { /* convfloat is off the heap */ str = convfloat(marg.u.d, 0, 0, NULL); } else { char buf[BDIGBUFSIZE]; convbase(buf, marg.u.l, 10); str = dupstring(buf); } addlinknode(l, str); } else { q = (mnumber *) zhalloc(sizeof(mnumber)); *q = mathevall(a, MPREC_ARG, &a); addlinknode(l, q); } if (errflag || mtok != COMMA) break; } } if (*a && !errflag) zerr("bad math expression: illegal character: %c", *a); if (!errflag) { if (argc >= f->minargs && (f->maxargs < 0 || argc <= f->maxargs)) { if (f->flags & MFF_USERFUNC) { char *shfnam = f->module ? f->module : n; Shfunc shfunc = getshfunc(shfnam); if (!shfunc) zerr("no such function: %s", shfnam); else { doshfunc(shfunc, l, 1); return lastmathval; } } else { if (argc) { q = argv = (mnumber *)zhalloc(argc * sizeof(mnumber)); for (node = firstnode(l); node; incnode(node)) *q++ = *(mnumber *)getdata(node); } return f->nfunc(n, argc, argv, f->funcid); } } else zerr("wrong number of arguments: %s", o); } } } else { zerr("unknown function: %s", n); } dummy.type = MN_INTEGER; dummy.u.l = 0; return dummy; }
void loop(int toplevel, int justonce) { List list; #ifdef DEBUG int oasp = toplevel ? 0 : alloc_stackp; #endif pushheap(); for (;;) { freeheap(); errflag = 0; if (isset(SHINSTDIN)) { setblock_stdin(); if (interact) preprompt(); } hbegin(); /* init history mech */ intr(); /* interrupts on */ lexinit(); /* initialize lexical state */ if (!(list = parse_event())) { /* if we couldn't parse a list */ hend(); if ((tok == ENDINPUT && !errflag) || justonce) break; continue; } if (hend()) { int toksav = tok; List prelist; if (toplevel && (prelist = getshfunc("preexec")) != &dummy_list) { Histent he = gethistent(curhist); LinkList args; PERMALLOC { args = newlinklist(); addlinknode(args, "preexec"); if (he && he->text) addlinknode(args, he->text); } LASTALLOC; doshfunc(prelist, args, 0, 1); freelinklist(args, (FreeFunc) NULL); errflag = 0; } if (stopmsg) /* unset 'you have stopped jobs' flag */ stopmsg--; execlist(list, 0, 0); tok = toksav; if (toplevel) noexitct = 0; } DPUTS(alloc_stackp != oasp, "BUG: alloc_stackp changed in loop()"); if (ferror(stderr)) { zerr("write error", NULL, 0); clearerr(stderr); } if (subsh) /* how'd we get this far in a subshell? */ exit(lastval); if (((!interact || sourcelevel) && errflag) || retflag) break; if (trapreturn) { lastval = trapreturn; trapreturn = 0; } if (isset(SINGLECOMMAND) && toplevel) { if (sigtrapped[SIGEXIT]) dotrap(SIGEXIT); exit(lastval); } if (justonce) break; }
enum loop_return loop(int toplevel, int justonce) { Eprog prog; int err, non_empty = 0; pushheap(); if (!toplevel) lexsave(); for (;;) { freeheap(); if (stophist == 3) /* re-entry via preprompt() */ hend(NULL); hbegin(1); /* init history mech */ if (isset(SHINSTDIN)) { setblock_stdin(); if (interact && toplevel) { int hstop = stophist; stophist = 3; preprompt(); if (stophist != 3) hbegin(1); else stophist = hstop; errflag = 0; } } use_exit_printed = 0; intr(); /* interrupts on */ lexinit(); /* initialize lexical state */ if (!(prog = parse_event())) { /* if we couldn't parse a list */ hend(NULL); if ((tok == ENDINPUT && !errflag) || (tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) || justonce) break; if (exit_pending) { /* * Something down there (a ZLE function?) decided * to exit when there was stuff to clear up. * Handle that now. */ stopmsg = 1; zexit(exit_pending >> 1, 0); } if (tok == LEXERR && !lastval) lastval = 1; continue; } if (hend(prog)) { int toksav = tok; non_empty = 1; if (toplevel && (getshfunc("preexec") || paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) { LinkList args; char *cmdstr; /* * As we're about to freeheap() or popheap() * anyway, there's no gain in using permanent * storage here. */ args = newlinklist(); addlinknode(args, "preexec"); /* If curline got dumped from the history, we don't know * what the user typed. */ if (hist_ring && curline.histnum == curhist) addlinknode(args, hist_ring->node.nam); else addlinknode(args, ""); addlinknode(args, dupstring(getjobtext(prog, NULL))); addlinknode(args, cmdstr = getpermtext(prog, NULL, 0)); callhookfunc("preexec", args, 1, NULL); /* The only permanent storage is from getpermtext() */ zsfree(cmdstr); errflag = 0; } if (stopmsg) /* unset 'you have stopped jobs' flag */ stopmsg--; execode(prog, 0, 0, toplevel ? "toplevel" : "file"); tok = toksav; if (toplevel) noexitct = 0; } if (ferror(stderr)) { zerr("write error"); clearerr(stderr); } if (subsh) /* how'd we get this far in a subshell? */ exit(lastval); if (((!interact || sourcelevel) && errflag) || retflag) break; if (isset(SINGLECOMMAND) && toplevel) { if (sigtrapped[SIGEXIT]) dotrap(SIGEXIT); exit(lastval); } if (justonce) break; }
void parseargs(char **argv) { char **x; int action, optno; LinkList paramlist; int bourne = (emulation == EMULATE_KSH || emulation == EMULATE_SH); hackzero = argzero = *argv++; SHIN = 0; /* There's a bit of trickery with opts[INTERACTIVE] here. It starts * * at a value of 2 (instead of 1) or 0. If it is explicitly set on * * the command line, it goes to 1 or 0. If input is coming from * * somewhere that normally makes the shell non-interactive, we do * * "opts[INTERACTIVE] &= 1", so that only a *default* on state will * * be changed. At the end of the function, a value of 2 gets * * changed to 1. */ opts[INTERACTIVE] = isatty(0) ? 2 : 0; opts[SHINSTDIN] = 0; opts[SINGLECOMMAND] = 0; /* loop through command line options (begins with "-" or "+") */ while (*argv && (**argv == '-' || **argv == '+')) { action = (**argv == '-'); if(!argv[0][1]) *argv = "--"; while (*++*argv) { /* The pseudo-option `--' signifies the end of options. * * `-b' does too, csh-style, unless we're emulating a * * Bourne style shell. */ if (**argv == '-' || (!bourne && **argv == 'b')) { argv++; goto doneoptions; } if (**argv == 'c') { /* -c command */ if (!*++argv) { zerr("string expected after -c", NULL, 0); exit(1); } cmd = *argv++; opts[INTERACTIVE] &= 1; opts[SHINSTDIN] = 0; goto doneoptions; } else if (**argv == 'o') { if (!*++*argv) argv++; if (!*argv) { zerr("string expected after -o", NULL, 0); exit(1); } if(!(optno = optlookup(*argv))) zerr("no such option: %s", *argv, 0); else dosetopt(optno, action, 1); break; } else { if (!(optno = optlookupc(**argv))) { zerr("bad option: -%c", NULL, **argv); exit(1); } else dosetopt(optno, action, 1); } } argv++; } doneoptions: paramlist = newlinklist(); if (*argv) { if (unset(SHINSTDIN)) { argzero = *argv; if (!cmd) SHIN = movefd(open(unmeta(argzero), O_RDONLY)); if (SHIN == -1) { zerr("can't open input file: %s", argzero, 0); exit(1); } opts[INTERACTIVE] &= 1; argv++; } while (*argv) addlinknode(paramlist, ztrdup(*argv++)); } else opts[SHINSTDIN] = 1; if(isset(SINGLECOMMAND)) opts[INTERACTIVE] &= 1; opts[INTERACTIVE] = !!opts[INTERACTIVE]; pparams = x = (char **) zcalloc((countlinknodes(paramlist) + 1) * sizeof(char *)); while ((*x++ = (char *)getlinknode(paramlist))); free(paramlist); argzero = ztrdup(argzero); }