diff options
10 files changed, 537 insertions, 119 deletions
diff --git a/system/ksh/ksh.SlackBuild b/system/ksh/ksh.SlackBuild index b0db7e1f68..041e44db1e 100644 --- a/system/ksh/ksh.SlackBuild +++ b/system/ksh/ksh.SlackBuild @@ -29,7 +29,7 @@ PRGNAM=ksh VERSION=openbsd49 -BUILD=${BUILD:-1} +BUILD=${BUILD:-3} TAG=${TAG:-_SBo} if [ -z "$ARCH" ]; then diff --git a/system/ksh/ksh.info b/system/ksh/ksh.info index 30d21021b2..d0f4688dc0 100644 --- a/system/ksh/ksh.info +++ b/system/ksh/ksh.info @@ -2,7 +2,7 @@ PRGNAM="ksh" VERSION="openbsd49" HOMEPAGE="http://leva.ecentrum.hu/slackbuilds/ksh-openbsd49.tar.gz" DOWNLOAD="http://leva.ecentrum.hu/slackbuilds/ksh-openbsd49.tar.gz" -MD5SUM="fd0c66373e7ae03673b0b7913e73a986" +MD5SUM="a625102e5961f76bc9918484b2f05940" DOWNLOAD_x86_64="" MD5SUM_x86_64="" MAINTAINER="Daniel LEVAI" diff --git a/system/ksh/patches/0001-ksh-vi-mode-complete-as-command-on-Ctrl-f.diff b/system/ksh/patches/0001-ksh-vi-mode-complete-as-command-on-Ctrl-f.diff new file mode 100644 index 0000000000..4888d25860 --- /dev/null +++ b/system/ksh/patches/0001-ksh-vi-mode-complete-as-command-on-Ctrl-f.diff @@ -0,0 +1,152 @@ +From 6af44d2fa0cdcba11368cf4eee141e42bf0dd422 Mon Sep 17 00:00:00 2001 +From: Alexander Polakov <polachok@gmail.com> +Date: Sun, 29 May 2011 14:55:46 +0400 +Subject: [PATCH 1/8] ksh/vi mode: complete as command on Ctrl-f. + + * adds a flag for x_cf_glob() to force completion like it was a command + * new argument for complete_word() to pass the flag + * reuse print_expansions() unused argument to pass the flag + + Why: useful for sudo or one-liner completion + XXX: use different key combination? +--- + edit.c | 2 ++ + edit.h | 7 ++++--- + vi.c | 22 +++++++++++----------- + 3 files changed, 17 insertions(+), 14 deletions(-) + +diff --git a/edit.c b/edit.c +index 6c357a7..0b1ff7d 100644 +--- a/edit.c ++++ b/edit.c +@@ -599,6 +599,8 @@ x_cf_glob(int flags, const char *buf, int buflen, int pos, int *startp, + len = x_locate_word(buf, buflen, pos, startp, &is_command); + if (!(flags & XCF_COMMAND)) + is_command = 0; ++ if (flags & XCF_FORCE_COMMAND) ++ is_command = 1; + /* Don't do command globing on zero length strings - it takes too + * long and isn't very useful. File globs are more likely to be + * useful, so allow these. +diff --git a/edit.h b/edit.h +index f966fe4..9c75ffc 100644 +--- a/edit.h ++++ b/edit.h +@@ -38,9 +38,10 @@ typedef struct { + EXTERN X_chars edchars; + + /* x_cf_glob() flags */ +-#define XCF_COMMAND BIT(0) /* Do command completion */ +-#define XCF_FILE BIT(1) /* Do file completion */ +-#define XCF_FULLPATH BIT(2) /* command completion: store full path */ ++#define XCF_COMMAND BIT(0) /* Do command completion */ ++#define XCF_FILE BIT(1) /* Do file completion */ ++#define XCF_FULLPATH BIT(2) /* command completion: store full path */ ++#define XCF_FORCE_COMMAND BIT(3) /* Force completion as a command */ + #define XCF_COMMAND_FILE (XCF_COMMAND|XCF_FILE) + + /* edit.c */ +diff --git a/vi.c b/vi.c +index 889b35a..e4173c7 100644 +--- a/vi.c ++++ b/vi.c +@@ -58,7 +58,7 @@ static int newcol(int, int); + static void display(char *, char *, int); + static void ed_mov_opt(int, char *); + static int expand_word(int); +-static int complete_word(int, int); ++static int complete_word(int, int, int); + static int print_expansions(struct edstate *, int); + static int char_len(int); + static void x_vi_zotc(int); +@@ -651,7 +651,7 @@ vi_insert(int ch) + break; + + case Ctrl('f'): +- complete_word(0, 0); ++ complete_word(0, 0, XCF_FORCE_COMMAND); + break; + + case Ctrl('e'): +@@ -660,7 +660,7 @@ vi_insert(int ch) + + case Ctrl('i'): + if (Flag(FVITABCOMPLETE)) { +- complete_word(0, 0); ++ complete_word(0, 0, 0); + break; + } + /* FALLTHROUGH */ +@@ -1111,14 +1111,14 @@ vi_cmd(int argcnt, const char *cmd) + + case '=': /* at&t ksh */ + case Ctrl('e'): /* Nonstandard vi/ksh */ +- print_expansions(es, 1); ++ print_expansions(es, 0); + break; + + + case Ctrl('i'): /* Nonstandard vi/ksh */ + if (!Flag(FVITABCOMPLETE)) + return -1; +- complete_word(1, argcnt); ++ complete_word(1, argcnt, 0); + break; + + case Ctrl('['): /* some annoying at&t ksh's */ +@@ -1126,7 +1126,7 @@ vi_cmd(int argcnt, const char *cmd) + return -1; + case '\\': /* at&t ksh */ + case Ctrl('f'): /* Nonstandard vi/ksh */ +- complete_word(1, argcnt); ++ complete_word(1, argcnt, 0); + break; + + +@@ -1939,7 +1939,7 @@ expand_word(int command) + } + + static int +-complete_word(int command, int count) ++complete_word(int command, int count, int flags) + { + static struct edstate *buf; + int rval = 0; +@@ -1953,7 +1953,7 @@ complete_word(int command, int count) + + /* Undo previous completion */ + if (command == 0 && expanded == COMPLETE && buf) { +- print_expansions(buf, 0); ++ print_expansions(buf, flags); + expanded = PRINT; + return 0; + } +@@ -1971,7 +1971,7 @@ complete_word(int command, int count) + /* XCF_FULLPATH for count 'cause the menu printed by print_expansions() + * was done this way. + */ +- nwords = x_cf_glob(XCF_COMMAND_FILE | (count ? XCF_FULLPATH : 0), ++ nwords = x_cf_glob(XCF_COMMAND_FILE | (count ? XCF_FULLPATH : 0) | flags, + es->cbuf, es->linelen, es->cursor, + &start, &end, &words, &is_command); + if (nwords == 0) { +@@ -2044,14 +2044,14 @@ complete_word(int command, int count) + } + + static int +-print_expansions(struct edstate *e, int command) ++print_expansions(struct edstate *e, int flags) + { + int nwords; + int start, end; + char **words; + int is_command; + +- nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH, ++ nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH|flags, + e->cbuf, e->linelen, e->cursor, + &start, &end, &words, &is_command); + if (nwords == 0) { +-- +1.7.5 + diff --git a/system/ksh/patches/0003-ksh-vi-Ctrl-l-in-insert-mode-to-clear-the-screen.diff b/system/ksh/patches/0003-ksh-vi-Ctrl-l-in-insert-mode-to-clear-the-screen.diff new file mode 100644 index 0000000000..7f94b8bc6c --- /dev/null +++ b/system/ksh/patches/0003-ksh-vi-Ctrl-l-in-insert-mode-to-clear-the-screen.diff @@ -0,0 +1,45 @@ +From 13ef2cd4206ed541fe1dae46c91a339fba5cf5cf Mon Sep 17 00:00:00 2001 +From: Alexander Polakov <polachok@gmail.com> +Date: Sun, 29 May 2011 15:12:31 +0400 +Subject: [PATCH 3/8] ksh/vi: Ctrl-l in insert mode to clear the screen. + + Why: typing "clear" is too slow. +--- + ksh.1 | 3 +++ + vi.c | 6 ++++++ + 2 files changed, 9 insertions(+), 0 deletions(-) + +diff --git a/ksh.1 b/ksh.1 +index f4b5815..01130ea 100644 +--- a/ksh.1 ++++ b/ksh.1 +@@ -5215,6 +5215,9 @@ List all the commands or files that match the current big-word. + Macro expansion. + Execute the commands found in the alias + .Ar c . ++.It ^L ++Clear the screen leaving the current line at the top of the ++screen. + .El + .Pp + Intra-line movement commands: +diff --git a/vi.c b/vi.c +index e4173c7..d0de478 100644 +--- a/vi.c ++++ b/vi.c +@@ -646,6 +646,12 @@ vi_insert(int ch) + return redo_insert(lastac - 1); + + /* { Begin nonstandard vi commands */ ++ case Ctrl('l'): ++ /* Use ANSI escape codes to clear the screen */ ++ x_puts("\033[2J\033[0;0H"); ++ redraw_line(0); ++ break; ++ + case Ctrl('x'): + expand_word(0); + break; +-- +1.7.5 + diff --git a/system/ksh/patches/0004-ksh-vi-make-Ctrl-f-in-command-mode-behave-the-same-a.diff b/system/ksh/patches/0004-ksh-vi-make-Ctrl-f-in-command-mode-behave-the-same-a.diff new file mode 100644 index 0000000000..ec86efd52a --- /dev/null +++ b/system/ksh/patches/0004-ksh-vi-make-Ctrl-f-in-command-mode-behave-the-same-a.diff @@ -0,0 +1,26 @@ +From 90f648bf6182d558ff6489caefb52240fb2eab4e Mon Sep 17 00:00:00 2001 +From: Alexander Polakov <polachok@gmail.com> +Date: Sun, 29 May 2011 15:34:55 +0400 +Subject: [PATCH 4/8] ksh/vi: make Ctrl-f in command mode behave the same as + in insert. + +--- + vi.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/vi.c b/vi.c +index d0de478..6eb5d8c 100644 +--- a/vi.c ++++ b/vi.c +@@ -1132,7 +1132,7 @@ vi_cmd(int argcnt, const char *cmd) + return -1; + case '\\': /* at&t ksh */ + case Ctrl('f'): /* Nonstandard vi/ksh */ +- complete_word(1, argcnt, 0); ++ complete_word(1, argcnt, XCF_FORCE_COMMAND); + break; + + +-- +1.7.5 + diff --git a/system/ksh/patches/0005-ksh-print-expansions-like-a-menu-with-numbers-in-vi-.diff b/system/ksh/patches/0005-ksh-print-expansions-like-a-menu-with-numbers-in-vi-.diff new file mode 100644 index 0000000000..aeb5413863 --- /dev/null +++ b/system/ksh/patches/0005-ksh-print-expansions-like-a-menu-with-numbers-in-vi-.diff @@ -0,0 +1,105 @@ +From 91ebd29a64451742b65115fc27034c6a3d154f90 Mon Sep 17 00:00:00 2001 +From: Alexander Polakov <polachok@gmail.com> +Date: Sun, 29 May 2011 15:41:53 +0400 +Subject: [PATCH 5/8] ksh: print expansions like a "menu" (with numbers) in vi + mode + + * adds an extra argument to x_print_expansions() + - preserves the emacs mode behaviour + + Why: in vi mode one can use the expansion number to + complete the word, but w/o numbers printed you + have to *count* expansions with your eyes to + find out the number. Stupid, huh? +--- + edit.c | 7 +++++-- + edit.h | 2 +- + emacs.c | 4 ++-- + vi.c | 4 ++-- + 4 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/edit.c b/edit.c +index 0b1ff7d..9cdcc6d 100644 +--- a/edit.c ++++ b/edit.c +@@ -292,7 +292,7 @@ static void glob_path(int flags, const char *pat, XPtrV *wp, + const char *path); + + void +-x_print_expansions(int nwords, char *const *words, int is_command) ++x_print_expansions(int nwords, char *const *words, int is_command, int menu) + { + int use_copy = 0; + int prefix_len; +@@ -330,7 +330,10 @@ x_print_expansions(int nwords, char *const *words, int is_command) + */ + x_putc('\r'); + x_putc('\n'); +- pr_list(use_copy ? (char **) XPptrv(l) : words); ++ if (menu) ++ pr_menu(use_copy ? (char **) XPptrv(l) : words); ++ else ++ pr_list(use_copy ? (char **) XPptrv(l) : words); + + if (use_copy) + XPfree(l); /* not x_free_words() */ +diff --git a/edit.h b/edit.h +index 37ccf28..258affe 100644 +--- a/edit.h ++++ b/edit.h +@@ -52,7 +52,7 @@ void x_puts(const char *); + bool x_mode(bool); + int promptlen(const char *, const char **); + int x_do_comment(char *, int, int *); +-void x_print_expansions(int, char *const *, int); ++void x_print_expansions(int, char *const *, int, int); + int x_cf_glob(int, const char *, int, int, int *, int *, char ***, int *); + int x_longest_prefix(int , char *const *); + int x_basename(const char *, const char *); +diff --git a/emacs.c b/emacs.c +index 0bfda96..3b2d083 100644 +--- a/emacs.c ++++ b/emacs.c +@@ -1684,7 +1684,7 @@ do_complete(int flags, /* XCF_{COMMAND,FILE,COMMAND_FILE} */ + } + + if (type == CT_LIST) { +- x_print_expansions(nwords, words, is_command); ++ x_print_expansions(nwords, words, is_command, 0); + x_redraw(0); + x_free_words(nwords, words); + return; +@@ -1707,7 +1707,7 @@ do_complete(int flags, /* XCF_{COMMAND,FILE,COMMAND_FILE} */ + } + + if (type == CT_COMPLIST && !completed) { +- x_print_expansions(nwords, words, is_command); ++ x_print_expansions(nwords, words, is_command, 0); + completed = 1; + } + +diff --git a/vi.c b/vi.c +index 6eb5d8c..95d192c 100644 +--- a/vi.c ++++ b/vi.c +@@ -1990,7 +1990,7 @@ complete_word(int command, int count, int flags) + count--; + if (count >= nwords) { + vi_error(); +- x_print_expansions(nwords, words, is_command); ++ x_print_expansions(nwords, words, is_command, 1); + x_free_words(nwords, words); + redraw_line(0); + return -1; +@@ -2064,7 +2064,7 @@ print_expansions(struct edstate *e, int flags) + vi_error(); + return -1; + } +- x_print_expansions(nwords, words, is_command); ++ x_print_expansions(nwords, words, is_command, 1); + x_free_words(nwords, words); + redraw_line(0); + return 0; +-- +1.7.5 + diff --git a/system/ksh/patches/0006-ksh-remove-backslashes-in-filenames-using-lex.diff b/system/ksh/patches/0006-ksh-remove-backslashes-in-filenames-using-lex.diff new file mode 100644 index 0000000000..4ce48a8104 --- /dev/null +++ b/system/ksh/patches/0006-ksh-remove-backslashes-in-filenames-using-lex.diff @@ -0,0 +1,115 @@ +From 458d69d8f10d582fd7a546eabc1b555bb7337627 Mon Sep 17 00:00:00 2001 +From: Alexander Polakov <polachok@gmail.com> +Date: Sun, 29 May 2011 16:05:58 +0400 +Subject: [PATCH 6/8] ksh: remove backslashes in filenames using lex. + + * this also removes the check for matching pattern and + returned filename. if it returns 1 name, then it must + be the filename of an existing file, right? i think + so. + + Why: + + * less ugly code + * working completion for special characters like [], () and so + * suggested by martynas +--- + edit.c | 31 +++++++------------------------ + lex.c | 4 ++++ + lex.h | 1 + + 3 files changed, 12 insertions(+), 24 deletions(-) + +diff --git a/edit.c b/edit.c +index 9cdcc6d..01c2fe6 100644 +--- a/edit.c ++++ b/edit.c +@@ -351,7 +351,7 @@ x_file_glob(int flags, const char *str, int slen, char ***wordsp) + { + char *toglob; + char **words; +- int nwords, i, idx, escaping; ++ int nwords; + XPtrV w; + struct source *s, *sold; + +@@ -360,20 +360,6 @@ x_file_glob(int flags, const char *str, int slen, char ***wordsp) + + toglob = add_glob(str, slen); + +- /* remove all escaping backward slashes */ +- escaping = 0; +- for (i = 0, idx = 0; toglob[i]; i++) { +- if (toglob[i] == '\\' && !escaping) { +- escaping = 1; +- continue; +- } +- +- toglob[idx] = toglob[i]; +- idx++; +- if (escaping) escaping = 0; +- } +- toglob[idx] = '\0'; +- + /* + * Convert "foo*" (toglob) to an array of strings (words) + */ +@@ -381,7 +367,7 @@ x_file_glob(int flags, const char *str, int slen, char ***wordsp) + s = pushs(SWSTR, ATEMP); + s->start = s->str = toglob; + source = s; +- if (yylex(ONEWORD) != LWORD) { ++ if (yylex(ONEWORD|RMBKSLSH) != LWORD) { + source = sold; + internal_errorf(0, "fileglob: substitute error"); + return 0; +@@ -397,15 +383,12 @@ x_file_glob(int flags, const char *str, int slen, char ***wordsp) + if (nwords == 1) { + struct stat statb; + +- /* Check if globbing failed (returned glob pattern), +- * but be careful (E.g. toglob == "ab*" when the file +- * "ab*" exists is not an error). +- * Also, check for empty result - happens if we tried +- * to glob something which evaluated to an empty +- * string (e.g., "$FOO" when there is no FOO, etc). ++ /* Check if file exists, also, check for empty ++ * result - happens if we tried to glob something ++ * which evaluated to an empty string (e.g., ++ * "$FOO" when there is no FOO, etc). + */ +- if ((strcmp(words[0], toglob) == 0 && +- stat(words[0], &statb) < 0) || ++ if((stat(words[0], &statb) < 0) || + words[0][0] == '\0') { + x_free_words(nwords, words); + words = NULL; +diff --git a/lex.c b/lex.c +index ef741c6..fe3d91d 100644 +--- a/lex.c ++++ b/lex.c +@@ -299,6 +299,10 @@ yylex(int cf) + } + /* FALLTHROUGH */ + default: ++ if (cf & RMBKSLSH) { ++ *wp++ = QCHAR, *wp++ = c; ++ break; ++ } + Xcheck(ws, wp); + if (c) { /* trailing \ is lost */ + *wp++ = CHAR, *wp++ = '\\'; +diff --git a/lex.h b/lex.h +index 0904fbd..6a0dbf9 100644 +--- a/lex.h ++++ b/lex.h +@@ -113,6 +113,7 @@ typedef union { + #define CMDWORD BIT(8) /* parsing simple command (alias related) */ + #define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */ + #define HEREDOC BIT(10) /* parsing heredoc */ ++#define RMBKSLSH BIT(11) /* remove backslashes */ + + #define HERES 10 /* max << in line */ + +-- +1.7.5 + diff --git a/system/ksh/patches/0007-ksh-vi-compensate-for-cursor-move-on-command-mode.diff b/system/ksh/patches/0007-ksh-vi-compensate-for-cursor-move-on-command-mode.diff new file mode 100644 index 0000000000..8db9a55c55 --- /dev/null +++ b/system/ksh/patches/0007-ksh-vi-compensate-for-cursor-move-on-command-mode.diff @@ -0,0 +1,55 @@ +From fc2058b4b6a64d66fe1ee318bccea42b4569d31f Mon Sep 17 00:00:00 2001 +From: Alexander Polakov <polachok@gmail.com> +Date: Sun, 29 May 2011 19:23:17 +0400 +Subject: [PATCH 7/8] ksh/vi: compensate for cursor move on command mode + + * move completion cursor one position right if the + character is space + * when we enter command mode, cursor is moved one + position left, and the space on the end is "lost". + So we are trying to complete "ls" instead of file + while having "ls " and "file.c" when having "file.c ". +--- + vi.c | 15 ++++++++++++++- + 1 files changed, 14 insertions(+), 1 deletions(-) + +diff --git a/vi.c b/vi.c +index 95d192c..0bac6be 100644 +--- a/vi.c ++++ b/vi.c +@@ -1956,6 +1956,7 @@ complete_word(int command, int count, int flags) + int match_len; + int is_unique; + int is_command; ++ int pos; + + /* Undo previous completion */ + if (command == 0 && expanded == COMPLETE && buf) { +@@ -1974,11 +1975,23 @@ complete_word(int command, int count, int flags) + buf = 0; + } + ++ /* XXX: hack. When we enter command mode, the cursor is moved ++ * one position left. This means that the space at the end is ++ * eaten and file completion becomes command completion. ++ * (see x_locate_word() for more on this) ++ */ ++ pos = es->cursor; ++ if (command) { ++ pos += (isspace(es->cbuf[es->cursor]) ? 1 : 0); ++ if (pos > es->linelen) ++ pos = es->linelen; ++ } ++ + /* XCF_FULLPATH for count 'cause the menu printed by print_expansions() + * was done this way. + */ + nwords = x_cf_glob(XCF_COMMAND_FILE | (count ? XCF_FULLPATH : 0) | flags, +- es->cbuf, es->linelen, es->cursor, ++ es->cbuf, es->linelen, pos, + &start, &end, &words, &is_command); + if (nwords == 0) { + vi_error(); +-- +1.7.5 + diff --git a/system/ksh/patches/0008-Remove-from-the-list-of-characters-blocking-addition.diff b/system/ksh/patches/0008-Remove-from-the-list-of-characters-blocking-addition.diff new file mode 100644 index 0000000000..1a767a4f8c --- /dev/null +++ b/system/ksh/patches/0008-Remove-from-the-list-of-characters-blocking-addition.diff @@ -0,0 +1,37 @@ +From 5fc8a0ae3c807bd57c8e8d55531770914ea6670a Mon Sep 17 00:00:00 2001 +From: Alexander Polakov <polachok@gmail.com> +Date: Mon, 20 Jun 2011 00:35:46 +0400 +Subject: [PATCH 8/8] Remove $ from the list of characters blocking * + addition. + +This allows things like $HOME/bi<tab> complete to /home/username/bin. +--- + edit.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/edit.c b/edit.c +index 01c2fe6..2702dab 100644 +--- a/edit.c ++++ b/edit.c +@@ -627,14 +627,14 @@ add_glob(const char *str, int slen) + + /* + * If the pathname contains a wildcard (an unquoted '*', +- * '?', or '[') or parameter expansion ('$'), or a ~username +- * with no trailing slash, then it is globbed based on that +- * value (i.e., without the appended '*'). ++ * '?', or '[') or a ~username with no trailing slash, ++ * then it is globbed based on that value (i.e., without ++ * the appended '*'). + */ + for (s = toglob; *s; s++) { + if (*s == '\\' && s[1]) + s++; +- else if (*s == '*' || *s == '[' || *s == '?' || *s == '$' || ++ else if ((*s == '*' || *s == '[' || *s == '?') || + (s[1] == '(' /*)*/ && strchr("+@!", *s))) + break; + else if (*s == '/') +-- +1.7.5 + diff --git a/system/ksh/patches/00_completion.diff b/system/ksh/patches/00_completion.diff deleted file mode 100644 index ee843032ca..0000000000 --- a/system/ksh/patches/00_completion.diff +++ /dev/null @@ -1,117 +0,0 @@ -Index: bin/ksh/edit.c -=================================================================== -RCS file: /cvs/src/bin/ksh/edit.c,v -retrieving revision 1.34 -diff -u -r1.34 edit.c ---- ksh/edit.c 20 May 2010 01:13:07 -0000 1.34 -+++ ksh/edit.c 9 May 2011 19:44:06 -0000 -@@ -357,20 +357,6 @@ - - toglob = add_glob(str, slen); - -- /* remove all escaping backward slashes */ -- escaping = 0; -- for (i = 0, idx = 0; toglob[i]; i++) { -- if (toglob[i] == '\\' && !escaping) { -- escaping = 1; -- continue; -- } -- -- toglob[idx] = toglob[i]; -- idx++; -- if (escaping) escaping = 0; -- } -- toglob[idx] = '\0'; -- - /* - * Convert "foo*" (toglob) to an array of strings (words) - */ -@@ -378,7 +364,7 @@ - s = pushs(SWSTR, ATEMP); - s->start = s->str = toglob; - source = s; -- if (yylex(ONEWORD) != LWORD) { -+ if (yylex(ONEWORD|RMBKSLSH) != LWORD) { - source = sold; - internal_errorf(0, "fileglob: substitute error"); - return 0; -@@ -394,6 +380,20 @@ - if (nwords == 1) { - struct stat statb; - -+ /* remove all escaping backward slashes (see below) */ -+ escaping = 0; -+ for (i = 0, idx = 0; toglob[i]; i++) { -+ if (toglob[i] == '\\' && !escaping) { -+ escaping = 1; -+ continue; -+ } -+ -+ toglob[idx] = toglob[i]; -+ idx++; -+ if (escaping) escaping = 0; -+ } -+ toglob[idx] = '\0'; -+ - /* Check if globbing failed (returned glob pattern), - * but be careful (E.g. toglob == "ab*" when the file - * "ab*" exists is not an error). -@@ -821,7 +821,7 @@ - int rval = 0; - - for (add = 0, wlen = len; wlen - add > 0; add++) { -- if (strchr("\"#$&'()*;<=>?[\\]`{|}", s[add]) || -+ if (strchr(ESCAPEDCHARS, s[add]) || - strchr(ifs, s[add])) { - if (putbuf_func(s, add) != 0) { - rval = -1; -Index: bin/ksh/lex.c -=================================================================== -RCS file: /cvs/src/bin/ksh/lex.c,v -retrieving revision 1.45 -diff -u -r1.45 lex.c ---- ksh/lex.c 9 Mar 2011 09:30:39 -0000 1.45 -+++ ksh/lex.c 9 May 2011 19:44:07 -0000 -@@ -299,6 +299,10 @@ - } - /* FALLTHROUGH */ - default: -+ if ((cf & RMBKSLSH) && strchr(" " ESCAPEDCHARS, c)) { -+ *wp++ = QCHAR, *wp++ = c; -+ break; -+ } - Xcheck(ws, wp); - if (c) { /* trailing \ is lost */ - *wp++ = CHAR, *wp++ = '\\'; -Index: bin/ksh/lex.h -=================================================================== -RCS file: /cvs/src/bin/ksh/lex.h,v -retrieving revision 1.11 -diff -u -r1.11 lex.h ---- ksh/lex.h 29 May 2006 18:22:24 -0000 1.11 -+++ ksh/lex.h 9 May 2011 19:44:07 -0000 -@@ -113,6 +113,7 @@ - #define CMDWORD BIT(8) /* parsing simple command (alias related) */ - #define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */ - #define HEREDOC BIT(10) /* parsing heredoc */ -+#define RMBKSLSH BIT(11) /* remove backslashes */ - - #define HERES 10 /* max << in line */ - -Index: bin/ksh/sh.h -=================================================================== -RCS file: /cvs/src/bin/ksh/sh.h,v -retrieving revision 1.30 -diff -u -r1.30 sh.h ---- ksh/sh.h 4 Jan 2010 18:07:11 -0000 1.30 -+++ ksh/sh.h 9 May 2011 19:44:07 -0000 -@@ -398,6 +398,9 @@ - #define OBRACE '{' - #define CBRACE '}' - -+/* Characters to be escaped */ -+#define ESCAPEDCHARS "\"#$&'()*;<=>?[\\]`{|}" -+ - /* Determine the location of the system (common) profile */ - #define KSH_SYSTEM_PROFILE "/etc/profile" - |