Please review changes against upstream code using SCM,
see the Vcs-* tags in debian/control for its location.

--- mksh-40.9.20120630.orig/edit.c
+++ mksh-40.9.20120630/edit.c
@@ -28,7 +28,7 @@
 
 #ifndef MKSH_NO_CMDLINE_EDITING
 
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.237 2012/05/05 17:32:31 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.237.4.1 2012/07/20 22:51:40 tg Exp $");
 
 /*
  * in later versions we might use libtermcap for this, but since external
@@ -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.orig/sh.h
+++ mksh-40.9.20120630/sh.h
@@ -157,9 +157,9 @@
 #endif
 
 #ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.568 2012/06/28 20:17:37 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.568.2.2 2012/07/20 23:31:06 tg Exp $");
 #endif
-#define MKSH_VERSION "R40 2012/06/28"
+#define MKSH_VERSION "R40 2012/07/20 Debian-2"
 
 /* arithmetic types: C implementation */
 #if !HAVE_CAN_INTTYPES
@@ -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
  */
--- mksh-40.9.20120630.orig/check.t
+++ mksh-40.9.20120630/check.t
@@ -1,4 +1,4 @@
-# $MirOS: src/bin/mksh/check.t,v 1.549 2012/06/28 20:17:35 tg Exp $
+# $MirOS: src/bin/mksh/check.t,v 1.549.2.1 2012/07/20 23:31:02 tg Exp $
 # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
 # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
 # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@@ -29,7 +29,7 @@
 # http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
 
 expected-stdout:
-	@(#)MIRBSD KSH R40 2012/06/28
+	@(#)MIRBSD KSH R40 2012/07/20 Debian-2
 description:
 	Check version of shell.
 stdin:
@@ -38,7 +38,7 @@ name: KSH_VERSION
 category: shell:legacy-no
 ---
 expected-stdout:
-	@(#)LEGACY KSH R40 2012/06/28
+	@(#)LEGACY KSH R40 2012/07/20 Debian-2
 description:
 	Check version of legacy shell.
 stdin:
--- mksh-40.9.20120630.orig/Build.sh
+++ mksh-40.9.20120630/Build.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.577 2012/06/28 20:17:33 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.578 2012/07/01 15:51:24 tg Exp $'
 #-
 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 #		2011, 2012
@@ -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
@@ -1485,7 +1486,7 @@ else
 		#define EXTERN
 		#define MKSH_INCLUDES_ONLY
 		#include "sh.h"
-		__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.577 2012/06/28 20:17:33 tg Exp $");
+		__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.578 2012/07/01 15:51:24 tg Exp $");
 		int main(void) { printf("Hello, World!\n"); return (0); }
 EOF
 	case $cm in
