summaryrefslogtreecommitdiffstats
path: root/Src/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Modules')
-rw-r--r--Src/Modules/attr.c8
-rw-r--r--Src/Modules/attr.mdd2
-rw-r--r--Src/Modules/cap.c26
-rw-r--r--Src/Modules/clone.c6
-rw-r--r--Src/Modules/curses.c139
-rw-r--r--Src/Modules/db_gdbm.c2
-rw-r--r--Src/Modules/hlgroup.c4
-rw-r--r--Src/Modules/ksh93.c10
-rw-r--r--Src/Modules/langinfo.c13
-rw-r--r--Src/Modules/langinfo.mdd2
-rw-r--r--Src/Modules/nearcolor.c18
-rw-r--r--Src/Modules/parameter.c55
-rw-r--r--Src/Modules/pcre.c2
-rw-r--r--Src/Modules/random.c43
-rw-r--r--Src/Modules/random_real.c2
-rw-r--r--Src/Modules/regex.c2
-rw-r--r--Src/Modules/socket.c27
-rw-r--r--Src/Modules/stat.c6
-rw-r--r--Src/Modules/system.c5
-rw-r--r--Src/Modules/tcp.c48
-rw-r--r--Src/Modules/tcp.h5
-rw-r--r--Src/Modules/termcap.c41
-rw-r--r--Src/Modules/terminfo.c34
-rw-r--r--Src/Modules/watch.c22
-rw-r--r--Src/Modules/zftp.c22
-rw-r--r--Src/Modules/zpty.c51
-rw-r--r--Src/Modules/zselect.c4
-rw-r--r--Src/Modules/zutil.c228
28 files changed, 466 insertions, 361 deletions
diff --git a/Src/Modules/attr.c b/Src/Modules/attr.c
index f4bd04982..dd29e42f6 100644
--- a/Src/Modules/attr.c
+++ b/Src/Modules/attr.c
@@ -68,7 +68,7 @@ xsetxattr(const char *path, const char *name, const void *value,
size_t size, int flags, int symlink)
{
#ifdef XATTR_EXTRA_ARGS
- return setxattr(path, name, value, size, 0, flags | symlink ? XATTR_NOFOLLOW : 0);
+ return setxattr(path, name, value, size, 0, flags | (symlink ? XATTR_NOFOLLOW : 0));
#else
switch (symlink) {
case 0:
@@ -98,7 +98,8 @@ static int
bin_getattr(char *nam, char **argv, Options ops, UNUSED(int func))
{
int ret = 0;
- int val_len = 0, attr_len = 0, slen;
+ int slen;
+ ssize_t val_len = 0, attr_len = 0;
char *value, *file = argv[0], *attr = argv[1], *param = argv[2];
int symlink = OPT_ISSET(ops, 'h');
@@ -169,7 +170,8 @@ static int
bin_listattr(char *nam, char **argv, Options ops, UNUSED(int func))
{
int ret = 0;
- int val_len, list_len = 0, slen;
+ int slen;
+ ssize_t val_len, list_len = 0;
char *value, *file = argv[0], *param = argv[1];
int symlink = OPT_ISSET(ops, 'h');
diff --git a/Src/Modules/attr.mdd b/Src/Modules/attr.mdd
index fbe917bbf..3b765f489 100644
--- a/Src/Modules/attr.mdd
+++ b/Src/Modules/attr.mdd
@@ -7,6 +7,6 @@ fi
'
load=no
-autofeatures="b:zgetattr b:zsetattr b:zdelattr"
+autofeatures="b:zgetattr b:zsetattr b:zdelattr b:zlistattr"
objects="attr.o"
diff --git a/Src/Modules/cap.c b/Src/Modules/cap.c
index c79c9f07c..6db7cbc2a 100644
--- a/Src/Modules/cap.c
+++ b/Src/Modules/cap.c
@@ -37,14 +37,14 @@ bin_cap(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
{
int ret = 0;
cap_t caps;
- if(*argv) {
+ if (*argv) {
unmetafy(*argv, NULL);
caps = cap_from_text(*argv);
- if(!caps) {
+ if (!caps) {
zwarnnam(nam, "invalid capability string");
return 1;
}
- if(cap_set_proc(caps)) {
+ if (cap_set_proc(caps)) {
zwarnnam(nam, "can't change capabilities: %e", errno);
ret = 1;
}
@@ -52,15 +52,18 @@ bin_cap(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
char *result = NULL;
ssize_t length;
caps = cap_get_proc();
- if(caps)
+ if (caps)
result = cap_to_text(caps, &length);
- if(!caps || !result) {
+ if (!caps || !result) {
zwarnnam(nam, "can't get capabilities: %e", errno);
ret = 1;
} else
puts(result);
+ if (result)
+ cap_free(result);
}
- cap_free(caps);
+ if (caps)
+ cap_free(caps);
return ret;
}
@@ -75,14 +78,17 @@ bin_getcap(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
cap_t caps;
caps = cap_get_file(unmetafy(dupstring(*argv), NULL));
- if(caps)
+ if (caps)
result = cap_to_text(caps, &length);
if (!caps || !result) {
zwarnnam(nam, "%s: %e", *argv, errno);
ret = 1;
} else
printf("%s %s\n", *argv, result);
- cap_free(caps);
+ if (result)
+ cap_free(result);
+ if (caps)
+ cap_free(caps);
} while(*++argv);
return ret;
}
@@ -95,13 +101,13 @@ bin_setcap(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
unmetafy(*argv, NULL);
caps = cap_from_text(*argv++);
- if(!caps) {
+ if (!caps) {
zwarnnam(nam, "invalid capability string");
return 1;
}
do {
- if(cap_set_file(unmetafy(dupstring(*argv), NULL), caps)) {
+ if (cap_set_file(unmetafy(dupstring(*argv), NULL), caps)) {
zwarnnam(nam, "%s: %e", *argv, errno);
ret = 1;
}
diff --git a/Src/Modules/clone.c b/Src/Modules/clone.c
index 4b2655505..db6d4b401 100644
--- a/Src/Modules/clone.c
+++ b/Src/Modules/clone.c
@@ -60,9 +60,9 @@ bin_clone(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
if (setsid() != mypid)
zwarnnam(nam, "failed to create new session: %e", errno);
#elif defined(TIOCNOTTY)
- if (ioctl(SHTTY, TIOCNOTTY, 0))
- zwarnnam(*args, "%e", errno);
- setpgrp(0L, mypid);
+ if (ioctl(SHTTY, TIOCNOTTY, 0))
+ zwarnnam(nam, "%e", errno);
+ setpgrp(0L, mypid);
#endif
dup2(ttyfd,0);
dup2(ttyfd,1);
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index 8950cc153..f07ce7fd2 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -260,7 +260,7 @@ zcurses_validate_window(char *win, int criteria)
{
LinkNode target;
- if (win==NULL || strlen(win) < 1) {
+ if (win==NULL || !*win) {
zc_errno = ZCURSES_EINVALID;
return NULL;
}
@@ -284,8 +284,14 @@ zcurses_validate_window(char *win, int criteria)
static int
zcurses_free_window(ZCWin w)
{
- if (!(w->flags & ZCWF_PERMANENT) && delwin(w->win)!=OK)
- return 1;
+ int ret = 0;
+
+ if (!(w->flags & ZCWF_PERMANENT) && delwin(w->win)!=OK) {
+ DPUTS2(1, "BUG: Failed to delete ncurses window %s with %d children",
+ w->name ? w->name : "(null)",
+ w->children ? countlinknodes(w->children) : 0);
+ ret = 1;
+ }
if (w->name)
zsfree(w->name);
@@ -295,7 +301,7 @@ zcurses_free_window(ZCWin w)
zfree(w, sizeof(struct zc_win));
- return 0;
+ return ret;
}
static struct zcurses_namenumberpair *
@@ -378,6 +384,7 @@ zcurses_colorget(const char *nam, char *colorpair)
++next_cp;
if (next_cp >= COLOR_PAIRS || init_pair(next_cp, f, b) == ERR) {
+ --next_cp;
zsfree(cp);
return NULL;
}
@@ -385,6 +392,7 @@ zcurses_colorget(const char *nam, char *colorpair)
cpn = (Colorpairnode)zshcalloc(sizeof(struct colorpairnode));
if (!cpn) {
+ --next_cp;
zsfree(cp);
return NULL;
}
@@ -507,7 +515,7 @@ zccmd_addwin(const char *nam, char **args)
if (zcurses_validate_window(args[0], ZCURSES_UNUSED) == NULL &&
zc_errno) {
- zerrnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
return 1;
}
@@ -527,8 +535,7 @@ zccmd_addwin(const char *nam, char **args)
node = zcurses_validate_window(args[5], ZCURSES_USED);
if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0],
- 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[5]);
zsfree(w->name);
zfree(w, sizeof(struct zc_win));
return 1;
@@ -555,7 +562,9 @@ zccmd_addwin(const char *nam, char **args)
return 1;
}
- zinsertlinknode(zcurses_windows, lastnode(zcurses_windows), (void *)w);
+ /* prepend window so that freelinklist will free children before parents,
+ * otherwise they will be leaked */
+ zinsertlinknode(zcurses_windows, (LinkNode)zcurses_windows, (void *)w);
return 0;
}
@@ -622,6 +631,9 @@ zccmd_delwin(const char *nam, char **args)
if (w->name)
zsfree(w->name);
+ if (w->children)
+ freelinklist(w->children, (FreeFunc)NULL);
+
zfree((ZCWin)remnode(zcurses_windows, node), sizeof(struct zc_win));
return ret;
@@ -641,8 +653,7 @@ zccmd_refresh(const char *nam, char **args)
node = zcurses_validate_window(args[0], ZCURSES_USED);
if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0],
- 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
return 1;
}
@@ -727,6 +738,7 @@ zccmd_char(const char *nam, char **args)
#ifdef HAVE_SETCCHAR
wchar_t c;
cchar_t cc;
+ size_t ret;
#endif
node = zcurses_validate_window(args[0], ZCURSES_USED);
@@ -738,7 +750,8 @@ zccmd_char(const char *nam, char **args)
w = (ZCWin)getdata(node);
#ifdef HAVE_SETCCHAR
- if (mbrtowc(&c, args[1], MB_CUR_MAX, NULL) < 1)
+ ret = mbrtowc(&c, args[1], MB_CUR_MAX, NULL);
+ if (ret == 0 || ret == MB_INVALID || ret == MB_INCOMPLETE)
return 1;
if (setcchar(&cc, &c, A_NORMAL, 0, NULL)==ERR)
@@ -834,6 +847,14 @@ zccmd_endwin(UNUSED(const char *nam), UNUSED(char **args))
* doing stuff with shttyinfo when we shouldn't really be.
*/
gettyinfo(&shttyinfo);
+ freelinklist(zcurses_windows, (FreeFunc) zcurses_free_window);
+ zcurses_windows = znewlinklist();
+ if (zcurses_colorpairs) {
+ deletehashtable(zcurses_colorpairs);
+ zcurses_colorpairs = NULL;
+ }
+ next_cp = 0;
+ zc_color_phase = 0;
}
return 0;
}
@@ -911,7 +932,14 @@ zccmd_bg(const char *nam, char **args)
ZCWin w;
char **attrs;
int ret = 0;
+#ifdef HAVE_SETCCHAR
+ cchar_t cc;
+ wchar_t wch = L' ';
+ attr_t bg_attrs = A_NORMAL;
+ short bg_cp = 0;
+#else
chtype ch = 0;
+#endif
if (!args[0])
return 1;
@@ -924,12 +952,20 @@ zccmd_bg(const char *nam, char **args)
w = (ZCWin)getdata(node);
- for(attrs = args+1; *attrs; attrs++) {
+ for (attrs = args+1; *attrs; attrs++) {
if (strchr(*attrs, '/')) {
Colorpairnode cpn;
if ((cpn = zcurses_colorget(nam, *attrs)) == NULL)
ret = 1;
- else if (cpn->colorpair >= 256) {
+ else
+#ifdef HAVE_SETCCHAR
+ bg_cp = (short)cpn->colorpair;
+ } else if (**attrs == '@') {
+ wch = (wchar_t)(unsigned char)((*attrs)[1] == Meta
+ ? (*attrs)[2] ^ 32
+ : (*attrs)[1]);
+#else
+ if (cpn->colorpair >= 256) {
/* pretty unlikely, but... */
zwarnnam(nam, "bg color pair %s has index (%d) too large (max 255)",
cpn->node.nam, cpn->colorpair);
@@ -939,6 +975,7 @@ zccmd_bg(const char *nam, char **args)
}
} else if (**attrs == '@') {
ch |= (*attrs)[1] == Meta ? (*attrs)[2] ^ 32 : (*attrs)[1];
+#endif
} else {
char *ptr;
int onoff;
@@ -962,14 +999,31 @@ zccmd_bg(const char *nam, char **args)
zwarnnam(nam, "attribute `%s' not known", ptr);
ret = 1;
} else {
+#ifdef HAVE_SETCCHAR
+ switch (onoff) {
+ case ZCURSES_ATTRON:
+ bg_attrs |= zca->number;
+ break;
+ case ZCURSES_ATTROFF:
+ bg_attrs &= ~zca->number;
+ break;
+ }
+ }
+ }
+ }
+
+ if (ret == 0) {
+ if (setcchar(&cc, &wch, bg_attrs, bg_cp, NULL) == ERR)
+ return 1;
+ return wbkgrnd(w->win, &cc) != OK;
+ }
+#else
switch(onoff) {
case ZCURSES_ATTRON:
- if (wattron(w->win, zca->number) == ERR)
- ret = 1;
+ ch |= zca->number;
break;
case ZCURSES_ATTROFF:
- if (wattroff(w->win, zca->number) == ERR)
- ret = 1;
+ ch &= ~zca->number;
break;
}
}
@@ -978,6 +1032,7 @@ zccmd_bg(const char *nam, char **args)
if (ret == 0)
return wbkgd(w->win, ch) != OK;
+#endif
return ret;
}
@@ -998,12 +1053,10 @@ zccmd_scroll(const char *nam, char **args)
w = (ZCWin)getdata(node);
if (!strcmp(args[1], "on")) {
- if (scrollok(w->win, TRUE) == ERR)
- return 1;
+ scrollok(w->win, TRUE);
w->flags |= ZCWF_SCROLL;
} else if (!strcmp(args[1], "off")) {
- if (scrollok(w->win, FALSE) == ERR)
- return 1;
+ scrollok(w->win, FALSE);
w->flags &= ~ZCWF_SCROLL;
} else {
char *endptr;
@@ -1050,17 +1103,13 @@ zccmd_input(const char *nam, char **args)
w = (ZCWin)getdata(node);
- if (nargs >= 3) {
- keypad(w->win, TRUE);
- } else {
- keypad(w->win, FALSE);
- }
+ keypad(w->win, nargs >= 3);
if (nargs >= 4) {
#ifdef NCURSES_MOUSE_VERSION
if (!(zcurses_flags & ZCF_MOUSE_ACTIVE) ||
(zcurses_flags & ZCF_MOUSE_MASK_CHANGED)) {
- if (mousemask(zcurses_mouse_mask, NULL) == (mmask_t)ERR) {
+ if (!mousemask(zcurses_mouse_mask, NULL)) {
zwarnnam(nam, "current mouse mode is not supported");
return 1;
}
@@ -1112,10 +1161,8 @@ zccmd_input(const char *nam, char **args)
switch (ret) {
case OK:
ret = wctomb(instr, (wchar_t)wi);
- if (ret == 0) {
- instr[0] = Meta;
- instr[1] = '\0' ^ 32;
- instr[2] = '\0';
+ if (ret <= 0) {
+ return 1;
} else {
(void)metafy(instr, ret, META_NOALLOC);
}
@@ -1306,8 +1353,7 @@ zccmd_mouse(const char *nam, char **args)
zwarnnam(nam, "mouse delay requires an integer argument");
return 1;
}
- if (mouseinterval((int)delay) != OK)
- ret = 1;
+ mouseinterval((int)delay);
} else {
char *arg = *args;
int onoff = 1;
@@ -1373,8 +1419,7 @@ zccmd_position(const char *nam, char **args)
}
array[6] = NULL;
- setaparam(args[1], array);
- return 0;
+ return !setaparam(args[1], array);
}
@@ -1412,8 +1457,11 @@ zccmd_querychar(const char *nam, char **args)
if (getcchar(&cc, &c, &attrs, &cp, NULL) == ERR)
return 1;
- /* Hmmm... I always get 0 for cp, whereas the following works... */
- cp = PAIR_NUMBER(winch(w->win));
+ /* only overwrite with workaround if we do get 0, the winch method
+ * is limited to 256 color pairs */
+ if (!cp)
+ /* Hmmm... I always get 0 for cp, whereas the following works... */
+ cp = PAIR_NUMBER(winch(w->win));
count = wctomb(instr, c);
if (count == -1)
@@ -1423,6 +1471,7 @@ zccmd_querychar(const char *nam, char **args)
inc = winch(w->win);
/* I think the following is correct, the manual is a little terse */
cp = PAIR_NUMBER(inc);
+ attrs = inc & A_ATTRIBUTES;
inc &= A_CHARTEXT;
if (imeta(inc)) {
instr[0] = Meta;
@@ -1432,7 +1481,6 @@ zccmd_querychar(const char *nam, char **args)
instr[0] = (unsigned char) inc;
instr[1] = '\0';
}
- attrs = inc;
#endif
/*
@@ -1568,10 +1616,10 @@ static int
bin_zcurses(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
{
char **saargs;
- struct zcurses_subcommand *zcsc;
+ const struct zcurses_subcommand *zcsc;
int num_args;
- struct zcurses_subcommand scs[] = {
+ static const struct zcurses_subcommand scs[] = {
{"init", zccmd_init, 0, 0},
{"addwin", zccmd_addwin, 5, 6},
{"delwin", zccmd_delwin, 1, 1},
@@ -1671,14 +1719,14 @@ static char **
zcurses_windowsgetfn(UNUSED(Param pm))
{
LinkNode node;
- char **arr, **arrptr;
+ char **arr;
int count = countlinknodes(zcurses_windows);
- arrptr = arr = (char **)zhalloc((count+1) * sizeof(char *));
+ arr = (char **)zhalloc((count+1) * sizeof(char *)) + count;
+ *arr = NULL;
for (node = firstnode(zcurses_windows); node; incnode(node))
- *arrptr++ = dupstring(((ZCWin)getdata(node))->name);
- *arrptr = NULL;
+ *--arr = dupstring(((ZCWin)getdata(node))->name);
return arr;
}
@@ -1774,9 +1822,8 @@ boot_(UNUSED(Module m))
int
cleanup_(Module m)
{
+ zccmd_endwin(NULL, NULL);
freelinklist(zcurses_windows, (FreeFunc) zcurses_free_window);
- if (zcurses_colorpairs)
- deletehashtable(zcurses_colorpairs);
return setfeatureenables(m, &module_features, NULL);
}
diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index 7d1720de5..34f577e30 100644
--- a/Src/Modules/db_gdbm.c
+++ b/Src/Modules/db_gdbm.c
@@ -150,7 +150,7 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
* We need to do this before attempting to open the DB
* in case this variable is already tied to a DB.
*
- * This can fail if the variable is readonly or restricted.
+ * This can fail if the variable is readonly.
* We could call unsetparam() and check errflag instead
* of the return status.
*/
diff --git a/Src/Modules/hlgroup.c b/Src/Modules/hlgroup.c
index 1dc6ac2ef..819b54696 100644
--- a/Src/Modules/hlgroup.c
+++ b/Src/Modules/hlgroup.c
@@ -124,6 +124,8 @@ scangroup(ScanFunc func, int flags, int sgr)
PM_TYPE(v->pm->node.flags) != PM_HASHED)
return;
hlg = v->pm->gsu.h->getfn(v->pm);
+ if (!hlg)
+ return;
memset((void *)&pm, 0, sizeof(struct param));
pm.node.flags = PM_SCALAR;
@@ -131,6 +133,8 @@ scangroup(ScanFunc func, int flags, int sgr)
for (i = 0; i < hlg->hsize; i++)
for (hn = hlg->nodes[i]; hn; hn = hn->next) {
+ if (((Param) hn)->node.flags & PM_UNSET)
+ continue;
pm.u.str = convertattr(((Param) hn)->u.str, sgr);
pm.node.nam = hn->nam;
func(&pm.node, flags);
diff --git a/Src/Modules/ksh93.c b/Src/Modules/ksh93.c
index fa0785cda..159a4fe7c 100644
--- a/Src/Modules/ksh93.c
+++ b/Src/Modules/ksh93.c
@@ -73,11 +73,13 @@ matchgetfn(Param pm)
if (zsh_match && *zsh_match) {
if (isset(KSHARRAYS)) {
char **ap =
- (char **) zalloc(sizeof(char *) * (arrlen(zsh_match)+1));
+ (char **) zalloc(sizeof(char *) * (arrlen(zsh_match)+2));
+ char *match;
pm->u.arr = ap;
- *ap++ = ztrdup(getsparam("MATCH"));
+ match = ztrdup(getsparam("MATCH"));
+ *ap++ = match ? match : ztrdup("");
while (*zsh_match)
- *ap = ztrdup(*zsh_match++);
+ *ap++ = ztrdup(*zsh_match++);
} else
pm->u.arr = zarrdup(zsh_match);
} else if (isset(KSHARRAYS)) {
@@ -159,7 +161,7 @@ ksh93_wrapper(Eprog prog, FuncWrap w, char *name)
#define LOCAL_NAMEREF (PM_LOCAL|PM_UNSET|PM_NAMEREF)
if ((pm = createparam(".sh.command", LOCAL_NAMEREF))) {
pm->level = locallevel; /* Why is this necessary? */
- /* Force scoping by assignent hack */
+ /* Force scoping by assignment hack */
setloopvar(".sh.command", "ZSH_DEBUG_CMD");
pm->node.flags |= PM_READONLY;
}
diff --git a/Src/Modules/langinfo.c b/Src/Modules/langinfo.c
index 520b0370c..3f5af82f2 100644
--- a/Src/Modules/langinfo.c
+++ b/Src/Modules/langinfo.c
@@ -384,7 +384,7 @@ liitem(const char *name)
nlcode = &nl_vals[0];
for (element = (char **)nl_names; *element; element++, nlcode++) {
- if ((!strcmp(*element, name)))
+ if (!strcmp(*element, name))
return nlcode;
}
@@ -395,23 +395,19 @@ liitem(const char *name)
static HashNode
getlanginfo(UNUSED(HashTable ht), const char *name)
{
- int len;
nl_item *elem;
char *listr, *nameu;
Param pm = NULL;
nameu = dupstring(name);
- unmetafy(nameu, &len);
+ unmetafy(nameu, NULL);
pm = (Param) hcalloc(sizeof(struct param));
- pm->node.nam = nameu;
+ pm->node.nam = dupstring(name);
pm->node.flags = PM_READONLY | PM_SCALAR;
pm->gsu.s = &nullsetscalar_gsu;
- if(name)
- elem = liitem(name);
- else
- elem = NULL;
+ elem = liitem(nameu);
if (elem && (listr = nl_langinfo(*elem))) {
pm->u.str = dupstring(listr);
@@ -445,7 +441,6 @@ scanlanginfo(UNUSED(HashTable ht), ScanFunc func, int flags)
func(&pm->node, flags);
}
}
-
}
static struct paramdef partab[] = {
diff --git a/Src/Modules/langinfo.mdd b/Src/Modules/langinfo.mdd
index d56898d42..33166746c 100644
--- a/Src/Modules/langinfo.mdd
+++ b/Src/Modules/langinfo.mdd
@@ -1,6 +1,6 @@
name=zsh/langinfo
-link=`if test x$ac_cv_func_nl_langinfo; then echo either; else echo no; fi`
+link=`if test x$ac_cv_func_nl_langinfo = xyes; then echo either; else echo no; fi`
load=no
autofeatures="p:langinfo"
diff --git a/Src/Modules/nearcolor.c b/Src/Modules/nearcolor.c
index 83d7118b0..08bc7d8b1 100644
--- a/Src/Modules/nearcolor.c
+++ b/Src/Modules/nearcolor.c
@@ -37,13 +37,19 @@ struct cielab {
};
typedef struct cielab *Cielab;
+static inline double
+square(double a)
+{
+ return a*a;
+}
+
static double
deltae(Cielab lab1, Cielab lab2)
{
/* taking square root unnecessary as we're just comparing values */
- return pow(lab1->L - lab2->L, 2) +
- pow(lab1->a - lab2->a, 2) +
- pow(lab1->b - lab2->b, 2);
+ return square(lab1->L - lab2->L) +
+ square(lab1->a - lab2->a) +
+ square(lab1->b - lab2->b);
}
static void
@@ -73,7 +79,7 @@ RGBtoLAB(int red, int green, int blue, Cielab lab)
static int
mapRGBto88(int red, int green, int blue)
{
- int component[] = { 0, 0x8b, 0xcd, 0xff, 0x2e, 0x5c, 0x8b, 0xa2, 0xb9, 0xd0, 0xe7 };
+ int component[] = { 0, 0x8b, 0xcd, 0xff, 0x2e, 0x5c, 0x73, 0x8b, 0xa2, 0xb9, 0xd0, 0xe7 };
struct cielab orig, next;
double nextl, bestl = -1;
int r, g, b;
@@ -83,7 +89,7 @@ mapRGBto88(int red, int green, int blue)
RGBtoLAB(red, green, blue, &orig);
/* try every one of the 72 colours */
- for (r = 0; r < 11; r++) {
+ for (r = 0; r < 12; r++) {
for (g = 0; g <= 3; g++) {
for (b = 0; b <= 3; b++) {
if (r > 3) g = b = r; /* advance inner loops to the block of greys */
@@ -99,7 +105,7 @@ mapRGBto88(int red, int green, int blue)
}
}
- return (comp_r > 3) ? 77 + comp_r :
+ return (comp_r > 3) ? 76 + comp_r :
16 + (comp_r * 16) + (comp_g * 4) + comp_b;
}
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 779dcd024..6d1f74d22 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -40,7 +40,7 @@ static int incleanup;
/**/
static char *
-paramtypestr(Param pm)
+paramtypestr(Param pm, int append)
{
char *val = NULL;
int f = pm->node.flags;
@@ -91,6 +91,13 @@ paramtypestr(Param pm)
} else
val = dupstring("");
+ if (append) {
+ if ((pm->node.flags & PM_NAMEREF) && pm->u.str && *(pm->u.str) &&
+ (pm = (Param) realparamtab->getnode(realparamtab, pm->node.nam)) &&
+ !(pm->node.flags & PM_UNSET)) {
+ val = zhtricat(val, "-", paramtypestr(pm, 0));
+ }
+ }
return val;
}
@@ -106,12 +113,7 @@ getpmparameter(UNUSED(HashTable ht), const char *name)
pm->gsu.s = &nullsetscalar_gsu;
if ((rpm = (Param) realparamtab->getnode2(realparamtab, name)) &&
!(rpm->node.flags & PM_UNSET)) {
- pm->u.str = paramtypestr(rpm);
- if ((rpm->node.flags & PM_NAMEREF) && rpm->u.str && *(rpm->u.str) &&
- (rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
- !(rpm->node.flags & PM_UNSET)) {
- pm->u.str = zhtricat(pm->u.str, "-", paramtypestr(rpm));
- }
+ pm->u.str = paramtypestr(rpm, 1);
} else {
pm->u.str = dupstring("");
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
@@ -139,7 +141,7 @@ scanpmparameters(UNUSED(HashTable ht), ScanFunc func, int flags)
if (func != scancountparams &&
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
!(flags & SCANPM_WANTKEYS)))
- pm.u.str = paramtypestr((Param) hn);
+ pm.u.str = paramtypestr((Param) hn, 1);
func(&pm.node, flags);
}
}
@@ -150,17 +152,12 @@ scanpmparameters(UNUSED(HashTable ht), ScanFunc func, int flags)
static void
setpmcommand(Param pm, char *value)
{
- if (isset(RESTRICTED)) {
- zwarn("restricted: %s", value);
- zsfree(value);
- } else {
- Cmdnam cn = zshcalloc(sizeof(*cn));
+ Cmdnam cn = zshcalloc(sizeof(*cn));
- cn->node.flags = HASHED;
- cn->u.cmd = value;
+ cn->node.flags = HASHED;
+ cn->u.cmd = value;
- cmdnamtab->addnode(cmdnamtab, ztrdup(pm->node.nam), &cn->node);
- }
+ cmdnamtab->addnode(cmdnamtab, ztrdup(pm->node.nam), &cn->node);
}
/**/
@@ -967,6 +964,7 @@ setpmoptions(Param pm, HashTable ht)
for (hn = ht->nodes[i]; hn; hn = hn->next) {
struct value v;
char *val;
+ int n;
v.scanflags = v.valflags = v.start = 0;
v.end = -1;
@@ -976,8 +974,9 @@ setpmoptions(Param pm, HashTable ht)
val = getstrvalue(&v);
if (!val || (strcmp(val, "on") && strcmp(val, "off")))
zwarn("invalid value: %s", val);
- else if (dosetopt(optlookup(hn->nam),
- (val && strcmp(val, "off")), 0, opts))
+ else if (!(n = optlookup(hn->nam)))
+ zwarn("no such option: %s", hn->nam);
+ else if (dosetopt(n, (val && strcmp(val, "off")), 0, opts))
zwarn("can't change option: %s", hn->nam);
}
/* See setpmcommands() above */
@@ -1293,7 +1292,7 @@ getpmjobtext(UNUSED(HashTable ht), const char *name)
selectjobtab(&jtab, &jmax);
- job = strtod(name, &pend);
+ job = strtol(name, &pend, 10);
/* Non-numeric keys are looked up by job name */
if (*pend)
job = getjob(name, NULL);
@@ -1367,7 +1366,8 @@ pmjobstate(Job jtab, int job)
state = "running";
else if (WIFEXITED(pn->status)) {
if (WEXITSTATUS(pn->status))
- sprintf((state = buf2), "exit %d", (pn->status));
+ sprintf((state = buf2), "exit %d",
+ WEXITSTATUS(pn->status));
else
state = "done";
} else if (WIFSTOPPED(pn->status))
@@ -1401,7 +1401,7 @@ getpmjobstate(UNUSED(HashTable ht), const char *name)
selectjobtab(&jtab, &jmax);
- job = strtod(name, &pend);
+ job = strtol(name, &pend, 10);
if (*pend)
job = getjob(name, NULL);
if (job >= 1 && job <= jmax &&
@@ -1473,7 +1473,7 @@ getpmjobdir(UNUSED(HashTable ht), const char *name)
selectjobtab(&jtab, &jmax);
- job = strtod(name, &pend);
+ job = strtol(name, &pend, 10);
if (*pend)
job = getjob(name, NULL);
if (job >= 1 && job <= jmax &&
@@ -2091,9 +2091,12 @@ static Groupset get_all_groups(void)
for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
grptr = getgrgid(gaptr->gid);
if (!grptr) {
- return NULL;
- }
- gaptr->name = dupstring(grptr->gr_name);
+ /* a group we're in has been deleted from /etc/groups */
+ char buf[DIGBUFSIZE];
+ convbase(buf, (zlong)gaptr->gid, 10);
+ gaptr->name = dupstring(buf);
+ } else
+ gaptr->name = dupstring(grptr->gr_name);
}
return gs;
diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c
index 67157cc01..98b52f8de 100644
--- a/Src/Modules/pcre.c
+++ b/Src/Modules/pcre.c
@@ -134,7 +134,7 @@ pcre_callout(pcre2_callout_block_8 *block, UNUSED(void *callout_data))
Eprog prog;
int ret=0;
- if (!block->callout_number &&
+ if (!block->callout_number && block->callout_string &&
((prog = parse_string((char *) block->callout_string, 0))))
{
int ef = errflag, lv = lastval;
diff --git a/Src/Modules/random.c b/Src/Modules/random.c
index 88ac9543c..8aca7e9d4 100644
--- a/Src/Modules/random.c
+++ b/Src/Modules/random.c
@@ -82,12 +82,15 @@ getrandom_buffer(void *buf, size_t len)
zwarn("Unable to get random data: %e.", errno);
return -1;
}
+ continue;
}
-#ifndef HAVE_ARC4RANDOM_BUF
+#ifdef HAVE_ARC4RANDOM_BUF
+ } while (0);
+#else
bufptr += ret;
val += ret;
+ } while (val < len);
#endif
- } while (ret < len);
return ret;
}
@@ -110,17 +113,11 @@ get_bound_random_buffer(uint32_t *buffer, size_t count, uint32_t max)
size_t i; /* loop counter */
getrandom_buffer((void*) buffer, count*sizeof(uint32_t));
- if (max == UINT32_MAX)
- return;
for(i=0;i<count;i++) {
multi_result = ((uint64_t) buffer[i]) * (uint64_t) max;
leftover = (uint32_t) multi_result;
- /*
- * The following if statement should (according to Google's Gemini)
- * only be executed with a probability of 1/2**32 or 2.33e-10
- */
if(leftover < max) {
threshold= -max % max;
while (leftover < threshold) {
@@ -162,30 +159,37 @@ math_zrand_int(UNUSED(char *name), int argc, mnumber *argv, UNUSED(int id))
{
mnumber ret;
uint32_t i;
- zlong lower=0, upper=UINT32_MAX,incl=0, diff;
+ zlong lower = 0,
+ upper = UINT32_MAX,
+ incl = 0,
+ diff = UINT32_MAX;
ret.type = MN_INTEGER;
switch (argc) {
- case 0: ret.u.l=get_srandom(NULL);
- return ret;
- break;
+ case 0: incl = 1; break;
case 3: incl = (argv[2].u.l != 0)?1:0;
case 2: lower = argv[1].u.l;
case 1: upper = argv[0].u.l;
default: diff = upper-lower+incl;
}
- if (lower < 0 || lower >= UINT32_MAX) {
- zwarn("Lower bound (%z) out of range: 0-4294967295",lower);
+ if (lower < 0 || lower > UINT32_MAX) {
+ zwarn("lower bound (%z) out of range: 0-4294967295",lower);
+ ret.u.l = 0; return ret;
} else if (upper < lower) {
- zwarn("Upper bound (%z) must be greater than Lower Bound (%z)",upper,lower);
- } else if (upper < 0 || upper >= UINT32_MAX) {
- zwarn("Upper bound (%z) out of range: 0-4294967295",upper);
+ zwarn("upper bound (%z) must be greater than lower bound (%z)",upper,lower);
+ ret.u.l = 0; return ret;
+ } else if (upper < 0 || upper > UINT32_MAX) {
+ zwarn("upper bound (%z) out of range: 0-4294967295", upper);
+ ret.u.l = 0; return ret;
}
- if ( diff == 0 ) {
+ if (diff == 0) {
ret.u.l=upper; /* still not convinced this shouldn't be an error. */
+ } else if (upper == UINT32_MAX && lower == 0 && incl == 1) {
+ ret.u.l = get_srandom(NULL);
+ return ret;
} else {
get_bound_random_buffer(&i,1,(uint32_t) diff);
ret.u.l=i+lower;
@@ -253,9 +257,8 @@ setup_(UNUSED(Module m))
return 1;
}
- errno=0;
if (!(S_ISCHR(st.st_mode)) ) {
- zwarn("Error getting kernel random pool: %e.", errno);
+ zwarn("Error getting kernel random pool: /dev/urandom is not a character device");
return 1;
}
#endif /* USE_URANDOM */
diff --git a/Src/Modules/random_real.c b/Src/Modules/random_real.c
index 4a8fcae19..3fc279b6d 100644
--- a/Src/Modules/random_real.c
+++ b/Src/Modules/random_real.c
@@ -70,7 +70,7 @@ _zclz64(uint64_t x) {
}
if (!(x & 0xC000000000000000ull)) {
n+=2;
- x<<=1;
+ x<<=2;
}
if (!(x & 0x8000000000000000ull)) {
n+=1;
diff --git a/Src/Modules/regex.c b/Src/Modules/regex.c
index d02769ef0..859312a2a 100644
--- a/Src/Modules/regex.c
+++ b/Src/Modules/regex.c
@@ -77,7 +77,7 @@ zcond_regex_match(char **a, int id)
r = regcomp(&re, rhre, rcflags);
if (r) {
zregex_regerrwarn(r, &re, "failed to compile regex");
- break;
+ goto CLEAN_BASEMETA;
}
/* re.re_nsub is number of parenthesized groups, we also need
* 1 for the 0 offset, which is the entire matched portion
diff --git a/Src/Modules/socket.c b/Src/Modules/socket.c
index c65b7dfce..3ecab42c9 100644
--- a/Src/Modules/socket.c
+++ b/Src/Modules/socket.c
@@ -56,9 +56,9 @@
static int
bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
{
- int err=1, verbose=0, test=0, targetfd=0;
+ int verbose=0, test=0, targetfd=0;
ZSOCKLEN_T len;
- struct sockaddr_un soun;
+ struct sockaddr_un soun = { 0 };
int sfd;
if (OPT_ISSET(ops,'v'))
@@ -90,6 +90,10 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
}
localfn = args[0];
+ if (strlen(localfn) >= sizeof(soun.sun_path)) {
+ zwarnnam(nam, "socket path too long: %d > %d", strlen(localfn), sizeof(soun.sun_path) -1 );
+ return 1;
+ }
sfd = socket(PF_UNIX, SOCK_STREAM, 0);
@@ -225,6 +229,16 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
if (verbose)
printf("new connection from %s is on fd %d\n", soun.sun_path, sfd);
}
+ else if (OPT_ISSET(ops,'s'))
+ {
+ if (!args[0]) {
+ zwarnnam(nam, "-s requires an argument");
+ return 1;
+ }
+
+ if (shutdown(atoi(args[0]), SHUT_WR))
+ zwarn("shutdown failed: %e", errno);
+ }
else
{
if (!args[0]) {
@@ -232,6 +246,11 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
return 1;
}
+ if (strlen(args[0]) >= sizeof(soun.sun_path)) {
+ zwarnnam(nam, "socket path too long: %d > %d", strlen(args[0]), sizeof(soun.sun_path) -1 );
+ return 1;
+ }
+
sfd = socket(PF_UNIX, SOCK_STREAM, 0);
if (sfd == -1) {
@@ -242,7 +261,7 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
soun.sun_family = AF_UNIX;
strncpy(soun.sun_path, args[0], sizeof(soun.sun_path)-1);
- if ((err = connect(sfd, (struct sockaddr *)&soun, sizeof(struct sockaddr_un)))) {
+ if (connect(sfd, (struct sockaddr *)&soun, sizeof(struct sockaddr_un))) {
zwarnnam(nam, "connection failed: %e", errno);
close(sfd);
return 1;
@@ -273,7 +292,7 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
}
static struct builtin bintab[] = {
- BUILTIN("zsocket", 0, bin_zsocket, 0, 3, 0, "ad:ltv", NULL),
+ BUILTIN("zsocket", 0, bin_zsocket, 0, 3, 0, "ad:lstv", NULL),
};
static struct features module_features = {
diff --git a/Src/Modules/stat.c b/Src/Modules/stat.c
index 5bf201dd3..f7ec06e9e 100644
--- a/Src/Modules/stat.c
+++ b/Src/Modules/stat.c
@@ -191,14 +191,14 @@ static void
stattimeprint(time_t tim, long nsecs, char *outbuf, int flags)
{
if (flags & STF_RAW) {
- sprintf(outbuf, "%ld", (unsigned long)tim);
+ sprintf(outbuf, "%ld", (long)tim);
if (flags & STF_STRING)
strcat(outbuf, " (");
}
if (flags & STF_STRING) {
char *oend = outbuf + strlen(outbuf);
- /* Where the heck does "40" come from? */
- ztrftime(oend, 40, timefmt, (flags & STF_GMT) ? gmtime(&tim) :
+ /* the buffer is PATH_MAX+9 long, but we already printed some stuff */
+ ztrftime(oend, PATH_MAX - DIGBUFSIZE - 10, timefmt, (flags & STF_GMT) ? gmtime(&tim) :
localtime(&tim), nsecs);
if (flags & STF_RAW)
strcat(oend, ")");
diff --git a/Src/Modules/system.c b/Src/Modules/system.c
index f1c0d7042..3c0b8421a 100644
--- a/Src/Modules/system.c
+++ b/Src/Modules/system.c
@@ -357,7 +357,7 @@ bin_sysopen(char *nam, char **args, Options ops, UNUSED(int func))
for (o = sizeof(openopts)/sizeof(*openopts) - 1; o >= 0 &&
strcasecmp(openopts[o].name, opt); o--) {}
if (o < 0) {
- zwarnnam(nam, "unsupported option: %s\n", opt);
+ zwarnnam(nam, "unsupported option: %s", opt);
return 1;
}
#if defined(FD_CLOEXEC) && !defined(O_CLOEXEC)
@@ -686,7 +686,8 @@ bin_zsystem_flock(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
else
flags = O_RDWR | O_NOCTTY;
if ((flock_fd = open(unmeta(args[0]), flags)) < 0) {
- zwarnnam(nam, "failed to open %s for writing: %e", args[0], errno);
+ zwarnnam(nam, "failed to open %s for %sing: %e", args[0],
+ readlock ? "read" : "writ", errno);
return 1;
}
flock_fd = movefd(flock_fd);
diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c
index 0bbce5d49..4366f3c02 100644
--- a/Src/Modules/tcp.c
+++ b/Src/Modules/tcp.c
@@ -279,6 +279,29 @@ zts_byfd(int fd)
return NULL;
}
+/**/
+mod_export int
+tcp_shutdown(Tcp_session sess)
+{
+ if (sess && sess->fd != -1)
+ {
+ if (sess->flags & ZTCP_LISTEN) {
+ zwarn("can't shutdown a listening socket");
+ return 1;
+ }
+ if (sess->flags & ZTCP_SHUTDOWN) {
+ zwarn("session is already shutdown");
+ return 1;
+ }
+ int err = shutdown(sess->fd, SHUT_WR);
+ if (err)
+ zwarn("shutdown failed: %e", errno);
+ sess->flags |= ZTCP_SHUTDOWN;
+ return 0;
+ }
+ return -1;
+}
+
static void
tcp_cleanup(void)
{
@@ -366,6 +389,22 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
}
}
+ if (OPT_ISSET(ops,'s')) {
+ targetfd = atoi(args[0]);
+ if(!targetfd) {
+ zwarnnam(nam, "%s is an invalid argument to -s", args[0]);
+ return 1;
+ }
+
+ sess = zts_byfd(targetfd);
+ if (sess) {
+ tcp_shutdown(sess);
+ return 0;
+ } else {
+ zwarnnam(nam, "fd %s not found in tcp table", args[0]);
+ return 1;
+ }
+ }
if (OPT_ISSET(ops,'c')) {
if (!args[0]) {
@@ -373,12 +412,12 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
}
else {
targetfd = atoi(args[0]);
- sess = zts_byfd(targetfd);
if(!targetfd) {
zwarnnam(nam, "%s is an invalid argument to -c", args[0]);
return 1;
}
+ sess = zts_byfd(targetfd);
if (sess)
{
if ((sess->flags & ZTCP_ZFTP) && !force)
@@ -594,6 +633,8 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
schar = 'Z';
else if (sess->flags & ZTCP_LISTEN)
schar = 'L';
+ else if (sess->flags & ZTCP_SHUTDOWN)
+ schar = 'S';
else if (sess->flags & ZTCP_INBOUND)
schar = 'I';
else
@@ -606,7 +647,8 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
printf("%s:%d %s %s:%d is on fd %d%s\n",
localname, ntohs(sess->sock.in.sin_port),
((sess->flags & ZTCP_LISTEN) ? "-<" :
- ((sess->flags & ZTCP_INBOUND) ? "<-" : "->")),
+ ((sess->flags & ZTCP_SHUTDOWN) ? "<>" :
+ ((sess->flags & ZTCP_INBOUND) ? "<-" : "->"))),
remotename, ntohs(sess->peer.in.sin_port),
sess->fd,
(sess->flags & ZTCP_ZFTP) ? " ZFTP" : "");
@@ -696,7 +738,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
}
static struct builtin bintab[] = {
- BUILTIN("ztcp", 0, bin_ztcp, 0, 3, 0, "acd:flLtv", NULL),
+ BUILTIN("ztcp", 0, bin_ztcp, 0, 3, 0, "acd:flLstv", NULL),
};
static struct features module_features = {
diff --git a/Src/Modules/tcp.h b/Src/Modules/tcp.h
index f69e246e0..a9ea7df2d 100644
--- a/Src/Modules/tcp.h
+++ b/Src/Modules/tcp.h
@@ -81,8 +81,9 @@ union tcp_sockaddr {
typedef struct tcp_session *Tcp_session;
-#define ZTCP_LISTEN 1
-#define ZTCP_INBOUND 2
+#define ZTCP_LISTEN 1
+#define ZTCP_INBOUND 2
+#define ZTCP_SHUTDOWN 4
#define ZTCP_ZFTP 16
struct tcp_session {
diff --git a/Src/Modules/termcap.c b/Src/Modules/termcap.c
index af4009a3a..2187bec42 100644
--- a/Src/Modules/termcap.c
+++ b/Src/Modules/termcap.c
@@ -51,7 +51,7 @@ static char *boolcodes[] = {
/**/
static int
-ztgetflag(char *s)
+ztgetflag(const char *s)
{
char **b;
@@ -59,7 +59,7 @@ ztgetflag(char *s)
* off, but other curses variants can't, so we fudge it. *
* This feature of ncurses appears to have gone away as *
* of NCURSES_MAJOR_VERSION == 5, so don't rely on it. */
- switch (tgetflag(s)) {
+ switch (tgetflag((char *) s)) {
case -1:
break;
case 0:
@@ -82,11 +82,20 @@ bin_echotc(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
char *s, buf[2048], *t, *u;
int num, argct;
- s = *argv++;
if (termflags & TERM_BAD)
return 1;
if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
return 1;
+
+ s = *argv++;
+ for (t = s; *t; t++) {
+ /* ncurses helpfully just crashes if you pass it nonascii */
+ if ((unsigned char)*t > 0x7f) {
+ zwarnnam(name, "no such capability: %s", s);
+ return 1;
+ }
+ }
+
/* if the specified termcap has a numeric value, display it */
if ((num = tgetnum(s)) != -1) {
printf("%d\n", num);
@@ -143,8 +152,9 @@ static struct builtin bintab[] = {
static HashNode
gettermcap(UNUSED(HashTable ht), const char *name)
{
- int len, num;
- char *tcstr, buf[2048], *u, *nameu;
+ int num;
+ char *tcstr, buf[2048], *u;
+ const char *t;
Param pm = NULL;
/* This depends on the termcap stuff in init.c */
@@ -153,18 +163,21 @@ gettermcap(UNUSED(HashTable ht), const char *name)
if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
return NULL;
-
- nameu = dupstring(name);
- unmetafy(nameu, &len);
+ for (t = name; *t; t++) {
+ /* ncurses helpfully just crashes if you pass it nonascii */
+ if ((unsigned char)*t > 0x7f) {
+ return NULL;
+ }
+ }
pm = (Param) hcalloc(sizeof(struct param));
- pm->node.nam = nameu;
+ pm->node.nam = dupstring(name);
pm->node.flags = PM_READONLY;
u = buf;
/* logic in the following cascade copied from echotc, above */
- if ((num = tgetnum(nameu)) != -1) {
+ if ((num = tgetnum((char *) name)) != -1) {
pm->gsu.i = &nullsetinteger_gsu;
pm->u.val = num;
pm->node.flags |= PM_INTEGER;
@@ -172,7 +185,7 @@ gettermcap(UNUSED(HashTable ht), const char *name)
}
pm->gsu.s = &nullsetscalar_gsu;
- switch (ztgetflag(nameu)) {
+ switch (ztgetflag(name)) {
case -1:
break;
case 0:
@@ -184,7 +197,7 @@ gettermcap(UNUSED(HashTable ht), const char *name)
pm->node.flags |= PM_SCALAR;
return &pm->node;
}
- if ((tcstr = tgetstr(nameu, &u)) != NULL && tcstr != (char *)-1) {
+ if ((tcstr = tgetstr((char *) name, &u)) != NULL && tcstr != (char *)-1) {
pm->u.str = dupstring(tcstr);
pm->node.flags |= PM_SCALAR;
} else {
@@ -201,7 +214,7 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags)
{
Param pm = NULL;
int num;
- char **capcode, *tcstr, buf[2048], *u;
+ char **capcode, *tcstr, buf[2048];
#ifndef HAVE_NUMCODES
static char *numcodes[] = {
@@ -252,7 +265,6 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags)
#endif
pm = (Param) hcalloc(sizeof(struct param));
- u = buf;
pm->node.flags = PM_READONLY | PM_SCALAR;
pm->gsu.s = &nullsetscalar_gsu;
@@ -286,6 +298,7 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags)
zstrcodes
#endif
; *capcode; capcode++) {
+ char *u = buf;
if ((tcstr = (char *)tgetstr(*capcode,&u)) != NULL &&
tcstr != (char *)-1) {
pm->u.str = dupstring(tcstr);
diff --git a/Src/Modules/terminfo.c b/Src/Modules/terminfo.c
index f9ab64fb3..1df5f5c30 100644
--- a/Src/Modules/terminfo.c
+++ b/Src/Modules/terminfo.c
@@ -68,12 +68,20 @@ bin_echoti(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
long pars[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
char *strcap[] = { "pfkey", "pfloc", "pfx", "pln", "pfxl", NULL };
- s = *argv++;
/* This depends on the termcap stuff in init.c */
if (termflags & TERM_BAD)
return 1;
if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
return 1;
+
+ s = *argv++;
+ for (t = s; *t; t++) {
+ /* ncurses helpfully just crashes if you pass it nonascii */
+ if ((unsigned char)*t > 0x7f) {
+ zwarnnam(name, "no such terminfo capability: %s", s);
+ return 1;
+ }
+ }
/* if the specified capability has a numeric value, display it */
if (((num = tigetnum(s)) != -1) && (num != -2)) {
printf("%d\n", num);
@@ -111,7 +119,7 @@ bin_echoti(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
/* get the arguments */
for (arg=0; argv[arg]; arg++) {
if (strarg && arg > 0)
- pars[arg] = (long) argv[arg];
+ pars[arg] = (long) unmetafy(dupstring(argv[arg]), NULL);
else
pars[arg] = atoi(argv[arg]);
}
@@ -134,8 +142,9 @@ static struct builtin bintab[] = {
static HashNode
getterminfo(UNUSED(HashTable ht), const char *name)
{
- int len, num;
- char *tistr, *nameu;
+ int num;
+ char *tistr;
+ const char *t;
Param pm = NULL;
/* This depends on the termcap stuff in init.c */
@@ -144,22 +153,27 @@ getterminfo(UNUSED(HashTable ht), const char *name)
if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
return NULL;
- nameu = dupstring(name);
- unmetafy(nameu, &len);
+ for (t = name; *t; t++) {
+ /* ncurses helpfully just crashes if you pass it nonascii */
+ if ((unsigned char)*t > 0x7f) {
+ return NULL;
+ }
+ }
pm = (Param) hcalloc(sizeof(struct param));
- pm->node.nam = nameu;
+ pm->node.nam = dupstring(name);
pm->node.flags = PM_READONLY;
- if (((num = tigetnum(nameu)) != -1) && (num != -2)) {
+ if (((num = tigetnum((char *) name)) != -1) && (num != -2)) {
pm->u.val = num;
pm->node.flags |= PM_INTEGER;
pm->gsu.i = &nullsetinteger_gsu;
- } else if ((num = tigetflag(nameu)) != -1) {
+ } else if ((num = tigetflag((char *) name)) != -1) {
pm->u.str = num ? dupstring("yes") : dupstring("no");
pm->node.flags |= PM_SCALAR;
pm->gsu.s = &nullsetscalar_gsu;
- } else if ((tistr = (char *)tigetstr(nameu)) != NULL && tistr != (char *)-1) {
+ } else if ((tistr = (char *)tigetstr((char *) name)) != NULL &&
+ tistr != (char *)-1) {
pm->u.str = metafy(tistr, -1, META_HEAPDUP);
pm->node.flags |= PM_SCALAR;
pm->gsu.s = &nullsetscalar_gsu;
diff --git a/Src/Modules/watch.c b/Src/Modules/watch.c
index bb27ab9db..c4571c7e7 100644
--- a/Src/Modules/watch.c
+++ b/Src/Modules/watch.c
@@ -241,7 +241,7 @@ watch3ary(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt)
static char *
watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
{
- char buf[40], buf2[80];
+ char buf[256], buf2[80];
time_t timet;
struct tm *tm;
char *fm2;
@@ -332,7 +332,7 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
case 'D':
if (fm2[1] == '{') {
char *dd, *ss;
- int n = 79;
+ int n = sizeof(buf2)-1;
for (ss = fm2 + 2, dd = buf2;
n-- && *ss && *ss != '}'; ++ss, ++dd)
@@ -349,7 +349,8 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
}
timet = getlogtime(u, inout);
tm = localtime(&timet);
- len = ztrftime(buf, 40, fm2, tm, 0L);
+ /* metafy may double the length in the worst case */
+ len = ztrftime(buf, sizeof(buf)/2, fm2, tm, 0L);
if (len > 0)
metafy(buf, len, META_NOALLOC);
applytextattributes(TSC_RAW);
@@ -695,8 +696,10 @@ static struct builtin bintab[] = {
};
static struct paramdef partab[] = {
- PARAMDEF("WATCH", PM_SCALAR|PM_SPECIAL, &watch, NULL),
- PARAMDEF("watch", PM_ARRAY|PM_SPECIAL, &watch, NULL),
+ PARAMDEF("WATCH", PM_SCALAR|PM_SPECIAL|PM_TIED, &watch,
+ NULL /* &colonarr_gsu (see setup_()) */),
+ PARAMDEF("watch", PM_ARRAY|PM_SPECIAL|PM_TIED, &watch,
+ NULL /* &vararray_gsu (see setup_() */),
};
static struct features module_features = {
@@ -739,15 +742,6 @@ boot_(UNUSED(Module m))
{
static char const * const default_watchfmt = DEFAULT_WATCHFMT;
- Param pma = (Param) paramtab->getnode(paramtab, "watch");
- Param pms = (Param) paramtab->getnode(paramtab, "WATCH");
- if (pma && pms && pma->u.arr == watch && pms->u.arr == watch) {
- /* only tie the two parameters if both were added */
- pma->ename = "WATCH";
- pms->ename = "watch";
- pma->node.flags |= PM_TIED;
- pms->node.flags |= PM_TIED;
- }
watch = mkarray(NULL);
/* These two parameters are only set to defaults if not set.
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index 230ad86f6..29170ad11 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -82,10 +82,6 @@ union zftp_sockaddr {
#endif
};
-#ifdef USE_LOCAL_H_ERRNO
-int h_errno;
-#endif
-
/*
* For FTP block mode
*
@@ -119,8 +115,8 @@ struct zfheader {
enum {
ZFHD_MARK = 16, /* restart marker */
ZFHD_ERRS = 32, /* suspected errors in block */
- ZFHD_EOFB = 64, /* block is end of record */
- ZFHD_EORB = 128 /* block is end of file */
+ ZFHD_EOFB = 64, /* block is end of file */
+ ZFHD_EORB = 128 /* block is end of record */
};
typedef int (*readwrite_t)(int, char *, off_t, int);
@@ -2038,7 +2034,7 @@ zfgetinfo(char *prompt, int noecho)
}
if (fgets(instr, 256, stdin) == NULL)
- instr[len = 0] = '\0';
+ instr[0] = '\0';
else if (instr[len = strlen(instr)-1] == '\n')
instr[len] = '\0';
@@ -2102,7 +2098,7 @@ zftp_params(UNUSED(char *name), char **args, UNUSED(int flags))
/* maybe user CTRL-c'd in the middle somewhere */
for (aptr = newarr; *aptr; aptr++)
zsfree(*aptr);
- zfree(newarr, len+1);
+ zfree(newarr, (len+1)*sizeof(char *));
return 1;
}
if (zfsess->userparams)
@@ -2191,7 +2187,7 @@ zftp_login(char *name, char **args, UNUSED(int flags))
int cnt;
for (cnt = 0; *args; args++)
cnt++;
- zwarnnam(name, "warning: %d command arguments not used\n", cnt);
+ zwarnnam(name, "warning: %d command arguments not used", cnt);
}
zfstatusp[zfsessno] |= ZFST_LOGI;
zfsetparam("ZFTP_USER", ztrdup(user), ZFPM_READONLY);
@@ -2480,7 +2476,7 @@ zftp_mode(char *name, char **args, UNUSED(int flags))
cmd[5] = (char) nt;
if (zfsendcmd(cmd) > 2)
return 1;
- zfstatusp[zfsessno] &= ZFST_MMSK;
+ zfstatusp[zfsessno] &= ~ZFST_MMSK;
zfstatusp[zfsessno] |= (nt == 'S') ? ZFST_STRE : ZFST_BLOC;
zfsetparam("ZFTP_MODE", ztrdup(str), ZFPM_READONLY);
return 0;
@@ -2563,7 +2559,7 @@ zftp_getput(char *name, char **args, int flags)
for (; *args; args++) {
char *ln, *rest = NULL;
off_t startat = 0;
- if (progress && (shfunc = getshfunc("zftp_progress"))) {
+ if (progress && getshfunc("zftp_progress")) {
off_t sz = -1;
/*
* This calls the SIZE command to get the size for remote
@@ -2875,10 +2871,10 @@ freesession(Zftp_session sptr)
{
char **ps, **pd;
zsfree(sptr->name);
- for (ps = zfparams, pd = zfsess->params; *ps; ps++, pd++)
+ for (ps = zfparams, pd = sptr->params; *ps; ps++, pd++)
if (*pd)
zsfree(*pd);
- zfree(zfsess->params, sizeof(zfparams));
+ zfree(sptr->params, sizeof(zfparams));
if (sptr->userparams)
freearray(sptr->userparams);
zfree(sptr, sizeof(struct zftp_session));
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index c2656698c..de450be7a 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -292,6 +292,7 @@ get_pty(int master, int *retfd)
}
}
}
+ return 1; /* don't try to open a slave if we got no master */
}
name[5] = 't';
if ((sfd = open(name, O_RDWR|O_NOCTTY)) >= 0) {
@@ -436,12 +437,15 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
zexit(lastval, ZEXIT_NORMAL);
}
#ifndef USE_CYGWIN_FIX
- master = movefd(master);
- if (master == -1) {
- zerrnam(nam, "cannot duplicate fd %d: %e", master, errno);
- scriptname = oscriptname;
- ineval = oineval;
- return 1;
+ {
+ int orig_master = master;
+ master = movefd(master);
+ if (master == -1) {
+ zerrnam(nam, "cannot duplicate fd %d: %e", orig_master, errno);
+ scriptname = oscriptname;
+ ineval = oineval;
+ return 1;
+ }
}
#else
addmodulefd(master, FDT_INTERNAL);
@@ -529,12 +533,11 @@ deleteallptycmds(void)
static void
checkptycmd(Ptycmd cmd)
{
- char c;
- int r;
+ unsigned char c;
if (cmd->read != -1 || cmd->fin)
return;
- if ((r = read(cmd->fd, &c, 1)) <= 0) {
+ if (read(cmd->fd, &c, 1) <= 0) {
if (kill(cmd->pid, 0) < 0) {
cmd->fin = 1;
zclose(cmd->fd);
@@ -581,14 +584,19 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch)
buf = (char *) zhalloc((blen = 256) + 1);
}
if (cmd->read != -1) {
- buf[used] = (char) cmd->read;
- buf[used + 1] = '\0';
- seen = used = 1;
+ int readchar = cmd->read;
cmd->read = -1;
+ if (imeta(readchar)) {
+ buf[used++] = Meta;
+ buf[used++] = (char) (readchar ^ 32);
+ } else
+ buf[used++] = (char) readchar;
+ buf[used] = '\0';
+ seen = 1;
}
do {
if (noblock && cmd->read == -1) {
- int pollret;
+ int pollret = -1;
/*
* Check there is data available. Borrowed from
* poll_read() in utils.c and simplified.
@@ -604,6 +612,7 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch)
(SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
#else
#ifdef FIONREAD
+ int val;
if (ioctl(cmd->fd, FIONREAD, (char *) &val) == 0)
pollret = (val > 0);
#endif
@@ -617,9 +626,13 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch)
* character. cmd->read stores the character read.
*/
long mode;
+ unsigned char c;
- if (setblock_fd(0, cmd->fd, &mode))
- pollret = read(cmd->fd, &cmd->read, 1);
+ if (setblock_fd(0, cmd->fd, &mode)) {
+ pollret = read(cmd->fd, &c, 1);
+ if (pollret == 1)
+ cmd->read = (int) c;
+ }
if (mode != -1)
fcntl(cmd->fd, F_SETFL, mode);
}
@@ -688,8 +701,12 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch)
#endif
#endif
) {
- cmd->old = (char *) zalloc(cmd->olen = used);
- memcpy(cmd->old, buf, cmd->olen);
+ if (used) {
+ cmd->old = (char *) zalloc(cmd->olen = used);
+ memcpy(cmd->old, buf, cmd->olen);
+ }
+ if (prog)
+ freepatprog(prog);
return 1;
}
diff --git a/Src/Modules/zselect.c b/Src/Modules/zselect.c
index 8c1267240..92a3b38c2 100644
--- a/Src/Modules/zselect.c
+++ b/Src/Modules/zselect.c
@@ -47,6 +47,10 @@ handle_digits(char *nam, char *argptr, fd_set *fdset, int *fdmax)
return 1;
}
fd = (int)zstrtol(argptr, &endptr, 10);
+ if (fd < 0 || fd >= FD_SETSIZE) {
+ zwarnnam(nam, "file descriptor out of range [0-%d]: %d", FD_SETSIZE-1, fd);
+ return 1;
+ }
if (*endptr) {
zwarnnam(nam, "garbage after file descriptor: %s", endptr);
return 1;
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 9e1eabcf1..53b3abe72 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -844,6 +844,14 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
} else if (*s == '.' || testit)
s++;
+ // next char isn't a legal spec char -- unwind, treat the sequence
+ // literally
+ if (!testit && (!*s || *s == '%' || *s == ')' || *s == '-' || *s == '.')) {
+ // but swallow the % if this is %% or %)
+ start += (s - start == 1 && (*s == '%' || *s == ')'));
+ s = start;
+ }
+
if (testit && (unsigned char) *s) {
int actval, testval, endcharl;
@@ -880,10 +888,10 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
* vice versa... unless we are already skipping.
*/
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
- olenp, endcharl, presence, skip || actval)))
+ olenp, endcharl, presence, skip || actval)) || !*s)
return NULL;
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
- olenp, ')', presence, skip || !actval)))
+ olenp, ')', presence, skip || !actval)) || !*s)
return NULL;
} else if (skip) {
continue;
@@ -972,22 +980,23 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
char **ap, *specs[256] = {0}, *out;
int olen, oused = 0;
- specs['%'] = "%";
- specs[')'] = ")";
-
/* Parse the specs in argv. */
for (ap = args + 2; *ap; ap++) {
if (!ap[0][0] || ap[0][0] == '-' || ap[0][0] == '.' ||
+ ap[0][0] == '%' || ap[0][0] == ')' ||
idigit(ap[0][0]) || ap[0][1] != ':') {
- zwarnnam(nam, "invalid argument: %s", *ap);
+ zwarnnam(nam, "invalid spec: %s", *ap);
return 1;
}
specs[(unsigned char) ap[0][0]] = ap[0] + 2;
}
out = (char *) zhalloc(olen = 128);
- zformat_substring(args[1], specs, &out, &oused, &olen, '\0',
- presence, 0);
+ if (!zformat_substring(args[1], specs, &out, &oused, &olen, '\0',
+ presence, 0)) {
+ zwarnnam(nam, "malformed format string: %s", args[1]);
+ return 1;
+ }
out[oused] = '\0';
setsparam(args[0], ztrdup(out));
@@ -1401,8 +1410,10 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
next = br->state;
if (next->pattern && !next->patprog) {
tokenize(next->pattern);
- if (!(next->patprog = patcompile(next->pattern, 0, NULL)))
+ if (!(next->patprog = patcompile(next->pattern, 0, NULL))) {
+ freematch(&match1);
return 3;
+ }
}
if (next->pattern && pattry(next->patprog, subj) &&
(!next->guard || (execstring(next->guard, 1, 0,
@@ -1654,9 +1665,9 @@ add_opt_val(Zoptdesc d, char *arg)
if (!v) {
v = (Zoptval) zhalloc(sizeof(*v));
v->next = v->onext = NULL;
- v->name = n;
new = 1;
}
+ v->name = n; // insert the last given name into arrays
v->arg = arg;
if ((d->flags & ZOF_ARG) && !(d->flags & (ZOF_OPT | ZOF_SAME))) {
v->str = NULL;
@@ -1735,11 +1746,12 @@ zalloc_default_array(char ***aval, char *assoc, int keep, int num)
}
static int
-bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
+bin_zparseopts(char *nam, char **args, Options ops, UNUSED(int func))
{
char *o, *p, *n, **pp, **aval, **ap, *assoc = NULL, **cp, **np;
char *paramsname = NULL, **params;
- int del = 0, flags = 0, extract = 0, fail = 0, gnu = 0, keep = 0;
+ char *progname = scriptname ? scriptname : (argzero ? argzero : nam);
+ int flags = 0, del, extract, fail, gnu, keep;
Zoptdesc sopts[256], d;
Zoptarr a, defarr = NULL;
Zoptval v;
@@ -1748,133 +1760,61 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
opt_arrs = NULL;
memset(sopts, 0, 256 * sizeof(Zoptdesc));
- while ((o = *args++)) {
- if (*o == '-') {
- switch (o[1]) {
- case '\0':
- o = NULL;
- break;
- case '-':
- if (o[2])
- args--;
- /* else unreachable, default parsing removes "--" */
- o = NULL;
- break;
- case 'D':
- if (o[2]) {
- args--;
- o = NULL;
- break;
- }
- del = 1;
- break;
- case 'E':
- if (o[2]) {
- args--;
- o = NULL;
- break;
- }
- extract = 1;
- break;
- case 'F':
- if (o[2]) {
- args--;
- o = NULL;
- break;
- }
- fail = 1;
- break;
- case 'G':
- if (o[2]) {
- args--;
- o = NULL;
- break;
- }
- gnu = 1;
- break;
- case 'K':
- if (o[2]) {
- args--;
- o = NULL;
- break;
- }
- 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");
- return 1;
- }
- if (o[2])
- n = o + 2;
- else if (*args)
- n = *args++;
- else {
- zwarnnam(nam, "missing array name");
- return 1;
- }
- defarr = (Zoptarr) zhalloc(sizeof(*defarr));
- defarr->name = n;
- defarr->num = 0;
- defarr->vals = defarr->last = NULL;
- defarr->next = NULL;
- 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)
- assoc = *args++;
- else {
- zwarnnam(nam, "missing array name");
- return 1;
- }
- break;
- case 'v':
- if (paramsname) {
- zwarnnam(nam, "argv array given more than once");
- return 1;
- }
- if (o[2])
- paramsname = o + 2;
- else if (*args)
- paramsname = *args++;
- else {
- zwarnnam(nam, "missing array name");
- return 1;
- }
- break;
- default:
- /* Anything else is an option description */
- args--;
- o = NULL;
- break;
- }
- if (!o) {
- o = "";
- break;
- }
- } else {
- args--;
- break;
+ del = OPT_ISSET(ops, 'D');
+ extract = OPT_ISSET(ops, 'E');
+ fail = OPT_ISSET(ops, 'F');
+ gnu = OPT_ISSET(ops, 'G');
+ keep = OPT_ISSET(ops, 'K');
+ flags |= OPT_ISSET(ops, 'M') ? ZOF_MAP : 0;
+
+ if (OPT_ISSET(ops, 'a')) {
+ if (!*OPT_ARG(ops, 'a')) {
+ zwarnnam(nam, "missing array name for -a");
+ return 1;
+ }
+ defarr = (Zoptarr) zhalloc(sizeof(*defarr));
+ defarr->name = OPT_ARG(ops, 'a');
+ defarr->num = 0;
+ defarr->vals = defarr->last = NULL;
+ defarr->next = NULL;
+ opt_arrs = defarr;
+ }
+ if (OPT_ISSET(ops, 'A')) {
+ if (!*OPT_ARG(ops, 'A')) {
+ zwarnnam(nam, "missing array name for -A");
+ return 1;
}
+ assoc = OPT_ARG(ops, 'A');
}
- if (!o) {
+ if (OPT_ISSET(ops, 'n')) {
+ if (!*OPT_ARG(ops, 'n')) {
+ zwarnnam(nam, "missing program name for -n");
+ return 1;
+ }
+ progname = OPT_ARG(ops, 'n');
+ }
+ if (OPT_ISSET(ops, 'v')) {
+ if (!*OPT_ARG(ops, 'v')) {
+ zwarnnam(nam, "missing array name for -v");
+ return 1;
+ }
+ paramsname = OPT_ARG(ops, 'v');
+ }
+
+ params = getaparam((paramsname = paramsname ? paramsname : "argv"));
+ if (!params) {
+ zwarnnam(nam, "no such array: %s", paramsname);
+ return 1;
+ }
+
+ /* allow a single '' or - spec to signify no options recognised */
+ if (*args && !args[1] && (!**args || !strcmp(*args, "-"))) {
+ args++;
+ } else if (!*args) {
zwarnnam(nam, "missing option descriptions");
return 1;
}
+
while ((o = dupstring(*args++))) {
int f = 0;
if (!*o) {
@@ -1952,11 +1892,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
return 1;
}
}
- params = getaparam((paramsname = paramsname ? paramsname : "argv"));
- if (!params) {
- zwarnnam(nam, "no such array: %s", paramsname);
- return 1;
- }
+
np = cp = pp = ((extract && del) ? arrdup(params) : params);
for (; (o = *pp); pp++) {
/* Not an option. With GNU style, this includes '-' */
@@ -1981,9 +1917,9 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
if (!(d = sopts[(unsigned char) *o])) {
if (fail) {
if (*o != '-' || o > *pp + 1)
- zwarnnam(nam, "bad option: -%c", *o);
+ fprintf(stderr, "%s: bad option: -%c\n", progname, *o);
else
- zwarnnam(nam, "bad option: -%s", o);
+ fprintf(stderr, "%s: bad option: -%s\n", progname, o);
return 1;
}
o = NULL;
@@ -2002,8 +1938,8 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
(!(d->flags & (ZOF_GNUL | ZOF_GNUS)) &&
pp[1] && pp[1][0] != '-')) {
if (!pp[1]) {
- zwarnnam(nam, "missing argument for option: -%s",
- d->name);
+ fprintf(stderr, "%s: missing argument for option: -%s\n",
+ progname, d->name);
return 1;
}
add_opt_val(d, *++pp);
@@ -2045,8 +1981,8 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
(!(d->flags & (ZOF_GNUL | ZOF_GNUS)) &&
pp[1] && pp[1][0] != '-')) {
if (!pp[1]) {
- zwarnnam(nam, "missing argument for option: -%s",
- d->name);
+ fprintf(stderr, "%s: missing argument for option: -%s\n",
+ progname, d->name);
return 1;
}
add_opt_val(d, *++pp);
@@ -2134,7 +2070,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
static struct builtin bintab[] = {
BUILTIN("zformat", 0, bin_zformat, 3, -1, 0, NULL, NULL),
- BUILTIN("zparseopts", 0, bin_zparseopts, 1, -1, 0, NULL, NULL),
+ BUILTIN("zparseopts", 0, bin_zparseopts, 0, -1, 0, "a:A:DEFGKMn:v:", NULL),
BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL),
BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL),
};