int argumentbase(char **args) { int multbase; if (*args) multbase = (int)zstrtol(*args, NULL, 0); else multbase = zmod.mult; if (multbase < 2 || multbase > ('9' - '0' + 1) + ('z' - 'a' + 1)) return 1; zmod.base = multbase; /* reset modifier, apart from base... */ zmod.flags = 0; zmod.mult = 1; zmod.tmult = 1; zmod.vibuf = 0; /* ...but indicate we are still operating on a prefix argument. */ prefixflag = 1; return 0; }
static rlim_t zstrtorlimt(const char *s, char **t, int base) { rlim_t ret = 0; if (strcmp(s, "unlimited") == 0) { if (t) *t = (char *) s + 9; return RLIM_INFINITY; } # if defined(RLIM_T_IS_QUAD_T) || defined(RLIM_T_IS_LONG_LONG) || defined(RLIM_T_IS_UNSIGNED) if (!base) { if (*s != '0') base = 10; else if (*++s == 'x' || *s == 'X') base = 16, s++; else base = 8; } if (base <= 10) for (; *s >= '0' && *s < ('0' + base); s++) ret = ret * base + *s - '0'; else for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10)) || (*s >= 'A' && *s < ('A' + base - 10)); s++) ret = ret * base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9); if (t) *t = (char *)s; # else /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_LONG_LONG && !RLIM_T_IS_UNSIGNED */ ret = zstrtol(s, t, base); # endif /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_LONG_LONG && !RLIM_T_IS_UNSIGNED */ return ret; }
mod_export int match_colour(const char **teststrp, int is_fg, int colour) { int shft, on, named = 0, tc; if (teststrp) { if ((named = ialpha(**teststrp))) { colour = match_named_colour(teststrp); if (colour == 8) { /* default */ return is_fg ? TXTNOFGCOLOUR : TXTNOBGCOLOUR; } } else colour = (int)zstrtol(*teststrp, (char **)teststrp, 10); } if (colour < 0 || colour >= 256) return -1; if (is_fg) { shft = TXT_ATTR_FG_COL_SHIFT; on = TXTFGCOLOUR; tc = TCFGCOLOUR; } else { shft = TXT_ATTR_BG_COL_SHIFT; on = TXTBGCOLOUR; tc = TCBGCOLOUR; } /* * Try termcap for numbered characters if posible. * Don't for named characters, since our best bet * of getting the names right is with ANSI sequences. */ if (!named && tccan(tc)) { if (tccolours >= 0 && colour >= tccolours) { /* * Out of range of termcap colours. * Can we assume ANSI colours work? */ if (colour > 7) return -1; /* No. */ } else { /* * We can handle termcap colours and the number * is in range, so use termcap. */ on |= is_fg ? TXT_ATTR_FG_TERMCAP : TXT_ATTR_BG_TERMCAP; } } return on | (colour << shft); }
static int getposint(char *instr, char *nam) { char *eptr; int ret; ret = (int)zstrtol(instr, &eptr, 10); if (*eptr || ret < 0) { zwarnnam(nam, "integer expected: %s", instr); return -1; } return ret; }
static int bin_mkdir(char *nam, char **args, Options ops, UNUSED(int func)) { mode_t oumask = umask(0); mode_t mode = 0777 & ~oumask; int err = 0; umask(oumask); if(OPT_ISSET(ops,'m')) { char *str = OPT_ARG(ops,'m'), *ptr; mode = zstrtol(str, &ptr, 8); if(!*str || *ptr) { zwarnnam(nam, "invalid mode `%s'", str); return 1; } } for(; *args; args++) { char *ptr = strchr(*args, 0); while(ptr > *args + (**args == '/') && *--ptr == '/') *ptr = 0; if(OPT_ISSET(ops,'p')) { char *ptr = *args; for(;;) { while(*ptr == '/') ptr++; while(*ptr && *ptr != '/') ptr++; if(!*ptr) { err |= domkdir(nam, *args, mode, 1); break; } else { int e; *ptr = 0; e = domkdir(nam, *args, mode | 0300, 1); if(e) { err = 1; break; } *ptr = '/'; } } } else err |= domkdir(nam, *args, mode, 0); } return err; }
/* * Handle an fd by adding it to the current fd_set. * Return 1 for error (after printing a message), 0 for OK. */ static int handle_digits(char *nam, char *argptr, fd_set *fdset, int *fdmax) { int fd; char *endptr; if (!idigit(*argptr)) { zwarnnam(nam, "expecting file descriptor: %s", argptr); return 1; } fd = (int)zstrtol(argptr, &endptr, 10); if (*endptr) { zwarnnam(nam, "garbage after file descriptor: %s", endptr); return 1; } FD_SET(fd, fdset); if (fd+1 > *fdmax) *fdmax = fd+1; return 0; }
int undo(char **args) { zlong last_change = (zlong)0; if (*args) { last_change = zstrtol(*args, NULL, 0); } handleundo(); do { if(!curchange->prev) return 1; if (unapplychange(curchange->prev)) curchange = curchange->prev; else break; } while (*args ? curchange->changeno != last_change : (curchange->flags & CH_PREV)); setlastline(); return 0; }
static int bin_zselect(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { #ifdef HAVE_SELECT int i, fd, fdsetind = 0, fdmax = 0, fdcount; fd_set fdset[3]; const char fdchar[3] = "rwe"; struct timeval tv, *tvptr = NULL; char *outarray = "reply", **outdata, **outptr; char *outhash = NULL; LinkList fdlist; for (i = 0; i < 3; i++) FD_ZERO(fdset+i); for (; *args; args++) { char *argptr = *args, *endptr; zlong tempnum; if (*argptr == '-') { for (argptr++; *argptr; argptr++) { switch (*argptr) { /* * Array name for reply, if not $reply. * This gets set to e.g. `-r 0 -w 1' if 0 is ready * for reading and 1 is ready for writing. */ case 'a': case 'A': i = *argptr; if (argptr[1]) argptr++; else if (args[1]) { argptr = *++args; } else { zwarnnam(nam, "argument expected after -%c", *argptr); return 1; } if (idigit(*argptr) || !isident(argptr)) { zwarnnam(nam, "invalid array name: %s", argptr); return 1; } if (i == 'a') outarray = argptr; else outhash = argptr; /* set argptr to next to last char because of increment */ while (argptr[1]) argptr++; break; /* Following numbers indicate fd's for reading */ case 'r': fdsetind = 0; break; /* Following numbers indicate fd's for writing */ case 'w': fdsetind = 1; break; /* Following numbers indicate fd's for errors */ case 'e': fdsetind = 2; break; /* * Get a timeout value in hundredths of a second * (same units as KEYTIMEOUT). 0 means just poll. * If not given, blocks indefinitely. */ case 't': if (argptr[1]) argptr++; else if (args[1]) { argptr = *++args; } else { zwarnnam(nam, "argument expected after -%c", *argptr); return 1; } if (!idigit(*argptr)) { zwarnnam(nam, "number expected after -t"); return 1; } tempnum = zstrtol(argptr, &endptr, 10); if (*endptr) { zwarnnam(nam, "garbage after -t argument: %s", endptr); return 1; } /* timevalue now active */ tvptr = &tv; tv.tv_sec = (long)(tempnum / 100); tv.tv_usec = (long)(tempnum % 100) * 10000L; /* remember argptr is incremented at end of loop */ argptr = endptr - 1; break; /* Digits following option without arguments are fd's. */ default: if (handle_digits(nam, argptr, fdset+fdsetind, &fdmax)) return 1; } } } else if (handle_digits(nam, argptr, fdset+fdsetind, &fdmax)) return 1; } errno = 0; do { i = select(fdmax, (SELECT_ARG_2_T)fdset, (SELECT_ARG_2_T)(fdset+1), (SELECT_ARG_2_T)(fdset+2), tvptr); } while (i < 0 && errno == EINTR && !errflag); if (i <= 0) { if (i < 0) zwarnnam(nam, "error on select: %e", errno); /* else no fd's set. Presumably a timeout. */ return 1; } /* * Make a linked list of all file descriptors which are ready. * These go into an array preceded by -r, -w or -e for read, write, * error as appropriate. Typically there will only be one set * so this looks rather like overkill. */ fdlist = znewlinklist(); for (i = 0; i < 3; i++) { int doneit = 0; for (fd = 0; fd < fdmax; fd++) { if (FD_ISSET(fd, fdset+i)) { char buf[BDIGBUFSIZE]; if (outhash) { /* * Key/value pairs; keys are fd's (as strings), * value is a (possibly improper) subset of "rwe". */ LinkNode nptr; int found = 0; convbase(buf, fd, 10); for (nptr = firstnode(fdlist); nptr; nptr = nextnode(nextnode(nptr))) { if (!strcmp((char *)getdata(nptr), buf)) { /* Already there, add new character. */ void **dataptr = getaddrdata(nextnode(nptr)); char *data = (char *)*dataptr, *ptr; found = 1; if (!strchr(data, fdchar[i])) { strcpy(buf, data); for (ptr = buf; *ptr; ptr++) ; *ptr++ = fdchar[i]; *ptr = '\0'; zsfree(data); *dataptr = ztrdup(buf); } break; } } if (!found) { /* Add new key/value pair. */ zaddlinknode(fdlist, ztrdup(buf)); buf[0] = fdchar[i]; buf[1] = '\0'; zaddlinknode(fdlist, ztrdup(buf)); } } else { /* List of fd's preceded by -r, -w, -e. */ if (!doneit) { buf[0] = '-'; buf[1] = fdchar[i]; buf[2] = 0; zaddlinknode(fdlist, ztrdup(buf)); doneit = 1; } convbase(buf, fd, 10); zaddlinknode(fdlist, ztrdup(buf)); } } } } /* convert list to array */ fdcount = countlinknodes(fdlist); outptr = outdata = (char **)zalloc((fdcount+1)*sizeof(char *)); while (nonempty(fdlist)) *outptr++ = getlinknode(fdlist); *outptr = NULL; /* and store in array parameter */ if (outhash) sethparam(outhash, outdata); else setaparam(outarray, outdata); freelinklist(fdlist, NULL); return 0; #else /* TODO: use poll */ zerrnam(nam, "your system does not implement the select system call."); return 2; #endif }
int evalcond(Estate state, char *fromtest) { struct stat *st; char *left, *right, *overridename, overridebuf[13]; Wordcode pcode; wordcode code; int ctype, htok = 0, ret; rec: left = right = overridename = NULL; pcode = state->pc++; code = *pcode; ctype = WC_COND_TYPE(code); switch (ctype) { case COND_NOT: if (tracingcond) fprintf(xtrerr, " %s", condstr[ctype]); ret = evalcond(state, fromtest); if (ret == 2) return ret; else return !ret; case COND_AND: if (!(ret = evalcond(state, fromtest))) { if (tracingcond) fprintf(xtrerr, " %s", condstr[ctype]); goto rec; } else { state->pc = pcode + (WC_COND_SKIP(code) + 1); return ret; } case COND_OR: if ((ret = evalcond(state, fromtest)) == 1) { if (tracingcond) fprintf(xtrerr, " %s", condstr[ctype]); goto rec; } else { state->pc = pcode + (WC_COND_SKIP(code) + 1); return ret; } case COND_REGEX: { char *modname = isset(REMATCHPCRE) ? "zsh/pcre" : "zsh/regex"; sprintf(overridename = overridebuf, "-%s-match", modname+4); (void)ensurefeature(modname, "C:", overridename+1); ctype = COND_MODI; } /*FALLTHROUGH*/ case COND_MOD: case COND_MODI: { Conddef cd; char *name = overridename, *errname; char **strs; int l = WC_COND_SKIP(code); if (name == NULL) name = ecgetstr(state, EC_NODUP, NULL); if (ctype == COND_MOD) strs = ecgetarr(state, l, EC_DUP, NULL); else { char *sbuf[3]; sbuf[0] = ecgetstr(state, EC_NODUP, NULL); sbuf[1] = ecgetstr(state, EC_NODUP, NULL); sbuf[2] = NULL; strs = arrdup(sbuf); l = 2; } if (name && name[0] == '-') errname = name; else if (strs[0] && *strs[0] == '-') errname = strs[0]; else errname = "<null>"; if (name && name[0] == '-' && (cd = getconddef((ctype == COND_MODI), name + 1, 1))) { if (ctype == COND_MOD && (l < cd->min || (cd->max >= 0 && l > cd->max))) { zwarnnam(fromtest, "unknown condition: %s", name); return 2; } if (tracingcond) tracemodcond(name, strs, ctype == COND_MODI); return !cd->handler(strs, cd->condid); } else { char *s = strs[0]; if (overridename) { /* * Standard regex function not available: this * is a hard error. */ zerrnam(fromtest, "%s not available for regex", overridename); return 2; } strs[0] = dupstring(name); name = s; if (name && name[0] == '-' && (cd = getconddef(0, name + 1, 1))) { if (l < cd->min || (cd->max >= 0 && l > cd->max)) { zwarnnam(fromtest, "unknown condition: %s", errname); return 2; } if (tracingcond) tracemodcond(name, strs, ctype == COND_MODI); return !cd->handler(strs, cd->condid); } else { zwarnnam(fromtest, "unknown condition: %s", errname); } } /* module not found, error */ return 2; } } left = ecgetstr(state, EC_DUPTOK, &htok); if (htok) { cond_subst(&left, !fromtest); untokenize(left); } if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRNEQ) { right = ecgetstr(state, EC_DUPTOK, &htok); if (htok) { cond_subst(&right, !fromtest); untokenize(right); } } if (tracingcond) { if (ctype < COND_MOD) { fputc(' ',xtrerr); quotedzputs(left, xtrerr); fprintf(xtrerr, " %s ", condstr[ctype]); if (ctype == COND_STREQ || ctype == COND_STRNEQ) { char *rt = dupstring(ecrawstr(state->prog, state->pc, NULL)); cond_subst(&rt, !fromtest); quote_tokenized_output(rt, xtrerr); } else quotedzputs((char *)right, xtrerr); } else { fprintf(xtrerr, " -%c ", ctype); quotedzputs(left, xtrerr); } } if (ctype >= COND_EQ && ctype <= COND_GE) { mnumber mn1, mn2; if (fromtest) { /* * For test and [, the expressions must be base 10 integers, * not integer expressions. */ char *eptr, *err; mn1.u.l = zstrtol(left, &eptr, 10); if (!*eptr) { mn2.u.l = zstrtol(right, &eptr, 10); err = right; } else err = left; if (*eptr) { zwarnnam(fromtest, "integer expression expected: %s", err); return 2; } mn1.type = mn2.type = MN_INTEGER; } else { mn1 = matheval(left); mn2 = matheval(right); } if (((mn1.type|mn2.type) & (MN_INTEGER|MN_FLOAT)) == (MN_INTEGER|MN_FLOAT)) { /* promote to float */ if (mn1.type & MN_INTEGER) { mn1.type = MN_FLOAT; mn1.u.d = (double)mn1.u.l; } if (mn2.type & MN_INTEGER) { mn2.type = MN_FLOAT; mn2.u.d = (double)mn2.u.l; } } switch(ctype) { case COND_EQ: return !((mn1.type & MN_FLOAT) ? (mn1.u.d == mn2.u.d) : (mn1.u.l == mn2.u.l)); case COND_NE: return !((mn1.type & MN_FLOAT) ? (mn1.u.d != mn2.u.d) : (mn1.u.l != mn2.u.l)); case COND_LT: return !((mn1.type & MN_FLOAT) ? (mn1.u.d < mn2.u.d) : (mn1.u.l < mn2.u.l)); case COND_GT: return !((mn1.type & MN_FLOAT) ? (mn1.u.d > mn2.u.d) : (mn1.u.l > mn2.u.l)); case COND_LE: return !((mn1.type & MN_FLOAT) ? (mn1.u.d <= mn2.u.d) : (mn1.u.l <= mn2.u.l)); case COND_GE: return !((mn1.type & MN_FLOAT) ? (mn1.u.d >= mn2.u.d) : (mn1.u.l >= mn2.u.l)); } } switch (ctype) { case COND_STREQ: case COND_STRNEQ: { int test, npat = state->pc[1]; Patprog pprog = state->prog->pats[npat]; if (pprog == dummy_patprog1 || pprog == dummy_patprog2) { char *opat; int save; right = dupstring(opat = ecrawstr(state->prog, state->pc, &htok)); singsub(&right); save = (!(state->prog->flags & EF_HEAP) && !strcmp(opat, right) && pprog != dummy_patprog2); if (!(pprog = patcompile(right, (save ? PAT_ZDUP : PAT_STATIC), NULL))) { zwarnnam(fromtest, "bad pattern: %s", right); return 2; } else if (save) state->prog->pats[npat] = pprog; } state->pc += 2; test = (pprog && pattry(pprog, left)); return !(ctype == COND_STREQ ? test : !test); } case COND_STRLT: return !(strcmp(left, right) < 0); case COND_STRGTR: return !(strcmp(left, right) > 0); case 'e': case 'a': return (!doaccess(left, F_OK)); case 'b': return (!S_ISBLK(dostat(left))); case 'c': return (!S_ISCHR(dostat(left))); case 'd': return (!S_ISDIR(dostat(left))); case 'f': return (!S_ISREG(dostat(left))); case 'g': return (!(dostat(left) & S_ISGID)); case 'k': return (!(dostat(left) & S_ISVTX)); case 'n': return (!strlen(left)); case 'o': return (optison(fromtest, left)); case 'p': return (!S_ISFIFO(dostat(left))); case 'r': return (!doaccess(left, R_OK)); case 's': return !((st = getstat(left)) && !!(st->st_size)); case 'S': return (!S_ISSOCK(dostat(left))); case 'u': return (!(dostat(left) & S_ISUID)); case 'w': return (!doaccess(left, W_OK)); case 'x': if (privasserted()) { mode_t mode = dostat(left); return !((mode & S_IXUGO) || S_ISDIR(mode)); } return !doaccess(left, X_OK); case 'z': return !!(strlen(left)); case 'h': case 'L': return (!S_ISLNK(dolstat(left))); case 'O': return !((st = getstat(left)) && st->st_uid == geteuid()); case 'G': return !((st = getstat(left)) && st->st_gid == getegid()); case 'N': #if defined(GET_ST_MTIME_NSEC) && defined(GET_ST_ATIME_NSEC) if (!(st = getstat(left))) return 1; return (st->st_atime == st->st_mtime) ? GET_ST_ATIME_NSEC(*st) > GET_ST_MTIME_NSEC(*st) : st->st_atime > st->st_mtime; #else return !((st = getstat(left)) && st->st_atime <= st->st_mtime); #endif case 't': return !isatty(mathevali(left)); case COND_NT: case COND_OT: { time_t a; #ifdef GET_ST_MTIME_NSEC long nsecs; #endif if (!(st = getstat(left))) return 1; a = st->st_mtime; #ifdef GET_ST_MTIME_NSEC nsecs = GET_ST_MTIME_NSEC(*st); #endif if (!(st = getstat(right))) return 1; #ifdef GET_ST_MTIME_NSEC if (a == st->st_mtime) { return !((ctype == COND_NT) ? nsecs > GET_ST_MTIME_NSEC(*st) : nsecs < GET_ST_MTIME_NSEC(*st)); } #endif return !((ctype == COND_NT) ? a > st->st_mtime : a < st->st_mtime); } case COND_EF: { dev_t d; ino_t i; if (!(st = getstat(left))) return 1; d = st->st_dev; i = st->st_ino; if (!(st = getstat(right))) return 1; return !(d == st->st_dev && i == st->st_ino); } default: zwarnnam(fromtest, "bad cond code"); return 2; } }
static int zzlex(void) { int cct = 0; char *ie; yyval.type = MN_INTEGER; for (;; cct = 0) switch (*ptr++) { case '+': if (*ptr == '+') { ptr++; return (unary) ? PREPLUS : POSTPLUS; } if (*ptr == '=') { ptr++; return PLUSEQ; } return (unary) ? UPLUS : PLUS; case '-': if (*ptr == '-') { ptr++; return (unary) ? PREMINUS : POSTMINUS; } if (*ptr == '=') { ptr++; return MINUSEQ; } if (unary) { if (idigit(*ptr) || *ptr == '.') { ptr--; return lexconstant(); } else return UMINUS; } else return MINUS; case '(': return M_INPAR; case ')': return M_OUTPAR; case '!': if (*ptr == '=') { ptr++; return NEQ; } return NOT; case '~': return COMP; case '&': if (*ptr == '&') { if (*++ptr == '=') { ptr++; return DANDEQ; } return DAND; } else if (*ptr == '=') { ptr++; return ANDEQ; } return AND; case '|': if (*ptr == '|') { if (*++ptr == '=') { ptr++; return DOREQ; } return DOR; } else if (*ptr == '=') { ptr++; return OREQ; } return OR; case '^': if (*ptr == '^') { if (*++ptr == '=') { ptr++; return DXOREQ; } return DXOR; } else if (*ptr == '=') { ptr++; return XOREQ; } return XOR; case '*': if (*ptr == '*') { if (*++ptr == '=') { ptr++; return POWEREQ; } return POWER; } if (*ptr == '=') { ptr++; return MULEQ; } return MUL; case '/': if (*ptr == '=') { ptr++; return DIVEQ; } return DIV; case '%': if (*ptr == '=') { ptr++; return MODEQ; } return MOD; case '<': if (*ptr == '<') { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; } else if (*ptr == '=') { ptr++; return LEQ; } return LES; case '>': if (*ptr == '>') { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; } else if (*ptr == '=') { ptr++; return GEQ; } return GRE; case '=': if (*ptr == '=') { ptr++; return DEQ; } return EQ; case '$': yyval.u.l = mypid; return NUM; case '?': if (unary) { yyval.u.l = lastval; return NUM; } return QUEST; case ':': return COLON; case ',': return COMMA; case '\0': ptr--; return EOI; case '[': { int n, checkradix = 0; if (idigit(*ptr)) { n = zstrtol(ptr, &ptr, 10); if (*ptr != ']' || !idigit(*++ptr)) { zerr("bad base syntax"); return EOI; } yyval.u.l = zstrtol(ptr, &ptr, lastbase = n); return NUM; } if (*ptr == '#') { n = 1; if (*++ptr == '#') { n = -1; ptr++; } if (!idigit(*ptr) && *ptr != '_') goto bofs; if (idigit(*ptr)) { outputradix = n * zstrtol(ptr, &ptr, 10); checkradix = 1; } if (*ptr == '_') { ptr++; if (idigit(*ptr)) outputunderscore = zstrtol(ptr, &ptr, 10); else outputunderscore = 3; } } else { bofs: zerr("bad output format specification"); return EOI; } if(*ptr != ']') goto bofs; if (checkradix) { n = (outputradix < 0) ? -outputradix : outputradix; if (n < 2 || n > 36) { zerr("invalid base (must be 2 to 36 inclusive): %d", outputradix); return EOI; } } ptr++; break; } case ' ': case '\t': case '\n': break; /* Fall through! */ default: if (idigit(*--ptr) || *ptr == '.') return lexconstant(); if (*ptr == '#') { if (*++ptr == '\\' || *ptr == '#') { int v; ptr++; if (!*ptr) { zerr("character missing after ##"); return EOI; } ptr = getkeystring(ptr, NULL, GETKEYS_MATH, &v); yyval.u.l = v; return NUM; } cct = 1; } if ((ie = itype_end(ptr, IIDENT, 0)) != ptr) { int func = 0; char *p; p = ptr; ptr = ie; if (*ptr == '[' || (!cct && *ptr == '(')) { char op = *ptr, cp = ((*ptr == '[') ? ']' : ')'); int l; func = (op == '('); for (ptr++, l = 1; *ptr && l; ptr++) { if (*ptr == op) l++; if (*ptr == cp) l--; if (*ptr == '\\' && ptr[1]) ptr++; } } yylval = dupstrpfx(p, ptr - p); return (func ? FUNC : (cct ? CID : ID)); } else if (cct) { yyval.u.l = poundgetfn(NULL); return NUM; } return EOI; } }
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; }
static int bin_sched(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) { char *s, **argptr; time_t t; long h, m, sec; struct tm *tm; struct schedcmd *sch, *sch2, *schl; int sn, flags = 0; /* If the argument begins with a -, remove the specified item from the schedule. */ for (argptr = argv; *argptr && **argptr == '-'; argptr++) { char *arg = *argptr + 1; if (idigit(*arg)) { sn = atoi(arg); if (!sn) { zwarnnam("sched", "usage for delete: sched -<item#>."); return 1; } for (schl = NULL, sch = schedcmds, sn--; sch && sn; sch = (schl = sch)->next, sn--); if (!sch) { zwarnnam("sched", "not that many entries"); return 1; } if (schl) schl->next = sch->next; else { scheddeltimed(); schedcmds = sch->next; if (schedcmds) { DPUTS(timedfns && firstnode(timedfns), "BUG: already timed fn (2)"); schedaddtimed(schedcmds->time); } } zsfree(sch->cmd); zfree(sch, sizeof(struct schedcmd)); return 0; } else if (*arg == '-') { /* end of options */ argptr++; break; } else if (!strcmp(arg, "o")) { flags |= SCHEDFLAG_TRASH_ZLE; } else { if (*arg) zwarnnam(nam, "bad option: -%c", *arg); else zwarnnam(nam, "option expected"); return 1; } } /* given no arguments, display the schedule list */ if (!*argptr) { for (sn = 1, sch = schedcmds; sch; sch = sch->next, sn++) { char tbuf[60], *flagstr, *endstr; time_t t; struct tm *tmp; t = sch->time; tmp = localtime(&t); ztrftime(tbuf, 40, "%a %b %e %k:%M:%S", tmp, 0L); if (sch->flags & SCHEDFLAG_TRASH_ZLE) flagstr = "-o "; else flagstr = ""; if (*sch->cmd == '-') endstr = "-- "; else endstr = ""; printf("%3d %s %s%s%s\n", sn, tbuf, flagstr, endstr, sch->cmd); } return 0; } else if (!argptr[1]) { /* other than the two cases above, sched * *requires at least two arguments */ zwarnnam("sched", "not enough arguments"); return 1; } /* The first argument specifies the time to schedule the command for. The remaining arguments form the command. */ s = *argptr++; if (*s == '+') { /* * + introduces a relative time. The rest of the argument may be an * hour:minute offset from the current time. Once the hour and minute * numbers have been extracted, and the format verified, the resulting * offset is simply added to the current time. */ zlong zl = zstrtol(s + 1, &s, 10); if (*s == ':') { m = (long)zstrtol(s + 1, &s, 10); if (*s == ':') sec = (long)zstrtol(s + 1, &s, 10); else sec = 0; if (*s) { zwarnnam("sched", "bad time specifier"); return 1; } t = time(NULL) + (long)zl * 3600 + m * 60 + sec; } else if (!*s) { /* * Alternatively, it may simply be a number of seconds. * This is here for consistency with absolute times. */ t = time(NULL) + (time_t)zl; } else { zwarnnam("sched", "bad time specifier"); return 1; } } else { /* * If there is no +, an absolute time must have been given. * This may be in hour:minute format, optionally followed by a string * starting with `a' or `p' (for a.m. or p.m.). Characters after the * `a' or `p' are ignored. */ zlong zl = zstrtol(s, &s, 10); if (*s == ':') { h = (long)zl; m = (long)zstrtol(s + 1, &s, 10); if (*s == ':') sec = (long)zstrtol(s + 1, &s, 10); else sec = 0; if (*s && *s != 'a' && *s != 'A' && *s != 'p' && *s != 'P') { zwarnnam("sched", "bad time specifier"); return 1; } t = time(NULL); tm = localtime(&t); t -= tm->tm_sec + tm->tm_min * 60 + tm->tm_hour * 3600; if (*s == 'p' || *s == 'P') h += 12; t += h * 3600 + m * 60 + sec; /* * If the specified time is before the current time, it must refer * to tomorrow. */ if (t < time(NULL)) t += 3600 * 24; } else if (!*s) { /* * Otherwise, it must be a raw time specifier. */ t = (long)zl; } else { zwarnnam("sched", "bad time specifier"); return 1; } } /* The time has been calculated; now add the new entry to the linked list of scheduled commands. */ sch = (struct schedcmd *) zalloc(sizeof *sch); sch->time = t; sch->cmd = zjoin(argptr, ' ', 0); sch->flags = flags; /* Insert into list in time order */ if (schedcmds) { if (sch->time < schedcmds->time) { scheddeltimed(); sch->next = schedcmds; schedcmds = sch; DPUTS(timedfns && firstnode(timedfns), "BUG: already timed fn (3)"); schedaddtimed(t); } else { for (sch2 = schedcmds; sch2->next && sch2->next->time < sch->time; sch2 = sch2->next) ; sch->next = sch2->next; sch2->next = sch; } } else { sch->next = NULL; schedcmds = sch; DPUTS(timedfns && firstnode(timedfns), "BUG: already timed fn (4)"); schedaddtimed(t); } return 0; }
int filesubstr(char **namptr, int assign) { #define isend(c) ( !(c) || (c)=='/' || (c)==Inpar || (assign && (c)==':') ) #define isend2(c) ( !(c) || (c)==Inpar || (assign && (c)==':') ) char *str = *namptr; if (*str == Tilde && str[1] != '=' && str[1] != Equals) { char *ptr; int val; val = zstrtol(str + 1, &ptr, 10); if (isend(str[1])) { /* ~ */ *namptr = dyncat(home, str + 1); return 1; } else if (str[1] == '+' && isend(str[2])) { /* ~+ */ *namptr = dyncat(pwd, str + 2); return 1; } else if (str[1] == '-' && isend(str[2])) { /* ~- */ char *tmp; *namptr = dyncat((tmp = oldpwd) ? tmp : pwd, str + 2); return 1; } else if (!inblank(str[1]) && isend(*ptr) && (!idigit(str[1]) || (ptr - str < 4))) { char *ds; if (val < 0) val = -val; ds = dstackent(str[1], val); if (!ds) return 0; *namptr = dyncat(ds, ptr); return 1; } else if (iuser(str[1])) { /* ~foo */ char *ptr, *hom, save; for (ptr = ++str; *ptr && iuser(*ptr); ptr++); save = *ptr; if (!isend(save)) return 0; *ptr = 0; if (!(hom = getnameddir(str))) { if (isset(NOMATCH)) zerr("no such user or named directory: %s", str, 0); *ptr = save; return 0; } *ptr = save; *namptr = dyncat(hom, ptr); return 1; } } else if (*str == Equals && isset(EQUALS) && str[1]) { /* =foo */ char sav, *pp, *cnam; for (pp = str + 1; !isend2(*pp); pp++); sav = *pp; *pp = 0; if (!(cnam = findcmd(str + 1))) { Alias a = (Alias) aliastab->getnode(aliastab, str + 1); if (a) cnam = ztrdup(a->text); else { if (isset(NOMATCH)) zerr("%s not found", str + 1, 0); return 0; } } *namptr = dupstring(cnam); zsfree(cnam); if (sav) { *pp = sav; *namptr = dyncat(*namptr, pp); } return 1; } return 0; #undef isend #undef isend2 }
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 lexconstant(void) { #ifdef USE_LOCALE char *prev_locale; #endif char *nptr; nptr = ptr; if (*nptr == '-') nptr++; if (*nptr == '0') { nptr++; if (*nptr == 'x' || *nptr == 'X') { /* Let zstrtol parse number with base */ yyval.u.l = zstrtol(ptr, &ptr, 0); /* Should we set lastbase here? */ lastbase = 16; return NUM; } else if (isset(OCTALZEROES)) { char *ptr2; /* * Make sure this is a real octal constant; * it can't be a base indication (always decimal) * or a floating point number. */ for (ptr2 = nptr; idigit(*ptr2); ptr2++) ; if (ptr2 > nptr && *ptr2 != '.' && *ptr2 != 'e' && *ptr2 != 'E' && *ptr2 != '#') { yyval.u.l = zstrtol(ptr, &ptr, 0); lastbase = 8; return NUM; } nptr = ptr2; } } else { while (idigit(*nptr)) nptr++; } if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') { /* it's a float */ yyval.type = MN_FLOAT; #ifdef USE_LOCALE prev_locale = dupstring(setlocale(LC_NUMERIC, NULL)); setlocale(LC_NUMERIC, "POSIX"); #endif yyval.u.d = strtod(ptr, &nptr); #ifdef USE_LOCALE if (prev_locale) setlocale(LC_NUMERIC, prev_locale); #endif if (ptr == nptr || *nptr == '.') { zerr("bad floating point constant"); return EOI; } ptr = nptr; } else { /* it's an integer */ yyval.u.l = zstrtol(ptr, &ptr, 10); if (*ptr == '#') { ptr++; yyval.u.l = zstrtol(ptr, &ptr, lastbase = yyval.u.l); } } return NUM; }