diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2023-06-21 22:22:09 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2023-06-21 22:22:09 +0000 |
commit | 625fd0c48aa435c29fc067b64c7fcdd8200f31d6 (patch) | |
tree | 3802c42492055b3d31e469e3431eb3eccce860ed | |
parent | d75f65d40a7b2cf83a64349d3434fae7d50c2283 (diff) |
ksh: escape control chars when displaying file name completions.
If there are multiple matches when using autocomplete, the list of
matching file names was output as-is. However, for a single match,
control characters are escaped before the file name is displayed.
This makes the behavior more consistent by escaping control chars
in the list of matches too. Discussed with deraadt@, OK op@
-rw-r--r-- | bin/ksh/edit.c | 63 | ||||
-rw-r--r-- | bin/ksh/edit.h | 6 | ||||
-rw-r--r-- | bin/ksh/emacs.c | 6 | ||||
-rw-r--r-- | bin/ksh/exec.c | 29 | ||||
-rw-r--r-- | bin/ksh/sh.h | 3 |
5 files changed, 70 insertions, 37 deletions
diff --git a/bin/ksh/edit.c b/bin/ksh/edit.c index 3089d195d20..a06cbe7b4e0 100644 --- a/bin/ksh/edit.c +++ b/bin/ksh/edit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: edit.c,v 1.69 2019/06/28 13:34:59 deraadt Exp $ */ +/* $OpenBSD: edit.c,v 1.70 2023/06/21 22:22:08 millert Exp $ */ /* * Command line editing - common code @@ -294,6 +294,67 @@ static void glob_table(const char *pat, XPtrV *wp, struct table *tp); static void glob_path(int flags, const char *pat, XPtrV *wp, const char *path); +static char * +plain_fmt_entry(void *arg, int i, char *buf, int bsize) +{ + const char *str = ((char *const *)arg)[i]; + char *buf0 = buf; + int ch; + + if (buf == NULL || bsize <= 0) + internal_errorf("%s: buf %lx, bsize %d", + __func__, (long) buf, bsize); + + while ((ch = (unsigned char)*str++) != '\0') { + if (iscntrl(ch)) { + if (bsize < 3) + break; + *buf++ = '^'; + *buf++ = UNCTRL(ch); + bsize -= 2; + continue; + } + if (bsize < 2) + break; + *buf++ = ch; + bsize--; + } + *buf = '\0'; + + return buf0; +} + +/* Compute the length of string taking into account escape characters. */ +static size_t +strlen_esc(const char *str) +{ + size_t len = 0; + int ch; + + while ((ch = (unsigned char)*str++) != '\0') { + if (iscntrl(ch)) + len++; + len++; + } + return len; +} + +static int +pr_list(char *const *ap) +{ + char *const *pp; + int nwidth; + int i, n; + + for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) { + i = strlen_esc(*pp); + nwidth = (i > nwidth) ? i : nwidth; + } + print_columns(shl_out, n, plain_fmt_entry, (void *) ap, nwidth + 1, 0); + + return n; +} + void x_print_expansions(int nwords, char *const *words, int is_command) { diff --git a/bin/ksh/edit.h b/bin/ksh/edit.h index 0b604cd64fb..1d573e1f6fb 100644 --- a/bin/ksh/edit.h +++ b/bin/ksh/edit.h @@ -1,4 +1,4 @@ -/* $OpenBSD: edit.h,v 1.12 2018/06/18 17:03:58 millert Exp $ */ +/* $OpenBSD: edit.h,v 1.13 2023/06/21 22:22:08 millert Exp $ */ /* NAME: * edit.h - globals for edit modes @@ -16,6 +16,10 @@ #define BEL 0x07 +#undef CTRL +#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */ +#define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */ + /* tty driver characters we are interested in */ typedef struct { int erase; diff --git a/bin/ksh/emacs.c b/bin/ksh/emacs.c index 5370e814f70..3c9b0074d81 100644 --- a/bin/ksh/emacs.c +++ b/bin/ksh/emacs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: emacs.c,v 1.89 2021/10/09 21:38:00 halex Exp $ */ +/* $OpenBSD: emacs.c,v 1.90 2023/06/21 22:22:08 millert Exp $ */ /* * Emacs-like command line editing and history @@ -32,10 +32,6 @@ static Area aedit; #define AEDIT &aedit /* area for kill ring and macro defns */ -#undef CTRL -#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */ -#define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */ - /* values returned by keyboard functions */ #define KSTD 0 #define KEOL 1 /* ^M, ^J */ diff --git a/bin/ksh/exec.c b/bin/ksh/exec.c index 887f6f95a9b..69a1cb97b91 100644 --- a/bin/ksh/exec.c +++ b/bin/ksh/exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec.c,v 1.76 2022/10/10 14:57:48 kn Exp $ */ +/* $OpenBSD: exec.c,v 1.77 2023/06/21 22:22:08 millert Exp $ */ /* * execute command tree @@ -1340,33 +1340,6 @@ pr_menu(char *const *ap) return n; } -/* XXX: horrible kludge to fit within the framework */ - -static char *plain_fmt_entry(void *arg, int i, char *buf, int buflen); - -static char * -plain_fmt_entry(void *arg, int i, char *buf, int buflen) -{ - shf_snprintf(buf, buflen, "%s", ((char *const *)arg)[i]); - return buf; -} - -int -pr_list(char *const *ap) -{ - char *const *pp; - int nwidth; - int i, n; - - for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) { - i = strlen(*pp); - nwidth = (i > nwidth) ? i : nwidth; - } - print_columns(shl_out, n, plain_fmt_entry, (void *) ap, nwidth + 1, 0); - - return n; -} - /* * [[ ... ]] evaluation routines */ diff --git a/bin/ksh/sh.h b/bin/ksh/sh.h index 93beef31d46..bffb374e0d1 100644 --- a/bin/ksh/sh.h +++ b/bin/ksh/sh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sh.h,v 1.76 2020/07/07 10:33:58 jca Exp $ */ +/* $OpenBSD: sh.h,v 1.77 2023/06/21 22:22:08 millert Exp $ */ /* * Public Domain Bourne/Korn shell @@ -441,7 +441,6 @@ void flushcom(int); char * search(const char *, const char *, int, int *); int search_access(const char *, int, int *); int pr_menu(char *const *); -int pr_list(char *const *); /* expr.c */ int evaluate(const char *, int64_t *, int, bool); int v_evaluate(struct tbl *, const char *, volatile int, bool); |