ksh: escape control chars when displaying file name completions.
authormillert <millert@openbsd.org>
Wed, 21 Jun 2023 22:22:08 +0000 (22:22 +0000)
committermillert <millert@openbsd.org>
Wed, 21 Jun 2023 22:22:08 +0000 (22:22 +0000)
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@

bin/ksh/edit.c
bin/ksh/edit.h
bin/ksh/emacs.c
bin/ksh/exec.c
bin/ksh/sh.h

index 3089d19..a06cbe7 100644 (file)
@@ -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)
 {
index 0b604cd..1d573e1 100644 (file)
@@ -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
 
 #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;
index 5370e81..3c9b007 100644 (file)
@@ -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
 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 */
index 887f6f9..69a1cb9 100644 (file)
@@ -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
  */
index 93beef3..bffb374 100644 (file)
@@ -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);