Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Please unblock package mksh This is a resend of <pine.bsm.4.64l.1207240952130.30...@herc.mirbsd.org> as requested in the d-d-a mail of today. unblock mksh/40.9.20120630-2 Hi, after getting negative responses, I decided to start a wheezy maintenance branch and only cherry-pick the important fixes. The attached diff has been cleaned off "RCS ID" and other version numbering only noise from comments, and diffs the patched source + debian/ not the quilt patches, for easier review. The package's otherwise in a good shape, built everywhere, I've been using the new version for a while, etc. (and even the klibc version is safe, as longjmp is never passed 0). Changes: * Fix CONSERVATIVE_FDS: the definition was missing in one case and silently ignored in another due to use of the macro before its implicit definition; also add this fact to the lksh(1) manpage * Correct a regression wrt. tab completion, at least two other bugs in the same code, and the same bug class in similar code (e.g. inline-expansion with Esc+*) that could lead to unrelated input on the current command line being overwritten (and sanitise int into size_t, for 64-bit cleanliness), upstream bug LP#1025843 -- System Information: Debian Release: wheezy/sid APT prefers unreleased APT policy: (500, 'unreleased'), (500, 'unstable') Architecture: m68k Kernel: Linux 3.2.0-2-atari Locale: LANG=C, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/mksh-static
--- mksh-40.9.20120630-1/Build.sh 2012-06-28 20:18:21.000000000 +0000 +++ mksh-40.9.20120630-2/Build.sh 2012-07-24 09:54:20.000000000 +0000 @@ -414,6 +414,7 @@ else check_categories="$check_categories shell:legacy-yes" add_cppflags -DMKSH_LEGACY_MODE HAVE_PERSISTENT_HISTORY=0 + HAVE_ISSET_MKSH_CONSERVATIVE_FDS=1 # from sh.h fi if test x"$srcdir" = x"."; then --- mksh-40.9.20120630-1/debian/changelog 2012-06-30 17:34:53.000000000 +0000 +++ mksh-40.9.20120630-2/debian/changelog 2012-07-20 23:33:59.000000000 +0000 @@ -1,3 +1,14 @@ +mksh (40.9.20120630-2) unstable; urgency=low + + * The “kutweer” upload + * Apply cherry-picked fixes from mksh CVS (branch mksh-wheezy): + - [tg] Fix CONSERVATIVE_FDS use-before-definition bug + - [tg] Correct a regression when tab-completing (LP#1025843) and fix + bugs in the same code wrt. completion display and other expansions + * Document use of CONSERVATIVE_FDS in lksh manpage + + -- Thorsten Glaser <t...@mirbsd.de> Fri, 20 Jul 2012 23:32:37 +0000 + mksh (40.9.20120630-1) unstable; urgency=low * The “GC2TDN7” upload --- mksh-40.9.20120630-1/debian/lksh.1 2012-06-30 17:25:00.000000000 +0000 +++ mksh-40.9.20120630-2/debian/lksh.1 2012-07-20 23:34:00.000000000 +0000 @@ -223,6 +223,9 @@ but might work on 32-bit and 64-bit .Vt long types .Pc . +.It +.Nm +only offers the traditional ten file descriptors to scripts. .El .Sh SEE ALSO .Xr mksh 1 @@ -262,4 +265,8 @@ or the IRC channel at .Pa irc.freenode.net .Pq Port 6697 SSL, 6667 unencrypted -if you need any further quirks. +if you need any further quirks or assistance, +and consider migrating your legacy scripts to work with +.Nm mksh +instead of requiring +.Nm . --- mksh-40.9.20120630-1/edit.c 2012-05-05 17:33:19.000000000 +0000 +++ mksh-40.9.20120630-2/edit.c 2012-07-24 09:54:20.000000000 +0000 @@ -76,6 +76,8 @@ static int x_do_comment(char *, ssize_t, static void x_print_expansions(int, char *const *, bool); static int x_cf_glob(int *, const char *, int, int, int *, int *, char ***); static size_t x_longest_prefix(int, char *const *); +static void x_glob_hlp_add_qchar(char *); +static void x_glob_hlp_rem_qchar(char *); static int x_basename(const char *, const char *); static void x_free_words(int, char **); static int x_escape(const char *, size_t, int (*)(const char *, size_t)); @@ -281,50 +283,78 @@ x_print_expansions(int nwords, char * co XPfree(l); } -/** - * Do file globbing: - * - appends * to (copy of) str if no globbing chars found - * - does expansion, checks for no match, etc. - * - sets *wordsp to array of matching strings - * - returns number of matching strings +/* + * Convert backslash-escaped string to QCHAR-escaped + * string useful for globbing; loses QCHAR unless it + * can squeeze in, eg. by previous loss of backslash */ -static int -x_file_glob(int flags MKSH_A_UNUSED, char *toglob, char ***wordsp) +static void +x_glob_hlp_add_qchar(char *cp) { - char ch, **words; - int nwords, i = 0, idx = 0; - bool escaping; - XPtrV w; - struct source *s, *sold; + char ch, *dp = cp; + bool escaping = false; - /* remove all escaping backward slashes */ - escaping = false; - while ((ch = toglob[i++])) { + while ((ch = *cp++)) { if (ch == '\\' && !escaping) { escaping = true; continue; } - if (escaping) { + if (escaping || (ch == QCHAR && (cp - dp) > 1)) { /* * empirically made list of chars to escape - * for globbing; ASCII 0x02 probably too as - * that's what QCHAR is, but... + * for globbing as well as QCHAR itself */ switch (ch) { + case QCHAR: case '$': case '*': case '?': case '[': case '\\': case '`': - toglob[idx++] = QCHAR; + *dp++ = QCHAR; break; } escaping = false; } - toglob[idx++] = ch; + *dp++ = ch; } - toglob[idx] = '\0'; + *dp = '\0'; +} + +/* + * Unescape a QCHAR-escaped string + */ +static void +x_glob_hlp_rem_qchar(char *cp) +{ + char ch, *dp = cp; + + while ((ch = *cp++)) { + if (ch == QCHAR && !(ch = *cp++)) + break; + *dp++ = ch; + } + *dp = '\0'; +} + +/** + * Do file globbing: + * - appends * to (copy of) str if no globbing chars found + * - does expansion, checks for no match, etc. + * - sets *wordsp to array of matching strings + * - returns number of matching strings + */ +static int +x_file_glob(int flags MKSH_A_UNUSED, char *toglob, char ***wordsp) +{ + char **words; + int nwords; + XPtrV w; + struct source *s, *sold; + + /* remove all escaping backward slashes */ + x_glob_hlp_add_qchar(toglob); /* * Convert "foo*" (toglob) to an array of strings (words) @@ -350,13 +380,7 @@ x_file_glob(int flags MKSH_A_UNUSED, cha struct stat statb; /* Drop all QCHAR from toglob for strcmp below */ - i = 0; - idx = 0; - while ((ch = toglob[i++])) { - if (ch != QCHAR) - toglob[idx++] = ch; - } - toglob[idx] = '\0'; + x_glob_hlp_rem_qchar(toglob); /* * Check if globbing failed (returned glob pattern), @@ -915,9 +939,9 @@ static int holdlen; /* length of holdbu static bool prompt_redraw; /* false if newline forced after prompt */ static int x_ins(const char *); -static void x_delete(int, int); -static int x_bword(void); -static int x_fword(int); +static void x_delete(size_t, bool); +static size_t x_bword(void); +static size_t x_fword(bool); static void x_goto(char *); static void x_bs3(char **); static int x_size_str(char *); @@ -949,6 +973,7 @@ static int x_fold_case(int); #endif static char *x_lastcp(void); static void do_complete(int, Comp_type); +static size_t x_nb2nc(size_t); static int unget_char = -1; @@ -1067,6 +1092,17 @@ static struct x_defbindings const x_defb #endif }; +static size_t +x_nb2nc(size_t nb) +{ + char *cp; + size_t nc = 0; + + for (cp = xcp; cp < (xcp + nb); ++nc) + cp += utf_ptradj(cp); + return (nc); +} + #ifdef MKSH_SMALL static void x_modified(void); static void @@ -1329,7 +1365,7 @@ x_ins(const char *s) static int x_del_back(int c MKSH_A_UNUSED) { - int i = 0; + ssize_t i = 0; if (xcp == xbuf) { x_e_putc2(7); @@ -1346,7 +1382,7 @@ static int x_del_char(int c MKSH_A_UNUSED) { char *cp, *cp2; - int i = 0; + ssize_t i = 0; cp = xcp; while (i < x_arg) { @@ -1367,9 +1403,9 @@ x_del_char(int c MKSH_A_UNUSED) /* Delete nc chars to the right of the cursor (including cursor position) */ static void -x_delete(int nc, int push) +x_delete(size_t nc, bool push) { - int i, nb, nw; + size_t i, nb, nw; char *cp; if (nc == 0) @@ -1453,21 +1489,21 @@ x_mv_bword(int c MKSH_A_UNUSED) static int x_mv_fword(int c MKSH_A_UNUSED) { - x_fword(1); + x_fword(true); return (KSTD); } static int x_del_fword(int c MKSH_A_UNUSED) { - x_delete(x_fword(0), true); + x_delete(x_fword(false), true); return (KSTD); } -static int +static size_t x_bword(void) { - int nc = 0, nb = 0; + size_t nb = 0; char *cp = xcp; if (cp == xbuf) { @@ -1485,16 +1521,14 @@ x_bword(void) } } x_goto(cp); - for (cp = xcp; cp < (xcp + nb); ++nc) - cp += utf_ptradj(cp); - return (nc); + return (x_nb2nc(nb)); } -static int -x_fword(int move) +static size_t +x_fword(bool move) { - int nc = 0; - char *cp = xcp, *cp2; + size_t nc; + char *cp = xcp; if (cp == xep) { x_e_putc2(7); @@ -1506,8 +1540,7 @@ x_fword(int move) while (cp != xep && !is_mfs(*cp)) cp++; } - for (cp2 = xcp; cp2 < cp; ++nc) - cp2 += utf_ptradj(cp2); + nc = x_nb2nc(cp - xcp); if (move) x_goto(cp); return (nc); @@ -2195,20 +2228,18 @@ x_meta2(int c MKSH_A_UNUSED) static int x_kill(int c MKSH_A_UNUSED) { - int col = xcp - xbuf; - int lastcol = xep - xbuf; - int ndel; - - if (x_arg_defaulted) - x_arg = lastcol; - else if (x_arg > lastcol) - x_arg = lastcol; - ndel = x_arg - col; - if (ndel < 0) { - x_goto(xbuf + x_arg); - ndel = -ndel; - } - x_delete(ndel, true); + size_t col = xcp - xbuf; + size_t lastcol = xep - xbuf; + size_t ndel, narg; + + if (x_arg_defaulted || (narg = x_arg) > lastcol) + narg = lastcol; + if (narg < col) { + x_goto(xbuf + narg); + ndel = col - narg; + } else + ndel = narg - col; + x_delete(x_nb2nc(ndel), true); return (KSTD); } @@ -2256,7 +2287,7 @@ x_meta_yank(int c MKSH_A_UNUSED) } len = strlen(killstack[killtp]); x_goto(xcp - len); - x_delete(len, false); + x_delete(x_nb2nc(len), false); do { if (killtp == 0) killtp = KILLSIZE - 1; @@ -2576,7 +2607,7 @@ x_set_mark(int c MKSH_A_UNUSED) static int x_kill_region(int c MKSH_A_UNUSED) { - int rsize; + size_t rsize; char *xr; if (xmp == NULL) { @@ -2591,7 +2622,7 @@ x_kill_region(int c MKSH_A_UNUSED) xr = xmp; } x_goto(xr); - x_delete(rsize, true); + x_delete(x_nb2nc(rsize), true); xmp = xr; return (KSTD); } @@ -2684,7 +2715,7 @@ x_expand(int c MKSH_A_UNUSED) return (KSTD); } x_goto(xbuf + start); - x_delete(end - start, false); + x_delete(x_nb2nc(end - start), false); i = 0; while (i < nwords) { @@ -2708,7 +2739,7 @@ do_complete( { char **words; int start, end, nlen, olen, nwords; - bool completed = false; + bool completed; nwords = x_cf_glob(&flags, xbuf, xep - xbuf, xcp - xbuf, &start, &end, &words); @@ -2726,14 +2757,47 @@ do_complete( } olen = end - start; nlen = x_longest_prefix(nwords, words); - /* always complete */ - x_goto(xbuf + start); - x_delete(olen, false); - x_escape(words[0], nlen, x_do_ins); - x_adjust(); - /* check if we did add something */ - if (xcp - (xbuf + start) > olen) + if (nwords == 1 || (flags & XCF_IS_SUBGLOB)) { + /* + * always complete the expansion of parameter and + * homedir substitution as well as single matches + */ completed = true; + } else { + char *unescaped; + + /* make a copy of the original string part and... */ + strndupx(unescaped, xbuf + start, olen, ATEMP); + /* ... convert it from backslash-escaped via QCHAR-escaped... */ + x_glob_hlp_add_qchar(unescaped); + /* ... to unescaped, for comparison with the matches */ + x_glob_hlp_rem_qchar(unescaped); + /* + * match iff entire original string is part of the + * longest prefix, implying the latter is at least + * the same size (after unescaping) + */ + completed = !strncmp(words[0], unescaped, strlen(unescaped)); + + afree(unescaped, ATEMP); + } + if (type == CT_COMPLIST && nwords > 1) { + /* + * print expansions, since we didn't get back + * just a single match + */ + x_print_expansions(nwords, words, + tobool(flags & XCF_IS_COMMAND)); + } + if (completed) { + /* expand on the command line */ + xmp = NULL; + xcp = xbuf + start; + xep -= olen; + memmove(xcp, xcp + olen, xep - xcp + 1); + x_escape(words[0], nlen, x_do_ins); + } + x_adjust(); /* * append a space if this is a single non-directory match * and not a parameter or homedir substitution @@ -2741,15 +2805,7 @@ do_complete( if (nwords == 1 && words[0][nlen - 1] != '/' && !(flags & XCF_IS_SUBGLOB)) { x_ins(" "); - completed = true; } - if (type == CT_COMPLIST && !completed) { - x_print_expansions(nwords, words, - tobool(flags & XCF_IS_COMMAND)); - completed = true; - } - if (completed) - x_redraw(0); x_free_words(nwords, words); } --- mksh-40.9.20120630-1/sh.h 2012-06-28 20:18:25.000000000 +0000 +++ mksh-40.9.20120630-2/sh.h 2012-07-24 09:54:20.000000000 +0000 @@ -412,15 +412,6 @@ extern int wcwidth(__WCHAR_TYPE__); #define BIT(i) (1 << (i)) #define NELEM(a) (sizeof(a) / sizeof((a)[0])) -/* these shall be smaller than 100 */ -#ifdef MKSH_CONSERVATIVE_FDS -#define NUFILE 32 /* Number of user-accessible files */ -#define FDBASE 10 /* First file usable by Shell */ -#else -#define NUFILE 56 /* Number of user-accessible files */ -#define FDBASE 24 /* First file usable by Shell */ -#endif - /* * Make MAGIC a char that might be printed to make bugs more obvious, but * not a char that is used often. Also, can't use the high bit as it causes @@ -545,6 +536,9 @@ im_sorry_dave(void) #ifndef MKSH_NO_CMDLINE_EDITING #define MKSH_NO_CMDLINE_EDITING /* defined */ #endif +#ifndef MKSH_CONSERVATIVE_FDS +#define MKSH_CONSERVATIVE_FDS /* defined */ +#endif #undef MKSH_S_NOVI #define MKSH_S_NOVI 1 #endif @@ -569,6 +563,15 @@ im_sorry_dave(void) #define MKSH_UNEMPLOYED 1 #endif +/* these shall be smaller than 100 */ +#ifdef MKSH_CONSERVATIVE_FDS +#define NUFILE 32 /* Number of user-accessible files */ +#define FDBASE 10 /* First file usable by Shell */ +#else +#define NUFILE 56 /* Number of user-accessible files */ +#define FDBASE 24 /* First file usable by Shell */ +#endif + /* * simple grouping allocator */