diff --git a/contrib/libedit/ChangeLog b/contrib/libedit/ChangeLog new file mode 100644 index 000000000000..35c9205a43d8 --- /dev/null +++ b/contrib/libedit/ChangeLog @@ -0,0 +1,6 @@ +2021-08-29 Christos Zoulas + + Change default mappings: + map ^W to ed-delete-prev-word and not kill-region + map ^R to em-inc-search-next and not redisplay + diff --git a/contrib/libedit/TEST/fuzz1.c b/contrib/libedit/TEST/fuzz1.c new file mode 100644 index 000000000000..e31d26538885 --- /dev/null +++ b/contrib/libedit/TEST/fuzz1.c @@ -0,0 +1,63 @@ +/* + * build: + * CC=clang CXX=clang++ CFLAGS="-fsanitize=address,fuzzer-no-link -g" \ + * CXXFLAGS="-fsanitize=address,fuzzer-no-link -g" ./configure && make + * run: + * LD_LIBRARY_PATH=../src/.libs/ .libs/fuzz1 -max_len=32 \ + * -use_value_profile=1 -only_ascii=1 + */ +#include +#include +#include +#include +#include +#include + +int init = 0; + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (!Size) + return 0; + + if (!init) { + setlocale(LC_CTYPE, ""); + stifle_history(7); + init = 1; + } + + clear_history(); + + size_t lasti = 0; + + for (size_t i = 0;; ++i) { + if (i == Size || Data[i] == '\n') { + if (i - lasti) { + char *s = (char *)malloc(i - lasti + 1); + memcpy(s, &Data[lasti], i - lasti); + s[i - lasti] = '\0'; + + char *expansion; + int result; + +#ifdef DEBUG + fprintf(stderr, "Calling history_expand: >%s<\n", s); +#endif + result = history_expand(s, &expansion); + + if (result < 0 || result == 2) { + /* Errors ignored */ + } else { + add_history(expansion); + } + free(expansion); + free(s); + } + lasti = i + 1; + } + + if (i == Size) + break; + } + + return 0; +} diff --git a/contrib/libedit/editline.3 b/contrib/libedit/editline.3 index feec9a6cac25..f104dcc07c7a 100644 --- a/contrib/libedit/editline.3 +++ b/contrib/libedit/editline.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: editline.3,v 1.99 2018/11/18 17:09:39 christos Exp $ +.\" $NetBSD: editline.3,v 1.101 2021/08/15 10:12:54 wiz Exp $ .\" .\" Copyright (c) 1997-2014 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -26,7 +26,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd November 9, 2018 +.Dd August 15, 2021 .Dt EDITLINE 3 .Os .Sh NAME @@ -507,6 +507,16 @@ unbuffered mode is disabled (the default). In unbuffered mode, .Fn el_gets will return immediately after processing a single character. +.It Dv EL_SAFEREAD , Fa "int flag" +If the +.Fa flag +argument is non-zero, then +.Nm editline +attempts to recover from read errors, ignoring the first interrrupted +error, and trying to reset the input file descriptor to reset non-blocking I/O. +This is disabled by default, and desirable only when +.Nm editline +is used in shell-like applications. .It Dv EL_GETCFN , Fa "el_rfunc_t f" Whenever reading a character, use the function .Bd -ragged -offset indent -compact @@ -634,6 +644,10 @@ call. Set .Fa c to non-zero if unbuffered mode is enabled. +.It Dv EL_SAFEREAD , Fa "int *c" +Set +.Fa c +to non-zero if safe read is set. .It Dv EL_GETFP , Fa "int fd", Fa "FILE **fp" Set .Fa fp diff --git a/contrib/libedit/el.c b/contrib/libedit/el.c index 9ae7af3533d3..47b76d7a5302 100644 --- a/contrib/libedit/el.c +++ b/contrib/libedit/el.c @@ -1,4 +1,4 @@ -/* $NetBSD: el.c,v 1.99 2019/07/23 10:18:52 christos Exp $ */ +/* $NetBSD: el.c,v 1.100 2021/08/15 10:08:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; #else -__RCSID("$NetBSD: el.c,v 1.99 2019/07/23 10:18:52 christos Exp $"); +__RCSID("$NetBSD: el.c,v 1.100 2021/08/15 10:08:41 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -300,6 +300,14 @@ el_wset(EditLine *el, int op, ...) break; } + case EL_SAFEREAD: + if (va_arg(ap, int)) + el->el_flags |= FIXIO; + else + el->el_flags &= ~FIXIO; + rv = 0; + break; + case EL_EDITMODE: if (va_arg(ap, int)) el->el_flags &= ~EDIT_DISABLED; @@ -429,6 +437,11 @@ el_wget(EditLine *el, int op, ...) rv = 0; break; + case EL_SAFEREAD: + *va_arg(ap, int *) = (el->el_flags & FIXIO); + rv = 0; + break; + case EL_TERMINAL: terminal_get(el, va_arg(ap, const char **)); rv = 0; diff --git a/contrib/libedit/el.h b/contrib/libedit/el.h index b0d174eb62f6..757137839eb8 100644 --- a/contrib/libedit/el.h +++ b/contrib/libedit/el.h @@ -1,4 +1,4 @@ -/* $NetBSD: el.h,v 1.45 2019/07/23 10:18:52 christos Exp $ */ +/* $NetBSD: el.h,v 1.46 2021/08/15 10:08:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -51,12 +51,13 @@ #define EL_BUFSIZ ((size_t)1024) /* Maximum line size */ -#define HANDLE_SIGNALS 0x01 -#define NO_TTY 0x02 -#define EDIT_DISABLED 0x04 -#define UNBUFFERED 0x08 -#define NARROW_HISTORY 0x40 -#define NO_RESET 0x80 +#define HANDLE_SIGNALS 0x001 +#define NO_TTY 0x002 +#define EDIT_DISABLED 0x004 +#define UNBUFFERED 0x008 +#define NARROW_HISTORY 0x040 +#define NO_RESET 0x080 +#define FIXIO 0x100 typedef unsigned char el_action_t; /* Index to command array */ diff --git a/contrib/libedit/eln.c b/contrib/libedit/eln.c index e980bc5f9d2f..f432a2187c0d 100644 --- a/contrib/libedit/eln.c +++ b/contrib/libedit/eln.c @@ -1,4 +1,4 @@ -/* $NetBSD: eln.c,v 1.35 2019/04/26 16:56:57 christos Exp $ */ +/* $NetBSD: eln.c,v 1.36 2021/08/15 10:08:41 christos Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: eln.c,v 1.35 2019/04/26 16:56:57 christos Exp $"); +__RCSID("$NetBSD: eln.c,v 1.36 2021/08/15 10:08:41 christos Exp $"); #endif /* not lint && not SCCSID */ #include @@ -153,6 +153,7 @@ el_set(EditLine *el, int op, ...) case EL_SIGNAL: /* int */ case EL_EDITMODE: + case EL_SAFEREAD: case EL_UNBUFFERED: case EL_PREP_TERM: ret = el_wset(el, op, va_arg(ap, int)); @@ -315,6 +316,7 @@ el_get(EditLine *el, int op, ...) case EL_SIGNAL: /* int * */ case EL_EDITMODE: + case EL_SAFEREAD: case EL_UNBUFFERED: case EL_PREP_TERM: ret = el_wget(el, op, va_arg(ap, int *)); diff --git a/contrib/libedit/filecomplete.c b/contrib/libedit/filecomplete.c index 8279d7ff82b6..6dc7cff1d055 100644 --- a/contrib/libedit/filecomplete.c +++ b/contrib/libedit/filecomplete.c @@ -1,4 +1,4 @@ -/* $NetBSD: filecomplete.c,v 1.67 2021/03/28 13:39:39 christos Exp $ */ +/* $NetBSD: filecomplete.c,v 1.68 2021/05/05 14:49:59 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: filecomplete.c,v 1.67 2021/03/28 13:39:39 christos Exp $"); +__RCSID("$NetBSD: filecomplete.c,v 1.68 2021/05/05 14:49:59 christos Exp $"); #endif /* not lint && not SCCSID */ #include @@ -727,7 +727,7 @@ fn_complete2(EditLine *el, else completion = strdup(matches[0]); if (completion == NULL) - goto out; + goto out2; /* * Replace the completed string with the common part of @@ -810,6 +810,7 @@ fn_complete2(EditLine *el, } /* free elements of array and the array itself */ +out2: for (i = 0; matches[i]; i++) el_free(matches[i]); el_free(matches); diff --git a/contrib/libedit/histedit.h b/contrib/libedit/histedit.h index 56bb3ef9ea6a..511750e0137e 100644 --- a/contrib/libedit/histedit.h +++ b/contrib/libedit/histedit.h @@ -1,4 +1,4 @@ -/* $NetBSD: histedit.h,v 1.57 2017/09/01 10:19:10 christos Exp $ */ +/* $NetBSD: histedit.h,v 1.58 2021/08/15 10:08:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -158,6 +158,7 @@ unsigned char _el_fn_sh_complete(EditLine *, int); #define EL_RPROMPT_ESC 22 /* , prompt_func, Char); set/get */ #define EL_RESIZE 23 /* , el_zfunc_t, void *); set */ #define EL_ALIAS_TEXT 24 /* , el_afunc_t, void *); set */ +#define EL_SAFEREAD 25 /* , int); set/get */ #define EL_BUILTIN_GETCFN (NULL) diff --git a/contrib/libedit/map.c b/contrib/libedit/map.c index 46bf6f1c9472..321bb3539222 100644 --- a/contrib/libedit/map.c +++ b/contrib/libedit/map.c @@ -1,4 +1,4 @@ -/* $NetBSD: map.c,v 1.53 2020/03/30 06:54:37 ryo Exp $ */ +/* $NetBSD: map.c,v 1.54 2021/08/29 09:41:59 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: map.c,v 1.53 2020/03/30 06:54:37 ryo Exp $"); +__RCSID("$NetBSD: map.c,v 1.54 2021/08/29 09:41:59 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -85,12 +85,12 @@ static const el_action_t el_map_emacs[] = { /* 15 */ ED_IGNORE, /* ^O */ /* 16 */ ED_PREV_HISTORY, /* ^P */ /* 17 */ ED_IGNORE, /* ^Q */ - /* 18 */ ED_REDISPLAY, /* ^R */ + /* 18 */ EM_INC_SEARCH_PREV, /* ^R */ /* 19 */ ED_IGNORE, /* ^S */ /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ /* 21 */ EM_KILL_LINE, /* ^U */ /* 22 */ ED_QUOTED_INSERT, /* ^V */ - /* 23 */ EM_KILL_REGION, /* ^W */ + /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ /* 24 */ ED_SEQUENCE_LEAD_IN, /* ^X */ /* 25 */ EM_YANK, /* ^Y */ /* 26 */ ED_IGNORE, /* ^Z */ diff --git a/contrib/libedit/read.c b/contrib/libedit/read.c index d2095a244efa..a49a304de971 100644 --- a/contrib/libedit/read.c +++ b/contrib/libedit/read.c @@ -1,4 +1,4 @@ -/* $NetBSD: read.c,v 1.106 2019/07/23 10:18:52 christos Exp $ */ +/* $NetBSD: read.c,v 1.107 2021/08/15 10:08:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: read.c,v 1.106 2019/07/23 10:18:52 christos Exp $"); +__RCSID("$NetBSD: read.c,v 1.107 2021/08/15 10:08:41 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -277,7 +277,7 @@ static int read_char(EditLine *el, wchar_t *cp) { ssize_t num_read; - int tried = 0; + int tried = (el->el_flags & FIXIO) == 0; char cbuf[MB_LEN_MAX]; size_t cbp = 0; int save_errno = errno; diff --git a/contrib/libedit/readline.c b/contrib/libedit/readline.c index 792dddbaf70b..c12eb7481bf4 100644 --- a/contrib/libedit/readline.c +++ b/contrib/libedit/readline.c @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.159 2019/10/09 14:31:07 christos Exp $ */ +/* $NetBSD: readline.c,v 1.168 2021/09/10 18:51:36 rillig Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.159 2019/10/09 14:31:07 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.168 2021/09/10 18:51:36 rillig Exp $"); #endif /* not lint && not SCCSID */ #include @@ -108,6 +108,7 @@ int rl_attempted_completion_over = 0; const char *rl_basic_word_break_characters = break_chars; char *rl_completer_word_break_characters = NULL; const char *rl_completer_quote_characters = NULL; +const char *rl_basic_quote_characters = "\"'"; rl_compentry_func_t *rl_completion_entry_function = NULL; char *(*rl_completion_word_break_hook)(void) = NULL; rl_completion_func_t *rl_attempted_completion_function = NULL; @@ -122,11 +123,19 @@ int readline_echoing_p = 1; int _rl_print_completions_horizontally = 0; VFunction *rl_redisplay_function = NULL; Function *rl_startup_hook = NULL; -int rl_did_startup_hook = 0; VFunction *rl_completion_display_matches_hook = NULL; VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; KEYMAP_ENTRY_ARRAY emacs_meta_keymap; +unsigned long rl_readline_state; +int _rl_complete_mark_directories; +rl_icppfunc_t *rl_directory_completion_hook; +int rl_completion_suppress_append; +int rl_sort_completion_matches; +int _rl_completion_prefix_display_length; +int _rl_echoing_p; +int history_max_entries; +char *rl_display_prompt; /* * The current prompt string. @@ -208,11 +217,10 @@ static void _resize_fun(EditLine *el, void *a) { const LineInfo *li; - char **ap = a; + const char **ap = a; li = el_line(el); - /* a cheesy way to get rid of const cast. */ - *ap = memchr(li->buffer, *li->buffer, (size_t)1); + *ap = li->buffer; } static const char * @@ -416,8 +424,7 @@ readline(const char *p) if (e == NULL || h == NULL) rl_initialize(); - if (rl_did_startup_hook == 0 && rl_startup_hook) { - rl_did_startup_hook = 1; + if (rl_startup_hook) { (*rl_startup_hook)(NULL, 0); } tty_init(e); @@ -451,14 +458,10 @@ readline(const char *p) ret = el_gets(e, &count); if (ret && count > 0) { - int lastidx; - buf = strdup(ret); if (buf == NULL) goto out; - lastidx = count - 1; - if (buf[lastidx] == '\n') - buf[lastidx] = '\0'; + buf[strcspn(buf, "\n")] = '\0'; } else buf = NULL; @@ -593,7 +596,7 @@ get_history_event(const char *cmd, int *cindex, int qchar) if (sub && cmd[idx] == '?') break; if (!sub && (cmd[idx] == ':' || cmd[idx] == ' ' - || cmd[idx] == '\t' || cmd[idx] == qchar)) + || cmd[idx] == '\t' || cmd[idx] == qchar)) break; idx++; } @@ -619,8 +622,7 @@ get_history_event(const char *cmd, int *cindex, int qchar) if (sub) { if (pat != last_search_pat) { - if (last_search_pat) - el_free(last_search_pat); + el_free(last_search_pat); last_search_pat = pat; } ret = history_search(pat, -1); @@ -637,9 +639,8 @@ get_history_event(const char *cmd, int *cindex, int qchar) } if (sub && len) { - if (last_search_match && last_search_match != pat) - el_free(last_search_match); - last_search_match = pat; + el_free(last_search_match); + last_search_match = strdup(pat); } if (pat != last_search_pat) @@ -656,6 +657,123 @@ get_history_event(const char *cmd, int *cindex, int qchar) return rptr; } +static int +getfrom(const char **cmdp, char **fromp, const char *search, int delim) +{ + size_t size = 16; + size_t len = 0; + const char *cmd = *cmdp; + char *what = el_realloc(*fromp, size * sizeof(*what)); + if (what == NULL){ + el_free(*fromp); + *fromp = NULL; + return 0; + } + for (; *cmd && *cmd != delim; cmd++) { + if (*cmd == '\\' && cmd[1] == delim) + cmd++; + if (len - 1 >= size) { + char *nwhat; + nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat)); + if (nwhat == NULL) { + el_free(what); + el_free(*fromp); + *cmdp = cmd; + *fromp = NULL; + return 0; + } + what = nwhat; + } + what[len++] = *cmd; + } + what[len] = '\0'; + *fromp = what; + *cmdp = cmd; + if (*what == '\0') { + el_free(what); + if (search) { + *fromp = strdup(search); + if (*fromp == NULL) { + return 0; + } + } else { + *fromp = NULL; + return -1; + } + } + if (!*cmd) { + el_free(what); + *fromp = NULL; + return -1; + } + + cmd++; /* shift after delim */ + *cmdp = cmd; + + if (!*cmd) { + el_free(what); + *fromp = NULL; + return -1; + } + return 1; +} + +static int +getto(const char **cmdp, char **top, const char *from, int delim) +{ + size_t size = 16; + size_t len = 0; + size_t from_len = strlen(from); + const char *cmd = *cmdp; + char *with = el_realloc(*top, size * sizeof(*with)); + *top = NULL; + if (with == NULL) + goto out; + + for (; *cmd && *cmd != delim; cmd++) { + if (len + from_len + 1 >= size) { + char *nwith; + size += from_len + 1; + nwith = el_realloc(with, size * sizeof(*nwith)); + if (nwith == NULL) + goto out; + with = nwith; + } + if (*cmd == '&') { + /* safe */ + strcpy(&with[len], from); + len += from_len; + continue; + } + if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&')) + cmd++; + with[len++] = *cmd; + } + if (!*cmd) + goto out; + with[len] = '\0'; + *top = with; + *cmdp = cmd; + return 1; +out: + el_free(with); + el_free(*top); + *top = NULL; + *cmdp = cmd; + return -1; +} + +static void +replace(char **tmp, int c) +{ + char *aptr; + if ((aptr = strrchr(*tmp, c)) == NULL) + return; + aptr = strdup(aptr + 1); // XXX: check + el_free(*tmp); + *tmp = aptr; +} + /* * the real function doing history expansion - takes as argument command * to do and data upon which the command should be executed @@ -670,11 +788,11 @@ static int _history_expand_command(const char *command, size_t offs, size_t cmdlen, char **result) { - char *tmp, *search = NULL, *aptr; + char *tmp, *search = NULL, *aptr, delim; const char *ptr, *cmd; static char *from = NULL, *to = NULL; int start, end, idx, has_mods = 0; - int p_on = 0, g_on = 0; + int p_on = 0, g_on = 0, ev; *result = NULL; aptr = NULL; @@ -706,7 +824,8 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, } else { int qchar; - qchar = (offs > 0 && command[offs - 1] == '"')? '"':0; + qchar = (offs > 0 && command[offs - 1] == '"') + ? '"' : '\0'; ptr = get_history_event(command + offs, &idx, qchar); } has_mods = command[offs + (size_t)idx] == ':'; @@ -729,7 +848,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, /* Now parse any word designators */ if (*cmd == '%') /* last word matched by ?pat? */ - tmp = strdup(last_search_match? last_search_match:""); + tmp = strdup(last_search_match ? last_search_match : ""); else if (strchr("^*$-0123456789", *cmd)) { start = end = -1; if (*cmd == '^') @@ -738,7 +857,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, start = -1, cmd++; else if (*cmd == '*') start = 1, cmd++; - else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { + else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { start = 0; while (*cmd && '0' <= *cmd && *cmd <= '9') start = start * 10 + *cmd++ - '0'; @@ -781,132 +900,58 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, } for (; *cmd; cmd++) { - if (*cmd == ':') + switch (*cmd) { + case ':': continue; - else if (*cmd == 'h') { /* remove trailing path */ + case 'h': /* remove trailing path */ if ((aptr = strrchr(tmp, '/')) != NULL) *aptr = '\0'; - } else if (*cmd == 't') { /* remove leading path */ - if ((aptr = strrchr(tmp, '/')) != NULL) { - aptr = strdup(aptr + 1); - el_free(tmp); - tmp = aptr; - } - } else if (*cmd == 'r') { /* remove trailing suffix */ + continue; + case 't': /* remove leading path */ + replace(&tmp, '/'); + continue; + case 'r': /* remove trailing suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) *aptr = '\0'; - } else if (*cmd == 'e') { /* remove all but suffix */ - if ((aptr = strrchr(tmp, '.')) != NULL) { - aptr = strdup(aptr); - el_free(tmp); - tmp = aptr; - } - } else if (*cmd == 'p') /* print only */ + continue; + case 'e': /* remove all but suffix */ + replace(&tmp, '.'); + continue; + case 'p': /* print only */ p_on = 1; - else if (*cmd == 'g') + continue; + case 'g': g_on = 2; - else if (*cmd == 's' || *cmd == '&') { - char *what, *with, delim; - size_t len, from_len; - size_t size; - - if (*cmd == '&' && (from == NULL || to == NULL)) + continue; + case '&': + if (from == NULL || to == NULL) continue; - else if (*cmd == 's') { - delim = *(++cmd), cmd++; - size = 16; - what = el_realloc(from, size * sizeof(*what)); - if (what == NULL) { - el_free(from); - el_free(tmp); - return 0; - } - len = 0; - for (; *cmd && *cmd != delim; cmd++) { - if (*cmd == '\\' && cmd[1] == delim) - cmd++; - if (len >= size) { - char *nwhat; - nwhat = el_realloc(what, - (size <<= 1) * - sizeof(*nwhat)); - if (nwhat == NULL) { - el_free(what); - el_free(tmp); - return 0; - } - what = nwhat; - } - what[len++] = *cmd; - } - what[len] = '\0'; - from = what; - if (*what == '\0') { - el_free(what); - if (search) { - from = strdup(search); - if (from == NULL) { - el_free(tmp); - return 0; - } - } else { - from = NULL; - el_free(tmp); - return -1; - } - } - cmd++; /* shift after delim */ - if (!*cmd) - continue; - - size = 16; - with = el_realloc(to, size * sizeof(*with)); - if (with == NULL) { - el_free(to); - el_free(tmp); - return -1; - } - len = 0; - from_len = strlen(from); - for (; *cmd && *cmd != delim; cmd++) { - if (len + from_len + 1 >= size) { - char *nwith; - size += from_len + 1; - nwith = el_realloc(with, - size * sizeof(*nwith)); - if (nwith == NULL) { - el_free(with); - el_free(tmp); - return -1; - } - with = nwith; - } - if (*cmd == '&') { - /* safe */ - (void)strcpy(&with[len], from); - len += from_len; - continue; - } - if (*cmd == '\\' - && (*(cmd + 1) == delim - || *(cmd + 1) == '&')) - cmd++; - with[len++] = *cmd; - } - with[len] = '\0'; - to = with; - } - + /*FALLTHROUGH*/ + case 's': + ev = -1; + delim = *++cmd; + if (delim == '\0' || *++cmd == '\0') + goto out; + if ((ev = getfrom(&cmd, &from, search, delim)) != 1) + goto out; + if ((ev = getto(&cmd, &to, from, delim)) != 1) + goto out; aptr = _rl_compat_sub(tmp, from, to, g_on); if (aptr) { el_free(tmp); tmp = aptr; } g_on = 0; + cmd--; + continue; } } *result = tmp; - return p_on? 2:1; + return p_on ? 2 : 1; +out: + el_free(tmp); + return ev; + } @@ -952,8 +997,7 @@ history_expand(char *str, char **output) (size += len + 1) * sizeof(*nresult)); \ if (nresult == NULL) { \ el_free(*output); \ - if (/*CONSTCOND*/fr) \ - el_free(tmp); \ + el_free(fr); \ return 0; \ } \ result = nresult; \ @@ -1003,11 +1047,11 @@ loop: goto loop; } len = i - start; - ADD_STRING(&str[start], len, 0); + ADD_STRING(&str[start], len, NULL); if (str[i] == '\0' || str[i] != history_expansion_char) { len = j - i; - ADD_STRING(&str[i], len, 0); + ADD_STRING(&str[i], len, NULL); if (start == 0) ret = 0; else @@ -1017,7 +1061,7 @@ loop: ret = _history_expand_command (str, i, (j - i), &tmp); if (ret > 0 && tmp) { len = strlen(tmp); - ADD_STRING(tmp, len, 1); + ADD_STRING(tmp, len, tmp); } if (tmp) { el_free(tmp); @@ -1359,7 +1403,7 @@ read_history(const char *filename) return errno; errno = 0; if (history(h, &ev, H_LOAD, filename) == -1) - return errno ? errno : EINVAL; + return errno ? errno : EINVAL; if (history(h, &ev, H_GETSIZE) == 0) history_length = ev.num; if (history_length < 0) @@ -2037,7 +2081,7 @@ static unsigned char rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c) { if (map[c] == NULL) - return CC_ERROR; + return CC_ERROR; _rl_update_pos(); @@ -2070,6 +2114,7 @@ rl_callback_read_char(void) const char *buf = el_gets(e, &count); char *wbuf; + el_set(e, EL_UNBUFFERED, 1); if (buf == NULL || count-- <= 0) return; if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF]) @@ -2085,7 +2130,6 @@ rl_callback_read_char(void) } else wbuf = NULL; (*(void (*)(const char *))rl_linefunc)(wbuf); - el_set(e, EL_UNBUFFERED, 1); } } @@ -2103,9 +2147,8 @@ rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc) void rl_callback_handler_remove(void) { + el_set(e, EL_UNBUFFERED, 0); rl_linefunc = NULL; - el_end(e); - e = NULL; } void @@ -2439,3 +2482,40 @@ rl_echo_signal_char(int sig) return; re_putc(e, c, 0); } + +int +rl_crlf(void) +{ + re_putc(e, '\n', 0); + return 0; +} + +int +rl_ding(void) +{ + re_putc(e, '\a', 0); + return 0; +} + +int +rl_abort(int count, int key) +{ + return count && key ? 0 : 0; +} + +int +rl_set_keymap_name(const char *name, Keymap k) +{ + return name && k ? 0 : 0; +} + +histdata_t +free_history_entry(HIST_ENTRY *he) +{ + return he ? NULL : NULL; +} + +void +_rl_erase_entire_line(void) +{ +} diff --git a/contrib/libedit/readline/readline.h b/contrib/libedit/readline/readline.h index 7e53f417bc25..e9f941aeb249 100644 --- a/contrib/libedit/readline/readline.h +++ b/contrib/libedit/readline/readline.h @@ -1,4 +1,4 @@ -/* $NetBSD: readline.h,v 1.46 2019/06/07 15:19:29 christos Exp $ */ +/* $NetBSD: readline.h,v 1.47 2021/08/21 12:34:59 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -45,6 +45,7 @@ typedef char **rl_completion_func_t(const char *, int, int); typedef char *rl_compentry_func_t(const char *, int); typedef int rl_command_func_t(int, int); typedef int rl_hook_func_t(void); +typedef int rl_icppfunc_t(char **); /* only supports length */ typedef struct { @@ -106,6 +107,7 @@ extern char *rl_line_buffer; extern int rl_point, rl_end; extern int history_base, history_length; extern int max_input_history; +extern const char *rl_basic_quote_characters; extern const char *rl_basic_word_break_characters; extern char *rl_completer_word_break_characters; extern const char *rl_completer_quote_characters; @@ -127,6 +129,7 @@ extern int rl_done; /* * The following is not implemented */ +extern unsigned long rl_readline_state; extern int rl_catch_signals; extern int rl_catch_sigwinch; extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, @@ -142,6 +145,14 @@ extern VFunction *rl_deprep_term_function; extern rl_hook_func_t *rl_event_hook; extern int readline_echoing_p; extern int _rl_print_completions_horizontally; +extern int _rl_complete_mark_directories; +extern rl_icppfunc_t *rl_directory_completion_hook; +extern int rl_completion_suppress_append; +extern int rl_sort_completion_matches; +extern int _rl_completion_prefix_display_length; +extern int _rl_echoing_p; +extern int history_max_entries; +extern char *rl_display_prompt; /* supported functions */ char *readline(const char *); @@ -213,6 +224,8 @@ int rl_set_prompt(const char *); int rl_on_new_line(void); void rl_reset_after_signal(void); void rl_echo_signal_char(int); +int rl_crlf(void); +int rl_ding(void); /* * The following are not implemented @@ -226,6 +239,10 @@ int rl_bind_key_in_map(int, rl_command_func_t *, Keymap); void rl_cleanup_after_signal(void); void rl_free_line_state(void); int rl_set_keyboard_input_timeout(int); +int rl_abort(int, int); +int rl_set_keymap_name(const char *, Keymap); +histdata_t free_history_entry(HIST_ENTRY *); +void _rl_erase_entire_line(void); #ifdef __cplusplus } diff --git a/contrib/libedit/refresh.c b/contrib/libedit/refresh.c index fab29746478c..26a49fe751c6 100644 --- a/contrib/libedit/refresh.c +++ b/contrib/libedit/refresh.c @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.c,v 1.57 2020/03/30 06:54:37 ryo Exp $ */ +/* $NetBSD: refresh.c,v 1.58 2021/09/09 20:24:07 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: refresh.c,v 1.57 2020/03/30 06:54:37 ryo Exp $"); +__RCSID("$NetBSD: refresh.c,v 1.58 2021/09/09 20:24:07 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -105,7 +105,7 @@ re_nextline(EditLine *el) */ if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) { int i, lins = el->el_terminal.t_size.v; - wchar_t *firstline = el->el_vdisplay[0]; + wint_t *firstline = el->el_vdisplay[0]; for(i = 1; i < lins; i++) el->el_vdisplay[i - 1] = el->el_vdisplay[i]; @@ -334,7 +334,8 @@ re_refresh(EditLine *el) ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv)); for (i = 0; i <= el->el_refresh.r_newcv; i++) { /* NOTE THAT re_update_line MAY CHANGE el_display[i] */ - re_update_line(el, el->el_display[i], el->el_vdisplay[i], i); + re_update_line(el, (wchar_t *)el->el_display[i], + (wchar_t *)el->el_vdisplay[i], i); /* * Copy the new line to be the current one, and pad out with @@ -343,7 +344,8 @@ re_refresh(EditLine *el) * end of the screen line, it won't be a NUL or some old * leftover stuff. */ - re__copy_and_pad(el->el_display[i], el->el_vdisplay[i], + re__copy_and_pad((wchar_t *)el->el_display[i], + (wchar_t *)el->el_vdisplay[i], (size_t) el->el_terminal.t_size.h); } ELRE_DEBUG(1, (__F, @@ -355,7 +357,8 @@ re_refresh(EditLine *el) terminal_move_to_line(el, i); terminal_move_to_char(el, 0); /* This wcslen should be safe even with MB_FILL_CHARs */ - terminal_clear_EOL(el, (int) wcslen(el->el_display[i])); + terminal_clear_EOL(el, + (int) wcslen((const wchar_t *)el->el_display[i])); #ifdef DEBUG_REFRESH terminal_overwrite(el, L"C\b", 2); #endif /* DEBUG_REFRESH */ @@ -1091,7 +1094,7 @@ re_refresh_cursor(EditLine *el) static void re_fastputc(EditLine *el, wint_t c) { - wchar_t *lastline; + wint_t *lastline; int w; w = wcwidth(c); @@ -1126,7 +1129,8 @@ re_fastputc(EditLine *el, wint_t c) el->el_cursor.v++; lastline = el->el_display[++el->el_refresh.r_oldcv]; } - re__copy_and_pad(lastline, L"", (size_t)el->el_terminal.t_size.h); + re__copy_and_pad((wchar_t *)lastline, L"", + (size_t)el->el_terminal.t_size.h); if (EL_HAS_AUTO_MARGINS) { if (EL_HAS_MAGIC_MARGINS) { diff --git a/contrib/libedit/terminal.c b/contrib/libedit/terminal.c index b3ab5bfb6244..3bea1fc27a89 100644 --- a/contrib/libedit/terminal.c +++ b/contrib/libedit/terminal.c @@ -1,4 +1,4 @@ -/* $NetBSD: terminal.c,v 1.43 2020/07/10 20:34:24 christos Exp $ */ +/* $NetBSD: terminal.c,v 1.44 2021/09/09 20:24:07 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95"; #else -__RCSID("$NetBSD: terminal.c,v 1.43 2020/07/10 20:34:24 christos Exp $"); +__RCSID("$NetBSD: terminal.c,v 1.44 2021/09/09 20:24:07 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -588,7 +588,8 @@ mc_again: * NOTE THAT terminal_overwrite() WILL CHANGE * el->el_cursor.h!!! */ - terminal_overwrite(el, &el->el_display[ + terminal_overwrite(el, + (wchar_t *)&el->el_display[ el->el_cursor.v][el->el_cursor.h], (size_t)(where - el->el_cursor.h)); diff --git a/contrib/libedit/tty.c b/contrib/libedit/tty.c index bafc906ccc4e..b96c9a53c268 100644 --- a/contrib/libedit/tty.c +++ b/contrib/libedit/tty.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.69 2020/05/31 23:24:23 christos Exp $ */ +/* $NetBSD: tty.c,v 1.70 2021/07/14 07:47:23 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tty.c,v 1.69 2020/05/31 23:24:23 christos Exp $"); +__RCSID("$NetBSD: tty.c,v 1.70 2021/07/14 07:47:23 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -1350,19 +1350,19 @@ tty_get_signal_character(EditLine *el, int sig) return -1; #endif switch (sig) { -#ifdef SIGINT +#if defined(SIGINT) && defined(VINTR) case SIGINT: return el->el_tty.t_c[ED_IO][VINTR]; #endif -#ifdef SIGQUIT +#if defined(SIGQUIT) && defined(VQUIT) case SIGQUIT: return el->el_tty.t_c[ED_IO][VQUIT]; #endif -#ifdef SIGINFO +#if defined(SIGINFO) && defined(VSTATUS) case SIGINFO: return el->el_tty.t_c[ED_IO][VSTATUS]; #endif -#ifdef SIGTSTP +#if defined(SIGTSTP) && defined(VSUSP) case SIGTSTP: return el->el_tty.t_c[ED_IO][VSUSP]; #endif diff --git a/contrib/libedit/tty.h b/contrib/libedit/tty.h index 643091961976..ac817c8ad7b7 100644 --- a/contrib/libedit/tty.h +++ b/contrib/libedit/tty.h @@ -1,4 +1,4 @@ -/* $NetBSD: tty.h,v 1.23 2018/12/02 16:58:13 christos Exp $ */ +/* $NetBSD: tty.h,v 1.24 2021/07/31 20:51:32 andvar Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -432,7 +432,7 @@ #define C_SH(A) ((unsigned int)(1 << (A))) /* - * Terminal dependend data structures + * Terminal dependent data structures */ #define EX_IO 0 /* while we are executing */ #define ED_IO 1 /* while we are editing */ diff --git a/contrib/libedit/vi.c b/contrib/libedit/vi.c index 010616cdf1dc..e7f78494f88b 100644 --- a/contrib/libedit/vi.c +++ b/contrib/libedit/vi.c @@ -1,4 +1,4 @@ -/* $NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $ */ +/* $NetBSD: vi.c,v 1.64 2021/08/28 17:17:47 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $"); +__RCSID("$NetBSD: vi.c,v 1.64 2021/08/28 17:17:47 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -1008,12 +1008,15 @@ vi_histedit(EditLine *el, wint_t c __attribute__((__unused__))) char *cp = NULL; size_t len; wchar_t *line = NULL; + const char *editor; if (el->el_state.doingarg) { if (vi_to_history_line(el, 0) == CC_ERROR) return CC_ERROR; } + if ((editor = getenv("EDITOR")) == NULL) + editor = "vi"; fd = mkstemp(tempfile); if (fd < 0) return CC_ERROR; @@ -1038,7 +1041,7 @@ vi_histedit(EditLine *el, wint_t c __attribute__((__unused__))) goto error; case 0: close(fd); - execlp("vi", "vi", tempfile, (char *)NULL); + execlp(editor, editor, tempfile, (char *)NULL); exit(0); /*NOTREACHED*/ default: