static int zpcre_get_substrings(char *arg, int *ovec, int ret, char *receptacle) { char **captures, **matches; if(!pcre_get_substring_list(arg, ovec, ret, (const char ***)&captures)) { matches = zarrdup(&captures[1]); /* first one would be entire string */ if (receptacle == NULL) setaparam("match", matches); else setaparam(receptacle, matches); pcre_free_substring_list((const char **)captures); } return 0; }
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; } }
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; }
static int zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, char *substravar, int want_offset_pair, int matchedinarr, int want_begin_end) { char **captures, *match_all, **matches; char offset_all[50]; int capture_start = 1; if (matchedinarr) capture_start = 0; if (matchvar == NULL) matchvar = "MATCH"; if (substravar == NULL) substravar = "match"; /* captures[0] will be entire matched string, [1] first substring */ if (!pcre_get_substring_list(arg, ovec, ret, (const char ***)&captures)) { int nelem = arrlen(captures)-1; /* Set to the offsets of the complete match */ if (want_offset_pair) { sprintf(offset_all, "%d %d", ovec[0], ovec[1]); setsparam("ZPCRE_OP", ztrdup(offset_all)); } match_all = ztrdup(captures[0]); setsparam(matchvar, match_all); /* * If we're setting match, mbegin, mend we only do * so if there were parenthesised matches, for consistency * (c.f. regex.c). */ if (!want_begin_end || nelem) { matches = zarrdup(&captures[capture_start]); setaparam(substravar, matches); } if (want_begin_end) { char *ptr = arg; zlong offs = 0; /* Count the characters before the match */ MB_METACHARINIT(); while (ptr < arg + ovec[0]) { offs++; ptr += MB_METACHARLEN(ptr); } setiparam("MBEGIN", offs + !isset(KSHARRAYS)); /* Add on the characters in the match */ while (ptr < arg + ovec[1]) { offs++; ptr += MB_METACHARLEN(ptr); } setiparam("MEND", offs + !isset(KSHARRAYS) - 1); if (nelem) { char **mbegin, **mend, **bptr, **eptr; int i, *ipair; bptr = mbegin = zalloc(sizeof(char*)*(nelem+1)); eptr = mend = zalloc(sizeof(char*)*(nelem+1)); for (ipair = ovec + 2, i = 0; i < nelem; ipair += 2, i++, bptr++, eptr++) { char buf[DIGBUFSIZE]; ptr = arg; offs = 0; /* Find the start offset */ MB_METACHARINIT(); while (ptr < arg + ipair[0]) { offs++; ptr += MB_METACHARLEN(ptr); } convbase(buf, offs + !isset(KSHARRAYS), 10); *bptr = ztrdup(buf); /* Continue to the end offset */ while (ptr < arg + ipair[1]) { offs++; ptr += MB_METACHARLEN(ptr); } convbase(buf, offs + !isset(KSHARRAYS) - 1, 10); *eptr = ztrdup(buf); } *bptr = *eptr = NULL; setaparam("mbegin", mbegin); setaparam("mend", mend); } } pcre_free_substring_list((const char **)captures); } return 0; }
static int newptycmd(char *nam, char *pname, char **args, int echo, int nblock) { Ptycmd p; int master, slave, pid, oineval = ineval, ret; char *oscriptname = scriptname, syncch; Eprog prog; /* code borrowed from bin_eval() */ ineval = !isset(EVALLINENO); if (!ineval) scriptname = "(zpty)"; prog = parse_string(zjoin(args, ' ', 1), 0); if (!prog) { errflag &= ~ERRFLAG_ERROR; scriptname = oscriptname; ineval = oineval; return 1; } if (get_pty(1, &master)) { zwarnnam(nam, "can't open pseudo terminal: %e", errno); scriptname = oscriptname; ineval = oineval; return 1; } if ((pid = fork()) == -1) { zwarnnam(nam, "can't create pty command %s: %e", pname, errno); close(master); scriptname = oscriptname; ineval = oineval; return 1; } else if (!pid) { /* This code copied from the clone module, except for getting * * the descriptor from get_pty() and duplicating it to 0/1/2. */ deletehookfunc("exit", ptyhook); clearjobtab(0); ppid = getppid(); mypid = getpid(); #ifdef HAVE_SETSID if (setsid() != mypid) { zwarnnam(nam, "failed to create new session: %e", errno); #endif #ifdef TIOCNOTTY if (ioctl(SHTTY, TIOCNOTTY, 0)) zwarnnam(nam, "%e", errno); setpgrp(0L, mypid); #endif #ifdef HAVE_SETSID } #endif if (get_pty(0, &slave)) exit(1); SHTTY = slave; attachtty(mypid); #ifdef TIOCGWINSZ /* Set the window size before associating with the terminal * * so that we don't get hit with a SIGWINCH. I'm paranoid. */ if (interact) { struct ttyinfo info; if (ioctl(slave, TIOCGWINSZ, (char *) &info.winsize) == 0) { info.winsize.ws_row = zterm_lines; info.winsize.ws_col = zterm_columns; ioctl(slave, TIOCSWINSZ, (char *) &info.winsize); } } #endif /* TIOCGWINSZ */ if (!echo) { struct ttyinfo info; if (!ptygettyinfo(slave, &info)) { #ifdef HAVE_TERMIOS_H info.tio.c_lflag &= ~ECHO; #else #ifdef HAVE_TERMIO_H info.tio.c_lflag &= ~ECHO; #else info.tio.lmodes &= ~ECHO; /**** dunno if this is right */ #endif #endif ptysettyinfo(slave, &info); } } #ifdef TIOCSCTTY ioctl(slave, TIOCSCTTY, 0); #endif close(0); close(1); close(2); dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); closem(FDT_UNUSED, 0); close(slave); close(master); close(coprocin); close(coprocout); init_io(NULL); setsparam("TTY", ztrdup(ttystrname)); opts[INTERACTIVE] = 0; syncch = 0; do { ret = write(1, &syncch, 1); } while (ret != 1 && ( #ifdef EWOULDBLOCK errno == EWOULDBLOCK || #else #ifdef EAGAIN errno == EAGAIN || #endif #endif errno == EINTR)); execode(prog, 1, 0, "zpty"); stopmsg = 2; mypid = 0; /* trick to ensure we _exit() */ zexit(lastval, 0); } master = movefd(master); if (master == -1) { zerrnam(nam, "cannot duplicate fd %d: %e", master, errno); scriptname = oscriptname; ineval = oineval; return 1; } p = (Ptycmd) zalloc(sizeof(*p)); p->name = ztrdup(pname); p->args = zarrdup(args); p->fd = master; p->pid = pid; p->echo = echo; p->nblock = nblock; p->fin = 0; p->read = -1; p->old = NULL; p->olen = 0; p->next = ptycmds; ptycmds = p; if (nblock) ptynonblock(master); scriptname = oscriptname; ineval = oineval; do { ret = read(master, &syncch, 1); } while (ret != 1 && ( #ifdef EWOULDBLOCK errno == EWOULDBLOCK || #else #ifdef EAGAIN errno == EAGAIN || #endif #endif errno == EINTR)); setiparam_no_convert("REPLY", (zlong)master); return 0; }