diff options
Diffstat (limited to 'Src/Modules')
| -rw-r--r-- | Src/Modules/attr.c | 8 | ||||
| -rw-r--r-- | Src/Modules/attr.mdd | 2 | ||||
| -rw-r--r-- | Src/Modules/cap.c | 26 | ||||
| -rw-r--r-- | Src/Modules/clone.c | 6 | ||||
| -rw-r--r-- | Src/Modules/curses.c | 139 | ||||
| -rw-r--r-- | Src/Modules/db_gdbm.c | 2 | ||||
| -rw-r--r-- | Src/Modules/hlgroup.c | 4 | ||||
| -rw-r--r-- | Src/Modules/ksh93.c | 10 | ||||
| -rw-r--r-- | Src/Modules/langinfo.c | 13 | ||||
| -rw-r--r-- | Src/Modules/langinfo.mdd | 2 | ||||
| -rw-r--r-- | Src/Modules/nearcolor.c | 18 | ||||
| -rw-r--r-- | Src/Modules/parameter.c | 55 | ||||
| -rw-r--r-- | Src/Modules/pcre.c | 2 | ||||
| -rw-r--r-- | Src/Modules/random.c | 43 | ||||
| -rw-r--r-- | Src/Modules/random_real.c | 2 | ||||
| -rw-r--r-- | Src/Modules/regex.c | 2 | ||||
| -rw-r--r-- | Src/Modules/socket.c | 27 | ||||
| -rw-r--r-- | Src/Modules/stat.c | 6 | ||||
| -rw-r--r-- | Src/Modules/system.c | 5 | ||||
| -rw-r--r-- | Src/Modules/tcp.c | 48 | ||||
| -rw-r--r-- | Src/Modules/tcp.h | 5 | ||||
| -rw-r--r-- | Src/Modules/termcap.c | 41 | ||||
| -rw-r--r-- | Src/Modules/terminfo.c | 34 | ||||
| -rw-r--r-- | Src/Modules/watch.c | 22 | ||||
| -rw-r--r-- | Src/Modules/zftp.c | 22 | ||||
| -rw-r--r-- | Src/Modules/zpty.c | 51 | ||||
| -rw-r--r-- | Src/Modules/zselect.c | 4 | ||||
| -rw-r--r-- | Src/Modules/zutil.c | 228 |
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), }; |
