static int bin_getattr(char *nam, char **argv, Options ops, UNUSED(int func)) { int ret = 0; int val_len = 0, attr_len = 0, slen; char *value, *file = argv[0], *attr = argv[1], *param = argv[2]; int symlink = OPT_ISSET(ops, 'h'); unmetafy(file, &slen); unmetafy(attr, NULL); val_len = xgetxattr(file, attr, NULL, 0, symlink); if (val_len == 0) { if (param) unsetparam(param); return 0; } if (val_len > 0) { value = (char *)zalloc(val_len+1); attr_len = xgetxattr(file, attr, value, val_len, symlink); if (attr_len > 0 && attr_len <= val_len) { value[attr_len] = '\0'; if (param) setsparam(param, metafy(value, attr_len, META_DUP)); else printf("%s\n", value); } zfree(value, val_len+1); } if (val_len < 0 || attr_len < 0 || attr_len > val_len) { zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno); ret = 1 + ((val_len > 0 && attr_len > val_len) || attr_len < 0); } return ret; }
static int bin_listattr(char *nam, char **argv, Options ops, UNUSED(int func)) { int ret = 0; int val_len, list_len = 0, slen; char *value, *file = argv[0], *param = argv[1]; int symlink = OPT_ISSET(ops, 'h'); unmetafy(file, &slen); val_len = xlistxattr(file, NULL, 0, symlink); if (val_len == 0) { if (param) unsetparam(param); return 0; } if (val_len > 0) { value = (char *)zalloc(val_len+1); list_len = xlistxattr(file, value, val_len, symlink); if (list_len > 0 && list_len <= val_len) { char *p = value; if (param) { if (strlen(value) + 1 == list_len) setsparam(param, metafy(value, list_len-1, META_DUP)); else { int arrlen = 0; char **array = NULL, **arrptr = NULL; while (p < &value[list_len]) { arrlen++; p += strlen(p) + 1; } arrptr = array = (char **)zshcalloc((arrlen+1) * sizeof(char *)); p = value; while (p < &value[list_len]) { *arrptr++ = metafy(p, -1, META_DUP); p += strlen(p) + 1; } setaparam(param, array); } } else while (p < &value[list_len]) { printf("%s\n", p); p += strlen(p) + 1; } } zfree(value, val_len+1); } if (val_len < 0 || list_len < 0 || list_len > val_len) { zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno); ret = 1 + (list_len > val_len || list_len < 0); } return ret; }
int stuff(char *fn) { FILE *in; char *buf; off_t len; if (!(in = fopen(unmeta(fn), "r"))) { zerr("can't open %s", fn); return 1; } fseek(in, 0, 2); len = ftell(in); fseek(in, 0, 0); buf = (char *)zalloc(len + 1); if (!(fread(buf, len, 1, in))) { zerr("read error on %s", fn); fclose(in); zfree(buf, len + 1); return 1; } fclose(in); buf[len] = '\0'; fwrite(buf, len, 1, stderr); fflush(stderr); inputsetline(metafy(buf, len, META_REALLOC), INP_FREE); return 0; }
void remember_edits(void) { if (histline == curhist) { zsfree(curhistline); curhistline = metafy((char *) line, ll, META_DUP); } else { Histent ent = gethistent(histline); if (metadiffer(ZLETEXT(ent), (char *) line, ll)) { zsfree(ent->zle_text); ent->zle_text = metafy((char *) line, ll, META_DUP); } } }
mod_export void makesuffixstr(char *f, char *s, int n) { if (f) { zsfree(suffixfunc); suffixfunc = ztrdup(f); suffixfunclen = n; } else if (s) { int inv, i, z = 0; ZLE_STRING_T ws, lasts, wptr; if (*s == '^' || *s == '!') { inv = 1; s++; } else inv = 0; s = getkeystring(s, &i, GETKEYS_SUFFIX, &z); s = metafy(s, i, META_USEHEAP); ws = stringaszleline(s, 0, &i, NULL, NULL); if (z) suffixnoinslen = inv ? 0 : n; else if (inv) { /* * negative match, \- wasn't present, so it *should* * have this suffix length */ suffixnoinslen = n; } lasts = wptr = ws; while (i) { if (i >= 3 && wptr[1] == ZWC('-')) { ZLE_CHAR_T str[2]; if (wptr > lasts) addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0, lasts, wptr - lasts, n); str[0] = *wptr; str[1] = wptr[2]; addsuffix(inv ? SUFTYP_NEGRNG : SUFTYP_POSRNG, 0, str, 2, n); wptr += 3; i -= 3; lasts = wptr; } else { wptr++; i--; } } if (wptr > lasts) addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0, lasts, wptr - lasts, n); free(ws); } else makesuffix(n); }
static void set_colour_code(char *str, char **var) { char *keyseq; int len; zsfree(*var); keyseq = getkeystring(str, &len, GETKEYS_BINDKEY, NULL); *var = metafy(keyseq, len, META_DUP); }
mod_export void makesuffixstr(char *f, char *s, int n) { if (f) { zsfree(suffixfunc); suffixfunc = ztrdup(f); suffixfunclen = n; } else if (s) { int inv, i, z = 0; ZLE_STRING_T ws, lasts, wptr; if (*s == '^' || *s == '!') { inv = 1; s++; } else inv = 0; s = getkeystring(s, &i, GETKEYS_SUFFIX, &z); s = metafy(s, i, META_USEHEAP); ws = stringaszleline(s, 0, &i, NULL, NULL); /* Remove suffix on uninsertable characters if \- was given * * and the character class wasn't negated -- or vice versa. */ suffixnoinsrem = z ^ inv; suffixlen = n; lasts = wptr = ws; while (i) { if (i >= 3 && wptr[1] == ZWC('-')) { ZLE_CHAR_T str[2]; if (wptr > lasts) addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0, lasts, wptr - lasts, n); str[0] = *wptr; str[1] = wptr[2]; addsuffix(inv ? SUFTYP_NEGRNG : SUFTYP_POSRNG, 0, str, 2, n); wptr += 3; i -= 3; lasts = wptr; } else { wptr++; i--; } } if (wptr > lasts) addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0, lasts, wptr - lasts, n); free(ws); } else makesuffix(n); }
static int bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func)) { int bufsize, x; char *endptr = NULL, *scalar = NULL, *buffer; time_t secs; struct tm *t; if (OPT_ISSET(ops,'s')) { scalar = OPT_ARG(ops, 's'); if (!isident(scalar)) { zwarnnam(nam, "not an identifier: %s", scalar); return 1; } } if (OPT_ISSET(ops, 'r')) return reverse_strftime(nam, argv, scalar, OPT_ISSET(ops, 'q')); errno = 0; secs = (time_t)strtoul(argv[1], &endptr, 10); if (errno != 0) { zwarnnam(nam, "%s: %e", argv[1], errno); return 1; } else if (*endptr != '\0') { zwarnnam(nam, "%s: invalid decimal number", argv[1]); return 1; } t = localtime(&secs); if (!t) { zwarnnam(nam, "%s: unable to convert to time", argv[1]); return 1; } bufsize = strlen(argv[0]) * 8; buffer = zalloc(bufsize); for (x=0; x < 4; x++) { if (ztrftime(buffer, bufsize, argv[0], t) >= 0) break; buffer = zrealloc(buffer, bufsize *= 2); } if (scalar) { setsparam(scalar, metafy(buffer, -1, META_DUP)); } else { printf("%s\n", buffer); } zfree(buffer, bufsize); return 0; }
void pushline(void) { int n = zmult; if (n < 0) return; pushnode(bufstack, metafy((char *) line, ll, META_DUP)); while (--n) pushnode(bufstack, ztrdup("")); stackcs = cs; *line = '\0'; ll = cs = 0; clearlist = 1; }
static int bin_setattr(char *nam, char **argv, Options ops, UNUSED(int func)) { int ret = 0, slen, vlen; int symlink = OPT_ISSET(ops, 'h'); char *file = argv[0], *attr = argv[1], *value = argv[2]; unmetafy(file, &slen); unmetafy(attr, NULL); unmetafy(value, &vlen); if (xsetxattr(file, attr, value, vlen, 0, symlink)) { zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno); ret = 1; } return ret; }
static int bin_delattr(char *nam, char **argv, Options ops, UNUSED(int func)) { int ret = 0, slen; int symlink = OPT_ISSET(ops, 'h'); char *file = argv[0], **attr = argv; unmetafy(file, &slen); while (*++attr) { unmetafy(*attr, NULL); if (xremovexattr(file, *attr, symlink)) { zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno); ret = 1; break; } } return ret; }
static char * get_contents(char *fname) { int fd; #ifdef USE_MMAP caddr_t mmptr; struct stat sbuf; #endif char *val; unmetafy(fname = ztrdup(fname), &fd); #ifdef USE_MMAP if ((fd = open(fname, O_RDONLY | O_NOCTTY)) < 0 || fstat(fd, &sbuf) || (mmptr = (caddr_t)mmap((caddr_t)0, sbuf.st_size, PROT_READ, MMAP_ARGS, fd, (off_t)0)) == (caddr_t)-1) { if (fd >= 0) close(fd); free(fname); return NULL; } /* * Sadly, we need to copy the thing even if metafying doesn't * change it. We just don't know when we might get a chance to * munmap it, otherwise. */ val = metafy((char *)mmptr, sbuf.st_size, META_HEAPDUP); munmap(mmptr, sbuf.st_size); close(fd); #else /* don't USE_MMAP */ val = NULL; if ((fd = open(fname, O_RDONLY | O_NOCTTY)) >= 0) { LinkList ll; if ((ll = readoutput(fd, 1))) val = peekfirst(ll); } #endif /* USE_MMAP */ free(fname); return val; }
ZLE_INT_T vigetkey(void) { Keymap mn = openkeymap("main"); char m[3], *str; Thingy cmd; if (getbyte(0L, NULL) == EOF) return ZLEEOF; m[0] = lastchar; metafy(m, 1, META_NOALLOC); if(mn) cmd = keybind(mn, m, &str); else cmd = t_undefinedkey; if (!cmd || cmd == Th(z_sendbreak)) { return ZLEEOF; } else if (cmd == Th(z_quotedinsert)) { if (getfullchar(0) == ZLEEOF) return ZLEEOF; } else if(cmd == Th(z_viquotedinsert)) { ZLE_CHAR_T sav = zleline[zlecs]; zleline[zlecs] = '^'; zrefresh(); getfullchar(0); zleline[zlecs] = sav; if(LASTFULLCHAR == ZLEEOF) return ZLEEOF; } else if (cmd == Th(z_vicmdmode)) { return ZLEEOF; } #ifdef MULTIBYTE_SUPPORT if (!lastchar_wide_valid) { getrestchar(lastchar); } #endif return LASTFULLCHAR; }
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); if (!(prog = patcompile(p, PAT_STATIC, 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) { if (cmd->read != -1) { ret = 1; buf[used] = (char) cmd->read; cmd->read = -1; } seen = 1; if (++used == blen) { if (!*args) { 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')) 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(metafy(buf, used, META_HREALLOC))); else if (used) write_loop(1, buf, used); if (seen && (!prog || matchok || !mustmatch)) return 0; return cmd->fin + 1; }
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; }
static int zcond_regex_match(char **a, int id) { regex_t re; regmatch_t *m, *matches = NULL; size_t matchessz = 0; char *lhstr, *lhstr_zshmeta, *rhre, *rhre_zshmeta, *s, **arr, **x; int r, n, return_value, rcflags, reflags, nelem, start; lhstr_zshmeta = cond_str(a,0,0); rhre_zshmeta = cond_str(a,1,0); rcflags = reflags = 0; return_value = 0; /* 1 => matched successfully */ lhstr = ztrdup(lhstr_zshmeta); unmetafy(lhstr, NULL); rhre = ztrdup(rhre_zshmeta); unmetafy(rhre, NULL); switch(id) { case ZREGEX_EXTENDED: rcflags |= REG_EXTENDED; if (!isset(CASEMATCH)) rcflags |= REG_ICASE; r = regcomp(&re, rhre, rcflags); if (r) { zregex_regerrwarn(r, &re, "failed to compile regex"); break; } /* re.re_nsub is number of parenthesized groups, we also need * 1 for the 0 offset, which is the entire matched portion */ if ((int)re.re_nsub < 0) { zwarn("INTERNAL ERROR: regcomp() returned " "negative subpattern count %d", (int)re.re_nsub); break; } matchessz = (re.re_nsub + 1) * sizeof(regmatch_t); matches = zalloc(matchessz); r = regexec(&re, lhstr, re.re_nsub+1, matches, reflags); if (r == REG_NOMATCH) ; /* We do nothing when we fail to match. */ else if (r == 0) { return_value = 1; if (isset(BASHREMATCH)) { start = 0; nelem = re.re_nsub + 1; } else { start = 1; nelem = re.re_nsub; } arr = NULL; /* bogus gcc warning of used uninitialised */ /* entire matched portion + re_nsub substrings + NULL */ if (nelem) { arr = x = (char **) zalloc(sizeof(char *) * (nelem + 1)); for (m = matches + start, n = start; n <= (int)re.re_nsub; ++n, ++m, ++x) { *x = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP); } *x = NULL; } if (isset(BASHREMATCH)) { setaparam("BASH_REMATCH", arr); } else { zlong offs; char *ptr; int clen, leftlen; m = matches; s = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP); setsparam("MATCH", s); /* * Count the characters before the match. */ ptr = lhstr; leftlen = m->rm_so; offs = 0; MB_CHARINIT(); while (leftlen) { offs++; clen = MB_CHARLEN(ptr, leftlen); ptr += clen; leftlen -= clen; } setiparam("MBEGIN", offs + !isset(KSHARRAYS)); /* * Add on the characters in the match. */ leftlen = m->rm_eo - m->rm_so; while (leftlen) { offs++; clen = MB_CHARLEN(ptr, leftlen); ptr += clen; leftlen -= clen; } setiparam("MEND", offs + !isset(KSHARRAYS) - 1); if (nelem) { char **mbegin, **mend, **bptr, **eptr; bptr = mbegin = (char **)zalloc(sizeof(char *)*(nelem+1)); eptr = mend = (char **)zalloc(sizeof(char *)*(nelem+1)); for (m = matches + start, n = 0; n < nelem; ++n, ++m, ++bptr, ++eptr) { char buf[DIGBUFSIZE]; if (m->rm_so < 0 || m->rm_eo < 0) { *bptr = ztrdup("-1"); *eptr = ztrdup("-1"); continue; } ptr = lhstr; leftlen = m->rm_so; offs = 0; /* Find the start offset */ MB_CHARINIT(); while (leftlen) { offs++; clen = MB_CHARLEN(ptr, leftlen); ptr += clen; leftlen -= clen; } convbase(buf, offs + !isset(KSHARRAYS), 10); *bptr = ztrdup(buf); /* Continue to the end offset */ leftlen = m->rm_eo - m->rm_so; while (leftlen ) { offs++; clen = MB_CHARLEN(ptr, leftlen); ptr += clen; leftlen -= clen; } convbase(buf, offs + !isset(KSHARRAYS) - 1, 10); *eptr = ztrdup(buf); } *bptr = *eptr = NULL; setaparam("match", arr); setaparam("mbegin", mbegin); setaparam("mend", mend); } } } else zregex_regerrwarn(r, &re, "regex matching error"); break; default: DPUTS(1, "bad regex option"); return_value = 0; goto CLEAN_BASEMETA; } if (matches) zfree(matches, matchessz); regfree(&re); CLEAN_BASEMETA: free(lhstr); free(rhre); return return_value; }
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 = metafy(captures[0], -1, META_DUP); 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) { char **x, **y; y = &captures[capture_start]; matches = x = (char **) zalloc(sizeof(char *) * (arrlen(y) + 1)); do { if (*y) *x++ = metafy(*y, -1, META_DUP); else *x++ = NULL; } while (*y++); 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; }
int getvisrchstr(void) { char *sbuf = halloc(80); int sptr = 1, ret = 0, ssbuf = 80; int cmd; int *obindtab = bindtab; if (visrchstr) { zsfree(visrchstr); visrchstr = NULL; } clearlist = 1; statusline = sbuf; sbuf[0] = (visrchsense == -1) ? '?' : '/'; bindtab = mainbindtab; while (sptr) { sbuf[sptr] = '_'; statusll = sptr + 1; refresh(); if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) { ret = 0; break; } if(cmd == z_magicspace) { c = ' '; cmd = z_selfinsert; } switch(cmd) { case z_redisplay: redisplay(); break; case z_clearscreen: clearscreen(); break; case z_acceptline: case z_vicmdmode: sbuf[sptr] = 0; visrchstr = metafy(sbuf + 1, sptr - 1, META_DUP); ret = 1; sptr = 0; break; case z_backwarddeletechar: case z_vibackwarddeletechar: sptr--; break; case z_backwardkillword: case z_vibackwardkillword: while(sptr != 1 && iblank(sbuf[sptr - 1])) sptr--; if(iident(sbuf[sptr - 1])) while(sptr != 1 && iident(sbuf[sptr - 1])) sptr--; else while(sptr != 1 && !iident(sbuf[sptr - 1]) && !iblank(sbuf[sptr - 1])) sptr--; break; case z_sendstring: sendstring(); break; case z_viquotedinsert: sbuf[sptr] = '^'; refresh(); /* fall through */ case z_quotedinsert: if ((c = getkey(0)) == EOF) { feep(); break; } goto ins; case z_selfinsertunmeta: c &= 0x7f; if(c == '\r') c = '\n'; case z_selfinsert: ins: if(sptr == ssbuf - 1) { char *newbuf = halloc(ssbuf *= 2); strcpy(newbuf, sbuf); statusline = sbuf = newbuf; } sbuf[sptr++] = c; break; default: feep(); } } statusline = NULL; bindtab = obindtab; return ret; }
static int putpromptchar(int doprint, int endchar, unsigned int *txtchangep) { char *ss, *hostnam; int t0, arg, test, sep, j, numjobs; struct tm *tm; struct timezone dummy_tz; struct timeval tv; time_t timet; Nameddir nd; for (; *bv->fm && *bv->fm != endchar; bv->fm++) { arg = 0; if (*bv->fm == '%' && isset(PROMPTPERCENT)) { int minus = 0; bv->fm++; if (*bv->fm == '-') { minus = 1; bv->fm++; } if (idigit(*bv->fm)) { arg = zstrtol(bv->fm, &bv->fm, 10); if (minus) arg *= -1; } else if (minus) arg = -1; if (*bv->fm == '(') { int tc, otruncwidth; if (idigit(*++bv->fm)) { arg = zstrtol(bv->fm, &bv->fm, 10); } else if (arg < 0) { /* negative numbers don't make sense here */ arg *= -1; } test = 0; ss = pwd; switch (tc = *bv->fm) { case 'c': case '.': case '~': if ((nd = finddir(ss))) { arg--; ss += strlen(nd->dir); } /*FALLTHROUGH*/ case '/': case 'C': /* `/' gives 0, `/any' gives 1, etc. */ if (*ss++ == '/' && *ss) arg--; for (; *ss; ss++) if (*ss == '/') arg--; if (arg <= 0) test = 1; break; case 't': case 'T': case 'd': case 'D': case 'w': timet = time(NULL); tm = localtime(&timet); switch (tc) { case 't': test = (arg == tm->tm_min); break; case 'T': test = (arg == tm->tm_hour); break; case 'd': test = (arg == tm->tm_mday); break; case 'D': test = (arg == tm->tm_mon); break; case 'w': test = (arg == tm->tm_wday); break; } break; case '?': if (lastval == arg) test = 1; break; case '#': if (geteuid() == (uid_t)arg) test = 1; break; case 'g': if (getegid() == (gid_t)arg) test = 1; break; case 'j': for (numjobs = 0, j = 1; j <= maxjob; j++) if (jobtab[j].stat && jobtab[j].procs && !(jobtab[j].stat & STAT_NOPRINT)) numjobs++; if (numjobs >= arg) test = 1; break; case 'l': *bv->bp = '\0'; countprompt(bv->bufline, &t0, 0, 0); if (minus) t0 = zterm_columns - t0; if (t0 >= arg) test = 1; break; case 'e': { Funcstack fsptr = funcstack; test = arg; while (fsptr && test > 0) { test--; fsptr = fsptr->prev; } test = !test; } break; case 'L': if (shlvl >= arg) test = 1; break; case 'S': if (time(NULL) - shtimer.tv_sec >= arg) test = 1; break; case 'v': if (arrlen(psvar) >= arg) test = 1; break; case 'V': if (arrlen(psvar) >= arg) { if (*psvar[(arg ? arg : 1) - 1]) test = 1; } break; case '_': test = (cmdsp >= arg); break; case '!': test = privasserted(); break; default: test = -1; break; } if (!*bv->fm || !(sep = *++bv->fm)) return 0; bv->fm++; /* Don't do the current truncation until we get back */ otruncwidth = bv->truncwidth; bv->truncwidth = 0; if (!putpromptchar(test == 1 && doprint, sep, txtchangep) || !*++bv->fm || !putpromptchar(test == 0 && doprint, ')', txtchangep)) { bv->truncwidth = otruncwidth; return 0; } bv->truncwidth = otruncwidth; continue; } if (!doprint) switch(*bv->fm) { case '[': while(idigit(*++bv->fm)); while(*++bv->fm != ']'); continue; case '<': while(*++bv->fm != '<'); continue; case '>': while(*++bv->fm != '>'); continue; case 'D': if(bv->fm[1]=='{') while(*++bv->fm != '}'); continue; default: continue; } switch (*bv->fm) { case '~': promptpath(pwd, arg, 1); break; case 'd': case '/': promptpath(pwd, arg, 0); break; case 'c': case '.': promptpath(pwd, arg ? arg : 1, 1); break; case 'C': promptpath(pwd, arg ? arg : 1, 0); break; case 'N': promptpath(scriptname ? scriptname : argzero, arg, 0); break; case 'h': case '!': addbufspc(DIGBUFSIZE); convbase(bv->bp, curhist, 10); bv->bp += strlen(bv->bp); break; case 'j': for (numjobs = 0, j = 1; j <= maxjob; j++) if (jobtab[j].stat && jobtab[j].procs && !(jobtab[j].stat & STAT_NOPRINT)) numjobs++; addbufspc(DIGBUFSIZE); sprintf(bv->bp, "%d", numjobs); bv->bp += strlen(bv->bp); break; case 'M': queue_signals(); if ((hostnam = getsparam("HOST"))) stradd(hostnam); unqueue_signals(); break; case 'm': if (!arg) arg++; queue_signals(); if (!(hostnam = getsparam("HOST"))) break; if (arg < 0) { for (ss = hostnam + strlen(hostnam); ss > hostnam; ss--) if (ss[-1] == '.' && !++arg) break; stradd(ss); } else { for (ss = hostnam; *ss; ss++) if (*ss == '.' && !--arg) break; stradd(*ss ? dupstrpfx(hostnam, ss - hostnam) : hostnam); } unqueue_signals(); break; case 'S': txtchangeset(txtchangep, TXTSTANDOUT, TXTNOSTANDOUT); txtset(TXTSTANDOUT); tsetcap(TCSTANDOUTBEG, TSC_PROMPT); break; case 's': txtchangeset(txtchangep, TXTNOSTANDOUT, TXTSTANDOUT); txtunset(TXTSTANDOUT); tsetcap(TCSTANDOUTEND, TSC_PROMPT|TSC_DIRTY); break; case 'B': txtchangeset(txtchangep, TXTBOLDFACE, TXTNOBOLDFACE); txtset(TXTBOLDFACE); tsetcap(TCBOLDFACEBEG, TSC_PROMPT|TSC_DIRTY); break; case 'b': txtchangeset(txtchangep, TXTNOBOLDFACE, TXTBOLDFACE); txtchangeset(txtchangep, TXTNOSTANDOUT, TXTSTANDOUT); txtchangeset(txtchangep, TXTNOUNDERLINE, TXTUNDERLINE); txtunset(TXTBOLDFACE); tsetcap(TCALLATTRSOFF, TSC_PROMPT|TSC_DIRTY); break; case 'U': txtchangeset(txtchangep, TXTUNDERLINE, TXTNOUNDERLINE); txtset(TXTUNDERLINE); tsetcap(TCUNDERLINEBEG, TSC_PROMPT); break; case 'u': txtchangeset(txtchangep, TXTNOUNDERLINE, TXTUNDERLINE); txtunset(TXTUNDERLINE); tsetcap(TCUNDERLINEEND, TSC_PROMPT|TSC_DIRTY); break; case 'F': arg = parsecolorchar(arg, 1); if (arg >= 0 && !(arg & TXTNOFGCOLOUR)) { txtchangeset(txtchangep, arg & TXT_ATTR_FG_ON_MASK, TXTNOFGCOLOUR); txtset(arg & TXT_ATTR_FG_ON_MASK); set_colour_attribute(arg, COL_SEQ_FG, TSC_PROMPT); break; } /* else FALLTHROUGH */ case 'f': txtchangeset(txtchangep, TXTNOFGCOLOUR, TXT_ATTR_FG_ON_MASK); txtunset(TXT_ATTR_FG_ON_MASK); set_colour_attribute(TXTNOFGCOLOUR, COL_SEQ_FG, TSC_PROMPT); break; case 'K': arg = parsecolorchar(arg, 0); if (arg >= 0 && !(arg & TXTNOBGCOLOUR)) { txtchangeset(txtchangep, arg & TXT_ATTR_BG_ON_MASK, TXTNOBGCOLOUR); txtset(arg & TXT_ATTR_BG_ON_MASK); set_colour_attribute(arg, COL_SEQ_BG, TSC_PROMPT); break; } /* else FALLTHROUGH */ case 'k': txtchangeset(txtchangep, TXTNOBGCOLOUR, TXT_ATTR_BG_ON_MASK); txtunset(TXT_ATTR_BG_ON_MASK); set_colour_attribute(TXTNOBGCOLOUR, COL_SEQ_BG, TSC_PROMPT); break; case '[': if (idigit(*++bv->fm)) arg = zstrtol(bv->fm, &bv->fm, 10); if (!prompttrunc(arg, ']', doprint, endchar, txtchangep)) return *bv->fm; break; case '<': case '>': /* Test (minus) here so -0 means "at the right margin" */ if (minus) { *bv->bp = '\0'; countprompt(bv->bufline, &t0, 0, 0); arg = zterm_columns - t0 + arg; if (arg <= 0) arg = 1; } if (!prompttrunc(arg, *bv->fm, doprint, endchar, txtchangep)) return *bv->fm; break; case '{': /*}*/ if (!bv->dontcount++) { addbufspc(1); *bv->bp++ = Inpar; } if (arg <= 0) break; /* else */ /* FALLTHROUGH */ case 'G': if (arg > 0) { addbufspc(arg); while (arg--) *bv->bp++ = Nularg; } else { addbufspc(1); *bv->bp++ = Nularg; } break; case /*{*/ '}': if (bv->trunccount && bv->trunccount >= bv->dontcount) return *bv->fm; if (bv->dontcount && !--bv->dontcount) { addbufspc(1); *bv->bp++ = Outpar; } break; case 't': case '@': case 'T': case '*': case 'w': case 'W': case 'D': { char *tmfmt, *dd, *tmbuf = NULL; switch (*bv->fm) { case 'T': tmfmt = "%K:%M"; break; case '*': tmfmt = "%K:%M:%S"; break; case 'w': tmfmt = "%a %f"; break; case 'W': tmfmt = "%m/%d/%y"; break; case 'D': if (bv->fm[1] == '{' /*}*/) { for (ss = bv->fm + 2; *ss && *ss != /*{*/ '}'; ss++) if(*ss == '\\' && ss[1]) ss++; dd = tmfmt = tmbuf = zalloc(ss - bv->fm); for (ss = bv->fm + 2; *ss && *ss != /*{*/ '}'; ss++) { if(*ss == '\\' && ss[1]) ss++; *dd++ = *ss; } *dd = 0; bv->fm = ss - !*ss; if (!*tmfmt) { free(tmbuf); continue; } } else tmfmt = "%y-%m-%d"; break; default: tmfmt = "%l:%M%p"; break; } gettimeofday(&tv, &dummy_tz); tm = localtime(&tv.tv_sec); /* * Hack because strftime won't say how * much space it actually needs. Try to add it * a few times until it works. Some formats don't * actually have a length, so we could go on for * ever. */ for(j = 0, t0 = strlen(tmfmt)*8; j < 3; j++, t0*=2) { addbufspc(t0); if (ztrftime(bv->bp, t0, tmfmt, tm, tv.tv_usec) >= 0) break; } /* There is enough room for this because addbufspc(t0) * allocates room for t0 * 2 bytes. */ metafy(bv->bp, -1, META_NOALLOC); bv->bp += strlen(bv->bp); zsfree(tmbuf); break; } case 'n': stradd(get_username()); break; case 'l': if (*ttystrname) { ss = (strncmp(ttystrname, "/dev/tty", 8) ? ttystrname + 5 : ttystrname + 8); stradd(ss); } else stradd("()"); break; case 'y': if (*ttystrname) { ss = (strncmp(ttystrname, "/dev/", 5) ? ttystrname : ttystrname + 5); stradd(ss); } else stradd("()"); break; case 'L': addbufspc(DIGBUFSIZE); #if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD) sprintf(bv->bp, "%lld", shlvl); #else sprintf(bv->bp, "%ld", (long)shlvl); #endif bv->bp += strlen(bv->bp); break; case '?': addbufspc(DIGBUFSIZE); #if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD) sprintf(bv->bp, "%lld", lastval); #else sprintf(bv->bp, "%ld", (long)lastval); #endif bv->bp += strlen(bv->bp); break; case '%': case ')': addbufspc(1); *bv->bp++ = *bv->fm; break; case '#': addbufspc(1); *bv->bp++ = privasserted() ? '#' : '%'; break; case 'v': if (!arg) arg = 1; else if (arg < 0) arg += arrlen(psvar) + 1; if (arg > 0 && arrlen(psvar) >= arg) stradd(psvar[arg - 1]); break; case 'E': tsetcap(TCCLEAREOL, TSC_PROMPT); break; case '^': if (cmdsp) { if (arg >= 0) { if (arg > cmdsp || arg == 0) arg = cmdsp; for (t0 = cmdsp - 1; arg--; t0--) { stradd(cmdnames[cmdstack[t0]]); if (arg) { addbufspc(1); *bv->bp++=' '; } } } else { arg = -arg; if (arg > cmdsp) arg = cmdsp; for (t0 = arg - 1; arg--; t0--) { stradd(cmdnames[cmdstack[t0]]); if (arg) { addbufspc(1); *bv->bp++=' '; } } } } break; case '_': if (cmdsp) { if (arg >= 0) { if (arg > cmdsp || arg == 0) arg = cmdsp; for (t0 = cmdsp - arg; arg--; t0++) { stradd(cmdnames[cmdstack[t0]]); if (arg) { addbufspc(1); *bv->bp++=' '; } } } else { arg = -arg; if (arg > cmdsp) arg = cmdsp; for (t0 = 0; arg--; t0++) { stradd(cmdnames[cmdstack[t0]]); if (arg) { addbufspc(1); *bv->bp++=' '; } } } } break; case 'r': if(bv->rstring) stradd(bv->rstring); break; case 'R': if(bv->Rstring) stradd(bv->Rstring); break; case 'e': { int depth = 0; Funcstack fsptr = funcstack; while (fsptr) { depth++; fsptr = fsptr->prev; } addbufspc(DIGBUFSIZE); sprintf(bv->bp, "%d", depth); bv->bp += strlen(bv->bp); break; } case 'I': if (funcstack && funcstack->tp != FS_SOURCE && !IN_EVAL_TRAP()) { /* * We're in a function or an eval with * EVALLINENO. Calculate the line number in * the file. */ zlong flineno = lineno + funcstack->flineno; /* take account of eval line nos. starting at 1 */ if (funcstack->tp == FS_EVAL) lineno--; addbufspc(DIGBUFSIZE); #if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD) sprintf(bv->bp, "%lld", flineno); #else sprintf(bv->bp, "%ld", (long)flineno); #endif bv->bp += strlen(bv->bp); break; } /* else we're in a file and lineno is already correct */ /* FALLTHROUGH */ case 'i': addbufspc(DIGBUFSIZE); #if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD) sprintf(bv->bp, "%lld", lineno); #else sprintf(bv->bp, "%ld", (long)lineno); #endif bv->bp += strlen(bv->bp); break; case 'x': if (funcstack && funcstack->tp != FS_SOURCE && !IN_EVAL_TRAP()) promptpath(funcstack->filename ? funcstack->filename : "", arg, 0); else promptpath(scriptfilename ? scriptfilename : argzero, arg, 0); break; case '\0': return 0; case Meta: bv->fm++; break; } } else if(*bv->fm == '!' && isset(PROMPTBANG)) { if(doprint) { if(bv->fm[1] == '!') { bv->fm++; addbufspc(1); pputc('!'); } else { addbufspc(DIGBUFSIZE); convbase(bv->bp, curhist, 10); bv->bp += strlen(bv->bp); } } } else { char c = *bv->fm == Meta ? *++bv->fm ^ 32 : *bv->fm; if (doprint) { addbufspc(1); pputc(c); } } } return *bv->fm; }
int init_term(void) { #ifndef TGETENT_ACCEPTS_NULL static char termbuf[2048]; /* the termcap buffer */ #endif if (!*term) return termok = TERM_BAD; /* unset zle if using zsh under emacs */ if (!strcmp(term, "emacs")) opts[USEZLE] = 0; #ifdef TGETENT_ACCEPTS_NULL /* If possible, we let tgetent allocate its own termcap buffer */ if (tgetent(NULL, term) != 1) { #else if (tgetent(termbuf, term) != 1) { #endif if (isset(INTERACTIVE)) zerr("can't find termcap info for %s", term, 0); errflag = 0; return termok = TERM_BAD; } else { char tbuf[1024], *pp; int t0; termok = TERM_OK; for (t0 = 0; t0 != TC_COUNT; t0++) { pp = tbuf; zsfree(tcstr[t0]); /* AIX tgetstr() ignores second argument */ if (!(pp = tgetstr(tccapnams[t0], &pp))) tcstr[t0] = NULL, tclen[t0] = 0; else { tclen[t0] = strlen(pp); tcstr[t0] = (char *) zalloc(tclen[t0] + 1); memcpy(tcstr[t0], pp, tclen[t0] + 1); } } /* check whether terminal has automargin (wraparound) capability */ hasam = tgetflag("am"); /* if there's no termcap entry for cursor up, use single line mode: * * this is flagged by termok which is examined in zle_refresh.c * */ if (!tccan(TCUP)) { tcstr[TCUP] = NULL; termok = TERM_NOUP; } /* if there's no termcap entry for cursor left, use \b. */ if (!tccan(TCLEFT)) { tcstr[TCLEFT] = ztrdup("\b"); tclen[TCLEFT] = 1; } /* if the termcap entry for down is \n, don't use it. */ if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n') { tclen[TCDOWN] = 0; zsfree(tcstr[TCDOWN]); tcstr[TCDOWN] = NULL; } /* if there's no termcap entry for clear, use ^L. */ if (!tccan(TCCLEARSCREEN)) { tcstr[TCCLEARSCREEN] = ztrdup("\14"); tclen[TCCLEARSCREEN] = 1; } } return termok; } /* Initialize lots of global variables and hash tables */ /**/ void setupvals(void) { struct passwd *pswd; struct timezone dummy_tz; char *ptr; #ifdef HAVE_GETRLIMIT int i; #endif noeval = 0; curhist = 0; histsiz = DEFAULT_HISTSIZE; inithist(); clwords = (char **) zcalloc((clwsize = 16) * sizeof(char *)); cmdstack = (unsigned char *) zalloc(256); cmdsp = 0; bangchar = '!'; hashchar = '#'; hatchar = '^'; termok = TERM_BAD; curjob = prevjob = coprocin = coprocout = -1; gettimeofday(&shtimer, &dummy_tz); /* init $SECONDS */ srand((unsigned int)(shtimer.tv_sec + shtimer.tv_usec)); /* seed $RANDOM */ hostnam = (char *) zalloc(256); gethostname(hostnam, 256); /* Set default path */ path = (char **) zalloc(sizeof(*path) * 5); path[0] = ztrdup("/bin"); path[1] = ztrdup("/usr/bin"); path[2] = ztrdup("/usr/ucb"); path[3] = ztrdup("/usr/local/bin"); path[4] = NULL; cdpath = mkarray(NULL); manpath = mkarray(NULL); fignore = mkarray(NULL); fpath = mkarray(NULL); mailpath = mkarray(NULL); watch = mkarray(NULL); psvar = mkarray(NULL); #ifdef DYNAMIC module_path = mkarray(ztrdup(MODULE_DIR)); modules = newlinklist(); #endif /* Set default prompts */ if (opts[INTERACTIVE]) { prompt = ztrdup("%m%# "); prompt2 = ztrdup("%_> "); } else { prompt = ztrdup(""); prompt2 = ztrdup(""); } prompt3 = ztrdup("?# "); prompt4 = ztrdup("+ "); sprompt = ztrdup("zsh: correct '%R' to '%r' [nyae]? "); ifs = ztrdup(DEFAULT_IFS); wordchars = ztrdup(DEFAULT_WORDCHARS); postedit = ztrdup(""); underscore = ztrdup(""); zoptarg = ztrdup(""); zoptind = 1; schedcmds = NULL; ppid = (long) getppid(); mypid = (long) getpid(); term = ztrdup(""); #ifdef TIOCGWINSZ if (!(columns = shttyinfo.winsize.ws_col)) columns = 80; if (columns < 2) opts[USEZLE] = 0; if (!(lines = shttyinfo.winsize.ws_row)) lines = 24; if (lines < 2) opts[SINGLELINEZLE] = 1; #else columns = 80; lines = 24; #endif /* The following variable assignments cause zsh to behave more * * like Bourne and Korn shells when invoked as "sh" or "ksh". * * NULLCMD=":" and READNULLCMD=":" */ if (emulation == EMULATE_KSH || emulation == EMULATE_SH) { nullcmd = ztrdup(":"); readnullcmd = ztrdup(":"); } else { nullcmd = ztrdup("cat"); readnullcmd = ztrdup("more"); } /* We cache the uid so we know when to * * recheck the info for `USERNAME' */ cached_uid = getuid(); /* Get password entry and set info for `HOME' and `USERNAME' */ if ((pswd = getpwuid(cached_uid))) { home = metafy(pswd->pw_dir, -1, META_DUP); cached_username = ztrdup(pswd->pw_name); } else { home = ztrdup("/"); cached_username = ztrdup(""); } /* Try a cheap test to see if we can * * initialize `PWD' from `HOME' */ if (ispwd(home)) pwd = ztrdup(home); else if ((ptr = zgetenv("PWD")) && ispwd(ptr)) pwd = ztrdup(ptr); else pwd = metafy(zgetcwd(), -1, META_REALLOC); oldpwd = ztrdup(pwd); /* initialize `OLDPWD' = `PWD' */ #ifdef __EMX__ *cdrive = _getdrive(); strcat(cdrive+1,":"); #endif inittyptab(); /* initialize the ztypes table */ initlextabs(); /* initialize lexing tables */ createreswdtable(); /* create hash table for reserved words */ createaliastable(); /* create hash table for aliases */ createcmdnamtable(); /* create hash table for external commands */ createshfunctable(); /* create hash table for shell functions */ createbuiltintable(); /* create hash table for builtin commands */ createnameddirtable(); /* create hash table for named directories */ createparamtable(); /* create paramater hash table */ #ifdef ZLE_MODULE add_dep("compctl", "zle"); addbuiltin("bindkey", 0, NULL, 0, -1, "zle"); addbuiltin("vared", 0, NULL, 1, 7, "zle"); addbuiltin("compctl", 0, NULL, 0, -1, "compctl"); #endif #ifdef HAVE_GETRLIMIT for (i = 0; i != RLIM_NLIMITS; i++) { getrlimit(i, current_limits + i); limits[i] = current_limits[i]; } #endif breaks = loops = 0; lastmailcheck = time(NULL); locallist = NULL; locallevel = sourcelevel = 0; trapreturn = 0; noerrexit = 0; nohistsave = 1; dirstack = newlinklist(); bufstack = newlinklist(); hsubl = hsubr = NULL; lastpid = 0; bshin = SHIN ? fdopen(SHIN, "r") : stdin; if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) { #ifdef _IONBF setvbuf(stdin, NULL, _IONBF, 0); #else setlinebuf(stdin); #endif } times(&shtms); } /* Initialize signal handling */ /**/ void init_signals(void) { intr(); #ifndef QDEBUG signal_ignore(SIGQUIT); #endif install_handler(SIGHUP); install_handler(SIGCHLD); if (interact) { install_handler(SIGALRM); #ifdef SIGWINCH install_handler(SIGWINCH); #endif signal_ignore(SIGTERM); } if (jobbing) { long ttypgrp; #ifndef __EMX__ while ((ttypgrp = gettygrp()) != -1 && ttypgrp != mypgrp) kill(0, SIGTTIN); #endif if (ttypgrp == -1) { opts[MONITOR] = 0; } else { #ifndef __EMX__ signal_ignore(SIGTTOU); signal_ignore(SIGTSTP); signal_ignore(SIGTTIN); #endif signal_ignore(SIGPIPE); attachtty(mypgrp); } } if (islogin) { signal_setmask(signal_mask(0)); } else if (interact) { sigset_t set; sigemptyset(&set); sigaddset(&set, SIGINT); sigaddset(&set, SIGQUIT); signal_unblock(set); } }
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; }
mod_export char * zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp, int *outcsp, int useheap) { int outcs, outll, sub; struct region_highlight *rhp; #ifdef MULTIBYTE_SUPPORT char *s; int i, j; size_t mb_len = 0; mbstate_t mbs; s = zalloc(inll * MB_CUR_MAX + 1); outcs = 0; memset(&mbs, 0, sizeof(mbs)); for (i=0; i < inll; i++) { if (incs == 0) outcs = mb_len; incs--; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (rhp->start - sub == 0) rhp->start_meta = sub + mb_len; rhp->start--; if (rhp->end - sub == 0) rhp->end_meta = sub + mb_len; rhp->end--; } } #ifdef __STDC_ISO_10646__ if (ZSH_INVALID_WCHAR_TEST(instr[i])) { s[mb_len++] = ZSH_INVALID_WCHAR_TO_CHAR(instr[i]); } else #endif { j = wcrtomb(s + mb_len, instr[i], &mbs); if (j == -1) { /* invalid char */ s[mb_len++] = ZWC('?'); memset(&mbs, 0, sizeof(mbs)); } else { mb_len += j; } } } if (incs == 0) outcs = mb_len; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (rhp->start - sub == 0) rhp->start_meta = sub + mb_len; if (rhp->end - sub == 0) rhp->end_meta = sub + mb_len; } } s[mb_len] = '\0'; outll = mb_len; #else outll = inll; outcs = incs; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { rhp->start_meta = rhp->start; rhp->end_meta = rhp->end; } } #endif /* * *outcsp and *outllp are to be indexes into the final string, * not character offsets, so we need to take account of any * metafiable characters. */ if (outcsp != NULL || outllp != NULL) { #ifdef MULTIBYTE_SUPPORT char *strp = s; #else char *strp = instr; #endif char *stopcs = strp + outcs; char *stopll = strp + outll; char *startp = strp; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { /* Used as temporary storage */ rhp->start = rhp->start_meta; rhp->end = rhp->end_meta; } } while (strp < stopll) { if (imeta(*strp)) { if (strp < stopcs) outcs++; if (region_highlights && outcsp == &zlemetacs) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; rhp < region_highlights + n_region_highlights; rhp++) { if (rhp->flags & ZRH_PREDISPLAY) sub = predisplaylen; else sub = 0; if (strp < startp + rhp->start - sub) { rhp->start_meta++; } if (strp < startp + rhp->end - sub) { rhp->end_meta++; } } } outll++; } strp++; } if (outcsp != NULL) *outcsp = outcs; if (outllp != NULL) *outllp = outll; } #ifdef MULTIBYTE_SUPPORT if (useheap) { char *ret = metafy(s, mb_len, META_HEAPDUP); zfree(s, inll * MB_CUR_MAX + 1); return ret; } return metafy(s, mb_len, META_REALLOC); #else return metafy(instr, inll, useheap ? META_HEAPDUP : META_DUP); #endif }
int main(int argc, char **argv) { char **t; int t0; #ifdef USE_LOCALE setlocale(LC_ALL, ""); #endif #ifdef WINNT /* Do not use __try if compiling with MinGW */ #ifndef MINGW __try { #endif /* MINGW */ /* Start NT if we are compiling with MinGW, don't otherwise */ #ifdef MINGW nt_init(); #else //nt_init(); #endif /* MINGW */ fork_init(); /* Do not use __except if compiling with MinGW */ #ifndef MINGW }__except(1) { dprintf("damn 0x%08x\n",GetExceptionCode()); return 1; }; #endif /* MINGW */ #endif /* WINNT */ global_permalloc(); /* * Provisionally set up the type table to allow metafication. * This will be done properly when we have decided if we are * interactive */ typtab['\0'] |= IMETA; typtab[STOUC(Meta) ] |= IMETA; typtab[STOUC(Marker)] |= IMETA; for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++) typtab[t0] |= ITOK | IMETA; for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++); #ifndef WINNT if (!(zsh_name = strrchr(argv[0], '/'))) #else if (!(zsh_name = strrchr(argv[0], '/')) && !(zsh_name = strrchr(argv[0], '\\')) && !(zsh_name = strchr(argv[0],':')) // !(argv[0][1] ==':') ) #endif /* WINNT */ zsh_name = argv[0]; else zsh_name++; if (*zsh_name == '-') zsh_name++; fdtable_size = OPEN_MAX; fdtable = zcalloc(fdtable_size); emulate(zsh_name, 1); /* initialises most options */ opts[LOGINSHELL] = (**argv == '-'); opts[MONITOR] = 1; /* may be unset in init_io() */ opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid()); opts[USEZLE] = 1; /* may be unset in init_io() */ parseargs(argv); /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */ SHTTY = -1; init_io(); setupvals(); init_signals(); global_heapalloc(); run_init_scripts(); init_misc(); for (;;) { do loop(1,0); while (tok != ENDINPUT); if (!(isset(IGNOREEOF) && interact)) { #if 0 if (interact) fputs(islogin ? "logout\n" : "exit\n", shout); #endif zexit(lastval, 0); continue; } noexitct++; if (noexitct >= 10) { stopmsg = 1; zexit(lastval, 0); } zerrnam("zsh", (!islogin) ? "use 'exit' to exit." : "use 'logout' to logout.", NULL, 0); } return 0; /* WINNT change, patch I think */ }