Subject: Re: ksh: escape spaces when expanding
To: None <tech-userlevel@netbsd.org>
From: Jaromir Dolecek <dolecek@ics.muni.cz>
List: tech-userlevel
Date: 09/22/1999 18:51:27
Hi,
so I added escaping of (hopefully) all shell special chars. The only
change is in the vi.c:complete_word(). The " & ' quoting is still
not handled at all.
Index: edit.c
===================================================================
RCS file: /cvsroot/basesrc/bin/ksh/edit.c,v
retrieving revision 1.4
diff -u -p -r1.4 edit.c
--- edit.c 1998/11/04 18:27:21 1.4
+++ edit.c 1999/09/22 16:52:44
@@ -537,7 +537,7 @@ x_file_glob(flags, str, slen, wordsp)
{
char *toglob;
char **words;
- int nwords;
+ int nwords, i, idx, escaping;
XPtrV w;
struct source *s, *sold;
@@ -546,6 +546,20 @@ x_file_glob(flags, str, slen, 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)
*/
@@ -740,11 +754,14 @@ x_locate_word(buf, buflen, pos, startp,
/* Keep going backwards to start of word (has effect of allowing
* one blank after the end of a word)
*/
- for (; start > 0 && IS_WORDC(buf[start - 1]); start--)
+ for (; (start > 0 && IS_WORDC(buf[start - 1]))
+ || (start > 1 && buf[start-2] == '\\'); start--)
;
/* Go forwards to end of word */
- for (end = start; end < buflen && IS_WORDC(buf[end]); end++)
- ;
+ for (end = start; end < buflen && IS_WORDC(buf[end]); end++) {
+ if (buf[end] == '\\' && (end+1) < buflen && buf[end+1] == ' ')
+ end++;
+ }
if (is_commandp) {
int iscmd;
Index: vi.c
===================================================================
RCS file: /cvsroot/basesrc/bin/ksh/vi.c,v
retrieving revision 1.3
diff -u -p -r1.3 vi.c
--- vi.c 1998/11/04 18:27:21 1.3
+++ vi.c 1999/09/22 16:52:44
@@ -1996,7 +1996,7 @@ complete_word(command, count)
int start, end;
char **words;
char *match;
- int match_len;
+ int match_len, len, add;
int is_unique;
int is_command;
@@ -2069,16 +2069,37 @@ complete_word(command, count)
buf = save_edstate(es);
del_range(start, end);
es->cursor = start;
- if (putbuf(match, match_len, 0) != 0)
- rval = -1;
- else if (is_unique) {
+
+ /* escape all shell-sensitive characters in the word */
+ for (add = 0, len = match_len; len - add > 0; add++) {
+ if (strchr("\\$(){}*&;|<> \t\"'", match[add])) {
+ if (putbuf(match, add, 0) != 0) {
+ rval = -1;
+ break;
+ }
+
+ putbuf("\\", 1, 0);
+ putbuf(&match[add], 1, 0);
+
+ add++;
+ len -= add;
+ match += add;
+ add = -1; /* after the increment it will go to 0 */
+ }
+ }
+ if (len > 0) {
+ rval = putbuf(match, len, 0);
+ match += len;
+ }
+
+ if (rval == 0 && is_unique) {
/* If exact match, don't undo. Allows directory completions
* to be used (ie, complete the next portion of the path).
*/
expanded = NONE;
/* If not a directory, add a space to the end... */
- if (match_len > 0 && !ISDIRSEP(match[match_len - 1]))
+ if (match_len > 0 && !ISDIRSEP(match[-1]))
rval = putbuf(space, 1, 0);
}
x_free_words(nwords, words);
--
Jaromir Dolecek <jdolecek@NetBSD.org> http://www.ics.muni.cz/~dolecek/
"The only way how to get rid temptation is to yield to it." -- Oscar Wilde