Subject: pdksh: escaping special characters when expanding
To: None <pdksh@cs.mun.ca>
From: Jaromir Dolecek <dolecek@ics.muni.cz>
List: tech-userlevel
Date: 10/07/1999 11:00:40
--ELM939286840-2653-0_
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Hi,
I've cleaned up the patches to backslash-quote special shell characters
when expanding the file name (either via tab in vi-tabcomplete
or ^[^[ in emacs mode). I made them work in emacs mode as well and
the value of IFS is now honored.
I think this would be valueable addition to pdksh. It's very comfortable
when dealing with directories or files containing e.g. spaces
(all praise well-known "Program Files").
The patch is in attachment. Please let me know if the change is
okay.
Best regards
Jaromir
--
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
--ELM939286840-2653-0_
Content-Type: text/plain; charset=ISO-8859-2
Content-Disposition: attachment; filename=pdksh.quoteexp.diff
Content-Description: f
Content-Transfer-Encoding: 7bit
Index: edit.c
===================================================================
RCS file: /cvsroot/basesrc/bin/ksh/edit.c,v
retrieving revision 1.4
diff -u -r1.4 edit.c
--- edit.c 1998/11/04 18:27:21 1.4
+++ edit.c 1999/10/07 08:57:49
@@ -537,7 +537,7 @@
{
char *toglob;
char **words;
- int nwords;
+ int nwords, i, idx, escaping;
XPtrV w;
struct source *s, *sold;
@@ -546,6 +546,20 @@
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 @@
/* 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;
@@ -1011,4 +1028,40 @@
Xfree(xs, xp);
}
+/*
+ * if argument string contains any special characters, they will
+ * be escaped and the result will be put into edit buffer by
+ * keybinding-specific function
+ */
+int
+x_escape(s, len, putbuf_func)
+ const char *s;
+ size_t len;
+ int putbuf_func ARGS((const char *s, size_t len));
+{
+ size_t add, wlen;
+ const char *ifs = str_val(local("IFS", 0));
+ int rval=0;
+
+ for (add = 0, wlen = len; wlen - add > 0; add++) {
+ if (strchr("\\$(){}*&;|<>\"'", s[add]) || strchr(ifs, s[add])) {
+ if (putbuf_func(s, add) != 0) {
+ rval = -1;
+ break;
+ }
+
+ putbuf_func("\\", 1);
+ putbuf_func(&s[add], 1);
+
+ add++;
+ wlen -= add;
+ s += add;
+ add = -1; /* after the increment it will go to 0 */
+ }
+ }
+ if (wlen > 0 && rval == 0)
+ rval = putbuf_func(s, wlen);
+
+ return (rval);
+}
#endif /* EDIT */
Index: edit.h
===================================================================
RCS file: /cvsroot/basesrc/bin/ksh/edit.h,v
retrieving revision 1.2
diff -u -r1.2 edit.h
--- edit.h 1997/01/12 19:11:45 1.2
+++ edit.h 1999/10/07 08:57:49
@@ -57,6 +57,7 @@
int x_longest_prefix ARGS((int nwords, char *const *words));
int x_basename ARGS((const char *s, const char *se));
void x_free_words ARGS((int nwords, char **words));
+int x_escape ARGS((const char *, size_t, int (*)(const char *s, size_t len)));
/* emacs.c */
int x_emacs ARGS((char *buf, size_t len));
void x_init_emacs ARGS((void));
Index: emacs.c
===================================================================
RCS file: /cvsroot/basesrc/bin/ksh/emacs.c,v
retrieving revision 1.5
diff -u -r1.5 emacs.c
--- emacs.c 1998/11/04 18:27:21 1.5
+++ emacs.c 1999/10/07 08:57:52
@@ -144,6 +144,7 @@
static char *x_lastcp ARGS((void));
static void do_complete ARGS((int flags, Comp_type type));
static int x_do_ins ARGS((const char *, int));
+static int x_emacs_putbuf ARGS((const char *s, size_t len));
/* The lines between START-FUNC-TAB .. END-FUNC-TAB are run through a
@@ -472,6 +473,21 @@
return 0;
}
+/*
+ * this is used for x_escape() in do_complete()
+ */
+static int
+x_emacs_putbuf(s, len)
+ const char *s;
+ size_t len;
+{
+ int rval;
+
+ if ((rval = x_do_ins(s, len)) != 0)
+ return (rval);
+ return (rval);
+}
+
static int
x_del_back(c)
int c;
@@ -1806,8 +1822,8 @@
if (nlen > 0) {
x_goto(xbuf + start);
x_delete(end - start, FALSE);
- words[0][nlen] = '\0';
- x_ins(words[0]);
+ x_escape(words[0], nlen, x_emacs_putbuf);
+ x_adjust();
/* If single match is not a directory, add a
* space to the end...
*/
Index: vi.c
===================================================================
RCS file: /cvsroot/basesrc/bin/ksh/vi.c,v
retrieving revision 1.3
diff -u -r1.3 vi.c
--- vi.c 1998/11/04 18:27:21 1.3
+++ vi.c 1999/10/07 08:57:52
@@ -65,6 +65,7 @@
static void vi_pprompt ARGS((int full));
static void vi_error ARGS((void));
static void vi_macro_reset ARGS((void));
+static int x_vi_putbuf ARGS((const char *s, size_t len));
#define C_ 0x1 /* a valid command that isn't a M_, E_, U_ */
#define M_ 0x2 /* movement command (h, l, etc.) */
@@ -1471,6 +1472,17 @@
holdlen = 0;
}
+/*
+ * this is used for calling x_escape() in complete_word()
+ */
+static int
+x_vi_putbuf(s, len)
+ const char *s;
+ size_t len;
+{
+ return putbuf(s, len, 0);
+}
+
static int
putbuf(buf, len, repl)
const char *buf;
@@ -2069,9 +2081,12 @@
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 and put the result into
+ * command buffer */
+ rval = x_escape(match, match_len, x_vi_putbuf);
+
+ 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).
*/
--ELM939286840-2653-0_--