summaryrefslogtreecommitdiff
path: root/Src/Modules
diff options
context:
space:
mode:
authorFrank Terbeck <ft@bewatermyfriend.org>2011-06-02 10:50:35 +0200
committerFrank Terbeck <ft@bewatermyfriend.org>2011-06-02 10:50:35 +0200
commit2438a0e95aa448f0aeda468752444306b44fe7d0 (patch)
tree8477e9c6af360f6a89af13e8cb5f2a4f9c1cff2c /Src/Modules
parentb495ba1e5a3ab1396844490ad8cad17dec23d6c1 (diff)
parent21266db1d9ae433bf1dcb196a4e258c00541b599 (diff)
downloadzsh-2438a0e95aa448f0aeda468752444306b44fe7d0.tar.gz
zsh-2438a0e95aa448f0aeda468752444306b44fe7d0.zip
Merge commit 'zsh-4.3.12' into debian
Diffstat (limited to 'Src/Modules')
-rw-r--r--Src/Modules/curses.c48
-rw-r--r--Src/Modules/datetime.c2
-rw-r--r--Src/Modules/files.c16
-rw-r--r--Src/Modules/parameter.c139
-rw-r--r--Src/Modules/termcap.c23
-rw-r--r--Src/Modules/zftp.c1
-rw-r--r--Src/Modules/zpty.c4
-rw-r--r--Src/Modules/zutil.c71
8 files changed, 262 insertions, 42 deletions
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index 29e088c70..41ad2c6e4 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -1069,8 +1069,47 @@ zccmd_input(const char *nam, char **args)
}
#endif
+ /*
+ * Some documentation for wgetch() says:
+
+ The behavior of getch and friends in the presence of handled signals
+ is unspecified in the SVr4 and XSI Curses documentation. Under his-
+ torical curses implementations, it varied depending on whether the
+ operating system's implementation of handled signal receipt interrupts
+ a read(2) call in progress or not, and also (in some implementations)
+ depending on whether an input timeout or non-blocking mode has been
+ set.
+
+ Programmers concerned about portability should be prepared for either
+ of two cases: (a) signal receipt does not interrupt getch; (b) signal
+ receipt interrupts getch and causes it to return ERR with errno set to
+ EINTR. Under the ncurses implementation, handled signals never inter-
+ rupt getch.
+
+ * The observed behavior, however, is different: wgetch() consistently
+ * returns ERR with EINTR when a signal is handled by the shell "trap"
+ * command mechanism. Further, it consistently returns ERR twice, the
+ * second time without even attempting to repeat the interrupted read,
+ * which has the side-effect of NOT updating errno. A third call will
+ * then begin reading again.
+ *
+ * Therefore, to properly implement signal trapping, we must (1) call
+ * wgetch() in a loop as long as errno remains EINTR, and (2) clear
+ * errno only before beginning the loop, not on every pass.
+ *
+ * There remains a potential bug here in that, if the caller has set
+ * a timeout for the read [see zccmd_timeout()] the countdown is very
+ * likely restarted on every call to wgetch(), so an interrupted call
+ * might wait much longer than desired.
+ */
+ errno = 0;
+
#ifdef HAVE_WGET_WCH
- switch (wget_wch(w->win, &wi)) {
+ while ((ret = wget_wch(w->win, &wi)) == ERR) {
+ if (errno != EINTR || errflag || retflag || breaks || exit_pending)
+ break;
+ }
+ switch (ret) {
case OK:
ret = wctomb(instr, (wchar_t)wi);
if (ret == 0) {
@@ -1092,9 +1131,10 @@ zccmd_input(const char *nam, char **args)
return 1;
}
#else
- ci = wgetch(w->win);
- if (ci == ERR)
- return 1;
+ while ((ci = wgetch(w->win)) == ERR) {
+ if (errno != EINTR || errflag || retflag || breaks || exit_pending)
+ return 1;
+ }
if (ci >= 256) {
keypadnum = ci;
*instr = '\0';
diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c
index 0dc42fda8..45818b968 100644
--- a/Src/Modules/datetime.c
+++ b/Src/Modules/datetime.c
@@ -146,7 +146,7 @@ bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
}
static zlong
-getcurrentsecs()
+getcurrentsecs(UNUSED(Param pm))
{
return (zlong) time(NULL);
}
diff --git a/Src/Modules/files.c b/Src/Modules/files.c
index 3fbccf576..f86b9c1e9 100644
--- a/Src/Modules/files.c
+++ b/Src/Modules/files.c
@@ -195,7 +195,7 @@ bin_rmdir(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
static int
bin_ln(char *nam, char **args, Options ops, int func)
{
- MoveFunc move;
+ MoveFunc movefn;
int flags, have_dir, err = 0;
char **a, *ptr, *rp, *buf;
struct stat st;
@@ -203,7 +203,7 @@ bin_ln(char *nam, char **args, Options ops, int func)
if(func == BIN_MV) {
- move = (MoveFunc) rename;
+ movefn = (MoveFunc) rename;
flags = OPT_ISSET(ops,'f') ? 0 : MV_ASKNW;
flags |= MV_ATOMIC;
} else {
@@ -212,11 +212,11 @@ bin_ln(char *nam, char **args, Options ops, int func)
if(OPT_ISSET(ops,'h') || OPT_ISSET(ops,'n'))
flags |= MV_NOCHASETARGET;
if(OPT_ISSET(ops,'s'))
- move = (MoveFunc) symlink;
+ movefn = (MoveFunc) symlink;
else
#endif
{
- move = (MoveFunc) link;
+ movefn = (MoveFunc) link;
if(!OPT_ISSET(ops,'d'))
flags |= MV_NODIRS;
}
@@ -267,7 +267,7 @@ bin_ln(char *nam, char **args, Options ops, int func)
else
args[1] = args[0];
}
- return domove(nam, move, args[0], args[1], flags);
+ return domove(nam, movefn, args[0], args[1], flags);
havedir:
buf = ztrdup(*a);
*a = NULL;
@@ -283,7 +283,7 @@ bin_ln(char *nam, char **args, Options ops, int func)
buf[blen] = 0;
buf = appstr(buf, ptr);
- err |= domove(nam, move, *args, buf, flags);
+ err |= domove(nam, movefn, *args, buf, flags);
}
zsfree(buf);
return err;
@@ -291,7 +291,7 @@ bin_ln(char *nam, char **args, Options ops, int func)
/**/
static int
-domove(char *nam, MoveFunc move, char *p, char *q, int flags)
+domove(char *nam, MoveFunc movefn, char *p, char *q, int flags)
{
struct stat st;
char *pbuf, *qbuf;
@@ -341,7 +341,7 @@ domove(char *nam, MoveFunc move, char *p, char *q, int flags)
if(doit && !(flags & MV_ATOMIC))
unlink(qbuf);
}
- if(move(pbuf, qbuf)) {
+ if(movefn(pbuf, qbuf)) {
zwarnnam(nam, "%s: %e", p, errno);
zsfree(pbuf);
return 1;
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 793249f32..092efa0c3 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -1820,6 +1820,141 @@ scanpmdissaliases(HashTable ht, ScanFunc func, int flags)
scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX|DISABLED);
}
+
+/* Functions for the usergroups special parameter */
+
+/*
+ * Get GID and names for groups of which the current user is a member.
+ */
+
+/**/
+static Groupset get_all_groups(void)
+{
+ Groupset gs = zhalloc(sizeof(*gs));
+ Groupmap gaptr;
+ gid_t *list, *lptr, egid;
+ int add_egid;
+ struct group *grptr;
+
+ egid = getegid();
+ add_egid = 1;
+ gs->num = getgroups(0, NULL);
+ if (gs->num > 0) {
+ list = zhalloc(gs->num * sizeof(*list));
+ if (getgroups(gs->num, list) < 0) {
+ return NULL;
+ }
+
+ /*
+ * It's unspecified whether $EGID is included in the
+ * group set, so check.
+ */
+ for (lptr = list; lptr < list + gs->num; lptr++) {
+ if (*lptr == egid) {
+ add_egid = 0;
+ break;
+ }
+ }
+ gs->array = zhalloc((gs->num + add_egid) * sizeof(*gs->array));
+ /* Put EGID if needed first */
+ gaptr = gs->array + add_egid;
+ for (lptr = list; lptr < list + gs->num; lptr++) {
+ gaptr->gid = *lptr;
+ gaptr++;
+ }
+ gs->num += add_egid;
+ } else {
+ /* Just use effective GID */
+ gs->num = 1;
+ gs->array = zhalloc(sizeof(*gs->array));
+ }
+ if (add_egid) {
+ gs->array->gid = egid;
+ }
+
+ /* Get group names */
+ for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
+ grptr = getgrgid(gaptr->gid);
+ if (!grptr) {
+ return NULL;
+ }
+ gaptr->name = dupstring(grptr->gr_name);
+ }
+
+ return gs;
+}
+
+/* Standard hash element lookup. */
+
+/**/
+static HashNode
+getpmusergroups(UNUSED(HashTable ht), const char *name)
+{
+ Param pm = NULL;
+ Groupset gs = get_all_groups();
+ Groupmap gaptr;
+
+ pm = (Param)hcalloc(sizeof(struct param));
+ pm->node.nam = dupstring(name);
+ pm->node.flags = PM_SCALAR | PM_READONLY;
+ pm->gsu.s = &nullsetscalar_gsu;
+
+ if (!gs) {
+ zerr("failed to retrieve groups for user: %e", errno);
+ pm->u.str = dupstring("");
+ pm->node.flags |= PM_UNSET;
+ return &pm->node;
+ }
+
+ for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
+ if (!strcmp(name, gaptr->name)) {
+ char buf[DIGBUFSIZE];
+
+ sprintf(buf, "%d", (int)gaptr->gid);
+ pm->u.str = dupstring(buf);
+ return &pm->node;
+ }
+ }
+
+ pm->u.str = dupstring("");
+ pm->node.flags |= PM_UNSET;
+ return &pm->node;
+}
+
+/* Standard hash scan. */
+
+/**/
+static void
+scanpmusergroups(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ Groupset gs = get_all_groups();
+ Groupmap gaptr;
+
+ if (!gs) {
+ zerr("failed to retrieve groups for user: %e", errno);
+ return;
+ }
+
+ memset((void *)&pm, 0, sizeof(pm));
+ pm.node.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
+ pm.node.nam = gaptr->name;
+ if (func != scancountparams &&
+ ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS))) {
+ char buf[DIGBUFSIZE];
+
+ sprintf(buf, "%d", (int)gaptr->gid);
+ pm.u.str = dupstring(buf);
+ }
+ func(&pm.node, flags);
+ }
+}
+
+
/* Table for defined parameters. */
struct pardef {
@@ -1926,7 +2061,9 @@ static struct paramdef partab[] = {
SPECIALPMDEF("saliases", 0,
&pmsaliases_gsu, getpmsalias, scanpmsaliases),
SPECIALPMDEF("userdirs", PM_READONLY,
- NULL, getpmuserdir, scanpmuserdirs)
+ NULL, getpmuserdir, scanpmuserdirs),
+ SPECIALPMDEF("usergroups", PM_READONLY,
+ NULL, getpmusergroups, scanpmusergroups)
};
static struct features module_features = {
diff --git a/Src/Modules/termcap.c b/Src/Modules/termcap.c
index 7367dade7..cd0e85885 100644
--- a/Src/Modules/termcap.c
+++ b/Src/Modules/termcap.c
@@ -35,34 +35,11 @@
*/
#include "../../config.h"
-#ifdef HAVE_TGETENT
-# if defined(ZSH_HAVE_CURSES_H) && defined(ZSH_HAVE_TERM_H)
-# define USES_TERM_H 1
-# else
-# ifdef HAVE_TERMCAP_H
-# define USES_TERMCAP_H 1
-# endif
-# endif
-#endif
-
#include "termcap.mdh"
#include "termcap.pro"
/**/
#ifdef HAVE_TGETENT
-# ifdef USES_TERM_H
-# ifdef HAVE_TERMIO_H
-# include <termio.h>
-# endif
-# ifdef ZSH_HAVE_CURSES_H
-# include "../zshcurses.h"
-# endif
-# include "../zshterm.h"
-# else
-# ifdef USES_TERMCAP_H
-# include <termcap.h>
-# endif
-# endif
#ifndef HAVE_BOOLCODES
static char *boolcodes[] = {
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index 1558d354f..8d688abd4 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -50,6 +50,7 @@ struct zftp_session;
typedef struct zftp_session *Zftp_session;
#include "tcp.h"
+#include "tcp.mdh"
#include "zftp.mdh"
#include "zftp.pro"
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index 2a81e68cb..25ec7dfea 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -351,8 +351,8 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
struct ttyinfo info;
if (ioctl(slave, TIOCGWINSZ, (char *) &info.winsize) == 0) {
- info.winsize.ws_row = lines;
- info.winsize.ws_col = columns;
+ info.winsize.ws_row = zterm_lines;
+ info.winsize.ws_col = zterm_columns;
ioctl(slave, TIOCSWINSZ, (char *) &info.winsize);
}
}
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 3c71edfa7..399c45f46 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -1405,6 +1405,8 @@ struct zoptdesc {
#define ZOF_OPT 2
#define ZOF_MULT 4
#define ZOF_SAME 8
+#define ZOF_MAP 16
+#define ZOF_CYC 32
struct zoptarr {
Zoptarr next;
@@ -1459,6 +1461,34 @@ get_opt_arr(char *name)
return NULL;
}
+static Zoptdesc
+map_opt_desc(Zoptdesc start)
+{
+ Zoptdesc map = NULL;
+
+ if (!start || !(start->flags & ZOF_MAP))
+ return start;
+
+ map = get_opt_desc(start->arr->name);
+
+ if (!map)
+ return start;
+
+ if (map == start) {
+ start->flags &= ~ZOF_MAP; /* optimize */
+ return start;
+ }
+
+ if (map->flags & ZOF_CYC)
+ return NULL;
+
+ start->flags |= ZOF_CYC;
+ map = map_opt_desc(map);
+ start->flags &= ~ZOF_CYC;
+
+ return map;
+}
+
static void
add_opt_val(Zoptdesc d, char *arg)
{
@@ -1466,6 +1496,10 @@ add_opt_val(Zoptdesc d, char *arg)
char *n = dyncat("-", d->name);
int new = 0;
+ Zoptdesc map = map_opt_desc(d);
+ if (map)
+ d = map;
+
if (!(d->flags & ZOF_MULT))
v = d->vals;
if (!v) {
@@ -1513,7 +1547,7 @@ static int
bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
{
char *o, *p, *n, **pp, **aval, **ap, *assoc = NULL, **cp, **np;
- int del = 0, f, extract = 0, keep = 0;
+ int del = 0, flags = 0, extract = 0, keep = 0;
Zoptdesc sopts[256], d;
Zoptarr a, defarr = NULL;
Zoptval v;
@@ -1531,6 +1565,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
case '-':
if (o[2])
args--;
+ /* else unreachable, default parsing removes "--" */
o = NULL;
break;
case 'D':
@@ -1557,6 +1592,14 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
}
keep = 1;
break;
+ case 'M':
+ if (o[2]) {
+ args--;
+ o = NULL;
+ break;
+ }
+ flags |= ZOF_MAP;
+ break;
case 'a':
if (defarr) {
zwarnnam(nam, "default array given more than once");
@@ -1578,6 +1621,10 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
opt_arrs = defarr;
break;
case 'A':
+ if (assoc) {
+ zwarnnam(nam, "associative array given more than once");
+ return 1;
+ }
if (o[2])
assoc = o + 2;
else if (*args)
@@ -1587,6 +1634,11 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
return 1;
}
break;
+ default:
+ /* Anything else is an option description */
+ args--;
+ o = NULL;
+ break;
}
if (!o) {
o = "";
@@ -1602,11 +1654,11 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
return 1;
}
while ((o = dupstring(*args++))) {
+ int f = 0;
if (!*o) {
zwarnnam(nam, "invalid option description: %s", o);
return 1;
}
- f = 0;
for (p = o; *p; p++) {
if (*p == '\\' && p[1])
p++;
@@ -1633,6 +1685,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
a = NULL;
if (*p == '=') {
*p++ = '\0';
+ f |= flags;
if (!(a = get_opt_arr(p))) {
a = (Zoptarr) zhalloc(sizeof(*a));
a->name = p;
@@ -1666,6 +1719,10 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
opt_descs = d;
if (!o[1])
sopts[STOUC(*o)] = d;
+ if ((flags & ZOF_MAP) && !map_opt_desc(d)) {
+ zwarnnam(nam, "cyclic option mapping: %s", args[-1]);
+ return 1;
+ }
}
np = cp = pp = ((extract && del) ? arrdup(pparams) : pparams);
for (; (o = *pp); pp++) {
@@ -1732,12 +1789,20 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
add_opt_val(d, NULL);
}
}
+
+ if (flags & ZOF_MAP) {
+ for (d = opt_descs; d; d = d->next)
+ if (d->arr && !d->vals && (d->flags & ZOF_MAP)) {
+ if (d->arr->num == 0 && get_opt_desc(d->arr->name))
+ d->arr->num = -1; /* this is not a real array */
+ }
+ }
if (extract && del)
while (*pp)
*cp++ = *pp++;
for (a = opt_arrs; a; a = a->next) {
- if (!keep || a->num) {
+ if (a->num >= 0 && (!keep || a->num)) {
aval = (char **) zalloc((a->num + 1) * sizeof(char *));
for (ap = aval, v = a->vals; v; ap++, v = v->next) {
if (v->str)