示例#1
0
文件: zpty.c 项目: zsh-users/zsh
static void
deleteptycmd(Ptycmd cmd)
{
    Ptycmd p, q;

    for (q = NULL, p = ptycmds; p != cmd; q = p, p = p->next);

    if (p != cmd)
	return;

    if (q)
	q->next = p->next;
    else
	ptycmds = p->next;

    zsfree(p->name);
    freearray(p->args);

    zclose(cmd->fd);

    /* We kill the process group the command put itself in. */

    kill(-(p->pid), SIGHUP);

    zfree(p, sizeof(*p));
}
示例#2
0
void
semicolonarrsetfn(Param pm, char *x)
{
    char ***dptr = (char ***)pm->data;

    freearray(*dptr);
    *dptr = x ? semicolonsplit(x, pm->flags & PM_UNIQUE) : mkarray(NULL);
    if (pm->ename)
	semicolon_arrfixenv(pm->nam, *dptr);
}
示例#3
0
文件: complete.c 项目: Jaharmi/zsh
int
finish_(UNUSED(Module m))
{
    if (compwords)
	freearray(compwords);
    if (compredirs)
	freearray(compredirs);
    zsfree(compprefix);
    zsfree(compsuffix);
    zsfree(complastprefix);
    zsfree(complastsuffix);
    zsfree(compiprefix);
    zsfree(compisuffix);
    zsfree(compqiprefix);
    zsfree(compqisuffix);
    zsfree(compcontext);
    zsfree(compparameter);
    zsfree(compredirect);
    zsfree(compquote);
    zsfree(compqstack);
    zsfree(compquoting);
    zsfree(comprestore);
    zsfree(complist);
    zsfree(compinsert);
    zsfree(compexact);
    zsfree(compexactstr);
    zsfree(comppatmatch);
    zsfree(comppatinsert);
    zsfree(complastprompt);
    zsfree(comptoend);
    zsfree(compoldlist);
    zsfree(compoldins);
    zsfree(compvared);

    hascompmod = 0;

    return 0;
}
示例#4
0
文件: complete.c 项目: Jaharmi/zsh
mod_export void
restrict_range(int b, int e)
{
    int wl = arrlen(compwords) - 1;

    if (wl && b >= 0 && e >= 0 && (b > 0 || e < wl)) {
	int i;
	char **p, **q, **pp;

	if (e > wl)
	    e = wl;

	i = e - b + 1;
	p = (char **) zshcalloc((i + 1) * sizeof(char *));

	for (q = p, pp = compwords + b; i; i--, q++, pp++)
	    *q = ztrdup(*pp);
	freearray(compwords);
	compwords = p;
	compcurrent -= b;
    }
}
示例#5
0
文件: complete.c 项目: Jaharmi/zsh
static void
compunsetfn(Param pm, int exp)
{
    if (exp) {
	if (pm->u.data) {
	    if (PM_TYPE(pm->node.flags) == PM_SCALAR) {
		zsfree(*((char **) pm->u.data));
		*((char **) pm->u.data) = ztrdup("");
	    } else if (PM_TYPE(pm->node.flags) == PM_ARRAY) {
		freearray(*((char ***) pm->u.data));
		*((char ***) pm->u.data) = zshcalloc(sizeof(char *));
	    } else if (PM_TYPE(pm->node.flags) == PM_HASHED) {
		deleteparamtable(pm->u.hash);
		pm->u.hash = NULL;
	    }
	}
    } else if (PM_TYPE(pm->node.flags) == PM_HASHED) {
	Param *p;
	int i;

	deletehashtable(pm->u.hash);
	pm->u.hash = NULL;

	for (p = compkpms, i = CP_KEYPARAMS; i--; p++)
	    *p = NULL;
    }
    if (!exp) {
	Param *p;
	int i;

	for (p = comprpms, i = CP_REALPARAMS; i; p++, i--)
	    if (*p == pm) {
		*p = NULL;
		break;
	    }
    }
}
示例#6
0
文件: complete.c 项目: Jaharmi/zsh
static int
comp_wrapper(Eprog prog, FuncWrap w, char *name)
{
    if (incompfunc != 1)
	return 1;
    else {
	char *orest, *opre, *osuf, *oipre, *oisuf, **owords, **oredirs;
	char *oqipre, *oqisuf, *oq, *oqi, *oqs, *oaq;
	zlong ocur;
	unsigned int runset = 0, kunset = 0, m, sm;
	Param *pp;

	m = CP_WORDS | CP_REDIRS | CP_CURRENT | CP_PREFIX | CP_SUFFIX | 
	    CP_IPREFIX | CP_ISUFFIX | CP_QIPREFIX | CP_QISUFFIX;
	for (pp = comprpms, sm = 1; m; pp++, m >>= 1, sm <<= 1) {
	    if ((m & 1) && ((*pp)->node.flags & PM_UNSET))
		runset |= sm;
	}
	if (compkpms[CPN_RESTORE]->node.flags & PM_UNSET)
	    kunset = CP_RESTORE;
	orest = comprestore;
	comprestore = ztrdup("auto");
	ocur = compcurrent;
	opre = ztrdup(compprefix);
	osuf = ztrdup(compsuffix);
	oipre = ztrdup(compiprefix);
	oisuf = ztrdup(compisuffix);
	oqipre = ztrdup(compqiprefix);
	oqisuf = ztrdup(compqisuffix);
	oq = ztrdup(compquote);
	oqi = ztrdup(compquoting);
	oqs = ztrdup(compqstack);
	oaq = ztrdup(autoq);
	owords = zarrdup(compwords);
	oredirs = zarrdup(compredirs);

	runshfunc(prog, w, name);

	if (comprestore && !strcmp(comprestore, "auto")) {
	    compcurrent = ocur;
	    zsfree(compprefix);
	    compprefix = opre;
	    zsfree(compsuffix);
	    compsuffix = osuf;
	    zsfree(compiprefix);
	    compiprefix = oipre;
	    zsfree(compisuffix);
	    compisuffix = oisuf;
	    zsfree(compqiprefix);
	    compqiprefix = oqipre;
	    zsfree(compqisuffix);
	    compqisuffix = oqisuf;
	    zsfree(compquote);
	    compquote = oq;
	    zsfree(compquoting);
	    compquoting = oqi;
	    zsfree(compqstack);
	    compqstack = oqs;
	    zsfree(autoq);
	    autoq = oaq;
	    freearray(compwords);
	    freearray(compredirs);
	    compwords = owords;
            compredirs = oredirs;
	    comp_setunset(CP_COMPSTATE |
			  (~runset & (CP_WORDS | CP_REDIRS |
                                      CP_CURRENT | CP_PREFIX |
                                      CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX |
                                      CP_QIPREFIX | CP_QISUFFIX)),
			  (runset & CP_ALLREALS),
			  (~kunset & CP_RESTORE), (kunset & CP_ALLKEYS));
	} else {
	    comp_setunset(CP_COMPSTATE, 0, (~kunset & CP_RESTORE),
			  (kunset & CP_RESTORE));
	    zsfree(opre);
	    zsfree(osuf);
	    zsfree(oipre);
	    zsfree(oisuf);
	    zsfree(oqipre);
	    zsfree(oqisuf);
	    zsfree(oq);
	    zsfree(oqi);
	    zsfree(oqs);
	    zsfree(oaq);
	    freearray(owords);
	    freearray(oredirs);
	}
	zsfree(comprestore);
	comprestore = orest;

	return 0;
    }
}
示例#7
0
static char *
get_zle_state(UNUSED(Param pm))
{
    char *zle_state = NULL, *ptr = NULL, **arr = NULL;
    int itp, istate, len = 0;

    /*
     * Substrings are sorted at the end, so the user can
     * easily match against this parameter:
     * if [[ $ZLE_STATE == *bar*foo*zonk* ]]; then ...; fi
     */
    for (itp = 0; itp < 2; itp++) {
	char *str;
	for (istate = 0; istate < 2; istate++) {
	    int slen;
	    switch (istate) {
	    case 0:
		if (insmode) {
		    str = "insert";
		} else {
		    str = "overwrite";
		}
		break;
	    case 1:
		if (hist_skip_flags & HIST_FOREIGN) {
		    str = "localhistory";
		} else {
		    str = "globalhistory";
		}
		break;

	    default:
		str = "";
	    }
	    slen = strlen(str);
	    if (itp == 0) {
		/* Accumulating length */
		if (istate)
		    len++;	/* for space */
		len += slen;
	    } else {
		/* Accumulating string */
		if (istate)
		    *ptr++ = ':';
		memcpy(ptr, str, slen);
		ptr += slen;
	    }
	}
	if (itp == 0) {
	    len++;		/* terminating NULL */
	    ptr = zle_state = (char *)zhalloc(len);
	} else {
	    *ptr = '\0';
	}
    }

    arr = colonsplit(zle_state, 0);
    strmetasort(arr, SORTIT_ANYOLDHOW, NULL);
    zle_state = zjoin(arr, ' ', 1);
    freearray(arr);

    return zle_state;
}
示例#8
0
文件: stat.c 项目: zsh-users/zsh
static int
bin_stat(char *name, char **args, Options ops, UNUSED(int func))
{
    char **aptr, *arrnam = NULL, **array = NULL, **arrptr = NULL;
    char *hashnam = NULL, **hash = NULL, **hashptr = NULL;
    int len, iwhich = -1, ret = 0, flags = 0, arrsize = 0, fd = 0;
    struct stat statbuf;
    int found = 0, nargs;

    timefmt = "%a %b %e %k:%M:%S %Z %Y";

    for (; *args && (**args == '+' || **args == '-'); args++) {
	char *arg = *args+1;
	if (!*arg || *arg == '-' || *arg == '+') {
	    args++;
	    break;
	}

	if (**args == '+') {
	    if (found)
		break;
	    len = strlen(arg);
	    for (aptr = statelts; *aptr; aptr++)
		if (!strncmp(*aptr, arg, len)) {
		    found++;
		    iwhich = aptr - statelts;
		}
	    if (found > 1) {
		zwarnnam(name, "%s: ambiguous stat element", arg);
		return 1;
	    } else if (found == 0) {
		zwarnnam(name, "%s: no such stat element", arg);
		return 1;
	    }
	    /* if name of link requested, turn on lstat */
	    if (iwhich == ST_READLINK)
		ops->ind['L'] = 1;
	    flags |= STF_PICK;
	} else {
	    for (; *arg; arg++) {
		if (strchr("glLnNorstT", *arg))
		    ops->ind[STOUC(*arg)] = 1;
		else if (*arg == 'A') {
		    if (arg[1]) {
			arrnam = arg+1;
		    } else if (!(arrnam = *++args)) {
			zwarnnam(name, "missing parameter name");
			return 1;
		    }
		    flags |= STF_ARRAY;
		    break;
		} else if (*arg == 'H') {
		    if (arg[1]) {
			hashnam = arg+1;
		    } else if (!(hashnam = *++args)) {
			zwarnnam(name, "missing parameter name");
			return 1;
		    }
		    flags |= STF_HASH;
		    break;
		} else if (*arg == 'f') {
		    char *sfd;
		    ops->ind['f'] = 1;
		    if (arg[1]) {
			sfd = arg+1;
		    } else if (!(sfd = *++args)) {
			zwarnnam(name, "missing file descriptor");
			return 1;
		    }
		    fd = zstrtol(sfd, &sfd, 10);
		    if (*sfd) {
			zwarnnam(name, "bad file descriptor");
			return 1;
		    }
		    break;
		} else if (*arg == 'F') {
		    if (arg[1]) {
			timefmt = arg+1;
		    } else if (!(timefmt = *++args)) {
			zwarnnam(name, "missing time format");
			return 1;
		    }
		    /* force string format in order to use time format */
		    ops->ind['s'] = 1;
		    break;
		} else {
		    zwarnnam(name, "bad option: -%c", *arg);
		    return 1;
		}
	    }
	}
    }

    if ((flags & STF_ARRAY) && (flags & STF_HASH)) {
    	/* We don't implement setting multiple variables at once */
	zwarnnam(name, "both array and hash requested");
	return 1;
	/* Alternate method would be to make -H blank arrnam etc etc *
	 * and so get 'silent loss' of earlier choice, which would   *
	 * be similar to stat -A foo -A bar filename                 */
    }

    if (OPT_ISSET(ops,'l')) {
	/* list types and return:  can also list to array */
	if (arrnam) {
	    arrptr = array = (char **)zalloc((ST_COUNT+1)*sizeof(char *));
	    array[ST_COUNT] = NULL;
	}
	for (aptr = statelts; *aptr; aptr++) {
	    if (arrnam) {
		*arrptr++ = ztrdup(*aptr);
	    } else {
		printf("%s", *aptr);
		if (aptr[1])
		    putchar(' ');
	    }
	}
	if (arrnam) {
	    setaparam(arrnam, array);
	    if (errflag)
		return 1;
	} else
	    putchar('\n');
	return 0;
    }

    if (!*args && !OPT_ISSET(ops,'f')) {
	zwarnnam(name, "no files given");
	return 1;
    } else if (*args && OPT_ISSET(ops,'f')) {
	zwarnnam(name, "no files allowed with -f");
	return 1;
    }

    nargs = 0;
    if (OPT_ISSET(ops,'f'))
	nargs = 1;
    else
	for (aptr = args; *aptr; aptr++)
	    nargs++;

    if (OPT_ISSET(ops,'g')) {
	flags |= STF_GMT;
	ops->ind['s'] = 1;
    }
    if (OPT_ISSET(ops,'s') || OPT_ISSET(ops,'r'))
	flags |= STF_STRING;
    if (OPT_ISSET(ops,'r') || !OPT_ISSET(ops,'s'))
	flags |= STF_RAW;
    if (OPT_ISSET(ops,'n'))
	flags |= STF_FILE;
    if (OPT_ISSET(ops,'o'))
	flags |= STF_OCTAL;
    if (OPT_ISSET(ops,'t'))
	flags |= STF_NAME;

    if (!(arrnam || hashnam)) {
	if (nargs > 1)
	    flags |= STF_FILE;
	if (!(flags & STF_PICK))
	    flags |= STF_NAME;
    }

    if (OPT_ISSET(ops,'N') || OPT_ISSET(ops,'f'))
	flags &= ~STF_FILE;
    if (OPT_ISSET(ops,'T') || OPT_ISSET(ops,'H'))
	flags &= ~STF_NAME;

    if (hashnam) {
    	if (nargs > 1) {
	    zwarnnam(name, "only one file allowed with -H");
	    return 1;
	}
	arrsize = (flags & STF_PICK) ? 1 : ST_COUNT;
	if (flags & STF_FILE)
	    arrsize++;
	hashptr = hash = (char **)zshcalloc((arrsize+1)*2*sizeof(char *));
    }

    if (arrnam) {
	arrsize = (flags & STF_PICK) ? 1 : ST_COUNT;
	if (flags & STF_FILE)
	    arrsize++;
	arrsize *= nargs;
	arrptr = array = (char **)zshcalloc((arrsize+1)*sizeof(char *));
    }

    for (; OPT_ISSET(ops,'f') || *args; args++) {
	char outbuf[PATH_MAX + 9]; /* "link   " + link name + NULL */
	int rval = OPT_ISSET(ops,'f') ? fstat(fd, &statbuf) :
	    OPT_ISSET(ops,'L') ? lstat(unmeta(*args), &statbuf) :
	    stat(unmeta(*args), &statbuf);
	if (rval) {
	    if (OPT_ISSET(ops,'f'))
		sprintf(outbuf, "%d", fd);
	    zwarnnam(name, "%s: %e", OPT_ISSET(ops,'f') ? outbuf : *args,
		     errno);
	    ret = 1;
	    if (OPT_ISSET(ops,'f') || arrnam)
		break;
	    else
		continue;
	}

	if (flags & STF_FILE) {
	    if (arrnam)
		*arrptr++ = ztrdup(*args);
	    else if (hashnam) {
	    	*hashptr++ = ztrdup(HNAMEKEY);
		*hashptr++ = ztrdup(*args);
	    } else
		printf("%s%s", *args, (flags & STF_PICK) ? " " : ":\n");
	}
	if (iwhich > -1) {
	    statprint(&statbuf, outbuf, *args, iwhich, flags);
	    if (arrnam)
		*arrptr++ = metafy(outbuf, -1, META_DUP);
	    else if (hashnam) {
		/* STF_NAME explicitly turned off for ops.ind['H'] above */
	    	*hashptr++ = ztrdup(statelts[iwhich]);
		*hashptr++ = metafy(outbuf, -1, META_DUP);
	    } else
		printf("%s\n", outbuf);
	} else {
	    int i;
	    for (i = 0; i < ST_COUNT; i++) {
		statprint(&statbuf, outbuf, *args, i, flags);
		if (arrnam)
		    *arrptr++= metafy(outbuf, -1, META_DUP);
		else if (hashnam) {
		    /* STF_NAME explicitly turned off for ops.ind['H'] above */
		    *hashptr++ = ztrdup(statelts[i]);
		    *hashptr++ = metafy(outbuf, -1, META_DUP);
		} else
		    printf("%s\n", outbuf);
	    }
	}
	if (OPT_ISSET(ops,'f'))
	    break;

	if (!arrnam && !hashnam && args[1] && !(flags & STF_PICK))
	    putchar('\n');
    }

    if (arrnam) {
	if (ret)
	    freearray(array);
	else {
	    setaparam(arrnam, array);
	    if (errflag)
		return 1;
	}
    }

    if (hashnam) {
    	if (ret)
	    freearray(hash);
	else {
	    sethparam(hashnam, hash);
	    if (errflag)
		return 1;
	}
    }

    return ret;
}
示例#9
0
文件: zle_main.c 项目: Jaharmi/zsh
static int
raw_getbyte(long do_keytmout, char *cptr)
{
    int ret;
    struct ztmout tmout;
#if defined(HAS_TIO) && \
  (defined(sun) || (!defined(HAVE_POLL) && !defined(HAVE_SELECT)))
    struct ttyinfo ti;
#endif
#ifndef HAVE_POLL
# ifdef HAVE_SELECT
    fd_set foofd;
# endif
#endif

    calc_timeout(&tmout, do_keytmout);

    /*
     * Handle timeouts and watched fd's.  If a watched fd or a function
     * timeout triggers we restart any key timeout.  This is likely to
     * be harmless: the combination is extremely rare and a function
     * is likely to occupy the user for a little while anyway.  We used
     * to make timeouts take precedence, but we can't now that the
     * timeouts may be external, so we may have both a permanent watched
     * fd and a long-term timeout.
     */
    if ((nwatch || tmout.tp != ZTM_NONE)
#ifdef FIONREAD
	&& ! delayzsetterm
#endif
	) {
#if defined(HAVE_SELECT) || defined(HAVE_POLL)
	int i, errtry = 0, selret;
# ifdef HAVE_POLL
	int nfds;
	struct pollfd *fds;
# endif
# if defined(HAS_TIO) && defined(sun)
	/*
	 * Yes, I know this is complicated.  Yes, I know we
	 * already have three bits of code to poll the terminal
	 * down below.  No, I don't want to do this either.
	 * However, it turns out on certain OSes, specifically
	 * Solaris, that you can't poll typeahead for love nor
	 * money without actually trying to read it.  But
	 * if we are trying to select (and we need to if we
	 * are watching other fd's) we won't pick that up.
	 * So we just try and read it without blocking in
	 * the time-honoured (i.e. absurdly baroque) termios
	 * fashion.
	 */
	gettyinfo(&ti);
	ti.tio.c_cc[VMIN] = 0;
	settyinfo(&ti);
	ret = read(SHTTY, cptr, 1);
	ti.tio.c_cc[VMIN] = 1;
	settyinfo(&ti);
	if (ret > 0)
	    return 1;
# endif
# ifdef HAVE_POLL
	nfds = 1 + nwatch;
	/* First pollfd is SHTTY, following are the nwatch fds */
	fds = zalloc(sizeof(struct pollfd) * nfds);
	fds[0].fd = SHTTY;
	/*
	 * POLLIN, POLLIN, POLLIN,
	 * Keep those fd's POLLIN...
	 */
	fds[0].events = POLLIN;
	for (i = 0; i < nwatch; i++) {
	    fds[i+1].fd = watch_fds[i];
	    fds[i+1].events = POLLIN;
	}
# endif
	for (;;) {
# ifdef HAVE_POLL
	    int poll_timeout;

	    if (tmout.tp != ZTM_NONE)
		poll_timeout = tmout.exp100ths * 10;
	    else
		poll_timeout = -1;

	    selret = poll(fds, errtry ? 1 : nfds, poll_timeout);
# else
	    int fdmax = SHTTY;
	    struct timeval *tvptr;
	    struct timeval expire_tv;

	    FD_ZERO(&foofd);
	    FD_SET(SHTTY, &foofd);
	    if (!errtry) {
		for (i = 0; i < nwatch; i++) {
		    int fd = watch_fds[i];
		    FD_SET(fd, &foofd);
		    if (fd > fdmax)
			fdmax = fd;
		}
	    }

	    if (tmout.tp != ZTM_NONE) {
		expire_tv.tv_sec = tmout.exp100ths / 100;
		expire_tv.tv_usec = (tmout.exp100ths % 100) * 10000L;
		tvptr = &expire_tv;
	    }
	    else
		tvptr = NULL;

	    selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd,
			    NULL, NULL, tvptr);
# endif
	    /*
	     * Make sure a user interrupt gets passed on straight away.
	     */
	    if (selret < 0 && errflag)
		break;
	    /*
	     * Try to avoid errors on our special fd's from
	     * messing up reads from the terminal.  Try first
	     * with all fds, then try unsetting the special ones.
	     */
	    if (selret < 0 && !errtry) {
		errtry = 1;
		continue;
	    }
	    if (selret == 0) {
		/*
		 * Nothing ready and no error, so we timed out.
		 */
		switch (tmout.tp) {
		case ZTM_NONE:
		    /* keeps compiler happy if not debugging */
#ifdef DEBUG
		    dputs("BUG: timeout fired with no timeout set.");
#endif
		    /* treat as if a key timeout triggered */
		    /*FALLTHROUGH*/
		case ZTM_KEY:
		    /* Special value -2 signals nothing ready */
		    selret = -2;
		    break;

		case ZTM_FUNC:
		    while (firstnode(timedfns)) {
			Timedfn tfdat = (Timedfn)getdata(firstnode(timedfns));
			/*
			 * It's possible a previous function took
			 * a long time to run (though it can't
			 * call zle recursively), so recalculate
			 * the time on each iteration.
			 */
			time_t now = time(NULL);
			if (tfdat->when > now)
			    break;
			tfdat->func();
		    }
		    /* Function may have messed up the display */
		    if (resetneeded)
			zrefresh();
		    /* We need to recalculate the timeout */
		    /*FALLTHROUGH*/
		case ZTM_MAX:
		    /*
		     * Reached the limit of our range, but not the
		     * actual timeout; recalculate the timeout.
		     * We're cheating with the key timeout here:
		     * if one clashed with a function timeout we
		     * reconsider the key timeout from scratch.
		     * The effect of this is microscopic.
		     */
		    calc_timeout(&tmout, do_keytmout);
		    break;
		}
		/*
		 * If we handled the timeout successfully,
		 * carry on.
		 */
		if (selret == 0)
		    continue;
	    }
	    /* If error or unhandled timeout, give up. */
	    if (selret < 0)
		break;
	    /*
	     * If there's user input handle it straight away.
	     * This improves the user's ability to handle exceptional
	     * conditions like runaway output.
	     */
	    if (
# ifdef HAVE_POLL
		 (fds[0].revents & POLLIN)
# else
		 FD_ISSET(SHTTY, &foofd)
# endif
		 )
		break;
	    if (nwatch && !errtry) {
		/*
		 * Copy the details of the watch fds in case the
		 * user decides to delete one from inside the
		 * handler function.
		 */
		int lnwatch = nwatch;
		int *lwatch_fds = zalloc(lnwatch*sizeof(int));
		char **lwatch_funcs = zarrdup(watch_funcs);
		memcpy(lwatch_fds, watch_fds, lnwatch*sizeof(int));
		for (i = 0; i < lnwatch; i++) {
		    if (
# ifdef HAVE_POLL
			(fds[i+1].revents & POLLIN)
# else
			FD_ISSET(lwatch_fds[i], &foofd)
# endif
			) {
			/* Handle the fd. */
			LinkList funcargs = znewlinklist();
			zaddlinknode(funcargs, ztrdup(lwatch_funcs[i]));
			{
			    char buf[BDIGBUFSIZE];
			    convbase(buf, lwatch_fds[i], 10);
			    zaddlinknode(funcargs, ztrdup(buf));
			}
# ifdef HAVE_POLL
#  ifdef POLLERR
			if (fds[i+1].revents & POLLERR)
			    zaddlinknode(funcargs, ztrdup("err"));
#  endif
#  ifdef POLLHUP
			if (fds[i+1].revents & POLLHUP)
			    zaddlinknode(funcargs, ztrdup("hup"));
#  endif
#  ifdef POLLNVAL
			if (fds[i+1].revents & POLLNVAL)
			    zaddlinknode(funcargs, ztrdup("nval"));
#  endif
# endif


			callhookfunc(lwatch_funcs[i], funcargs, 0, NULL);
			if (errflag) {
			    /* No sensible way of handling errors here */
			    errflag = 0;
			    /*
			     * Paranoia: don't run the hooks again this
			     * time.
			     */
			    errtry = 1;
			}
			freelinklist(funcargs, freestr);
		    }
		}
		/* Function may have invalidated the display. */
		if (resetneeded)
		    zrefresh();
		zfree(lwatch_fds, lnwatch*sizeof(int));
		freearray(lwatch_funcs);
	    }
	}
# ifdef HAVE_POLL
	zfree(fds, sizeof(struct pollfd) * nfds);
# endif
	if (selret < 0)
	    return selret;
#else
# ifdef HAS_TIO
	ti = shttyinfo;
	ti.tio.c_lflag &= ~ICANON;
	ti.tio.c_cc[VMIN] = 0;
	ti.tio.c_cc[VTIME] = tmout.exp100ths / 10;
#  ifdef HAVE_TERMIOS_H
	tcsetattr(SHTTY, TCSANOW, &ti.tio);
#  else
	ioctl(SHTTY, TCSETA, &ti.tio);
#  endif
	ret = read(SHTTY, cptr, 1);
#  ifdef HAVE_TERMIOS_H
	tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
#  else
	ioctl(SHTTY, TCSETA, &shttyinfo.tio);
#  endif
	return (ret <= 0) ? ret : *cptr;
# endif
#endif
    }

    ret = read(SHTTY, cptr, 1);

    return ret;
}