summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Builtins/rlimits.awk116
-rw-r--r--Src/Builtins/rlimits.c692
-rw-r--r--Src/Builtins/rlimits.mdd15
-rw-r--r--Src/Modules/system.c2
-rw-r--r--Src/Zle/zle_keymap.c2
-rw-r--r--Src/Zle/zle_main.c2
-rw-r--r--Src/Zle/zle_move.c2
-rw-r--r--Src/builtin.c2
-rw-r--r--Src/compat.c2
-rw-r--r--Src/exec.c6
-rw-r--r--Src/init.c15
-rw-r--r--Src/jobs.c19
-rw-r--r--Src/loop.c2
-rw-r--r--Src/math.c15
-rw-r--r--Src/openssh_bsd_setres_id.c129
-rw-r--r--Src/options.c141
-rw-r--r--Src/params.c8
-rw-r--r--Src/signals.c3
-rw-r--r--Src/utils.c2
-rw-r--r--Src/zsh.mdd3
-rw-r--r--Src/zsh_system.h94
21 files changed, 634 insertions, 638 deletions
diff --git a/Src/Builtins/rlimits.awk b/Src/Builtins/rlimits.awk
deleted file mode 100644
index e9c576c66..000000000
--- a/Src/Builtins/rlimits.awk
+++ /dev/null
@@ -1,116 +0,0 @@
-#
-# rlimits.awk: {g,n}awk script to generate rlimits.h
-#
-# NB: On SunOS 4.1.3 - user-functions don't work properly, also \" problems
-# Without 0 + hacks some nawks compare numbers as strings
-#
-BEGIN {limidx = 0}
-
-/^[\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)
- limnam = substr(tmp[1], 8, 20)
- limnum = tmp[2]
- # in this case I assume GNU libc resourcebits.h
- if (limnum == "") {
- limnum = limidx++
- limindex = index($0, ",")
- limnam = substr(limnam, 1, limindex-1)
- }
- if (limnum == "=") {
- if (tmp[3] ~ /^[0-9]/) {
- limnum = tmp[3] + 0
- } else {
- limnum = limidx++
- }
- limindex = index($0, ",")
- limnam = substr(limnam, 1, limindex-1)
- }
- limrev[limnam] = limnum
- if (lim[limnum] == "") {
- lim[limnum] = limnam
- if (limnum ~ /^[0-9]*$/) {
- if (limnam == "AIO_MEM") { msg[limnum] = "Maiomemorylocked" }
- if (limnam == "AIO_OPS") { msg[limnum] = "Naiooperations" }
- if (limnam == "AS") { msg[limnum] = "Maddressspace" }
- if (limnam == "CORE") { msg[limnum] = "Mcoredumpsize" }
- 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" }
- if (limnam == "NTHR") { msg[limnum] = "Nmaxpthreads" }
- if (limnam == "OFILE") { msg[limnum] = "Ndescriptors" }
- if (limnam == "PTHREAD") { msg[limnum] = "Nmaxpthreads" }
- if (limnam == "RSS") { msg[limnum] = "Mresident" }
- if (limnam == "SBSIZE") { msg[limnum] = "Msockbufsize" }
- 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" }
- if (limnam == "NICE") { msg[limnum] = "Nnice" }
- if (limnam == "RTPRIO") { msg[limnum] = "Nrt_priority" }
- if (limnam == "RTTIME") { msg[limnum] = "Urt_time" }
- if (limnam == "POSIXLOCKS") { msg[limnum] = "Nposixlocks" }
- if (limnam == "NPTS") { msg[limnum] = "Npseudoterminals" }
- if (limnam == "SWAP") { msg[limnum] = "Mswapsize" }
- if (limnam == "KQUEUES") { msg[limnum] = "Nkqueues" }
- if (limnam == "UMTXP") { msg[limnum] = "Numtxp" }
- }
- }
-}
-/^[\t ]*#[\t ]*define[\t _]*RLIM_NLIMITS[\t ]*[0-9][0-9]*/ {
- limindex = index($0, "RLIM_")
- limtail = substr($0, limindex, 80)
- split(limtail, tmp)
- nlimits = tmp[2]
-}
-# in case of GNU libc
-/^[\t ]*RLIM_NLIMITS[\t ]*=[\t ]*RLIMIT_NLIMITS/ {
- 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 {
- if (limrev["MEMLOCK"] != "") {
- irss = limrev["RSS"]
- msg[irss] = "Mmemoryuse"
- }
- ps = "%s"
-
- printf("%s\n%s\n\n", "/** rlimits.h **/", "/** architecture-customized limits for zsh **/")
- printf("#define ZSH_NLIMITS %d\n\nstatic char const *recs[ZSH_NLIMITS] = {\n", 0 + nlimits)
-
- for (i = 0; i < 0 + nlimits; i++)
- if (msg[i] == "")
- printf("\t%c%s%c,\n", 34, lim[i], 34)
- else
- printf("\t%c%s%c,\n", 34, substr(msg[i], 2, 30), 34)
- print "};"
- print ""
- print "static int limtype[ZSH_NLIMITS] = {"
- for (i = 0; i < 0 + nlimits; i++) {
- if (msg[i] == "")
- limtype = "UNKNOWN"
- else {
- limtype = substr(msg[i], 1, 1)
- if(limtype == "M") { limtype = "MEMORY" }
- if(limtype == "N") { limtype = "NUMBER" }
- if(limtype == "T") { limtype = "TIME" }
- if(limtype == "U") { limtype = "MICROSECONDS" }
- }
- printf("\tZLIMTYPE_%s,\n", limtype)
- }
- print "};"
-
- exit(0)
-}
diff --git a/Src/Builtins/rlimits.c b/Src/Builtins/rlimits.c
index 6b552f3a9..b9128433f 100644
--- a/Src/Builtins/rlimits.c
+++ b/Src/Builtins/rlimits.c
@@ -32,20 +32,7 @@
#if defined(HAVE_GETRLIMIT) && defined(RLIM_INFINITY)
-#if defined(HAVE_RLIMIT_POSIXLOCKS) && !defined(HAVE_RLIMIT_LOCKS)
-# define RLIMIT_LOCKS RLIMIT_POSIXLOCKS
-# define HAVE_RLIMIT_LOCKS 1
-#endif
-
-#if defined(HAVE_RLIMIT_NTHR) && !defined(HAVE_RLIMIT_PTHREAD)
-# define RLIMIT_PTHREAD RLIMIT_NTHR
-# define HAVE_RLIMIT_PTHREAD 1
-# define THREAD_FMT "-T: threads "
-#else
-# define THREAD_FMT "-T: threads per process "
-#endif
-
-enum {
+enum zlimtype {
ZLIMTYPE_MEMORY,
ZLIMTYPE_NUMBER,
ZLIMTYPE_TIME,
@@ -53,11 +40,214 @@ enum {
ZLIMTYPE_UNKNOWN
};
-/* Generated rec array containing limits required for the limit builtin. *
- * They must appear in this array in numerical order of the RLIMIT_* macros. */
+typedef struct resinfo_T {
+ int res; /* RLIMIT_XXX */
+ char* name; /* used by limit builtin */
+ enum zlimtype type;
+ int unit; /* 1, 512, or 1024 */
+ char opt; /* option character */
+ char* descr; /* used by ulimit builtin */
+} resinfo_T;
+
+/* table of known resources */
+static const resinfo_T known_resources[] = {
+ {RLIMIT_CPU, "cputime", ZLIMTYPE_TIME, 1,
+ 't', "cpu time (seconds)"},
+ {RLIMIT_FSIZE, "filesize", ZLIMTYPE_MEMORY, 512,
+ 'f', "file size (blocks)"},
+ {RLIMIT_DATA, "datasize", ZLIMTYPE_MEMORY, 1024,
+ 'd', "data seg size (kbytes)"},
+ {RLIMIT_STACK, "stacksize", ZLIMTYPE_MEMORY, 1024,
+ 's', "stack size (kbytes)"},
+ {RLIMIT_CORE, "coredumpsize", ZLIMTYPE_MEMORY, 512,
+ 'c', "core file size (blocks)"},
+# ifdef HAVE_RLIMIT_NOFILE
+ {RLIMIT_NOFILE, "descriptors", ZLIMTYPE_NUMBER, 1,
+ 'n', "file descriptors"},
+# endif
+# if defined(HAVE_RLIMIT_AS) && !defined(RLIMIT_VMEM_IS_AS)
+ {RLIMIT_AS, "addressspace", ZLIMTYPE_MEMORY, 1024,
+ 'v', "address space (kbytes)"},
+# endif
+# if defined(HAVE_RLIMIT_RSS) && !defined(RLIMIT_VMEM_IS_RSS) && !defined(RLIMIT_RSS_IS_AS)
+ {RLIMIT_RSS, "resident", ZLIMTYPE_MEMORY, 1024,
+ 'm', "resident set size (kbytes)"},
+# endif
+# if defined(HAVE_RLIMIT_VMEM)
+ {RLIMIT_VMEM,
+# if defined(RLIMIT_VMEM_IS_RSS)
+ "resident", ZLIMTYPE_MEMORY, 1024,
+ 'm', "memory size (kbytes)"},
+# else
+ "vmemorysize", ZLIMTYPE_MEMORY, 1024,
+ 'v', "virtual memory size (kbytes)"},
+# endif
+# endif
+# ifdef HAVE_RLIMIT_NPROC
+ {RLIMIT_NPROC, "maxproc", ZLIMTYPE_NUMBER, 1,
+ 'u', "processes"},
+# endif
+# ifdef HAVE_RLIMIT_MEMLOCK
+ {RLIMIT_MEMLOCK, "memorylocked", ZLIMTYPE_MEMORY, 1024,
+ 'l', "locked-in-memory size (kbytes)"},
+# endif
+ /* Linux */
+# ifdef HAVE_RLIMIT_LOCKS
+ {RLIMIT_LOCKS, "maxfilelocks", ZLIMTYPE_NUMBER, 1,
+ 'x', "file locks"},
+# endif
+# ifdef HAVE_RLIMIT_SIGPENDING
+ {RLIMIT_SIGPENDING, "sigpending", ZLIMTYPE_NUMBER, 1,
+ 'i', "pending signals"},
+# endif
+# ifdef HAVE_RLIMIT_MSGQUEUE
+ {RLIMIT_MSGQUEUE, "msgqueue", ZLIMTYPE_NUMBER, 1,
+ 'q', "bytes in POSIX msg queues"},
+# endif
+# ifdef HAVE_RLIMIT_NICE
+ {RLIMIT_NICE, "nice", ZLIMTYPE_NUMBER, 1,
+ 'e', "max nice"},
+# endif
+# ifdef HAVE_RLIMIT_RTPRIO
+ {RLIMIT_RTPRIO, "rt_priority", ZLIMTYPE_NUMBER, 1,
+ 'r', "max rt priority"},
+# endif
+# ifdef HAVE_RLIMIT_RTTIME
+ {RLIMIT_RTTIME, "rt_time", ZLIMTYPE_MICROSECONDS, 1,
+ 'N', "rt cpu time (microseconds)"},
+# endif
+ /* BSD */
+# ifdef HAVE_RLIMIT_SBSIZE
+ {RLIMIT_SBSIZE, "sockbufsize", ZLIMTYPE_MEMORY, 1,
+ 'b', "socket buffer size (bytes)"},
+# endif
+# ifdef HAVE_RLIMIT_KQUEUES /* FreeBSD */
+ {RLIMIT_KQUEUES, "kqueues", ZLIMTYPE_NUMBER, 1,
+ 'k', "kqueues"},
+# endif
+# ifdef HAVE_RLIMIT_NPTS /* FreeBSD */
+ {RLIMIT_NPTS, "pseudoterminals", ZLIMTYPE_NUMBER, 1,
+ 'p', "pseudo-terminals"},
+# endif
+# ifdef HAVE_RLIMIT_SWAP /* FreeBSD */
+ {RLIMIT_SWAP, "swapsize", ZLIMTYPE_MEMORY, 1024,
+ 'w', "swap size (kbytes)"},
+# endif
+# ifdef HAVE_RLIMIT_UMTXP /* FreeBSD */
+ {RLIMIT_UMTXP, "umtxp", ZLIMTYPE_NUMBER, 1,
+ 'o', "umtx shared locks"},
+# endif
+
+# ifdef HAVE_RLIMIT_POSIXLOCKS /* DragonFly */
+ {RLIMIT_POSIXLOCKS, "posixlocks", ZLIMTYPE_NUMBER, 1,
+ 'x', "number of POSIX locks"},
+# endif
+# if defined(HAVE_RLIMIT_NTHR) && !defined(HAVE_RLIMIT_RTPRIO) /* Net/OpenBSD */
+ {RLIMIT_NTHR, "maxpthreads", ZLIMTYPE_NUMBER, 1,
+ 'r', "threads"},
+# endif
+ /* others */
+# if defined(HAVE_RLIMIT_PTHREAD) && !defined(HAVE_RLIMIT_NTHR) /* IRIX ? */
+ {RLIMIT_PTHREAD, "maxpthreads", ZLIMTYPE_NUMBER, 1,
+ 'T', "threads per process"},
+# endif
+# ifdef HAVE_RLIMIT_AIO_MEM /* HP-UX ? */
+ {RLIMIT_AIO_MEM, "aiomemorylocked", ZLIMTYPE_MEMORY, 1024,
+ 'N', "AIO locked-in-memory (kbytes)"},
+# endif
+# ifdef HAVE_RLIMIT_AIO_OPS /* HP-UX ? */
+ {RLIMIT_AIO_OPS, "aiooperations", ZLIMTYPE_NUMBER, 1,
+ 'N', "AIO operations"},
+# endif
+# ifdef HAVE_RLIMIT_TCACHE /* HP-UX ? */
+ {RLIMIT_TCACHE, "cachedthreads", ZLIMTYPE_NUMBER, 1,
+ 'N', "cached threads"},
+# endif
+};
-# include "rlimits.h"
+/* resinfo[RLIMIT_XXX] points to the corresponding entry
+ * in known_resources[] */
+static const resinfo_T **resinfo;
+/**/
+static void
+set_resinfo(void)
+{
+ int i;
+
+ resinfo = (const resinfo_T **)zshcalloc(RLIM_NLIMITS*sizeof(resinfo_T *));
+
+ for (i=0; i<sizeof(known_resources)/sizeof(resinfo_T); ++i) {
+ resinfo[known_resources[i].res] = &known_resources[i];
+ }
+ for (i=0; i<RLIM_NLIMITS; ++i) {
+ if (!resinfo[i]) {
+ /* unknown resource */
+ resinfo_T *info = (resinfo_T *)zshcalloc(sizeof(resinfo_T));
+ char *buf = (char *)zalloc(12);
+ snprintf(buf, 12, "UNKNOWN-%d", i);
+ info->res = - 1; /* negative value indicates "unknown" */
+ info->name = buf;
+ info->type = ZLIMTYPE_UNKNOWN;
+ info->unit = 1;
+ info->opt = 'N';
+ info->descr = buf;
+ resinfo[i] = info;
+ }
+ }
+}
+
+/**/
+static void
+free_resinfo(void)
+{
+ int i;
+ for (i=0; i<RLIM_NLIMITS; ++i) {
+ if (resinfo[i]->res < 0) { /* unknown resource */
+ free(resinfo[i]->name);
+ free((void*)resinfo[i]);
+ }
+ }
+ free(resinfo);
+ resinfo = NULL;
+}
+
+/* Find resource by its option character */
+
+/**/
+static int
+find_resource(char c)
+{
+ int i;
+ for (i=0; i<RLIM_NLIMITS; ++i) {
+ if (resinfo[i]->opt == c)
+ return i;
+ }
+ return -1;
+}
+
+/* Print a value of type rlim_t */
+
+/**/
+static void
+printrlim(rlim_t val, const char *unit)
+{
+# ifdef RLIM_T_IS_QUAD_T
+ printf("%qd%s", val, unit);
+# else
+# ifdef RLIM_T_IS_LONG_LONG
+ printf("%lld%s", val, unit);
+# else
+# ifdef RLIM_T_IS_UNSIGNED
+ printf("%lu%s", (unsigned long)val, unit);
+# else
+ printf("%ld%s", (long)val, unit);
+# endif /* RLIM_T_IS_UNSIGNED */
+# endif /* RLIM_T_IS_LONG_LONG */
+# endif /* RLIM_T_IS_QUAD_T */
+}
+
+/**/
static rlim_t
zstrtorlimt(const char *s, char **t, int base)
{
@@ -97,8 +287,8 @@ static void
showlimitvalue(int lim, rlim_t val)
{
/* display limit for resource number lim */
- if (lim < ZSH_NLIMITS)
- printf("%-16s", recs[lim]);
+ if (lim < RLIM_NLIMITS)
+ printf("%-16s", resinfo[lim]->name);
else
{
/* Unknown limit, hence unknown units. */
@@ -106,81 +296,25 @@ showlimitvalue(int lim, rlim_t val)
}
if (val == RLIM_INFINITY)
printf("unlimited\n");
- else if (lim >= ZSH_NLIMITS)
- {
-# ifdef RLIM_T_IS_QUAD_T
- printf("%qd\n", val);
-# else
-# ifdef RLIM_T_IS_LONG_LONG
- printf("%lld\n", val);
-# else
-# ifdef RLIM_T_IS_UNSIGNED
- printf("%lu\n", (unsigned long)val);
-# else
- printf("%ld\n", (long)val);
-# endif /* RLIM_T_IS_UNSIGNED */
-# endif /* RLIM_T_IS_LONG_LONG */
-# endif /* RLIM_T_IS_QUAD_T */
- }
- else if (limtype[lim] == ZLIMTYPE_TIME) {
+ else if (lim >= RLIM_NLIMITS)
+ printrlim(val, "\n");
+ else if (resinfo[lim]->type == 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_MICROSECONDS) {
- /* microseconds */
-# ifdef RLIM_T_IS_QUAD_T
- printf("%qdus\n", val);
-# else
-# ifdef RLIM_T_IS_LONG_LONG
- printf("%lldus\n", val);
-# else
-# ifdef RLIM_T_IS_UNSIGNED
- printf("%luus\n", (unsigned long)val);
-# else
- printf("%ldus\n", (long)val);
-# endif /* RLIM_T_IS_UNSIGNED */
-# endif /* RLIM_T_IS_LONG_LONG */
-# endif /* RLIM_T_IS_QUAD_T */
- } else if (limtype[lim] == ZLIMTYPE_NUMBER ||
- limtype[lim] == ZLIMTYPE_UNKNOWN) {
- /* pure numeric resource */
-# ifdef RLIM_T_IS_QUAD_T
- printf("%qd\n", val);
-# else
-# ifdef RLIM_T_IS_LONG_LONG
- printf("%lld\n", val);
-# else
-# ifdef RLIM_T_IS_UNSIGNED
- printf("%lu\n", (unsigned long)val);
-# else
- printf("%ld\n", (long)val);
-# endif /* RLIM_T_IS_UNSIGNED */
-# endif /* RLIM_T_IS_LONG_LONG */
-# endif /* RLIM_T_IS_QUAD_T */
- } 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", (unsigned long)(val / (1024L * 1024L)));
- else
- printf("%lukB\n", (unsigned long)(val / 1024L));
-# else
- printf("%ldMB\n", (long)val / (1024L * 1024L));
- else
- printf("%ldkB\n", (long)val / 1024L);
-# endif /* RLIM_T_IS_UNSIGNED */
-# endif /* RLIM_T_IS_LONG_LONG */
-# endif /* RLIM_T_IS_QUAD_T */
+ } else if (resinfo[lim]->type == ZLIMTYPE_MICROSECONDS)
+ printrlim(val, "us\n"); /* microseconds */
+ else if (resinfo[lim]->type == ZLIMTYPE_NUMBER ||
+ resinfo[lim]->type == ZLIMTYPE_UNKNOWN)
+ printrlim(val, "\n"); /* pure numeric resource */
+ else {
+ /* memory resource -- display with `k' or `M' modifier */
+ if (val >= 1024L * 1024L)
+ printrlim(val/(1024L * 1024L), "MB\n");
+ else
+ printrlim(val/1024L, "kB\n");
+ }
}
/* Display resource limits. hard indicates whether `hard' or `soft' *
@@ -193,7 +327,7 @@ showlimits(char *nam, int hard, int lim)
{
int rt;
- if (lim >= ZSH_NLIMITS)
+ if (lim >= RLIM_NLIMITS)
{
/*
* Not configured into the shell. Ask the OS
@@ -215,7 +349,7 @@ showlimits(char *nam, int hard, int lim)
else
{
/* main loop over resource types */
- for (rt = 0; rt != ZSH_NLIMITS; rt++)
+ for (rt = 0; rt != RLIM_NLIMITS; rt++)
showlimitvalue(rt, (hard) ? limits[rt].rlim_max :
limits[rt].rlim_cur);
}
@@ -234,7 +368,7 @@ printulimit(char *nam, int lim, int hard, int head)
rlim_t limit;
/* get the limit in question */
- if (lim >= ZSH_NLIMITS)
+ if (lim >= RLIM_NLIMITS)
{
struct rlimit vals;
@@ -248,199 +382,25 @@ printulimit(char *nam, int lim, int hard, int head)
else
limit = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur;
/* display the appropriate heading */
- switch (lim) {
- case RLIMIT_CORE:
- if (head)
- printf("-c: core file size (blocks) ");
- if (limit != RLIM_INFINITY)
- limit /= 512;
- break;
- case RLIMIT_DATA:
- if (head)
- printf("-d: data seg size (kbytes) ");
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
- case RLIMIT_FSIZE:
- if (head)
- printf("-f: file size (blocks) ");
- if (limit != RLIM_INFINITY)
- limit /= 512;
- break;
-# 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("-l: locked-in-memory size (kbytes) ");
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
-# 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) && !defined(RLIMIT_RSS_IS_AS)
- case RLIMIT_RSS:
- if (head)
- printf("-m: resident set size (kbytes) ");
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
-# endif /* HAVE_RLIMIT_RSS */
-# if defined(HAVE_RLIMIT_VMEM) && defined(HAVE_RLIMIT_RSS) && defined(RLIMIT_VMEM_IS_RSS)
- case RLIMIT_VMEM:
- if (head)
- printf("-m: memory size (kbytes) ");
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
-# endif /* HAVE_RLIMIT_VMEM */
-# ifdef HAVE_RLIMIT_NOFILE
- case RLIMIT_NOFILE:
- if (head)
- printf("-n: file descriptors ");
- break;
-# endif /* HAVE_RLIMIT_NOFILE */
-# ifdef HAVE_RLIMIT_MSGQUEUE
- case RLIMIT_MSGQUEUE:
- if (head)
- printf("-q: bytes in POSIX msg queues ");
- break;
-# endif
- case RLIMIT_STACK:
- if (head)
- printf("-s: stack size (kbytes) ");
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
- 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("-v: virtual memory size (kbytes) ");
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
-# endif /* HAVE_RLIMIT_VMEM */
-# if defined HAVE_RLIMIT_AS && !defined(RLIMIT_VMEM_IS_AS)
- case RLIMIT_AS:
- if (head)
- printf("-v: address space (kbytes) ");
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
-# endif /* HAVE_RLIMIT_AS */
-# ifdef HAVE_RLIMIT_LOCKS
- case RLIMIT_LOCKS:
- if (head)
- printf("-x: file locks ");
- break;
-# endif /* HAVE_RLIMIT_LOCKS */
-# ifdef HAVE_RLIMIT_AIO_MEM
- case RLIMIT_AIO_MEM:
- if (head)
- printf("-N %2d: AIO locked-in-memory (kbytes)", RLIMIT_AIO_MEM);
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
-# 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("-b: socket buffer size (bytes) ");
- break;
-# endif /* HAVE_RLIMIT_SBSIZE */
-# ifdef HAVE_RLIMIT_PTHREAD
- case RLIMIT_PTHREAD:
- if (head)
- printf("%s", THREAD_FMT);
- break;
-# endif /* HAVE_RLIMIT_PTHREAD */
-# ifdef HAVE_RLIMIT_NICE
- case RLIMIT_NICE:
- if (head)
- printf("-e: max nice ");
- break;
-# endif /* HAVE_RLIMIT_NICE */
-# ifdef HAVE_RLIMIT_RTPRIO
- case RLIMIT_RTPRIO:
- if (head)
- printf("-r: max rt priority ");
- break;
-# endif /* HAVE_RLIMIT_RTPRIO */
-# ifdef HAVE_RLIMIT_NPTS
- case RLIMIT_NPTS:
- if (head)
- printf("-p: pseudo-terminals ");
- break;
-# endif /* HAVE_RLIMIT_NPTS */
-# ifdef HAVE_RLIMIT_SWAP
- case RLIMIT_SWAP:
- if (head)
- printf("-w: swap size (kbytes) ");
- if (limit != RLIM_INFINITY)
- limit /= 1024;
- break;
-# endif /* HAVE_RLIMIT_SWAP */
-# ifdef HAVE_RLIMIT_KQUEUES
- case RLIMIT_KQUEUES:
- if (head)
- printf("-k: kqueues ");
- break;
-# endif /* HAVE_RLIMIT_KQUEUES */
-# ifdef HAVE_RLIMIT_UMTXP
- case RLIMIT_UMTXP:
- if (head)
- printf("-o: umtx shared locks ");
- break;
-# endif /* HAVE_RLIMIT_UMTXP */
- default:
- if (head)
- printf("-N %2d: ", lim);
- break;
+ if (head) {
+ if (lim < RLIM_NLIMITS) {
+ const resinfo_T *info = resinfo[lim];
+ if (info->opt == 'N')
+ printf("-N %2d: %-29s", lim, info->descr);
+ else
+ printf("-%c: %-32s", info->opt, info->descr);
+ }
+ else
+ printf("-N %2d: %-29s", lim, "");
}
/* display the limit */
if (limit == RLIM_INFINITY)
printf("unlimited\n");
else {
-# ifdef RLIM_T_IS_QUAD_T
- printf("%qd\n", limit);
-# else
-# ifdef RLIM_T_IS_LONG_LONG
- printf("%lld\n", limit);
-# else
-# ifdef RLIM_T_IS_UNSIGNED
- printf("%lu\n", (unsigned long)limit);
-# else
- printf("%ld\n", (long)limit);
-# endif /* RLIM_T_IS_UNSIGNED */
-# endif /* RLIM_T_IS_LONG_LONG */
-# endif /* RLIM_T_IS_QUAD_T */
+ if (lim < RLIM_NLIMITS)
+ printrlim(limit/resinfo[lim]->unit, "\n");
+ else
+ printrlim(limit, "\n");
}
return 0;
@@ -450,7 +410,7 @@ printulimit(char *nam, int lim, int hard, int head)
static int
do_limit(char *nam, int lim, rlim_t val, int hard, int soft, int set)
{
- if (lim >= ZSH_NLIMITS) {
+ if (lim >= RLIM_NLIMITS) {
struct rlimit vals;
if (getrlimit(lim, &vals) < 0)
{
@@ -558,8 +518,8 @@ bin_limit(char *nam, char **argv, Options ops, UNUSED(int func))
lim = (int)zstrtol(s, NULL, 10);
}
else
- for (lim = -1, limnum = 0; limnum < ZSH_NLIMITS; limnum++)
- if (!strncmp(recs[limnum], s, strlen(s))) {
+ for (lim = -1, limnum = 0; limnum < RLIM_NLIMITS; limnum++)
+ if (!strncmp(resinfo[limnum]->name, s, strlen(s))) {
if (lim != -1)
lim = -2;
else
@@ -576,7 +536,7 @@ bin_limit(char *nam, char **argv, Options ops, UNUSED(int func))
/* without value for limit, display the current limit */
if (!(s = *argv++))
return showlimits(nam, hard, lim);
- if (lim >= ZSH_NLIMITS)
+ if (lim >= RLIM_NLIMITS)
{
val = zstrtorlimt(s, &s, 10);
if (*s)
@@ -586,7 +546,7 @@ bin_limit(char *nam, char **argv, Options ops, UNUSED(int func))
return 1;
}
}
- else if (limtype[lim] == ZLIMTYPE_TIME) {
+ else if (resinfo[lim]->type == 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 *
@@ -604,9 +564,9 @@ bin_limit(char *nam, char **argv, Options ops, UNUSED(int func))
return 1;
}
}
- } else if (limtype[lim] == ZLIMTYPE_NUMBER ||
- limtype[lim] == ZLIMTYPE_UNKNOWN ||
- limtype[lim] == ZLIMTYPE_MICROSECONDS) {
+ } else if (resinfo[lim]->type == ZLIMTYPE_NUMBER ||
+ resinfo[lim]->type == ZLIMTYPE_UNKNOWN ||
+ resinfo[lim]->type == ZLIMTYPE_MICROSECONDS) {
/* pure numeric resource -- only a straight decimal number is
permitted. */
char *t = s;
@@ -642,7 +602,7 @@ static int
do_unlimit(char *nam, int lim, int hard, int soft, int set, int euid)
{
/* remove specified limit */
- if (lim >= ZSH_NLIMITS) {
+ if (lim >= RLIM_NLIMITS) {
struct rlimit vals;
if (getrlimit(lim, &vals) < 0)
{
@@ -718,8 +678,8 @@ bin_unlimit(char *nam, char **argv, Options ops, UNUSED(int func))
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))) {
+ for (lim = -1, limnum = 0; limnum < RLIM_NLIMITS; limnum++)
+ if (!strncmp(resinfo[limnum]->name, *argv, strlen(*argv))) {
if (lim != -1)
lim = -2;
else
@@ -800,116 +760,14 @@ bin_ulimit(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
resmask = (1 << RLIM_NLIMITS) - 1;
nres = RLIM_NLIMITS;
continue;
- case 't':
- res = RLIMIT_CPU;
- break;
- case 'f':
- res = RLIMIT_FSIZE;
- break;
- case 'd':
- res = RLIMIT_DATA;
- break;
- case 's':
- res = RLIMIT_STACK;
- break;
- case 'c':
- res = RLIMIT_CORE;
- break;
-# ifdef HAVE_RLIMIT_SBSIZE
- case 'b':
- res = RLIMIT_SBSIZE;
- break;
-# endif /* HAVE_RLIMIT_SBSIZE */
-# ifdef HAVE_RLIMIT_MEMLOCK
- case 'l':
- res = RLIMIT_MEMLOCK;
- break;
-# endif /* HAVE_RLIMIT_MEMLOCK */
-# ifdef HAVE_RLIMIT_RSS
- case 'm':
- res = RLIMIT_RSS;
- break;
-# endif /* HAVE_RLIMIT_RSS */
-# ifdef HAVE_RLIMIT_NOFILE
- case 'n':
- res = RLIMIT_NOFILE;
- break;
-# endif /* HAVE_RLIMIT_NOFILE */
-# ifdef HAVE_RLIMIT_NPROC
- case 'u':
- res = RLIMIT_NPROC;
- break;
-# 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
-# ifdef HAVE_RLIMIT_NICE
- case 'e':
- res = RLIMIT_NICE;
- break;
-# endif
-# ifdef HAVE_RLIMIT_RTPRIO
- case 'r':
- res = RLIMIT_RTPRIO;
- break;
-# else
-# ifdef HAVE_RLIMIT_NTHR
- /* For compatibility with sh on NetBSD */
- case 'r':
- res = RLIMIT_NTHR;
- break;
-# endif /* HAVE_RLIMIT_NTHR */
-# endif
-# ifdef HAVE_RLIMIT_NPTS
- case 'p':
- res = RLIMIT_NPTS;
- break;
-# endif
-# ifdef HAVE_RLIMIT_SWAP
- case 'w':
- res = RLIMIT_SWAP;
- break;
-# endif
-# ifdef HAVE_RLIMIT_KQUEUES
- case 'k':
- res = RLIMIT_KQUEUES;
- break;
-# endif
-# ifdef HAVE_RLIMIT_PTHREAD
- case 'T':
- res = RLIMIT_PTHREAD;
- break;
-# endif
-# ifdef HAVE_RLIMIT_UMTXP
- case 'o':
- res = RLIMIT_UMTXP;
- break;
-# endif
default:
- /* unrecognised limit */
- zwarnnam(name, "bad option: -%c", *options);
- return 1;
+ res = find_resource(*options);
+ if (res < 0) {
+ /* unrecognised limit */
+ zwarnnam(name, "bad option: -%c", *options);
+ return 1;
+ }
+ break;
}
if (options[1]) {
resmask |= 1 << res;
@@ -961,34 +819,8 @@ bin_ulimit(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
return 1;
}
/* scale appropriately */
- switch (res) {
- case RLIMIT_FSIZE:
- case RLIMIT_CORE:
- limit *= 512;
- break;
- case RLIMIT_DATA:
- case RLIMIT_STACK:
-# ifdef HAVE_RLIMIT_RSS
- case RLIMIT_RSS:
-# endif /* HAVE_RLIMIT_RSS */
-# ifdef HAVE_RLIMIT_MEMLOCK
- case RLIMIT_MEMLOCK:
-# 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 /* HAVE_RLIMIT_VMEM */
-/* ditto RLIMIT_VMEM and RLIMIT_AS */
-# if defined(HAVE_RLIMIT_AS) && !defined(RLIMIT_VMEM_IS_AS) && !defined(RLIMIT_RSS_IS_AS)
- case RLIMIT_AS:
-# endif /* HAVE_RLIMIT_AS */
-# ifdef HAVE_RLIMIT_AIO_MEM
- case RLIMIT_AIO_MEM:
-# endif /* HAVE_RLIMIT_AIO_MEM */
- limit *= 1024;
- break;
- }
+ if (res < RLIM_NLIMITS)
+ limit *= resinfo[res]->unit;
}
if (do_limit(name, res, limit, hard, soft, 1))
ret++;
@@ -1052,6 +884,7 @@ enables_(Module m, int **enables)
int
boot_(UNUSED(Module m))
{
+ set_resinfo();
return 0;
}
@@ -1059,6 +892,7 @@ boot_(UNUSED(Module m))
int
cleanup_(Module m)
{
+ free_resinfo();
return setfeatureenables(m, &module_features, NULL);
}
diff --git a/Src/Builtins/rlimits.mdd b/Src/Builtins/rlimits.mdd
index 9e6e9e598..06c9e9c7f 100644
--- a/Src/Builtins/rlimits.mdd
+++ b/Src/Builtins/rlimits.mdd
@@ -6,18 +6,3 @@ autofeatures="b:limit b:ulimit b:unlimit"
autofeatures_emu="b:ulimit"
objects="rlimits.o"
-
-:<<\Make
-rlimits.o rlimits..o: rlimits.h
-
-# this file will not be made if limits are unavailable
-rlimits.h: rlimits.awk @RLIMITS_INC_H@
- $(AWK) -f $(sdir)/rlimits.awk @RLIMITS_INC_H@ /dev/null > rlimits.h
- @if grep ZLIMTYPE_UNKNOWN rlimits.h >/dev/null; then \
- echo >&2 WARNING: unknown limits: mail Src/Builtins/rlimits.h to developers; \
- else :; fi
-
-clean-here: clean.rlimits
-clean.rlimits:
- rm -f rlimits.h
-Make
diff --git a/Src/Modules/system.c b/Src/Modules/system.c
index 50de59cf9..fb3d80773 100644
--- a/Src/Modules/system.c
+++ b/Src/Modules/system.c
@@ -174,7 +174,7 @@ bin_sysread(char *nam, char **args, Options ops, UNUSED(int func))
}
while ((ret = select(infd+1, (SELECT_ARG_2_T) &fds,
- NULL, NULL,&select_tv)) < 1) {
+ NULL, NULL,&select_tv)) < 0) {
if (errno != EINTR || errflag || retflag || breaks || contflag)
break;
}
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index d13aed594..2389ab754 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -404,7 +404,7 @@ scankeys(HashNode hn, UNUSED(int flags))
/**************************/
/**/
-Keymap
+mod_export Keymap
openkeymap(char *name)
{
KeymapName n = (KeymapName) keymapnamtab->getnode(keymapnamtab, name);
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index be68f4722..8c0534708 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -1056,7 +1056,7 @@ getrestchar(int inchar, char *outstr, int *outcount)
#endif
/**/
-void
+mod_export void
redrawhook(void)
{
Thingy initthingy;
diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c
index 155fda80d..3bafff3f1 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -166,7 +166,7 @@ decpos(int *pos)
*/
/**/
-char *
+mod_export char *
backwardmetafiedchar(char *start, char *endptr, convchar_t *retchr)
{
#ifdef MULTIBYTE_SUPPORT
diff --git a/Src/builtin.c b/Src/builtin.c
index aa5767cf1..407cad159 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2597,7 +2597,7 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
*/
/**/
-int
+mod_export int
bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
{
Param pm;
diff --git a/Src/compat.c b/Src/compat.c
index 8ab335aa1..74e426fba 100644
--- a/Src/compat.c
+++ b/Src/compat.c
@@ -496,7 +496,7 @@ zgetdir(struct dirsav *d)
*/
/**/
-char *
+mod_export char *
zgetcwd(void)
{
char *ret = zgetdir(NULL);
diff --git a/Src/exec.c b/Src/exec.c
index 356e2974b..bca051d4f 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1036,7 +1036,8 @@ entersubsh(int flags, struct entersubsh_ret *retp)
} else if (thisjob != -1 && (flags & ESUB_PGRP)) {
if (jobtab[list_pipe_job].gleader && (list_pipe || list_pipe_child)) {
if (setpgrp(0L, jobtab[list_pipe_job].gleader) == -1 ||
- killpg(jobtab[list_pipe_job].gleader, 0) == -1) {
+ (killpg(jobtab[list_pipe_job].gleader, 0) == -1 &&
+ errno == ESRCH)) {
jobtab[list_pipe_job].gleader =
jobtab[thisjob].gleader = (list_pipe_child ? mypgrp : getpid());
setpgrp(0L, jobtab[list_pipe_job].gleader);
@@ -5101,7 +5102,6 @@ execarith(Estate state, UNUSED(int do_exec))
mnumber val = zero_mnumber;
int htok = 0;
- queue_signals();
if (isset(XTRACE)) {
printprompt4();
fprintf(xtrerr, "((");
@@ -5121,8 +5121,6 @@ execarith(Estate state, UNUSED(int do_exec))
fprintf(xtrerr, " ))\n");
fflush(xtrerr);
}
- unqueue_signals();
-
if (errflag) {
errflag &= ~ERRFLAG_ERROR;
return 2;
diff --git a/Src/init.c b/Src/init.c
index 2e2ef881c..04a5856ff 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -882,7 +882,7 @@ setupvals(char *cmd, char *runscript, char *zsh_name)
char *ptr;
int i, j;
#if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined (ADDITIONAL_FPATH) || defined(FIXED_FPATH_DIR)
-#define FPATH_NEEDS_INIT 1
+# define FPATH_NEEDS_INIT 1
char **fpathptr;
# if defined(FPATH_DIR) && defined(FPATH_SUBDIRS)
char *fpath_subdirs[] = FPATH_SUBDIRS;
@@ -994,18 +994,29 @@ setupvals(char *cmd, char *runscript, char *zsh_name)
# endif /* ADDITONAL_FPATH */
fpath = fpathptr = (char **)zalloc((fpathlen+1)*sizeof(char *));
# ifdef FIXED_FPATH_DIR
+ /* Zeroth: /usr/local/share/zsh/site-functions */
*fpathptr++ = ztrdup(FIXED_FPATH_DIR);
fpathlen--;
# endif
# ifdef SITEFPATH_DIR
+ /* First: the directory from --enable-site-fndir
+ *
+ * default: /usr/local/share/zsh/site-functions
+ * (but changeable by passing --prefix or --datadir to configure) */
*fpathptr++ = ztrdup(SITEFPATH_DIR);
fpathlen--;
# endif /* SITEFPATH_DIR */
# if defined(ADDITIONAL_FPATH)
+ /* Second: the directories from --enable-additional-fpath
+ *
+ * default: empty list */
for (j = 0; j < more_fndirs_len; j++)
*fpathptr++ = ztrdup(more_fndirs[j]);
# endif
# ifdef FPATH_DIR
+ /* Third: The directory from --enable-fndir
+ *
+ * default: /usr/local/share/zsh/${ZSH_VERSION}/functions */
# ifdef FPATH_SUBDIRS
# ifdef ADDITIONAL_FPATH
for (j = more_fndirs_len; j < fpathlen; j++)
@@ -1013,7 +1024,7 @@ setupvals(char *cmd, char *runscript, char *zsh_name)
# else
for (j = 0; j < fpathlen; j++)
*fpathptr++ = tricat(FPATH_DIR, "/", fpath_subdirs[j]);
-#endif
+# endif
# else
*fpathptr++ = ztrdup(FPATH_DIR);
# endif
diff --git a/Src/jobs.c b/Src/jobs.c
index e7438251e..8353f1152 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -283,7 +283,8 @@ handle_sub(int job, int fg)
if ((cp = ((WIFEXITED(jn->procs->status) ||
WIFSIGNALED(jn->procs->status)) &&
- killpg(jn->gleader, 0) == -1))) {
+ (killpg(jn->gleader, 0) == -1 &&
+ errno == ESRCH)))) {
Process p;
for (p = jn->procs; p->next; p = p->next);
jn->gleader = p->pid;
@@ -541,9 +542,13 @@ update_job(Job jn)
/* is this job in the foreground of an interactive shell? */
if (mypgrp != pgrp && inforeground &&
- (jn->gleader == pgrp || (pgrp > 1 && kill(-pgrp, 0) == -1))) {
+ (jn->gleader == pgrp ||
+ (pgrp > 1 &&
+ (kill(-pgrp, 0) == -1 && errno == ESRCH)))) {
if (list_pipe) {
- if (somestopped || (pgrp > 1 && kill(-pgrp, 0) == -1)) {
+ if (somestopped || (pgrp > 1 &&
+ kill(-pgrp, 0) == -1 &&
+ errno == ESRCH)) {
attachtty(mypgrp);
/* check window size and adjust if necessary */
adjustwinsize(0);
@@ -1854,13 +1859,14 @@ scanjobs(void)
/* This simple function indicates whether or not s may represent *
* a number. It returns true iff s consists purely of digits and *
- * minuses. Note that minus may appear more than once, and the empty *
- * string will produce a `true' response. */
+ * minuses. Note that minus may appear more than once. */
/**/
static int
isanum(char *s)
{
+ if (*s == '\0')
+ return 0;
while (*s == '-' || idigit(*s))
s++;
return *s == '\0';
@@ -2469,7 +2475,8 @@ bin_fg(char *name, char **argv, Options ops, int func)
if ((jobtab[job].stat & STAT_SUPERJOB) &&
((!jobtab[job].procs->next ||
(jobtab[job].stat & STAT_SUBLEADER) ||
- killpg(jobtab[job].gleader, 0) == -1)) &&
+ (killpg(jobtab[job].gleader, 0) == -1 &&
+ errno == ESRCH))) &&
jobtab[jobtab[job].other].gleader)
attachtty(jobtab[jobtab[job].other].gleader);
else
diff --git a/Src/loop.c b/Src/loop.c
index 57858a150..95ef48b33 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -570,7 +570,7 @@ execif(Estate state, int do_exec)
if (run) {
/* we need to ignore lastval until we reach execcmd() */
- if (olderrexit)
+ if (olderrexit || run == 2)
noerrexit = olderrexit;
else if (lastval)
noerrexit |= NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_UNTIL_EXEC;
diff --git a/Src/math.c b/Src/math.c
index a38770073..905b910ec 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -1133,8 +1133,7 @@ notzero(mnumber a)
/* macro to pop three values off the value stack */
-/**/
-void
+static void
op(int what)
{
mnumber a, b, c, *spval;
@@ -1569,14 +1568,19 @@ mathparse(int pc)
if (errflag)
return;
+ queue_signals();
mtok = zzlex();
/* Handle empty input */
- if (pc == TOPPREC && mtok == EOI)
+ if (pc == TOPPREC && mtok == EOI) {
+ unqueue_signals();
return;
+ }
checkunary(mtok, optr);
while (prec[mtok] <= pc) {
- if (errflag)
+ if (errflag) {
+ unqueue_signals();
return;
+ }
switch (mtok) {
case NUM:
push(yyval, NULL, 0);
@@ -1595,6 +1599,7 @@ mathparse(int pc)
if (mtok != M_OUTPAR) {
if (!errflag)
zerr("bad math expression: ')' expected");
+ unqueue_signals();
return;
}
break;
@@ -1613,6 +1618,7 @@ mathparse(int pc)
if (mtok != COLON) {
if (!errflag)
zerr("bad math expression: ':' expected");
+ unqueue_signals();
return;
}
if (q)
@@ -1636,4 +1642,5 @@ mathparse(int pc)
mtok = zzlex();
checkunary(mtok, optr);
}
+ unqueue_signals();
}
diff --git a/Src/openssh_bsd_setres_id.c b/Src/openssh_bsd_setres_id.c
new file mode 100644
index 000000000..65e91a40c
--- /dev/null
+++ b/Src/openssh_bsd_setres_id.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012 Darren Tucker (dtucker at zip com au).
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * openssh_bsd_setres_id.c - setresuid() and setresgid() wrappers
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * It is based on the file openbsd-compat/bsd-setres_id.c in OpenSSH 7.9p1,
+ * which is subject to the copyright notice above. The zsh modifications are
+ * licensed as follows:
+ *
+ * Copyright (c) 2019 Daniel Shahaf
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Daniel Shahaf or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Daniel Shahaf and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Daniel Shahaf and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Daniel Shahaf and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "zsh.mdh"
+
+#if defined(ZSH_IMPLEMENT_SETRESGID) || defined(BROKEN_SETRESGID)
+int
+setresgid(gid_t rgid, gid_t egid, gid_t sgid)
+{
+ int ret = 0, saved_errno;
+
+ if (rgid != sgid) {
+ errno = ENOSYS;
+ return -1;
+ }
+#if defined(ZSH_HAVE_NATIVE_SETREGID) && !defined(BROKEN_SETREGID)
+ if (setregid(rgid, egid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setregid", "to gid %L: %e", (long)rgid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+#else
+ if (setegid(egid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setegid", "to gid %L: %e", (long)(unsigned int)egid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+ if (setgid(rgid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setgid", "to gid %L: %e", (long)rgid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+#endif
+ return ret;
+}
+#endif
+
+#if defined(ZSH_IMPLEMENT_SETRESUID) || defined(BROKEN_SETRESUID)
+int
+setresuid(uid_t ruid, uid_t euid, uid_t suid)
+{
+ int ret = 0, saved_errno;
+
+ if (ruid != suid) {
+ errno = ENOSYS;
+ return -1;
+ }
+#if defined(ZSH_HAVE_NATIVE_SETREUID) && !defined(BROKEN_SETREUID)
+ if (setreuid(ruid, euid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setreuid", "to uid %L: %e", (long)ruid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+#else
+
+# ifndef SETEUID_BREAKS_SETUID
+ if (seteuid(euid) < 0) {
+ saved_errno = errno;
+ zwarnnam("seteuid", "to uid %L: %e", (long)euid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+# endif
+ if (setuid(ruid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setuid", "to uid %L: %e", (long)ruid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+#endif
+ return ret;
+}
+#endif
diff --git a/Src/options.c b/Src/options.c
index 48c14c179..08ba71917 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -577,6 +577,7 @@ int
bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
{
int action, optno, match = 0;
+ int retval = 0;
/* With no arguments or options, display options. */
if (!*args) {
@@ -604,18 +605,24 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
inittyptab();
return 1;
}
- if(!(optno = optlookup(*args)))
+ if(!(optno = optlookup(*args))) {
zwarnnam(nam, "no such option: %s", *args);
- else if(dosetopt(optno, action, 0, opts))
+ retval |= 1;
+ } else if (dosetopt(optno, action, 0, opts)) {
zwarnnam(nam, "can't change option: %s", *args);
+ retval |= 1;
+ }
break;
} else if(**args == 'm') {
match = 1;
} else {
- if (!(optno = optlookupc(**args)))
+ if (!(optno = optlookupc(**args))) {
zwarnnam(nam, "bad option: -%c", **args);
- else if(dosetopt(optno, action, 0, opts))
+ retval |= 1;
+ } else if (dosetopt(optno, action, 0, opts)) {
zwarnnam(nam, "can't change option: -%c", **args);
+ retval |= 1;
+ }
}
}
args++;
@@ -625,10 +632,13 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
if (!match) {
/* Not globbing the arguments -- arguments are simply option names. */
while (*args) {
- if(!(optno = optlookup(*args++)))
+ if(!(optno = optlookup(*args++))) {
zwarnnam(nam, "no such option: %s", args[-1]);
- else if(dosetopt(optno, !isun, 0, opts))
+ retval |= 1;
+ } else if (dosetopt(optno, !isun, 0, opts)) {
zwarnnam(nam, "can't change option: %s", args[-1]);
+ retval |= 1;
+ }
}
} else {
/* Globbing option (-m) set. */
@@ -651,7 +661,8 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
tokenize(s);
if (!(pprog = patcompile(s, PAT_HEAPDUP, NULL))) {
zwarnnam(nam, "bad pattern: %s", *args);
- continue;
+ retval |= 1;
+ break;
}
/* Loop over expansions. */
scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS,
@@ -660,7 +671,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
}
}
inittyptab();
- return 0;
+ return retval;
}
/* Identify an option name */
@@ -769,37 +780,99 @@ dosetopt(int optno, int value, int force, char *new_opts)
return -1;
} else if(optno == PRIVILEGED && !value) {
/* unsetting PRIVILEGED causes the shell to make itself unprivileged */
-#ifdef HAVE_SETUID
- int ignore_err;
- errno = 0;
+
+/* For simplicity's sake, require both setresgid() and setresuid() up-front. */
+#if !defined(HAVE_SETRESGID)
+ zwarnnam("unsetopt",
+ "PRIVILEGED: can't drop privileges; setresgid() and friends not available");
+ return -1;
+#elif !defined(HAVE_SETRESUID)
+ zwarnnam("unsetopt",
+ "PRIVILEGED: can't drop privileges; setresuid() and friends not available");
+ return -1;
+#else
+ /* If set, return -1 so lastval will be non-zero. */
+ int failed = 0;
+ const int orig_euid = geteuid();
+ const int orig_egid = getegid();
+
/*
* Set the GID first as if we set the UID to non-privileged it
* might be impossible to restore the GID.
- *
- * Some OSes (possibly no longer around) have been known to
- * fail silently the first time, so we attempt the change twice.
- * If it fails we are guaranteed to pick this up the second
- * time, so ignore the first time.
- *
- * Some versions of gcc make it hard to ignore the results the
- * first time, hence the following. (These are probably not
- * systems that require the doubled calls.)
*/
- ignore_err = setgid(getgid());
- (void)ignore_err;
- ignore_err = setuid(getuid());
- (void)ignore_err;
- if (setgid(getgid())) {
- zwarn("failed to change group ID: %e", errno);
- return -1;
- } else if (setuid(getuid())) {
- zwarn("failed to change user ID: %e", errno);
- return -1;
+ if (setresgid(getgid(), getgid(), getgid())) {
+ zwarnnam("unsetopt",
+ "PRIVILEGED: can't drop privileges; failed to change group ID: %e",
+ errno);
+ return -1;
}
-#else
- zwarn("setuid not available");
- return -1;
-#endif /* not HAVE_SETUID */
+
+# ifdef HAVE_INITGROUPS
+ /* Set the supplementary groups list.
+ *
+ * Note that on macOS, FreeBSD, and possibly some other platforms,
+ * initgroups() resets the EGID to its second argument (see setgroups(2) for
+ * details). This has the potential to leave the EGID in an unexpected
+ * state. However, it seems common in other projects that do this dance to
+ * simply re-use the same GID that's going to become the EGID anyway, in
+ * which case it doesn't matter. That's what we do here. It's therefore
+ * possible, in some probably uncommon cases, that the shell ends up not
+ * having the privileges of the RUID user's primary/passwd group. */
+ if (geteuid() == 0) {
+ struct passwd *pw = getpwuid(getuid());
+ if (pw == NULL) {
+ zwarnnam("unsetopt",
+ "can't drop privileges; failed to get user information for uid %L: %e",
+ (long)getuid(), errno);
+ failed = 1;
+ /* This may behave strangely in the unlikely event that the same user
+ * name appears with multiple UIDs in the passwd database */
+ } else if (initgroups(pw->pw_name, getgid())) {
+ zwarnnam("unsetopt",
+ "can't drop privileges; failed to set supplementary group list: %e",
+ errno);
+ return -1;
+ }
+ } else if (getuid() != 0 &&
+ (geteuid() != getuid() || orig_egid != getegid())) {
+ zwarnnam("unsetopt",
+ "PRIVILEGED: supplementary group list not changed due to lack of permissions: EUID=%L",
+ (long)geteuid());
+ failed = 1;
+ }
+# else
+ /* initgroups() isn't in POSIX. If it's not available on the system,
+ * we silently skip it. */
+# endif
+
+ /* Set the UID second. */
+ if (setresuid(getuid(), getuid(), getuid())) {
+ zwarnnam("unsetopt",
+ "PRIVILEGED: can't drop privileges; failed to change user ID: %e",
+ errno);
+ return -1;
+ }
+
+ if (getuid() != 0 && orig_egid != getegid() &&
+ (setgid(orig_egid) != -1 || setegid(orig_egid) != -1)) {
+ zwarnnam("unsetopt",
+ "PRIVILEGED: can't drop privileges; was able to restore the egid");
+ return -1;
+ }
+
+ if (getuid() != 0 && orig_euid != geteuid() &&
+ (setuid(orig_euid) != -1 || seteuid(orig_euid) != -1)) {
+ zwarnnam("unsetopt",
+ "PRIVILEGED: can't drop privileges; was able to restore the euid");
+ return -1;
+ }
+
+ if (failed) {
+ /* A warning message has been printed. */
+ return -1;
+ }
+#endif /* HAVE_SETRESGID && HAVE_SETRESUID */
+
#ifdef JOB_CONTROL
} else if (!force && optno == MONITOR && value) {
if (new_opts[optno] == value)
diff --git a/Src/params.c b/Src/params.c
index 5eaafe34e..863b32600 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -478,7 +478,13 @@ static initparam argvparam_pm = IPDEF9("", &pparams, NULL, \
static Param argvparam;
-/* hash table containing the parameters */
+/* "parameter table" - hash table containing the parameters
+ *
+ * realparamtab always points to the shell's global table. paramtab is sometimes
+ * temporarily changed to point at another table, while dealing with the keys
+ * of an associative array (for example, see makecompparams() which initializes
+ * the associative array ${compstate}).
+ */
/**/
mod_export HashTable paramtab, realparamtab;
diff --git a/Src/signals.c b/Src/signals.c
index 96ff9e9b3..4adf03202 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -539,7 +539,8 @@ wait_for_processes(void)
#endif
if (WIFEXITED(status) &&
pn->pid == jn->gleader &&
- killpg(pn->pid, 0) == -1) {
+ killpg(pn->pid, 0) == -1 &&
+ errno == ESRCH) {
if (last_attached_pgrp == jn->gleader &&
!(jn->stat & STAT_NOSTTY)) {
/*
diff --git a/Src/utils.c b/Src/utils.c
index f5667f389..f9c2d4a2b 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1023,7 +1023,7 @@ xsymlinks(char *s, int full)
*/
/**/
-char *
+mod_export char *
xsymlink(char *s, int heap)
{
if (*s != '/')
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index 3e5788af5..9bcaccae5 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -13,7 +13,8 @@ objects="builtin.o compat.o cond.o context.o \
exec.o glob.o hashtable.o hashnameddir.o \
hist.o init.o input.o jobs.o lex.o linklist.o loop.o math.o \
mem.o module.o options.o params.o parse.o pattern.o prompt.o signals.o \
-signames.o sort.o string.o subst.o text.o utils.o watch.o"
+signames.o sort.o string.o subst.o text.o utils.o watch.o \
+openssh_bsd_setres_id.o"
headers="../config.h zsh_system.h zsh.h sigcount.h signals.h \
prototypes.h hashtable.h ztype.h"
diff --git a/Src/zsh_system.h b/Src/zsh_system.h
index 85e198f2e..161b073b4 100644
--- a/Src/zsh_system.h
+++ b/Src/zsh_system.h
@@ -468,30 +468,90 @@ struct timespec {
# define setpgrp setpgid
#endif
-/* can we set the user/group id of a process */
+/* compatibility wrappers */
-#ifndef HAVE_SETUID
+/* Our strategy is as follows:
+ *
+ * - Ensure that either setre[ug]id() or set{e,}[ug]id() is available.
+ * - If setres[ug]id() are missing, provide them in terms of either
+ * setre[ug]id() or set{e,}[ug]id(), whichever is available.
+ * - Provide replacement setre[ug]id() or set{e,}[ug]id() if they are not
+ * available natively.
+ *
+ * There isn't a circular dependency because, right off the bat, we check that
+ * there's an end condition, and #error out otherwise.
+ */
+#if !defined(HAVE_SETREUID) && !(defined(HAVE_SETEUID) && defined(HAVE_SETUID))
+ /*
+ * If you run into this error, you have two options:
+ * - Teach zsh how to do the equivalent of setreuid() on your system
+ * - Remove support for PRIVILEGED option, and then remove the #error.
+ */
+# error "Don't know how to change UID"
+#endif
+#if !defined(HAVE_SETREGID) && !(defined(HAVE_SETEGID) && defined(HAVE_SETGID))
+ /* See above comment. */
+# error "Don't know how to change GID"
+#endif
+
+/* Provide setresuid(). */
+#ifndef HAVE_SETRESUID
+int setresuid(uid_t, uid_t, uid_t);
+# define HAVE_SETRESUID
+# define ZSH_IMPLEMENT_SETRESUID
# ifdef HAVE_SETREUID
-# define setuid(X) setreuid(X,X)
-# define setgid(X) setregid(X,X)
-# define HAVE_SETUID
+# define ZSH_HAVE_NATIVE_SETREUID
# endif
#endif
-/* can we set the effective user/group id of a process */
+/* Provide setresgid(). */
+#ifndef HAVE_SETRESGID
+int setresgid(gid_t, gid_t, gid_t);
+# define HAVE_SETRESGID
+# define ZSH_IMPLEMENT_SETRESGID
+# ifdef HAVE_SETREGID
+# define ZSH_HAVE_NATIVE_SETREGID
+# endif
+#endif
+/* Provide setreuid(). */
+#ifndef HAVE_SETREUID
+# define setreuid(X, Y) setresuid((X), (Y), -1)
+# define HAVE_SETREUID
+#endif
+
+/* Provide setregid(). */
+#ifndef HAVE_SETREGID
+# define setregid(X, Y) setresgid((X), (Y), -1)
+# define HAVE_SETREGID
+#endif
+
+/* Provide setuid(). */
+/* ### TODO: Either remove this (this function has been standard since 1985),
+ * ### or rewrite this without multiply-evaluating the argument */
+#ifndef HAVE_SETUID
+# define setuid(X) setreuid((X), (X))
+# define HAVE_SETUID
+#endif
+
+/* Provide setgid(). */
+#ifndef HAVE_SETGID
+/* ### TODO: Either remove this (this function has been standard since 1985),
+ * ### or rewrite this without multiply-evaluating the argument */
+# define setgid(X) setregid((X), (X))
+# define HAVE_SETGID
+#endif
+
+/* Provide seteuid(). */
#ifndef HAVE_SETEUID
-# ifdef HAVE_SETREUID
-# define seteuid(X) setreuid(-1,X)
-# define setegid(X) setregid(-1,X)
-# define HAVE_SETEUID
-# else
-# ifdef HAVE_SETRESUID
-# define seteuid(X) setresuid(-1,X,-1)
-# define setegid(X) setresgid(-1,X,-1)
-# define HAVE_SETEUID
-# endif
-# endif
+# define seteuid(X) setreuid(-1, (X))
+# define HAVE_SETEUID
+#endif
+
+/* Provide setegid(). */
+#ifndef HAVE_SETEGID
+# define setegid(X) setregid(-1, (X))
+# define HAVE_SETEGID
#endif
#ifdef HAVE_SYS_RESOURCE_H