/* * Get a number from a variable. * Try to be clever about reusing subscripts by caching the Value structure. */ static mnumber getmathparam(struct mathvalue *mptr) { mnumber result; if (!mptr->pval) { char *s = mptr->lval; mptr->pval = (Value)zhalloc(sizeof(struct value)); if (!getvalue(mptr->pval, &s, 1)) { mptr->pval = NULL; if (isset(FORCEFLOAT)) { result.type = MN_FLOAT; result.u.d = 0.0; return result; } return zero_mnumber; } } result = getnumvalue(mptr->pval); if (isset(FORCEFLOAT) && result.type == MN_INTEGER) { result.type = MN_FLOAT; result.u.d = (double)result.u.l; } return result; }
mod_export LinkList newlinklist(void) { LinkList list; list = (LinkList) zhalloc(sizeof *list); list->first = NULL; list->last = (LinkNode) list; return list; }
static char * get_zle_state(UNUSED(Param pm)) { char *zle_state = NULL, *ptr = NULL; int itp, istate, len = 0; /* * When additional substrings are added, they should be kept in * alphabetical order, 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; /* * Currently there is only one state: insert or overwrite. * This loop is to make it easy to add others. */ for (istate = 0; istate < 1; istate++) { int slen; switch (istate) { case 0: if (insmode) { str = "insert"; } else { str = "overwrite"; } 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'; } } return zle_state; }
static void makeprivate(HashNode hn, UNUSED(int flags)) { Param pm = (Param)hn; if (pm->level == locallevel) { if (pm->ename || (pm->node.flags & PM_NORESTORE) || (pm->old && (pm->old->level == locallevel - 1 || ((pm->node.flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL && /* typeset_single() line 2300 discards PM_REMOVABLE -- why? */ !is_private(pm->old))))) { zwarnnam("private", "can't change scope of existing param: %s", pm->node.nam); makeprivate_error = 1; return; } struct gsu_closure *gsu = zhalloc(sizeof(struct gsu_closure)); switch (PM_TYPE(pm->node.flags)) { case PM_SCALAR: gsu->g = (void *)(pm->gsu.s); gsu->u.s = scalar_private_gsu; pm->gsu.s = (GsuScalar)gsu; break; case PM_INTEGER: gsu->g = (void *)(pm->gsu.i); gsu->u.i = integer_private_gsu; pm->gsu.i = (GsuInteger)gsu; break; case PM_EFLOAT: case PM_FFLOAT: gsu->g = (void *)(pm->gsu.f); gsu->u.f = float_private_gsu; pm->gsu.f = (GsuFloat)gsu; break; case PM_ARRAY: gsu->g = (void *)(pm->gsu.a); gsu->u.a = array_private_gsu; pm->gsu.a = (GsuArray)gsu; break; case PM_HASHED: gsu->g = (void *)(pm->gsu.h); gsu->u.h = hash_private_gsu; pm->gsu.h = (GsuHash)gsu; break; default: makeprivate_error = 1; break; } /* PM_HIDE so new parameters in deeper scopes do not shadow */ pm->node.flags |= (PM_HIDE|PM_SPECIAL|PM_REMOVABLE); pm->level -= 1; } }
/* * Get a number from a variable. * Try to be clever about reusing subscripts by caching the Value structure. */ static mnumber getmathparam(struct mathvalue *mptr) { if (!mptr->pval) { char *s = mptr->lval; mptr->pval = (Value)zhalloc(sizeof(struct value)); if (!getvalue(mptr->pval, &s, 1)) { mptr->pval = NULL; return zero_mnumber; } } return getnumvalue(mptr->pval); }
static char * get_compqstack(UNUSED(Param pm)) { char *p, *ptr, *cqp; if (!compqstack) /* TODO: don't think this can happen... */ return ""; ptr = p = zhalloc(2*strlen(compqstack)+1); for (cqp = compqstack; *cqp; cqp++) { char *str = comp_quoting_string(*cqp); *ptr++ = *str; } *ptr = '\0'; return p; }
static ZLE_STRING_T makequote(ZLE_STRING_T str, size_t *len) { int qtct = 0; ZLE_STRING_T l, ol; ZLE_STRING_T end = str + *len; for (l = str; l < end; l++) if (*l == ZWC('\'')) qtct++; *len += 2 + qtct*3; l = ol = (ZLE_STRING_T)zhalloc(*len * ZLE_CHAR_SIZE); *l++ = ZWC('\''); for (; str < end; str++) if (*str == ZWC('\'')) { *l++ = ZWC('\''); *l++ = ZWC('\\'); *l++ = ZWC('\''); *l++ = ZWC('\''); } else *l++ = *str; *l++ = ZWC('\''); return ol; }
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; }
static char * parse_class(Cpattern p, char *iptr) { int endchar, firsttime = 1; char *optr, *nptr; if (*iptr++ == '[') { endchar = ']'; /* TODO: surely [^]] is valid? */ if ((*iptr == '!' || *iptr == '^') && iptr[1] != ']') { p->tp = CPAT_NCLASS; iptr++; } else p->tp = CPAT_CCLASS; } else { endchar = '}'; p->tp = CPAT_EQUIV; } /* find end of class. End character can appear literally first. */ for (optr = iptr; optr == iptr || *optr != endchar; optr++) if (!*optr) return optr; /* * We can always fit the parsed class within the same length * because of the tokenization (including a null byte). * * As the input string is metafied, but shouldn't contain shell * tokens, we can just add our own tokens willy nilly. */ optr = p->u.str = zhalloc((optr-iptr) + 1); while (firsttime || *iptr != endchar) { int ch; if (*iptr == '[' && iptr[1] == ':' && (nptr = strchr((char *)iptr + 2, ':')) && nptr[1] == ']') { /* Range type */ iptr += 2; ch = range_type((char *)iptr, nptr-iptr); iptr = nptr + 2; if (ch != PP_UNKWN) *optr++ = STOUC(Meta) + ch; } else { /* characters stay metafied */ char *ptr1 = iptr; if (*iptr == Meta) iptr++; iptr++; if (*iptr == '-' && iptr[1] && iptr[1] != endchar) { /* a run of characters */ iptr++; /* range token */ *optr++ = Meta + PP_RANGE; /* start of range character */ if (*ptr1 == Meta) { *optr++ = Meta; *optr++ = ptr1[1] ^ 32; } else *optr++ = *ptr1; if (*iptr == Meta) { *optr++ = *iptr++; *optr++ = *iptr++; } else *optr++ = *iptr++; } else { if (*ptr1 == Meta) { *optr++ = Meta; *optr++ = ptr1[1] ^ 32; } else *optr++ = *ptr1; } } firsttime = 0; } *optr = '\0'; return iptr; }
static int bin_vared(char *name, char **args, Options ops, UNUSED(int func)) { char *s, *t, *ova = varedarg; struct value vbuf; Value v; Param pm = 0; int ifl; int type = PM_SCALAR, obreaks = breaks, haso = 0, oSHTTY = 0; char *p1, *p2, *main_keymapname, *vicmd_keymapname, *init, *finish; Keymap main_keymapsave = NULL, vicmd_keymapsave = NULL; FILE *oshout = NULL; if ((interact && unset(USEZLE)) || !strcmp(term, "emacs")) { zwarnnam(name, "ZLE not enabled"); return 1; } if (zleactive) { zwarnnam(name, "ZLE cannot be used recursively (yet)"); return 1; } if (OPT_ISSET(ops,'A')) { if (OPT_ISSET(ops, 'a')) { zwarnnam(name, "specify only one of -a and -A"); return 1; } type = PM_HASHED; } else if (OPT_ISSET(ops,'a')) type = PM_ARRAY; p1 = OPT_ARG_SAFE(ops,'p'); p2 = OPT_ARG_SAFE(ops,'r'); main_keymapname = OPT_ARG_SAFE(ops,'M'); vicmd_keymapname = OPT_ARG_SAFE(ops,'m'); init = OPT_ARG_SAFE(ops,'i'); finish = OPT_ARG_SAFE(ops,'f'); if (type != PM_SCALAR && !OPT_ISSET(ops,'c')) { zwarnnam(name, "-%s ignored", type == PM_ARRAY ? "a" : "A"); } /* handle non-existent parameter */ s = args[0]; queue_signals(); v = fetchvalue(&vbuf, &s, (!OPT_ISSET(ops,'c') || type == PM_SCALAR), SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY); if (!v && !OPT_ISSET(ops,'c')) { unqueue_signals(); zwarnnam(name, "no such variable: %s", args[0]); return 1; } else if (v) { if (*s) { zwarnnam(name, "not an identifier: `%s'", args[0]); return 1; } if (v->isarr) { /* Array: check for separators and quote them. */ char **arr = getarrvalue(v), **aptr, **tmparr, **tptr; tptr = tmparr = (char **)zhalloc(sizeof(char *)*(arrlen(arr)+1)); for (aptr = arr; *aptr; aptr++) { int sepcount = 0, clen; convchar_t c; /* * See if this word contains a separator character * or backslash */ MB_METACHARINIT(); for (t = *aptr; *t; ) { if (*t == '\\') { t++; sepcount++; } else { t += MB_METACHARLENCONV(t, &c); if (WC_ZISTYPE(c, ISEP)) sepcount++; } } if (sepcount) { /* Yes, so allocate enough space to quote it. */ char *newstr, *nptr; newstr = zhalloc(strlen(*aptr)+sepcount+1); /* Go through string quoting separators */ MB_METACHARINIT(); for (t = *aptr, nptr = newstr; *t; ) { if (*t == '\\') { *nptr++ = '\\'; *nptr++ = *t++; } else { clen = MB_METACHARLENCONV(t, &c); if (WC_ZISTYPE(c, ISEP)) *nptr++ = '\\'; while (clen--) *nptr++ = *t++; } } *nptr = '\0'; /* Stick this into the array of words to join up */ *tptr++ = newstr; } else *tptr++ = *aptr; /* No, keep original array element */ } *tptr = NULL; s = sepjoin(tmparr, NULL, 0); } else { s = ztrdup(getstrvalue(v)); } unqueue_signals(); } else if (*s) { unqueue_signals(); zwarnnam(name, "invalid parameter name: %s", args[0]); return 1; } else { unqueue_signals(); s = ztrdup(s); } if (SHTTY == -1 || OPT_ISSET(ops,'t')) { /* need to open /dev/tty specially */ oSHTTY = SHTTY; if ((SHTTY = open(OPT_ISSET(ops,'t') ? OPT_ARG(ops,'t') : "/dev/tty", O_RDWR|O_NOCTTY)) == -1) { zwarnnam(name, "can't access terminal"); zsfree(s); return 1; } if (!isatty(SHTTY)) { zwarnnam(name, "%s: not a terminal", OPT_ARG(ops,'t')); close(SHTTY); SHTTY = oSHTTY; zsfree(s); return 1; } oshout = shout; init_shout(); haso = 1; } /* edit the parameter value */ zpushnode(bufstack, s); if (main_keymapname && savekeymap(name, "main", main_keymapname, &main_keymapsave)) main_keymapname = NULL; if (vicmd_keymapname && savekeymap(name, "vicmd", vicmd_keymapname, &vicmd_keymapsave)) vicmd_keymapname = NULL; varedarg = *args; ifl = isfirstln; if (OPT_ISSET(ops,'h')) hbegin(2); isfirstln = OPT_ISSET(ops,'e'); t = zleread(&p1, &p2, OPT_ISSET(ops,'h') ? ZLRF_HISTORY : 0, ZLCON_VARED, init ? init : "zle-line-init", finish ? finish : "zle-line-finish"); if (OPT_ISSET(ops,'h')) hend(NULL); isfirstln = ifl; varedarg = ova; restorekeymap(name, "main", main_keymapname, main_keymapsave); restorekeymap(name, "vicmd", vicmd_keymapname, vicmd_keymapsave); if (haso) { fclose(shout); /* close(SHTTY) */ shout = oshout; SHTTY = oSHTTY; } if (!t || errflag) { /* error in editing */ errflag &= ~ERRFLAG_ERROR; breaks = obreaks; if (t) zsfree(t); return 1; } /* strip off trailing newline, if any */ if (t[strlen(t) - 1] == '\n') t[strlen(t) - 1] = '\0'; /* final assignment of parameter value */ if (OPT_ISSET(ops,'c')) { unsetparam(args[0]); createparam(args[0], type); } queue_signals(); pm = (Param) paramtab->getnode(paramtab, args[0]); if (pm && (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED))) { char **a; /* * Use spacesplit with fourth argument 1: identify quoted separators, * and unquote. This duplicates the string, so we still need to free. */ a = spacesplit(t, 1, 0, 1); zsfree(t); if (PM_TYPE(pm->node.flags) == PM_ARRAY) setaparam(args[0], a); else sethparam(args[0], a); } else setsparam(args[0], t); unqueue_signals(); return 0; }
static int bin_sysread(char *nam, char **args, Options ops, UNUSED(int func)) { int infd = 0, outfd = -1, bufsize = SYSREAD_BUFSIZE, count; char *outvar = NULL, *countvar = NULL, *inbuf; /* -i: input file descriptor if not stdin */ if (OPT_ISSET(ops, 'i')) { infd = getposint(OPT_ARG(ops, 'i'), nam); if (infd < 0) return 1; } /* -o: output file descriptor, else store in REPLY */ if (OPT_ISSET(ops, 'o')) { if (*args) { zwarnnam(nam, "no argument allowed with -o"); return 1; } outfd = getposint(OPT_ARG(ops, 'o'), nam); if (outfd < 0) return 1; } /* -s: buffer size if not default SYSREAD_BUFSIZE */ if (OPT_ISSET(ops, 's')) { bufsize = getposint(OPT_ARG(ops, 's'), nam); if (bufsize < 0) return 1; } /* -c: name of variable to store count of transferred bytes */ if (OPT_ISSET(ops, 'c')) { countvar = OPT_ARG(ops, 'c'); if (!isident(countvar)) { zwarnnam(nam, "not an identifier: %s", countvar); return 1; } } if (*args) { /* * Variable in which to store result if doing a plain read. * Default variable if not specified is REPLY. * If writing, only stuff we couldn't write is stored here, * no default in that case (we just discard it if no variable). */ outvar = *args; if (!isident(outvar)) { zwarnnam(nam, "not an identifier: %s", outvar); return 1; } } inbuf = zhalloc(bufsize); #if defined(HAVE_POLL) || defined(HAVE_SELECT) /* -t: timeout */ if (OPT_ISSET(ops, 't')) { # ifdef HAVE_POLL struct pollfd poll_fd; mnumber to_mn; int to_int, ret; poll_fd.fd = infd; poll_fd.events = POLLIN; to_mn = matheval(OPT_ARG(ops, 't')); if (errflag) return 1; if (to_mn.type == MN_FLOAT) to_int = (int) (1000 * to_mn.u.d); else to_int = 1000 * (int)to_mn.u.l; while ((ret = poll(&poll_fd, 1, to_int)) < 0) { if (errno != EINTR || errflag || retflag || breaks || contflag) break; } if (ret <= 0) { /* treat non-timeout error as error on read */ return ret ? 2 : 4; } # else /* using select */ struct timeval select_tv; fd_set fds; mnumber to_mn; int ret; FD_ZERO(&fds); FD_SET(infd, &fds); to_mn = matheval(OPT_ARG(ops, 't')); if (errflag) return 1; if (to_mn.type == MN_FLOAT) { select_tv.tv_sec = (int) to_mn.u.d; select_tv.tv_usec = (int) ((to_mn.u.d - select_tv.tv_sec) * 1e6); } else { select_tv.tv_sec = (int) to_mn.u.l; select_tv.tv_usec = 0; } while ((ret = select(infd+1, (SELECT_ARG_2_T) &fds, NULL, NULL,&select_tv)) < 1) { if (errno != EINTR || errflag || retflag || breaks || contflag) break; } if (ret <= 0) { /* treat non-timeout error as error on read */ return ret ? 2 : 4; } # endif } #endif while ((count = read(infd, inbuf, bufsize)) < 0) { if (errno != EINTR || errflag || retflag || breaks || contflag) break; } if (countvar) setiparam(countvar, count); if (count < 0) return 2; if (outfd >= 0) { if (!count) return 5; while (count > 0) { int ret; ret = write(outfd, inbuf, count); if (ret < 0) { if (errno == EINTR && !errflag && !retflag && !breaks && !contflag) continue; if (outvar) setsparam(outvar, metafy(inbuf, count, META_DUP)); if (countvar) setiparam(countvar, count); return 3; } inbuf += ret; count -= ret; } return 0; } if (!outvar) outvar = "REPLY"; /* do this even if we read zero bytes */ setsparam(outvar, metafy(inbuf, count, META_DUP)); return count ? 0 : 5; }
int transposewords(UNUSED(char **args)) { int p1, p2, p3, p4, pt, len, x = zlecs, pos; ZLE_STRING_T temp, pp; int n = zmult; int neg = n < 0, ocs = zlecs; if (neg) n = -n; while (x != zlell && zleline[x] != ZWC('\n') && !ZC_iword(zleline[x])) INCPOS(x); if (x == zlell || zleline[x] == ZWC('\n')) { x = zlecs; while (x) { if (ZC_iword(zleline[x])) break; pos = x; DECPOS(pos); if (zleline[pos] == ZWC('\n')) break; x = pos; } if (!x) return 1; pos = x; DECPOS(pos); if (zleline[pos] == ZWC('\n')) return 1; } for (p4 = x; p4 != zlell && ZC_iword(zleline[p4]); INCPOS(p4)) ; for (p3 = p4; p3; ) { pos = p3; DECPOS(pos); if (!ZC_iword(zleline[pos])) break; p3 = pos; } if (!p3) return 1; p1 = p2 = pt = p3; while (n--) { for (p2 = pt; p2; ) { pos = p2; DECPOS(pos); if (ZC_iword(zleline[pos])) break; p2 = pos; } if (!p2) return 1; for (p1 = p2; p1; ) { pos = p1; DECPOS(pos); if (!ZC_iword(zleline[pos])) break; p1 = pos; } pt = p1; } pp = temp = (ZLE_STRING_T)zhalloc((p4 - p1)*ZLE_CHAR_SIZE); len = p4 - p3; ZS_memcpy(pp, zleline + p3, len); pp += len; len = p3 - p2; ZS_memcpy(pp, zleline + p2, len); pp += len; ZS_memcpy(pp, zleline + p1, p2 - p1); ZS_memcpy(zleline + p1, temp, p4 - p1); if (neg) zlecs = ocs; else zlecs = p4; return 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; }
mod_export void strmetasort(char **array, int sortwhat, int *unmetalenp) { char **arrptr; /* * Array of elements containing stuff to sort. Note sortptrarr * is an array of pointers, since that's more efficient * for qsort() to manipulate. sortarr is the array of * structures. */ SortElt *sortptrarr, *sortptrarrptr; SortElt sortarr, sortarrptr; int oldsortdir, oldsortnumeric, nsort; nsort = arrlen(array); if (nsort < 2) return; pushheap(); sortptrarr = (SortElt *) zhalloc(nsort * sizeof(SortElt)); sortarr = (SortElt) zhalloc(nsort * sizeof(struct sortelt)); for (arrptr = array, sortptrarrptr = sortptrarr, sortarrptr = sortarr; *arrptr; arrptr++, sortptrarrptr++, sortarrptr++) { char *metaptr; int needlen, needalloc; *sortptrarrptr = sortarrptr; sortarrptr->orig = *arrptr; if (unmetalenp) { /* * Already unmetafied. We just need to check for * embededded nulls. */ int count = unmetalenp[arrptr-array]; /* Remember this length for sorted array */ sortarrptr->origlen = count; for (metaptr = *arrptr; *metaptr != '\0' && count--; metaptr++) ; /* *metaptr must now be \0, even if we reached the end */ needlen = (count != 0); } else { /* * Not yet unmetafied. See if it needs unmetafying. * If it doesn't, there can't be any embedded nulls, * since these are metafied. */ needlen = 0; for (metaptr = *arrptr; *metaptr && *metaptr != Meta; metaptr++); } /* * See if we need to do some special checking. * Either we're going to need to copy it to transform it, * or we need to unmetafy it. */ if ((needalloc = (sortwhat & (SORTIT_IGNORING_CASE|SORTIT_IGNORING_BACKSLASHES))) || *metaptr == Meta) { char *s, *t, *src = *arrptr, *dst; int len; sortarrptr->cmp = dst = (char *)zhalloc(((sortwhat & SORTIT_IGNORING_CASE)?2:1)*strlen(src)+1); if (unmetalenp) { /* Already unmetafied and we have the length. */ len = unmetalenp[arrptr-array]; } else if (*metaptr != '\0') { /* * Needs unmetafying. We need to check for * embedded nulls while we do this. */ char *t = dst + (metaptr - src); if (metaptr != src) memcpy(dst, src, metaptr - src); while ((*t = *metaptr++)) { if (*t++ == Meta) { if ((t[-1] = *metaptr++ ^ 32) == '\0') needlen = 1; } } len = t - dst; src = dst; } else { /* * Doesn't need unmetafying. * This means metaptr is the NULL at the * end of the string, so we have the length, and * there are no embedded nulls, so we don't * need the length later. * We're only copying the string to transform it * below. */ len = metaptr - src; } if (sortwhat & SORTIT_IGNORING_CASE) { char *send = src + len; #ifdef MULTIBYTE_SUPPORT if (isset(MULTIBYTE)) { /* * Lower the case the hard way. Convert to a wide * character, process that, and convert back. We * don't assume the characters have the same * multibyte length. We can't use casemodify() * because we have unmetafied data, which may have * been passed down to use. */ mbstate_t mbsin, mbsout; int clen; wchar_t wc; memset(&mbsin, 0, sizeof(mbstate_t)); memset(&mbsout, 0, sizeof(mbstate_t)); for (s = src, t = dst; s < send; ) { clen = mbrtowc(&wc, s, send-s, &mbsin); if (clen < 0) { /* invalid or unfinished: treat as single bytes */ while (s < send) *t++ = tulower(*s++); break; } if (clen == 0) { /* embedded null */ *t++ = '\0'; s++; continue; } s += clen; wc = towlower(wc); clen = wcrtomb(t, wc, &mbsout); t += clen; DPUTS(clen < 0, "Bad conversion when lowering case"); } *t = '\0'; len = t - dst; } else #endif for (s = src, t = dst; s < send; ) *t++ = tulower(*s++); src = dst; } if (sortwhat & SORTIT_IGNORING_BACKSLASHES) { char *end = src + len + 1; /* copy null byte, so increment length */ for (s = src, t = dst; s < end; ) { if (*s == '\\') { s++; len--; } *t++ = *s++; } } /* Do we need to store the length (embedded null)? */ sortarrptr->len = needlen ? len : -1; } else { /* * We can use the string as is, although it's possible * we still need to take account of an embedded null. */ sortarrptr->cmp = *arrptr; sortarrptr->len = needlen ? unmetalenp[arrptr-array] : -1; } } /* * We probably don't need to restore the following, but it's pretty cheap. */ oldsortdir = sortdir; oldsortnumeric = sortnumeric; sortdir = (sortwhat & SORTIT_BACKWARDS) ? -1 : 1; sortnumeric = (sortwhat & SORTIT_NUMERICALLY) ? 1 : 0; qsort(sortptrarr, nsort, sizeof(SortElt), eltpcmp); sortnumeric = oldsortnumeric; sortdir = oldsortdir; for (arrptr = array, sortptrarrptr = sortptrarr; nsort--; ) { if (unmetalenp) unmetalenp[arrptr-array] = (*sortptrarrptr)->origlen; *arrptr++ = (*sortptrarrptr++)->orig; } popheap(); }
static int ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch) { int blen, used, seen = 0, ret = 0, matchok = 0; char *buf; Patprog prog = NULL; if (*args && args[1]) { char *p; if (args[2]) { zwarnnam(nam, "too many arguments"); return 1; } p = dupstring(args[1]); tokenize(p); remnulargs(p); /* Signals handlers might stomp PAT_STATIC */ if (!(prog = patcompile(p, PAT_ZDUP, NULL))) { zwarnnam(nam, "bad pattern: %s", args[1]); return 1; } } else fflush(stdout); if (cmd->old) { used = cmd->olen; buf = (char *) zhalloc((blen = 256 + used) + 1); memcpy(buf, cmd->old, cmd->olen); zfree(cmd->old, cmd->olen); cmd->old = NULL; cmd->olen = 0; } else { used = 0; buf = (char *) zhalloc((blen = 256) + 1); } if (cmd->read != -1) { buf[used] = (char) cmd->read; buf[used + 1] = '\0'; seen = used = 1; cmd->read = -1; } do { if (noblock && cmd->read == -1) { int pollret; /* * Check there is data available. Borrowed from * poll_read() in utils.c and simplified. */ #ifdef HAVE_SELECT fd_set foofd; struct timeval expire_tv; expire_tv.tv_sec = 0; expire_tv.tv_usec = 0; FD_ZERO(&foofd); FD_SET(cmd->fd, &foofd); pollret = select(cmd->fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv); #else #ifdef FIONREAD if (ioctl(cmd->fd, FIONREAD, (char *) &val) == 0) pollret = (val > 0); #endif #endif if (pollret < 0) { /* * See read_poll() for this. * Last despairing effort to poll: attempt to * set nonblocking I/O and actually read the * character. cmd->read stores the character read. */ long mode; if (setblock_fd(0, cmd->fd, &mode)) pollret = read(cmd->fd, &cmd->read, 1); if (mode != -1) fcntl(cmd->fd, F_SETFL, mode); } if (pollret == 0) break; } if (!ret) { checkptycmd(cmd); if (cmd->fin) break; } if (cmd->read != -1 || (ret = read(cmd->fd, buf + used, 1)) == 1) { int readchar; if (cmd->read != -1) { ret = 1; readchar = cmd->read; cmd->read = -1; } else readchar = STOUC(buf[used]); if (imeta(readchar)) { buf[used++] = Meta; buf[used++] = (char) (readchar ^ 32); } else buf[used++] = (char) readchar; seen = 1; if (used >= blen-1) { if (!*args) { buf[used] = '\0'; unmetafy(buf, &used); write_loop(1, buf, used); used = 0; } else { buf = hrealloc(buf, blen, blen << 1); blen <<= 1; } } } buf[used] = '\0'; if (!prog) { if (ret <= 0 || (*args && buf[used - 1] == '\n' && (used < 2 || buf[used-2] != Meta))) break; } else { if (ret < 0 #ifdef EWOULDBLOCK && errno != EWOULDBLOCK #else #ifdef EAGAIN && errno != EAGAIN #endif #endif ) break; } } while (!(errflag || breaks || retflag || contflag) && used < READ_MAX && !(prog && ret && (matchok = pattry(prog, buf)))); if (prog && ret < 0 && #ifdef EWOULDBLOCK errno == EWOULDBLOCK #else #ifdef EAGAIN errno == EAGAIN #endif #endif ) { cmd->old = (char *) zalloc(cmd->olen = used); memcpy(cmd->old, buf, cmd->olen); return 1; } if (*args) setsparam(*args, ztrdup(buf)); else if (used) { unmetafy(buf, &used); write_loop(1, buf, used); } { int ret = cmd->fin + 1; if (seen && (!prog || matchok || !mustmatch)) ret = 0; if (prog) freepatprog(prog); return ret; } }
Thingy executenamedcommand(char *prmt) { Thingy cmd, retval = NULL; int l, len, feep = 0, listed = 0, curlist = 0; int ols = (listshown && validlist), olll = lastlistlen; char *cmdbuf, *ptr; char *okeymap = ztrdup(curkeymapname); clearlist = 1; /* prmt may be constant */ prmt = ztrdup(prmt); l = strlen(prmt); cmdbuf = (char *)zhalloc(l + NAMLEN + 2 #ifdef MULTIBYTE_SUPPORT + 2 * MB_CUR_MAX #endif ); strcpy(cmdbuf, prmt); zsfree(prmt); statusline = cmdbuf; selectlocalmap(command_keymap); selectkeymap("main", 1); ptr = cmdbuf += l; len = 0; for (;;) { *ptr = '_'; ptr[1] = '\0'; zrefresh(); if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) { statusline = NULL; selectkeymap(okeymap, 1); zsfree(okeymap); if ((listshown = ols)) { showinglist = -2; lastlistlen = olll; } else if (listed) clearlist = listshown = 1; retval = NULL; goto done; } if(cmd == Th(z_clearscreen)) { clearscreen(zlenoargs); if (curlist) { int zmultsav = zmult; zmult = 1; listlist(namedcmdll); showinglist = 0; zmult = zmultsav; } } else if(cmd == Th(z_redisplay)) { redisplay(zlenoargs); if (curlist) { int zmultsav = zmult; zmult = 1; listlist(namedcmdll); showinglist = 0; zmult = zmultsav; } } else if(cmd == Th(z_viquotedinsert)) { *ptr = '^'; zrefresh(); getfullchar(0); if(LASTFULLCHAR == ZLEEOF || !LASTFULLCHAR || len >= NAMLEN) feep = 1; else { int ret = zlecharasstring(LASTFULLCHAR, ptr); len += ret; ptr += ret; curlist = 0; } } else if(cmd == Th(z_quotedinsert)) { if(getfullchar(0) == ZLEEOF || !LASTFULLCHAR || len == NAMLEN) feep = 1; else { int ret = zlecharasstring(LASTFULLCHAR, ptr); len += ret; ptr += ret; curlist = 0; } } else if(cmd == Th(z_backwarddeletechar) || cmd == Th(z_vibackwarddeletechar)) { if (len) { ptr = backwardmetafiedchar(cmdbuf, ptr, NULL); len = ptr - cmdbuf; curlist = 0; } } else if(cmd == Th(z_killregion) || cmd == Th(z_backwardkillword) || cmd == Th(z_vibackwardkillword)) { if (len) curlist = 0; while (len) { convchar_t cc; ptr = backwardmetafiedchar(cmdbuf, ptr, &cc); len = ptr - cmdbuf; if (cc == ZWC('-')) break; } } else if(cmd == Th(z_killwholeline) || cmd == Th(z_vikillline) || cmd == Th(z_backwardkillline)) { len = 0; ptr = cmdbuf; if (listed) clearlist = listshown = 1; curlist = 0; } else if (cmd == Th(z_bracketedpaste)) { char *insert = bracketedstring(); size_t inslen = strlen(insert); if (len + inslen > NAMLEN) feep = 1; else { strcpy(ptr, insert); len += inslen; ptr += inslen; if (listed) { clearlist = listshown = 1; listed = 0; } else curlist = 0; } free(insert); } else { if(cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) { Thingy r; unambiguous: *ptr = 0; r = rthingy(cmdbuf); if (!(r->flags & DISABLED)) { unrefthingy(r); statusline = NULL; selectkeymap(okeymap, 1); zsfree(okeymap); if ((listshown = ols)) { showinglist = -2; lastlistlen = olll; } else if (listed) clearlist = listshown = 1; retval = r; goto done; } unrefthingy(r); } if(cmd == Th(z_selfinsertunmeta)) { fixunmeta(); cmd = Th(z_selfinsert); } if (cmd == Th(z_listchoices) || cmd == Th(z_deletecharorlist) || cmd == Th(z_expandorcomplete) || cmd == Th(z_completeword) || cmd == Th(z_expandorcompleteprefix) || cmd == Th(z_vicmdmode) || cmd == Th(z_acceptline) || lastchar == ' ' || lastchar == '\t') { namedcmdambig = 100; namedcmdll = newlinklist(); *ptr = '\0'; namedcmdstr = cmdbuf; scanhashtable(thingytab, 1, 0, DISABLED, scancompcmd, 0); namedcmdstr = NULL; if (empty(namedcmdll)) { feep = 1; if (listed) clearlist = listshown = 1; curlist = 0; } else if (cmd == Th(z_listchoices) || cmd == Th(z_deletecharorlist)) { int zmultsav = zmult; *ptr = '_'; ptr[1] = '\0'; zmult = 1; listlist(namedcmdll); listed = curlist = 1; showinglist = 0; zmult = zmultsav; } else if (!nextnode(firstnode(namedcmdll))) { strcpy(ptr = cmdbuf, peekfirst(namedcmdll)); len = strlen(ptr); ptr += len; if (cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) goto unambiguous; } else { strcpy(cmdbuf, peekfirst(namedcmdll)); ptr = cmdbuf + namedcmdambig; *ptr = '_'; ptr[1] = '\0'; if (isset(AUTOLIST) && !(isset(LISTAMBIGUOUS) && namedcmdambig > len)) { int zmultsav = zmult; if (isset(LISTBEEP)) feep = 1; zmult = 1; listlist(namedcmdll); listed = curlist = 1; showinglist = 0; zmult = zmultsav; } len = namedcmdambig; } } else { if (len == NAMLEN || cmd != Th(z_selfinsert)) feep = 1; else { #ifdef MULTIBYTE_SUPPORT if (!lastchar_wide_valid) getrestchar(lastchar, NULL, NULL); if (lastchar_wide == WEOF) feep = 1; else #endif if (ZC_icntrl(LASTFULLCHAR)) feep = 1; else { int ret = zlecharasstring(LASTFULLCHAR, ptr); len += ret; ptr += ret; if (listed) { clearlist = listshown = 1; listed = 0; } else curlist = 0; } } } } if (feep) handlefeep(zlenoargs); feep = 0; } done: selectlocalmap(NULL); return retval; }
mod_export char * zgetdir(struct dirsav *d) { char nbuf[PATH_MAX+3]; char *buf; int bufsiz, pos; struct stat sbuf; ino_t pino; dev_t pdev; #if !defined(__CYGWIN__) && !defined(USE_GETCWD) struct dirent *de; DIR *dir; dev_t dev; ino_t ino; int len; #endif buf = zhalloc(bufsiz = PATH_MAX); pos = bufsiz - 1; buf[pos] = '\0'; strcpy(nbuf, "../"); if (stat(".", &sbuf) < 0) { return NULL; } /* Record the initial inode and device */ pino = sbuf.st_ino; pdev = sbuf.st_dev; if (d) d->ino = pino, d->dev = pdev; #if !defined(__CYGWIN__) && !defined(USE_GETCWD) #ifdef HAVE_FCHDIR else #endif holdintr(); for (;;) { /* Examine the parent of the current directory. */ if (stat("..", &sbuf) < 0) break; /* Inode and device of curtent directory */ ino = pino; dev = pdev; /* Inode and device of current directory's parent */ pino = sbuf.st_ino; pdev = sbuf.st_dev; /* If they're the same, we've reached the root directory. */ if (ino == pino && dev == pdev) { if (!buf[pos]) buf[--pos] = '/'; if (d) { #ifndef HAVE_FCHDIR zchdir(buf + pos); noholdintr(); #endif return d->dirname = ztrdup(buf + pos); } zchdir(buf + pos); noholdintr(); return buf + pos; } /* Search the parent for the current directory. */ if (!(dir = opendir(".."))) break; while ((de = readdir(dir))) { char *fn = de->d_name; /* Ignore `.' and `..'. */ if (fn[0] == '.' && (fn[1] == '\0' || (fn[1] == '.' && fn[2] == '\0'))) continue; #ifdef HAVE_STRUCT_DIRENT_D_STAT if(de->d_stat.st_dev == dev && de->d_stat.st_ino == ino) { /* Found the directory we're currently in */ strncpy(nbuf + 3, fn, PATH_MAX); break; } #else /* !HAVE_STRUCT_DIRENT_D_STAT */ # ifdef HAVE_STRUCT_DIRENT_D_INO if (dev != pdev || (ino_t) de->d_ino == ino) # endif /* HAVE_STRUCT_DIRENT_D_INO */ { /* Maybe found directory, need to check device & inode */ strncpy(nbuf + 3, fn, PATH_MAX); lstat(nbuf, &sbuf); if (sbuf.st_dev == dev && sbuf.st_ino == ino) break; } #endif /* !HAVE_STRUCT_DIRENT_D_STAT */ } closedir(dir); if (!de) break; /* Not found */ /* * We get the "/" free just by copying from nbuf+2 instead * of nbuf+3, which is where we copied the path component. * This means buf[pos] is always a "/". */ len = strlen(nbuf + 2); pos -= len; while (pos <= 1) { char *newbuf = zhalloc(2*bufsiz); memcpy(newbuf + bufsiz, buf, bufsiz); buf = newbuf; pos += bufsiz; bufsiz *= 2; } memcpy(buf + pos, nbuf + 2, len); #ifdef HAVE_FCHDIR if (d) return d->dirname = ztrdup(buf + pos + 1); #endif if (chdir("..")) break; } /* * Fix up the directory, if necessary. * We're changing back down the hierarchy, ignore the * "/" at buf[pos]. */ if (d) { #ifndef HAVE_FCHDIR if (buf[pos]) zchdir(buf + pos + 1); noholdintr(); #endif return NULL; } if (buf[pos]) zchdir(buf + pos + 1); noholdintr(); #else /* __CYGWIN__, USE_GETCWD cases */ if (!getcwd(buf, bufsiz)) { if (d) { return NULL; } } else { if (d) { return d->dirname = ztrdup(buf); } return buf; } #endif /* * Something bad happened. * This has been seen when inside a special directory, * such as the Netapp .snapshot directory, that doesn't * appear as a directory entry in the parent directory. * We'll just need our best guess. * * We only get here from zgetcwd(); let that fall back to pwd. */ return NULL; }
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; }