From 912826aeb6986cfb9d82291f749a7b226fccfee8 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 30 Jan 2005 00:05:52 +0000 Subject: Patches from zsh-4.2.3-dev-1 that affect compilation or C code, excluding any of those that introduce UTF-8 support. --- Src/Builtins/rlimits.awk | 18 +- Src/Builtins/rlimits.c | 698 ++++++++++++++++++++++++++++++++--------------- Src/cond.c | 216 +++++++++------ 3 files changed, 628 insertions(+), 304 deletions(-) (limited to 'Src') diff --git a/Src/Builtins/rlimits.awk b/Src/Builtins/rlimits.awk index 5e48725e2..e1a06fe2b 100644 --- a/Src/Builtins/rlimits.awk +++ b/Src/Builtins/rlimits.awk @@ -6,7 +6,7 @@ # BEGIN {limidx = 0} -/^[\t ]*(#[\t ]*define[\t _]*RLIMIT_[A-Z_]*[\t ]*[0-9][0-9]*|RLIMIT_[A-Z_]*,[\t ]*)/ { +/^[\t ]*(#[\t ]*define[\t _]*RLIMIT_[A-Z_]*[\t ]*[0-9][0-9]*|RLIMIT_[A-Z_]*,[\t ]*|RLIMIT_[A-Z_]*[\t ]*=[\t ]*[0-9][0-9]*,[\t ]*)/ { limindex = index($0, "RLIMIT_") limtail = substr($0, limindex, 80) split(limtail, tmp) @@ -18,6 +18,11 @@ BEGIN {limidx = 0} limindex = index($0, ",") limnam = substr(limnam, 1, limindex-1) } + if (limnum == "=") { + limnum = limidx++ + limindex = index($0, ",") + limnam = substr(limnam, 1, limindex-1) + } limrev[limnam] = limnum if (lim[limnum] == "") { lim[limnum] = limnam @@ -29,6 +34,7 @@ BEGIN {limidx = 0} if (limnam == "CPU") { msg[limnum] = "Tcputime" } if (limnam == "DATA") { msg[limnum] = "Mdatasize" } if (limnam == "FSIZE") { msg[limnum] = "Mfilesize" } + if (limnam == "LOCKS") { msg[limnum] = "Nmaxfilelocks" } if (limnam == "MEMLOCK") { msg[limnum] = "Mmemorylocked" } if (limnam == "NOFILE") { msg[limnum] = "Ndescriptors" } if (limnam == "NPROC") { msg[limnum] = "Nmaxproc" } @@ -39,6 +45,8 @@ BEGIN {limidx = 0} if (limnam == "STACK") { msg[limnum] = "Mstacksize" } if (limnam == "TCACHE") { msg[limnum] = "Ncachedthreads" } if (limnam == "VMEM") { msg[limnum] = "Mvmemorysize" } + if (limnam == "SIGPENDING") { msg[limnum] = "Nsigpending" } + if (limnam == "MSGQUEUE") { msg[limnum] = "Nmsgqueue" } } } } @@ -50,7 +58,13 @@ BEGIN {limidx = 0} } # in case of GNU libc /^[\t ]*RLIM_NLIMITS[\t ]*=[\t ]*RLIMIT_NLIMITS/ { - nlimits = limidx + if(!nlimits) { nlimits = limidx } +} +/^[\t ]*RLIM(IT)?_NLIMITS[\t ]*=[\t ]*[0-9][0-9]*/ { + limindex = index($0, "=") + limtail = substr($0, limindex, 80) + split(limtail, tmp) + nlimits = tmp[2] } END { diff --git a/Src/Builtins/rlimits.c b/Src/Builtins/rlimits.c index f81ce2412..9256f25b2 100644 --- a/Src/Builtins/rlimits.c +++ b/Src/Builtins/rlimits.c @@ -44,12 +44,17 @@ enum { # include "rlimits.h" -# if defined(RLIM_T_IS_QUAD_T) || defined(RLIM_T_IS_LONG_LONG) || defined(RLIM_T_IS_UNSIGNED) 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; @@ -67,63 +72,114 @@ zstrtorlimt(const char *s, char **t, int base) ret = ret * base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9); if (t) *t = (char *)s; - return ret; -} # else /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_LONG_LONG && !RLIM_T_IS_UNSIGNED */ -# define zstrtorlimt(a, b, c) zstrtol((a), (b), (c)) + ret = zstrtol(s, t, base); # endif /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_LONG_LONG && !RLIM_T_IS_UNSIGNED */ - -/* Display resource limits. hard indicates whether `hard' or `soft' * - * limits should be displayed. lim specifies the limit, or may be -1 * - * to show all. */ + return ret; +} /**/ static void -showlimits(int hard, int lim) +showlimitvalue(int lim, rlim_t val) { - int rt; - rlim_t val; - - /* main loop over resource types */ - for (rt = 0; rt != ZSH_NLIMITS; rt++) - if (rt == lim || lim == -1) { - /* display limit for resource number rt */ - printf("%-16s", recs[rt]); - val = (hard) ? limits[rt].rlim_max : limits[rt].rlim_cur; - if (val == RLIM_INFINITY) - printf("unlimited\n"); - else if (limtype[rt] == ZLIMTYPE_TIME) { - /* time-type resource -- display as hours, minutes and - seconds. */ - printf("%d:%02d:%02d\n", (int)(val / 3600), - (int)(val / 60) % 60, (int)(val % 60)); - } else if (limtype[rt] == ZLIMTYPE_NUMBER || limtype[rt] == ZLIMTYPE_UNKNOWN) { - /* pure numeric resource */ - printf("%d\n", (int)val); - } else if (val >= 1024L * 1024L) - /* memory resource -- display with `K' or `M' modifier */ + /* display limit for resource number lim */ + if (lim < ZSH_NLIMITS) + printf("%-16s", recs[lim]); + else + { + /* Unknown limit, hence unknown units. */ + printf("%-16d", lim); + } + if (val == RLIM_INFINITY) + printf("unlimited\n"); + else if (lim >= ZSH_NLIMITS) + { # ifdef RLIM_T_IS_QUAD_T - printf("%qdMB\n", val / (1024L * 1024L)); - else - printf("%qdkB\n", val / 1024L); + printf("%qd\n", val); # else # ifdef RLIM_T_IS_LONG_LONG - printf("%lldMB\n", val / (1024L * 1024L)); - else - printf("%lldkB\n", val / 1024L); + printf("%lld\n", val); # else # ifdef RLIM_T_IS_UNSIGNED - printf("%luMB\n", val / (1024L * 1024L)); - else - printf("%lukB\n", val / 1024L); + printf("%lu\n", val); # else - printf("%ldMB\n", val / (1024L * 1024L)); - else - printf("%ldkB\n", val / 1024L); + printf("%ld\n", val); # endif /* RLIM_T_IS_UNSIGNED */ # endif /* RLIM_T_IS_LONG_LONG */ # endif /* RLIM_T_IS_QUAD_T */ + } + else if (limtype[lim] == ZLIMTYPE_TIME) { + /* time-type resource -- display as hours, minutes and + seconds. */ + printf("%d:%02d:%02d\n", (int)(val / 3600), + (int)(val / 60) % 60, (int)(val % 60)); + } else if (limtype[lim] == ZLIMTYPE_NUMBER || + limtype[lim] == ZLIMTYPE_UNKNOWN) { + /* pure numeric resource */ + printf("%d\n", (int)val); + } else if (val >= 1024L * 1024L) + /* memory resource -- display with `K' or `M' modifier */ +# ifdef RLIM_T_IS_QUAD_T + printf("%qdMB\n", val / (1024L * 1024L)); + else + printf("%qdkB\n", val / 1024L); +# else +# ifdef RLIM_T_IS_LONG_LONG + printf("%lldMB\n", val / (1024L * 1024L)); + else + printf("%lldkB\n", val / 1024L); +# else +# ifdef RLIM_T_IS_UNSIGNED + printf("%luMB\n", val / (1024L * 1024L)); + else + printf("%lukB\n", val / 1024L); +# else + printf("%ldMB\n", val / (1024L * 1024L)); + else + printf("%ldkB\n", val / 1024L); +# endif /* RLIM_T_IS_UNSIGNED */ +# endif /* RLIM_T_IS_LONG_LONG */ +# endif /* RLIM_T_IS_QUAD_T */ +} + +/* Display resource limits. hard indicates whether `hard' or `soft' * + * limits should be displayed. lim specifies the limit, or may be -1 * + * to show all. */ + +/**/ +static int +showlimits(char *nam, int hard, int lim) +{ + int rt; + + if (lim >= ZSH_NLIMITS) + { + /* + * Not configured into the shell. Ask the OS + * explicitly for this limit. + */ + struct rlimit vals; + if (getrlimit(lim, &vals) < 0) + { + zwarnnam(nam, "can't read limit: %e", NULL, errno); + return 1; } + showlimitvalue(lim, hard ? vals.rlim_max : vals.rlim_cur); + } + else if (lim != -1) + { + showlimitvalue(lim, hard ? limits[lim].rlim_max : + limits[lim].rlim_cur); + } + else + { + /* main loop over resource types */ + for (rt = 0; rt != ZSH_NLIMITS; rt++) + showlimitvalue(rt, (hard) ? limits[rt].rlim_max : + limits[rt].rlim_cur); + } + + return 0; } /* Display a resource limit, in ulimit style. lim specifies which * @@ -131,121 +187,165 @@ showlimits(int hard, int lim) * soft limit should be displayed. */ /**/ -static void -printulimit(int lim, int hard, int head) +static int +printulimit(char *nam, int lim, int hard, int head) { rlim_t limit; /* get the limit in question */ - limit = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur; + if (lim >= ZSH_NLIMITS) + { + struct rlimit vals; + + if (getrlimit(lim, &vals) < 0) + { + zwarnnam(nam, "can't read limit: %e", NULL, errno); + return 1; + } + limit = (hard) ? vals.rlim_max : vals.rlim_cur; + } + else + limit = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur; /* display the appropriate heading */ switch (lim) { - case RLIMIT_CPU: - if (head) - printf("cpu time (seconds) "); - break; - case RLIMIT_FSIZE: + case RLIMIT_CORE: if (head) - printf("file size (blocks) "); + printf("-c: core file size (blocks) "); if (limit != RLIM_INFINITY) limit /= 512; break; case RLIMIT_DATA: if (head) - printf("data seg size (kbytes) "); + printf("-d: data seg size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; - case RLIMIT_STACK: + case RLIMIT_FSIZE: if (head) - printf("stack size (kbytes) "); + printf("-f: file size (blocks) "); if (limit != RLIM_INFINITY) - limit /= 1024; + limit /= 512; break; - case RLIMIT_CORE: +# ifdef HAVE_RLIMIT_SIGPENDING + case RLIMIT_SIGPENDING: + if (head) + printf("-i: pending signals "); + break; +# endif +# ifdef HAVE_RLIMIT_MEMLOCK + case RLIMIT_MEMLOCK: if (head) - printf("core file size (blocks) "); + printf("-l: locked-in-memory size (kb) "); if (limit != RLIM_INFINITY) - limit /= 512; + limit /= 1024; break; -# ifdef RLIMIT_RSS +# endif /* HAVE_RLIMIT_MEMLOCK */ +/* If RLIMIT_VMEM and RLIMIT_RSS are defined and equal, avoid * + * duplicate case statement. Observed on QNX Neutrino 6.1.0. */ +# if defined(HAVE_RLIMIT_RSS) && !defined(RLIMIT_VMEM_IS_RSS) case RLIMIT_RSS: if (head) - printf("resident set size (kbytes) "); + printf("-m: resident set size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; -# endif /* RLIMIT_RSS */ -# ifdef RLIMIT_MEMLOCK - case RLIMIT_MEMLOCK: +# endif /* HAVE_RLIMIT_RSS */ +# if defined(HAVE_RLIMIT_VMEM) && defined(HAVE_RLIMIT_RSS) && defined(RLIMIT_VMEM_IS_RSS) + case RLIMIT_VMEM: if (head) - printf("locked-in-memory size (kb) "); + printf("-m: memory size (kb) "); if (limit != RLIM_INFINITY) limit /= 1024; break; -# endif /* RLIMIT_MEMLOCK */ -# ifdef RLIMIT_NPROC - case RLIMIT_NPROC: +# endif /* HAVE_RLIMIT_VMEM */ +# ifdef HAVE_RLIMIT_NOFILE + case RLIMIT_NOFILE: if (head) - printf("processes "); + printf("-n: file descriptors "); break; -# endif /* RLIMIT_NPROC */ -# ifdef RLIMIT_NOFILE - case RLIMIT_NOFILE: +# endif /* HAVE_RLIMIT_NOFILE */ +# ifdef HAVE_RLIMIT_MSGQUEUE + case RLIMIT_MSGQUEUE: if (head) - printf("file descriptors "); + printf("-q: bytes in POSIX msg queues "); break; -# endif /* RLIMIT_NOFILE */ -# ifdef RLIMIT_VMEM - case RLIMIT_VMEM: +# endif + case RLIMIT_STACK: if (head) - printf("virtual memory size (kb) "); + printf("-s: stack size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; -# endif /* RLIMIT_VMEM */ -# if defined RLIMIT_AS && RLIMIT_AS != RLIMIT_VMEM - case RLIMIT_AS: + case RLIMIT_CPU: + if (head) + printf("-t: cpu time (seconds) "); + break; +# ifdef HAVE_RLIMIT_NPROC + case RLIMIT_NPROC: + if (head) + printf("-u: processes "); + break; +# endif /* HAVE_RLIMIT_NPROC */ +# if defined(HAVE_RLIMIT_VMEM) && (!defined(HAVE_RLIMIT_RSS) || !defined(RLIMIT_VMEM_IS_RSS)) + case RLIMIT_VMEM: if (head) - printf("address space (kb) "); + printf("-v: virtual memory size (kb) "); if (limit != RLIM_INFINITY) limit /= 1024; break; -# endif /* RLIMIT_AS */ -# ifdef RLIMIT_TCACHE - case RLIMIT_TCACHE: +# endif /* HAVE_RLIMIT_VMEM */ +# if defined HAVE_RLIMIT_AS && !defined(RLIMIT_VMEM_IS_AS) + case RLIMIT_AS: if (head) - printf("cached threads "); + printf("-v: address space (kb) "); + if (limit != RLIM_INFINITY) + limit /= 1024; break; -# endif /* RLIMIT_TCACHE */ -# ifdef RLIMIT_AIO_OPS - case RLIMIT_AIO_OPS: +# endif /* HAVE_RLIMIT_AS */ +# ifdef HAVE_RLIMIT_LOCKS + case RLIMIT_LOCKS: if (head) - printf("AIO operations "); + printf("-x: file locks "); break; -# endif /* RLIMIT_AIO_OPS */ -# ifdef RLIMIT_AIO_MEM +# endif /* HAVE_RLIMIT_LOCKS */ +# ifdef HAVE_RLIMIT_AIO_MEM case RLIMIT_AIO_MEM: if (head) - printf("AIO locked-in-memory (kb) "); + printf("-N %2d: AIO locked-in-memory (kb) ", RLIMIT_AIO_MEM); if (limit != RLIM_INFINITY) limit /= 1024; break; -# endif /* RLIMIT_AIO_MEM */ -# ifdef RLIMIT_SBSIZE +# endif /* HAVE_RLIMIT_AIO_MEM */ +# ifdef HAVE_RLIMIT_AIO_OPS + case RLIMIT_AIO_OPS: + if (head) + printf("-N %2d: AIO operations ", RLIMIT_AIO_OPS); + break; +# endif /* HAVE_RLIMIT_AIO_OPS */ +# ifdef HAVE_RLIMIT_TCACHE + case RLIMIT_TCACHE: + if (head) + printf("-N %2d: cached threads ", RLIMIT_TCACHE); + break; +# endif /* HAVE_RLIMIT_TCACHE */ +# ifdef HAVE_RLIMIT_SBSIZE case RLIMIT_SBSIZE: if (head) - printf("socket buffer size (kb) "); + printf("-N %2d: socket buffer size (kb) ", RLIMIT_SBSIZE); if (limit != RLIM_INFINITY) limit /= 1024; break; -# endif /* RLIMIT_SBSIZE */ -# ifdef RLIMIT_PTHREAD +# endif /* HAVE_RLIMIT_SBSIZE */ +# ifdef HAVE_RLIMIT_PTHREAD case RLIMIT_PTHREAD: if (head) - printf("threads per process "); + printf("-N %2d: threads per process ", RLIMIT_PTHREAD); + break; +# endif /* HAVE_RLIMIT_PTHREAD */ + default: + if (head) + printf("-N %2d: ", lim); break; -# endif /* RLIMIT_PTHREAD */ } /* display the limit */ if (limit == RLIM_INFINITY) @@ -265,6 +365,93 @@ printulimit(int lim, int hard, int head) # endif /* RLIM_T_IS_LONG_LONG */ # endif /* RLIM_T_IS_QUAD_T */ } + + return 0; +} + +/**/ +static int +do_limit(char *nam, int lim, rlim_t val, int hard, int soft, int set) +{ + if (lim >= ZSH_NLIMITS) { + struct rlimit vals; + if (getrlimit(lim, &vals) < 0) + { + /* best guess about error */ + zwarnnam(nam, "can't read limit: %e", NULL, errno); + return 1; + } + if (hard) + { + if (val > vals.rlim_max && geteuid()) { + zwarnnam(nam, "can't raise hard limits", NULL, 0); + return 1; + } + vals.rlim_max = val; + /* + * not show if all systems will do this silently, but + * best be safe... + */ + if (val < vals.rlim_cur) + vals.rlim_cur = val; + } + if (soft || !hard) { + if (val > vals.rlim_max) { + zwarnnam(nam, "limit exceeds hard limit", NULL, 0); + return 1; + } + else + vals.rlim_cur = val; + } + if (!set) + { + zwarnnam(nam, + "warning: unrecognised limit %d, use -s to set", + NULL, lim); + return 1; + } + else if (setrlimit(lim, &vals) < 0) + { + zwarnnam(nam, "setrlimit failed: %e", NULL, errno); + return 1; + } + } else { + /* new limit is valid and has been interpreted; apply it to the + specified resource */ + if (hard) { + /* can only raise hard limits if running as root */ + if (val > current_limits[lim].rlim_max && geteuid()) { + zwarnnam(nam, "can't raise hard limits", NULL, 0); + return 1; + } else { + limits[lim].rlim_max = val; + if (val < limits[lim].rlim_cur) + limits[lim].rlim_cur = val; + } + } + if (soft || !hard) { + if (val > limits[lim].rlim_max) { + /* no idea about this difference, don't intend to worry */ + if (*nam == 'u') + { + /* ulimit does this */ + if (val > current_limits[lim].rlim_max && geteuid()) { + zwarnnam(nam, "value exceeds hard limit", NULL, 0); + return 1; + } + limits[lim].rlim_max = limits[lim].rlim_cur = val; + } else { + /* but limit does this */ + zwarnnam(nam, "limit exceeds hard limit", NULL, 0); + return 1; + } + } else + limits[lim].rlim_cur = val; + if (set && zsetlimit(lim, "limit")) + return 1; + } + } + return 0; } /* limit: set or show resource limits. The variable hard indicates * @@ -272,46 +459,57 @@ printulimit(int lim, int hard, int head) /**/ static int -bin_limit(char *nam, char **argv, char *ops, int func) +bin_limit(char *nam, char **argv, Options ops, UNUSED(int func)) { char *s; int hard, limnum, lim; rlim_t val; int ret = 0; - hard = ops['h']; - if (ops['s'] && !*argv) + hard = OPT_ISSET(ops,'h'); + if (OPT_ISSET(ops,'s') && !*argv) return setlimits(NULL); /* without arguments, display limits */ - if (!*argv) { - showlimits(hard, -1); - return 0; - } + if (!*argv) + return showlimits(nam, hard, -1); while ((s = *argv++)) { /* Search for the appropriate resource name. When a name matches (i.e. * * starts with) the argument, the lim variable changes from -1 to the * * number of the resource. If another match is found, lim goes to -2. */ - for (lim = -1, limnum = 0; limnum < ZSH_NLIMITS; limnum++) - if (!strncmp(recs[limnum], s, strlen(s))) { - if (lim != -1) - lim = -2; - else - lim = limnum; - } + if (idigit(*s)) + { + lim = (int)zstrtol(s, NULL, 10); + } + else + for (lim = -1, limnum = 0; limnum < ZSH_NLIMITS; limnum++) + if (!strncmp(recs[limnum], s, strlen(s))) { + if (lim != -1) + lim = -2; + else + lim = limnum; + } /* lim==-1 indicates that no matches were found. * * lim==-2 indicates that multiple matches were found. */ if (lim < 0) { - zwarnnam("limit", + zwarnnam(nam, (lim == -2) ? "ambiguous resource specification: %s" : "no such resource: %s", s, 0); return 1; } /* without value for limit, display the current limit */ - if (!(s = *argv++)) { - showlimits(hard, lim); - return 0; + if (!(s = *argv++)) + return showlimits(nam, hard, lim); + if (lim >= ZSH_NLIMITS) + { + val = zstrtorlimt(s, &s, 10); + if (*s) + { + /* unknown limit, no idea how to scale */ + zwarnnam(nam, "unknown scaling factor: %s", s, 0); + return 1; + } } - if (limtype[lim] == ZLIMTYPE_TIME) { + else if (limtype[lim] == ZLIMTYPE_TIME) { /* time-type resource -- may be specified as seconds, or minutes or * * hours with the `m' and `h' modifiers, and `:' may be used to add * * together more than one of these. It's easier to understand from * @@ -325,48 +523,83 @@ bin_limit(char *nam, char **argv, char *ops, int func) else if (*s == ':') val = val * 60 + zstrtorlimt(s + 1, &s, 10); else { - zwarnnam("limit", "unknown scaling factor: %s", s, 0); + zwarnnam(nam, "unknown scaling factor: %s", s, 0); return 1; } } } else if (limtype[lim] == ZLIMTYPE_NUMBER || limtype[lim] == ZLIMTYPE_UNKNOWN) { /* pure numeric resource -- only a straight decimal number is permitted. */ - val = zstrtorlimt(s, &s, 10); + char *t = s; + val = zstrtorlimt(t, &s, 10); + if (s == t) { + zwarnnam(nam, "limit must be a number", NULL, 0); + return 1; + } } else { /* memory-type resource -- `k' and `M' modifiers are permitted, meaning (respectively) 2^10 and 2^20. */ val = zstrtorlimt(s, &s, 10); - if (!*s || ((*s == 'k' || *s == 'K') && !s[1])) - val *= 1024L; - else if ((*s == 'M' || *s == 'm') && !s[1]) + if (!*s || ((*s == 'k' || *s == 'K') && !s[1])) { + if (val != RLIM_INFINITY) + val *= 1024L; + } else if ((*s == 'M' || *s == 'm') && !s[1]) val *= 1024L * 1024; else { - zwarnnam("limit", "unknown scaling factor: %s", s, 0); + zwarnnam(nam, "unknown scaling factor: %s", s, 0); return 1; } } - /* new limit is valid and has been interpreted; apply it to the - specified resource */ + if (do_limit(nam, lim, val, hard, !hard, OPT_ISSET(ops, 's'))) + ret++; + } + return ret; +} + +/**/ +static int +do_unlimit(char *nam, int lim, int hard, int soft, int set, int euid) +{ + /* remove specified limit */ + if (lim >= ZSH_NLIMITS) { + struct rlimit vals; + if (getrlimit(lim, &vals) < 0) + { + zwarnnam(nam, "can't read limit: %e", NULL, errno); + return 1; + } if (hard) { - /* can only raise hard limits if running as root */ - if (val > current_limits[lim].rlim_max && geteuid()) { - zwarnnam("limit", "can't raise hard limits", NULL, 0); + if (euid && vals.rlim_max != RLIM_INFINITY) { + zwarnnam(nam, "can't remove hard limits", NULL, 0); return 1; - } else { - limits[lim].rlim_max = val; - if (val < limits[lim].rlim_cur) - limits[lim].rlim_cur = val; - } - } else if (val > limits[lim].rlim_max) { - zwarnnam("limit", "limit exceeds hard limit", NULL, 0); + } else + vals.rlim_max = RLIM_INFINITY; + } + if (!hard || soft) + vals.rlim_cur = vals.rlim_max; + if (!set) { + zwarnnam(nam, + "warning: unrecognised limit %d, use -s to set", + NULL, lim); + return 1; + } else if (setrlimit(lim, &vals) < 0) { + zwarnnam(nam, "setrlimit failed: %e", NULL, errno); + return 1; + } + } else { + if (hard) { + if (euid && current_limits[lim].rlim_max != RLIM_INFINITY) { + zwarnnam(nam, "can't remove hard limits", NULL, 0); + return 1; + } else + limits[lim].rlim_max = RLIM_INFINITY; + } + if (!hard || soft) + limits[lim].rlim_cur = limits[lim].rlim_max; + if (set && zsetlimit(lim, nam)) return 1; - } else - limits[lim].rlim_cur = val; - if (ops['s'] && zsetlimit(lim, "limit")) - ret++; } - return ret; + return 0; } /* unlimit: remove resource limits. Much of this code is the same as * @@ -374,13 +607,13 @@ bin_limit(char *nam, char **argv, char *ops, int func) /**/ static int -bin_unlimit(char *nam, char **argv, char *ops, int func) +bin_unlimit(char *nam, char **argv, Options ops, UNUSED(int func)) { int hard, limnum, lim; int ret = 0; uid_t euid = geteuid(); - hard = ops['h']; + hard = OPT_ISSET(ops,'h'); /* Without arguments, remove all limits. */ if (!*argv) { for (limnum = 0; limnum != RLIM_NLIMITS; limnum++) { @@ -392,7 +625,7 @@ bin_unlimit(char *nam, char **argv, char *ops, int func) } else limits[limnum].rlim_cur = limits[limnum].rlim_max; } - if (ops['s']) + if (OPT_ISSET(ops,'s')) ret += setlimits(nam); if (ret) zwarnnam(nam, "can't remove hard limits", NULL, 0); @@ -402,13 +635,17 @@ bin_unlimit(char *nam, char **argv, char *ops, int func) * matches (i.e. starts with) the argument, the lim variable * * changes from -1 to the number of the resource. If another * * match is found, lim goes to -2. */ - for (lim = -1, limnum = 0; limnum < ZSH_NLIMITS; limnum++) - if (!strncmp(recs[limnum], *argv, strlen(*argv))) { - if (lim != -1) - lim = -2; - else - lim = limnum; - } + if (idigit(**argv)) { + lim = (int)zstrtol(*argv, NULL, 10); + } else { + for (lim = -1, limnum = 0; limnum < ZSH_NLIMITS; limnum++) + if (!strncmp(recs[limnum], *argv, strlen(*argv))) { + if (lim != -1) + lim = -2; + else + lim = limnum; + } + } /* lim==-1 indicates that no matches were found. * * lim==-2 indicates that multiple matches were found. */ if (lim < 0) { @@ -417,16 +654,8 @@ bin_unlimit(char *nam, char **argv, char *ops, int func) : "no such resource: %s", *argv, 0); return 1; } - /* remove specified limit */ - if (hard) { - if (euid && current_limits[lim].rlim_max != RLIM_INFINITY) { - zwarnnam(nam, "can't remove hard limits", NULL, 0); - ret++; - } else - limits[lim].rlim_max = RLIM_INFINITY; - } else - limits[lim].rlim_cur = limits[lim].rlim_max; - if (ops['s'] && zsetlimit(lim, nam)) + else if (do_unlimit(nam, lim, hard, !hard, OPT_ISSET(ops, 's'), + euid)) ret++; } } @@ -437,9 +666,9 @@ bin_unlimit(char *nam, char **argv, char *ops, int func) /**/ static int -bin_ulimit(char *name, char **argv, char *ops, int func) +bin_ulimit(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) { - int res, resmask = 0, hard = 0, soft = 0, nres = 0; + int res, resmask = 0, hard = 0, soft = 0, nres = 0, all = 0, ret = 0; char *options; do { @@ -462,12 +691,29 @@ bin_ulimit(char *name, char **argv, char *ops, int func) case 'S': soft = 1; continue; + case 'N': + if (options[1]) { + res = (int)zstrtol(options+1, NULL, 10); + } else if (*argv) { + res = (int)zstrtol(*argv++, NULL, 10); + } else { + zwarnnam(name, "number required after -N", + NULL, 0); + return 1; + } + /* + * fake it so it looks like we just finished an option... + */ + while (options[1]) + options++; + break; case 'a': - if (*argv || options[1] || resmask) { - zwarnnam(name, "no arguments required after -a", + if (resmask) { + zwarnnam(name, "no limits allowed with -a", NULL, 0); return 1; } + all = 1; resmask = (1 << RLIM_NLIMITS) - 1; nres = RLIM_NLIMITS; continue; @@ -486,31 +732,50 @@ bin_ulimit(char *name, char **argv, char *ops, int func) case 'c': res = RLIMIT_CORE; break; -# ifdef RLIMIT_RSS +# ifdef HAVE_RLIMIT_RSS case 'm': res = RLIMIT_RSS; break; -# endif /* RLIMIT_RSS */ -# ifdef RLIMIT_MEMLOCK +# endif /* HAVE_RLIMIT_RSS */ +# ifdef HAVE_RLIMIT_MEMLOCK case 'l': res = RLIMIT_MEMLOCK; break; -# endif /* RLIMIT_MEMLOCK */ -# ifdef RLIMIT_NOFILE +# endif /* HAVE_RLIMIT_MEMLOCK */ +# ifdef HAVE_RLIMIT_NOFILE case 'n': res = RLIMIT_NOFILE; break; -# endif /* RLIMIT_NOFILE */ -# ifdef RLIMIT_NPROC +# endif /* HAVE_RLIMIT_NOFILE */ +# ifdef HAVE_RLIMIT_NPROC case 'u': res = RLIMIT_NPROC; break; -# endif /* RLIMIT_NPROC */ -# ifdef RLIMIT_VMEM +# endif /* HAVE_RLIMIT_NPROC */ +# if defined(HAVE_RLIMIT_VMEM) || defined(HAVE_RLIMIT_AS) case 'v': +# ifdef HAVE_RLIMIT_VMEM res = RLIMIT_VMEM; +# else + res = RLIMIT_AS; +# endif + break; +# endif /* HAVE_RLIMIT_VMEM */ +# ifdef HAVE_RLIMIT_LOCKS + case 'x': + res = RLIMIT_LOCKS; + break; +# endif +# ifdef HAVE_RLIMIT_SIGPENDING + case 'i': + res = RLIMIT_SIGPENDING; + break; +# endif +# ifdef HAVE_RLIMIT_MSGQUEUE + case 'q': + res = RLIMIT_MSGQUEUE; break; -# endif /* RLIMIT_VMEM */ +# endif default: /* unrecognised limit */ zwarnnam(name, "bad option: -%c", NULL, *options); @@ -520,6 +785,11 @@ bin_ulimit(char *name, char **argv, char *ops, int func) resmask |= 1 << res; nres++; } + if (all && res != -1) { + zwarnnam(name, "no limits allowed with -a", + NULL, 0); + return 1; + } } } if (!*argv || **argv == '-') { @@ -533,6 +803,10 @@ bin_ulimit(char *name, char **argv, char *ops, int func) nres++; continue; } + if (all) { + zwarnnam(name, "no arguments allowed after -a", NULL, 0); + return 1; + } if (res < 0) res = RLIMIT_FSIZE; if (strcmp(*argv, "unlimited")) { @@ -548,65 +822,39 @@ bin_ulimit(char *name, char **argv, char *ops, int func) break; case RLIMIT_DATA: case RLIMIT_STACK: -# ifdef RLIMIT_RSS +# ifdef HAVE_RLIMIT_RSS case RLIMIT_RSS: -# endif /* RLIMIT_RSS */ -# ifdef RLIMIT_MEMLOCK +# endif /* HAVE_RLIMIT_RSS */ +# ifdef HAVE_RLIMIT_MEMLOCK case RLIMIT_MEMLOCK: -# endif /* RLIMIT_MEMLOCK */ -# ifdef RLIMIT_VMEM +# endif /* HAVE_RLIMIT_MEMLOCK */ +/* If RLIMIT_VMEM and RLIMIT_RSS are defined and equal, avoid * + * duplicate case statement. Observed on QNX Neutrino 6.1.0. */ +# if defined(HAVE_RLIMIT_VMEM) && !defined(RLIMIT_VMEM_IS_RSS) case RLIMIT_VMEM: -# endif /* RLIMIT_VMEM */ -# ifdef RLIMIT_AIO_MEM +# endif /* HAVE_RLIMIT_VMEM */ +/* ditto RLIMIT_VMEM and RLIMIT_AS */ +# if defined(HAVE_RLIMIT_AS) && !defined(RLIMIT_VMEM_IS_AS) + case RLIMIT_AS: +# endif /* HAVE_RLIMIT_AS */ +# ifdef HAVE_RLIMIT_AIO_MEM case RLIMIT_AIO_MEM: -# endif /* RLIMIT_AIO_MEM */ +# endif /* HAVE_RLIMIT_AIO_MEM */ limit *= 1024; break; } - if (hard) { - /* can't raise hard limit unless running as root */ - if (limit > current_limits[res].rlim_max && geteuid()) { - zwarnnam(name, "can't raise hard limits", NULL, 0); - return 1; - } - limits[res].rlim_max = limit; - if (limit < limits[res].rlim_cur) - limits[res].rlim_cur = limit; - } - if (!hard || soft) { - /* can't raise soft limit above hard limit */ - if (limit > limits[res].rlim_max) { - if (limit > current_limits[res].rlim_max && geteuid()) { - zwarnnam(name, "value exceeds hard limit", NULL, 0); - return 1; - } - limits[res].rlim_max = limits[res].rlim_cur = limit; - } else - limits[res].rlim_cur = limit; - } + if (do_limit(name, res, limit, hard, soft, 1)) + ret++; } else { - /* remove specified limit */ - if (hard) { - /* can't remove hard limit unless running as root */ - if (current_limits[res].rlim_max != RLIM_INFINITY && geteuid()) { - zwarnnam(name, "can't remove hard limits", NULL, 0); - return 1; - } - limits[res].rlim_max = RLIM_INFINITY; - } - if (!hard || soft) - /* `removal' of soft limit means setting it equal to the - corresponding hard limit */ - limits[res].rlim_cur = limits[res].rlim_max; + if (do_unlimit(name, res, hard, soft, 1, geteuid())) + ret++; } - if (zsetlimit(res, name)) - return 1; argv++; } while (*argv); - for (res = 0; res < RLIM_NLIMITS; res++, resmask >>= 1) - if (resmask & 1) - printulimit(res, hard, nres > 1); - return 0; + for (res = 0; resmask; res++, resmask >>= 1) + if ((resmask & 1) && printulimit(name, res, hard, nres > 1)) + ret++; + return ret; } #else /* !HAVE_GETRLIMIT || !RLIM_INFINITY */ @@ -625,7 +873,7 @@ static struct builtin bintab[] = { /**/ int -setup_(Module m) +setup_(UNUSED(Module m)) { return 0; } @@ -647,7 +895,7 @@ cleanup_(Module m) /**/ int -finish_(Module m) +finish_(UNUSED(Module m)) { return 0; } diff --git a/Src/cond.c b/Src/cond.c index 5593097a0..aa808715f 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -37,15 +37,26 @@ static char *condstr[COND_MOD] = { "-ne", "-lt", "-gt", "-le", "-ge" }; +/* + * Evaluate a conditional expression given the arguments. + * If fromtest is set, the caller is the test or [ builtin; + * with the pointer giving the name of the command. + * for POSIX conformance this supports a more limited range + * of functionality. + * + * Return status is the final shell status, i.e. 0 for true, + * 1 for false and 2 for error. + */ + /**/ int -evalcond(Estate state) +evalcond(Estate state, char *fromtest) { struct stat *st; char *left, *right; Wordcode pcode; wordcode code; - int ctype, htok = 0; + int ctype, htok = 0, ret; rec: @@ -58,24 +69,28 @@ evalcond(Estate state) case COND_NOT: if (tracingcond) fprintf(xtrerr, " %s", condstr[ctype]); - return !evalcond(state); + ret = evalcond(state, fromtest); + if (ret == 2) + return ret; + else + return !ret; case COND_AND: - if (evalcond(state)) { + if (!(ret = evalcond(state, fromtest))) { if (tracingcond) fprintf(xtrerr, " %s", condstr[ctype]); goto rec; } else { state->pc = pcode + (WC_COND_SKIP(code) + 1); - return 0; + return ret; } case COND_OR: - if (!evalcond(state)) { + 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 1; + return ret; } case COND_MOD: case COND_MODI: @@ -99,12 +114,13 @@ evalcond(Estate state) if ((cd = getconddef((ctype == COND_MODI), name + 1, 1))) { if (ctype == COND_MOD && (l < cd->min || (cd->max >= 0 && l > cd->max))) { - zerr("unrecognized condition: `%s'", name, 0); - return 0; + zwarnnam(fromtest, "unrecognized condition: `%s'", + name, 0); + return 2; } if (tracingcond) tracemodcond(name, strs, ctype == COND_MODI); - return cd->handler(strs, cd->condid); + return !cd->handler(strs, cd->condid); } else { char *s = strs[0]; @@ -115,16 +131,20 @@ evalcond(Estate state) if (name && name[0] == '-' && (cd = getconddef(0, name + 1, 1))) { if (l < cd->min || (cd->max >= 0 && l > cd->max)) { - zerr("unrecognized condition: `%s'", name, 0); - return 0; + zwarnnam(fromtest, "unrecognized condition: `%s'", + name, 0); + return 2; } if (tracingcond) tracemodcond(name, strs, ctype == COND_MODI); - return cd->handler(strs, cd->condid); - } else - zerr("unrecognized condition: `%s'", name, 0); + return !cd->handler(strs, cd->condid); + } else { + zwarnnam(fromtest, + "unrecognized condition: `%s'", name, 0); + } } - return 0; + /* module not found, error */ + return 2; } } left = ecgetstr(state, EC_DUPTOK, &htok); @@ -147,15 +167,46 @@ evalcond(Estate state) singsub(&rt); untokenize(rt); } - fprintf(xtrerr, " %s %s %s", left, condstr[ctype], rt); - } else - fprintf(xtrerr, " -%c %s", ctype, left); + fputc(' ',xtrerr); + quotedzputs(left, xtrerr); + fprintf(xtrerr, " %s ", condstr[ctype]); + quotedzputs(rt, xtrerr); + } else { + fprintf(xtrerr, " -%c ", ctype); + quotedzputs(left, xtrerr); + } } if (ctype >= COND_EQ && ctype <= COND_GE) { mnumber mn1, mn2; - mn1 = matheval(left); - mn2 = matheval(right); + 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, 0); + 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)) { @@ -171,23 +222,23 @@ evalcond(Estate state) } switch(ctype) { case COND_EQ: - return (mn1.type & MN_FLOAT) ? (mn1.u.d == mn2.u.d) : - (mn1.u.l == mn2.u.l); + 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); + 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); + 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); + 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); + 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); + return !((mn1.type & MN_FLOAT) ? (mn1.u.d >= mn2.u.d) : + (mn1.u.l >= mn2.u.l)); } } @@ -202,89 +253,91 @@ evalcond(Estate state) char *opat; int save; - right = opat = dupstring(ecrawstr(state->prog, state->pc, + right = dupstring(opat = ecrawstr(state->prog, state->pc, &htok)); if (htok) singsub(&right); - save = (state->prog->alloc != EA_HEAP && + save = (!(state->prog->flags & EF_HEAP) && !strcmp(opat, right) && pprog != dummy_patprog2); if (!(pprog = patcompile(right, (save ? PAT_ZDUP : PAT_STATIC), - NULL))) - zerr("bad pattern: %s", right, 0); + NULL))) { + zwarnnam(fromtest, "bad pattern: %s", right, 0); + return 2; + } else if (save) state->prog->pats[npat] = pprog; } state->pc += 2; test = (pprog && pattry(pprog, left)); - return (ctype == COND_STREQ ? test : !test); + return !(ctype == COND_STREQ ? test : !test); } case COND_STRLT: - return strcmp(left, right) < 0; + return !(strcmp(left, right) < 0); case COND_STRGTR: - return strcmp(left, right) > 0; + return !(strcmp(left, right) > 0); case 'e': case 'a': - return (doaccess(left, F_OK)); + return (!doaccess(left, F_OK)); case 'b': - return (S_ISBLK(dostat(left))); + return (!S_ISBLK(dostat(left))); case 'c': - return (S_ISCHR(dostat(left))); + return (!S_ISCHR(dostat(left))); case 'd': - return (S_ISDIR(dostat(left))); + return (!S_ISDIR(dostat(left))); case 'f': - return (S_ISREG(dostat(left))); + return (!S_ISREG(dostat(left))); case 'g': - return (!!(dostat(left) & S_ISGID)); + return (!(dostat(left) & S_ISGID)); case 'k': - return (!!(dostat(left) & S_ISVTX)); + return (!(dostat(left) & S_ISVTX)); case 'n': - return (!!strlen(left)); + return (!strlen(left)); case 'o': - return (optison(left)); + return (optison(fromtest, left)); case 'p': - return (S_ISFIFO(dostat(left))); + return (!S_ISFIFO(dostat(left))); case 'r': - return (doaccess(left, R_OK)); + return (!doaccess(left, R_OK)); case 's': - return ((st = getstat(left)) && !!(st->st_size)); + return !((st = getstat(left)) && !!(st->st_size)); case 'S': - return (S_ISSOCK(dostat(left))); + return (!S_ISSOCK(dostat(left))); case 'u': - return (!!(dostat(left) & S_ISUID)); + return (!(dostat(left) & S_ISUID)); case 'w': - return (doaccess(left, W_OK)); + return (!doaccess(left, W_OK)); case 'x': if (privasserted()) { mode_t mode = dostat(left); - return (mode & S_IXUGO) || S_ISDIR(mode); + return !((mode & S_IXUGO) || S_ISDIR(mode)); } - return doaccess(left, X_OK); + return !doaccess(left, X_OK); case 'z': - return (!strlen(left)); + return !!(strlen(left)); case 'h': case 'L': - return (S_ISLNK(dolstat(left))); + return (!S_ISLNK(dolstat(left))); case 'O': - return ((st = getstat(left)) && st->st_uid == geteuid()); + return !((st = getstat(left)) && st->st_uid == geteuid()); case 'G': - return ((st = getstat(left)) && st->st_gid == getegid()); + return !((st = getstat(left)) && st->st_gid == getegid()); case 'N': - return ((st = getstat(left)) && st->st_atime <= st->st_mtime); + return !((st = getstat(left)) && st->st_atime <= st->st_mtime); case 't': - return isatty(mathevali(left)); + return !isatty(mathevali(left)); case COND_NT: case COND_OT: { time_t a; if (!(st = getstat(left))) - return 0; + return 1; a = st->st_mtime; if (!(st = getstat(right))) - return 0; - return (ctype == COND_NT) ? a > st->st_mtime : a < st->st_mtime; + return 1; + return !((ctype == COND_NT) ? a > st->st_mtime : a < st->st_mtime); } case COND_EF: { @@ -292,17 +345,18 @@ evalcond(Estate state) ino_t i; if (!(st = getstat(left))) - return 0; + return 1; d = st->st_dev; i = st->st_ino; if (!(st = getstat(right))) - return 0; - return d == st->st_dev && i == st->st_ino; + return 1; + return !(d == st->st_dev && i == st->st_ino); } default: - zerr("bad cond code", NULL, 0); + zwarnnam(fromtest, "bad cond code", NULL, 0); + return 2; } - return 0; + return 1; } @@ -324,6 +378,8 @@ static struct stat st; static struct stat * getstat(char *s) { + char *us; + /* /dev/fd/n refers to the open file descriptor n. We always use fstat * * in this case since on Solaris /dev/fd/n is a device special file */ if (!strncmp(s, "/dev/fd/", 8)) { @@ -332,7 +388,9 @@ getstat(char *s) return &st; } - if (stat(unmeta(s), &st)) + if (!(us = unmeta(s))) + return NULL; + if (stat(us, &st)) return NULL; return &st; } @@ -362,9 +420,13 @@ dolstat(char *s) } +/* + * optison returns evalcond-friendly statuses (true, false, error). + */ + /**/ static int -optison(char *s) +optison(char *name, char *s) { int i; @@ -373,12 +435,12 @@ optison(char *s) else i = optlookup(s); if (!i) { - zerr("no such option: %s", s, 0); - return 0; + zwarnnam(name, "no such option: %s", s, 0); + return 2; } else if(i < 0) - return unset(-i); + return !unset(-i); else - return isset(i); + return !isset(i); } /**/ -- cgit 1.4.1