Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libedit/readline.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libedit/readline.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.54 retrieving revision 1.86 diff -u -p -r1.54 -r1.86 --- src/lib/libedit/readline.c 2005/05/27 11:35:07 1.54 +++ src/lib/libedit/readline.c 2009/12/30 22:37:40 1.86 @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.54 2005/05/27 11:35:07 agc Exp $ */ +/* $NetBSD: readline.c,v 1.86 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,13 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -38,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.54 2005/05/27 11:35:07 agc Exp $"); +__RCSID("$NetBSD: readline.c,v 1.86 2009/12/30 22:37:40 christos Exp $"); #endif /* not lint && not SCCSID */ #include @@ -53,20 +46,21 @@ __RCSID("$NetBSD: readline.c,v 1.54 2005 #include #include #include +#include #ifdef HAVE_VIS_H #include #else #include "np/vis.h" #endif -#ifdef HAVE_ALLOCA_H -#include -#endif +#include "readline/readline.h" #include "el.h" #include "fcns.h" /* for EL_NUM_FCNS */ #include "histedit.h" -#include "readline/readline.h" #include "filecomplete.h" +void rl_prep_terminal(int); +void rl_deprep_terminal(void); + /* for rl_complete() */ #define TAB '\r' @@ -76,6 +70,7 @@ __RCSID("$NetBSD: readline.c,v 1.54 2005 /* readline compatibility stuff - look at readline sources/documentation */ /* to see what these variables mean */ const char *rl_library_version = "EditLine wrapper"; +int rl_readline_version = RL_READLINE_VERSION; static char empty[] = { '\0' }; static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', @@ -86,9 +81,12 @@ FILE *rl_outstream = NULL; int rl_point = 0; int rl_end = 0; char *rl_line_buffer = NULL; -VFunction *rl_linefunc = NULL; +VCPFunction *rl_linefunc = NULL; int rl_done = 0; VFunction *rl_event_hook = NULL; +KEYMAP_ENTRY_ARRAY emacs_standard_keymap, + emacs_meta_keymap, + emacs_ctlx_keymap; int history_base = 1; /* probably never subject to change */ int history_length = 0; @@ -108,17 +106,24 @@ Function *rl_completion_entry_function = CPPFunction *rl_attempted_completion_function = NULL; Function *rl_pre_input_hook = NULL; Function *rl_startup1_hook = NULL; -Function *rl_getc_function = NULL; +int (*rl_getc_function)(FILE *) = NULL; char *rl_terminal_name = NULL; int rl_already_prompted = 0; int rl_filename_completion_desired = 0; int rl_ignore_completion_duplicates = 0; int rl_catch_signals = 1; +int readline_echoing_p = 1; +int _rl_print_completions_horizontally = 0; VFunction *rl_redisplay_function = NULL; Function *rl_startup_hook = NULL; VFunction *rl_completion_display_matches_hook = NULL; -VFunction *rl_prep_term_function = NULL; -VFunction *rl_deprep_term_function = 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; + +#ifdef WIDECHAR +static ct_buffer_t conv; +#endif /* * The current prompt string. @@ -152,14 +157,16 @@ int rl_completion_append_character = ' ' /* stuff below is used internally by libedit for readline emulation */ -static History *h = NULL; +static TYPE(History) *h = NULL; static EditLine *e = NULL; static Function *map[256]; +static jmp_buf topbuf; /* internal functions */ static unsigned char _el_rl_complete(EditLine *, int); static unsigned char _el_rl_tstp(EditLine *, int); static char *_get_prompt(EditLine *); +static int _getc_function(EditLine *, char *); static HIST_ENTRY *_move_history(int); static int _history_expand_command(const char *, size_t, size_t, char **); @@ -184,13 +191,13 @@ _get_prompt(EditLine *el __attribute__(( static HIST_ENTRY * _move_history(int op) { - HistEvent ev; + TYPE(HistEvent) ev; static HIST_ENTRY rl_he; - if (history(h, &ev, op) != 0) + if (FUNW(history)(h, &ev, op) != 0) return (HIST_ENTRY *) NULL; - rl_he.line = ev.str; + rl_he.line = ct_encode_string(ev.str, &conv); rl_he.data = NULL; return (&rl_he); @@ -198,16 +205,73 @@ _move_history(int op) /* + * read one key from user defined input function + */ +static int +/*ARGSUSED*/ +_getc_function(EditLine *el, char *c) +{ + int i; + + i = (*rl_getc_function)(NULL); + if (i == -1) + return 0; + *c = i; + return 1; +} + +static const char _dothistory[] = "/.history"; + +static const char * +_default_history_file(void) +{ + struct passwd *p; + static char path[PATH_MAX]; + + if (*path) + return path; + if ((p = getpwuid(getuid())) == NULL) + return NULL; + strlcpy(path, p->pw_dir, PATH_MAX); + strlcat(path, _dothistory, PATH_MAX); + return path; +} + +/* * READLINE compatibility stuff */ /* + * Set the prompt + */ +int +rl_set_prompt(const char *prompt) +{ + char *p; + + if (!prompt) + prompt = ""; + if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) + return 0; + if (rl_prompt) + free(rl_prompt); + rl_prompt = strdup(prompt); + if (rl_prompt == NULL) + return -1; + + while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) + *p = RL_PROMPT_START_IGNORE; + + return 0; +} + +/* * initialize rl compat stuff */ int rl_initialize(void) { - HistEvent ev; + TYPE(HistEvent) ev; const LineInfo *li; int editmode = 1; struct termios t; @@ -237,19 +301,22 @@ rl_initialize(void) if (!e || !h) return (-1); - history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ + FUNW(history)(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ history_length = 0; max_input_history = INT_MAX; el_set(e, EL_HIST, history, h); + /* setup getc function if valid */ + if (rl_getc_function) + el_set(e, EL_GETCFN, _getc_function); + /* for proper prompt printing in readline() */ - rl_prompt = strdup(""); - if (rl_prompt == NULL) { + if (rl_set_prompt("") == -1) { history_end(h); el_end(e); return -1; } - el_set(e, EL_PROMPT, _get_prompt); + el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE); el_set(e, EL_SIGNAL, rl_catch_signals); /* set default mode to "emacs"-style and read setting afterwards */ @@ -301,9 +368,10 @@ rl_initialize(void) * trailing newline (if there is any) */ char * -readline(const char *prompt) +readline(const char *p) { - HistEvent ev; + TYPE(HistEvent) ev; + const char * volatile prompt = p; int count; const char *ret; char *buf; @@ -314,15 +382,11 @@ readline(const char *prompt) rl_done = 0; + (void)setjmp(topbuf); + /* update prompt accordingly to what has been passed */ - if (!prompt) - prompt = ""; - if (strcmp(rl_prompt, prompt) != 0) { - free(rl_prompt); - rl_prompt = strdup(prompt); - if (rl_prompt == NULL) - return NULL; - } + if (rl_set_prompt(prompt) == -1) + return NULL; if (rl_pre_input_hook) (*rl_pre_input_hook)(NULL, 0); @@ -354,7 +418,7 @@ readline(const char *prompt) } else buf = NULL; - history(h, &ev, H_GETSIZE); + FUNW(history)(h, &ev, H_GETSIZE); history_length = ev.num; return buf; @@ -420,7 +484,7 @@ _rl_compat_sub(const char *str, const ch } else *r++ = *s++; } - *r = 0; + *r = '\0'; return(result); } @@ -434,18 +498,18 @@ get_history_event(const char *cmd, int * size_t len; char *pat; const char *rptr; - HistEvent ev; + TYPE(HistEvent) ev; idx = *cindex; if (cmd[idx++] != history_expansion_char) return(NULL); /* find out which event to take */ - if (cmd[idx] == history_expansion_char || cmd[idx] == 0) { - if (history(h, &ev, H_FIRST) != 0) + if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { + if (FUNW(history)(h, &ev, H_FIRST) != 0) return(NULL); *cindex = cmd[idx]? (idx + 1):idx; - return(ev.str); + return ct_encode_string(ev.str, &conv); } sign = 0; if (cmd[idx] == '-') { @@ -500,7 +564,7 @@ get_history_event(const char *cmd, int * pat[len] = '\0'; } - if (history(h, &ev, H_CURR) != 0) { + if (FUNW(history)(h, &ev, H_CURR) != 0) { if (pat != last_search_pat) free(pat); return (NULL); @@ -519,7 +583,7 @@ get_history_event(const char *cmd, int * if (ret == -1) { /* restore to end of list on failed search */ - history(h, &ev, H_FIRST); + FUNW(history)(h, &ev, H_FIRST); (void)fprintf(rl_outstream, "%s: Event not found\n", pat); if (pat != last_search_pat) free(pat); @@ -535,13 +599,13 @@ get_history_event(const char *cmd, int * if (pat != last_search_pat) free(pat); - if (history(h, &ev, H_CURR) != 0) + if (FUNW(history)(h, &ev, H_CURR) != 0) return(NULL); *cindex = idx; - rptr = ev.str; + rptr = ct_encode_string(ev.str, &conv); /* roll back to original position */ - (void)history(h, &ev, H_SET, num); + (void)FUNW(history)(h, &ev, H_SET, num); return rptr; } @@ -606,9 +670,11 @@ _history_expand_command(const char *comm return(-1); if (!has_mods) { - *result = strdup(aptr? aptr : ptr); + *result = strdup(aptr ? aptr : ptr); if (aptr) free(aptr); + if (*result == NULL) + return -1; return(1); } @@ -663,7 +729,7 @@ _history_expand_command(const char *comm if (aptr) free(aptr); - if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) { + if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { *result = tmp; return(1); } @@ -673,7 +739,7 @@ _history_expand_command(const char *comm continue; else if (*cmd == 'h') { /* remove trailing path */ if ((aptr = strrchr(tmp, '/')) != NULL) - *aptr = 0; + *aptr = '\0'; } else if (*cmd == 't') { /* remove leading path */ if ((aptr = strrchr(tmp, '/')) != NULL) { aptr = strdup(aptr + 1); @@ -682,7 +748,7 @@ _history_expand_command(const char *comm } } else if (*cmd == 'r') { /* remove trailing suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) - *aptr = 0; + *aptr = '\0'; } else if (*cmd == 'e') { /* remove all but suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) { aptr = strdup(aptr); @@ -706,6 +772,7 @@ _history_expand_command(const char *comm what = realloc(from, size); if (what == NULL) { free(from); + free(tmp); return 0; } len = 0; @@ -718,6 +785,7 @@ _history_expand_command(const char *comm (size <<= 1)); if (nwhat == NULL) { free(what); + free(tmp); return 0; } what = nwhat; @@ -730,10 +798,13 @@ _history_expand_command(const char *comm free(what); if (search) { from = strdup(search); - if (from == NULL) + if (from == NULL) { + free(tmp); return 0; + } } else { from = NULL; + free(tmp); return (-1); } } @@ -745,6 +816,7 @@ _history_expand_command(const char *comm with = realloc(to, size); if (with == NULL) { free(to); + free(tmp); return -1; } len = 0; @@ -756,6 +828,7 @@ _history_expand_command(const char *comm nwith = realloc(with, size); if (nwith == NULL) { free(with); + free(tmp); return -1; } with = nwith; @@ -824,12 +897,14 @@ history_expand(char *str, char **output) return 0; } -#define ADD_STRING(what, len) \ +#define ADD_STRING(what, len, fr) \ { \ if (idx + len + 1 > size) { \ char *nresult = realloc(result, (size += len + 1));\ if (nresult == NULL) { \ free(*output); \ + if (/*CONSTCOND*/fr) \ + free(tmp); \ return 0; \ } \ result = nresult; \ @@ -841,6 +916,7 @@ history_expand(char *str, char **output) result = NULL; size = idx = 0; + tmp = NULL; for (i = 0; str[i];) { int qchar, loop_again; size_t len, start, j; @@ -878,13 +954,11 @@ loop: goto loop; } len = i - start; - tmp = &str[start]; - ADD_STRING(tmp, len); + ADD_STRING(&str[start], len, 0); if (str[i] == '\0' || str[i] != history_expansion_char) { len = j - i; - tmp = &str[i]; - ADD_STRING(tmp, len); + ADD_STRING(&str[i], len, 0); if (start == 0) ret = 0; else @@ -894,8 +968,11 @@ loop: ret = _history_expand_command (str, i, (j - i), &tmp); if (ret > 0 && tmp) { len = strlen(tmp); - ADD_STRING(tmp, len); + ADD_STRING(tmp, len, 1); + } + if (tmp) { free(tmp); + tmp = NULL; } i = j; } @@ -924,52 +1001,52 @@ char * history_arg_extract(int start, int end, const char *str) { size_t i, len, max; - char **arr, *result; + char **arr, *result = NULL; arr = history_tokenize(str); if (!arr) - return(NULL); - if (arr && *arr == NULL) { - free(arr); - return(NULL); - } + return NULL; + if (arr && *arr == NULL) + goto out; for (max = 0; arr[max]; max++) continue; max--; if (start == '$') - start = max; + start = (int)max; if (end == '$') - end = max; + end = (int)max; if (end < 0) - end = max + end + 1; + end = (int)max + end + 1; if (start < 0) start = end; - if (start < 0 || end < 0 || start > max || end > max || start > end) - return(NULL); + if (start < 0 || end < 0 || (size_t)start > max || + (size_t)end > max || start > end) + goto out; - for (i = start, len = 0; i <= end; i++) + for (i = start, len = 0; i <= (size_t)end; i++) len += strlen(arr[i]) + 1; len++; result = malloc(len); if (result == NULL) - return NULL; + goto out; - for (i = start, len = 0; i <= end; i++) { + for (i = start, len = 0; i <= (size_t)end; i++) { (void)strcpy(result + len, arr[i]); len += strlen(arr[i]); - if (i < end) + if (i < (size_t)end) result[len++] = ' '; } - result[len] = 0; + result[len] = '\0'; +out: for (i = 0; arr[i]; i++) free(arr[i]); free(arr); - return(result); + return result; } /* @@ -1038,12 +1115,12 @@ history_tokenize(const char *str) void stifle_history(int max) { - HistEvent ev; + TYPE(HistEvent) ev; if (h == NULL || e == NULL) rl_initialize(); - if (history(h, &ev, H_SETSIZE, max) == 0) + if (FUNW(history)(h, &ev, H_SETSIZE, max) == 0) max_input_history = max; } @@ -1054,10 +1131,10 @@ stifle_history(int max) int unstifle_history(void) { - HistEvent ev; + TYPE(HistEvent) ev; int omax; - history(h, &ev, H_SETSIZE, INT_MAX); + FUNW(history)(h, &ev, H_SETSIZE, INT_MAX); omax = max_input_history; max_input_history = INT_MAX; return (omax); /* some value _must_ be returned */ @@ -1072,6 +1149,142 @@ history_is_stifled(void) return (max_input_history != INT_MAX); } +static const char _history_tmp_template[] = "/tmp/.historyXXXXXX"; + +int +history_truncate_file (const char *filename, int nlines) +{ + int ret = 0; + FILE *fp, *tp; + char template[sizeof(_history_tmp_template)]; + char buf[4096]; + int fd; + char *cp; + off_t off; + int count = 0; + ssize_t left = 0; + + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + if ((fp = fopen(filename, "r+")) == NULL) + return errno; + strcpy(template, _history_tmp_template); + if ((fd = mkstemp(template)) == -1) { + ret = errno; + goto out1; + } + + if ((tp = fdopen(fd, "r+")) == NULL) { + close(fd); + ret = errno; + goto out2; + } + + for(;;) { + if (fread(buf, sizeof(buf), 1, fp) != 1) { + if (ferror(fp)) { + ret = errno; + break; + } + if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) == + (off_t)-1) { + ret = errno; + break; + } + left = fread(buf, 1, sizeof(buf), fp); + if (ferror(fp)) { + ret = errno; + break; + } + if (left == 0) { + count--; + left = sizeof(buf); + } else if (fwrite(buf, (size_t)left, 1, tp) != 1) { + ret = errno; + break; + } + fflush(tp); + break; + } + if (fwrite(buf, sizeof(buf), 1, tp) != 1) { + ret = errno; + break; + } + count++; + } + if (ret) + goto out3; + cp = buf + left - 1; + if(*cp != '\n') + cp++; + for(;;) { + while (--cp >= buf) { + if (*cp == '\n') { + if (--nlines == 0) { + if (++cp >= buf + sizeof(buf)) { + count++; + cp = buf; + } + break; + } + } + } + if (nlines <= 0 || count == 0) + break; + count--; + if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) { + ret = errno; + break; + } + if (fread(buf, sizeof(buf), 1, tp) != 1) { + if (ferror(tp)) { + ret = errno; + break; + } + ret = EAGAIN; + break; + } + cp = buf + sizeof(buf); + } + + if (ret || nlines > 0) + goto out3; + + if (fseeko(fp, 0, SEEK_SET) == (off_t)-1) { + ret = errno; + goto out3; + } + + if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) == + (off_t)-1) { + ret = errno; + goto out3; + } + + for(;;) { + if ((left = fread(buf, 1, sizeof(buf), tp)) == 0) { + if (ferror(fp)) + ret = errno; + break; + } + if (fwrite(buf, (size_t)left, 1, fp) != 1) { + ret = errno; + break; + } + } + fflush(fp); + if((off = ftello(fp)) > 0) + (void)ftruncate(fileno(fp), off); +out3: + fclose(tp); +out2: + unlink(template); +out1: + fclose(fp); + + return ret; +} + /* * read history from a file given @@ -1079,11 +1292,13 @@ history_is_stifled(void) int read_history(const char *filename) { - HistEvent ev; + TYPE(HistEvent) ev; if (h == NULL || e == NULL) rl_initialize(); - return (history(h, &ev, H_LOAD, filename)); + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + return (FUNW(history)(h, &ev, H_LOAD, filename) == -1 ? (errno ? errno : EINVAL) : 0); } @@ -1093,11 +1308,13 @@ read_history(const char *filename) int write_history(const char *filename) { - HistEvent ev; + TYPE(HistEvent) ev; if (h == NULL || e == NULL) rl_initialize(); - return (history(h, &ev, H_SAVE, filename)); + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + return (FUNW(history)(h, &ev, H_SAVE, filename) == -1 ? (errno ? errno : EINVAL) : 0); } @@ -1110,30 +1327,29 @@ HIST_ENTRY * history_get(int num) { static HIST_ENTRY she; - HistEvent ev; + TYPE(HistEvent) ev; int curr_num; if (h == NULL || e == NULL) rl_initialize(); /* save current position */ - if (history(h, &ev, H_CURR) != 0) + if (FUNW(history)(h, &ev, H_CURR) != 0) return (NULL); curr_num = ev.num; - /* start from most recent */ - if (history(h, &ev, H_FIRST) != 0) + /* start from the oldest */ + if (FUNW(history)(h, &ev, H_LAST) != 0) return (NULL); /* error */ - /* look backwards for event matching specified offset */ - if (history(h, &ev, H_NEXT_EVENT, num)) + /* look forwards for event matching specified offset */ + if (FUNW(history)(h, &ev, H_NEXT_EVDATA, num, &she.data)) return (NULL); - she.line = ev.str; - she.data = NULL; + she.line = ct_encode_string(ev.str, &conv); /* restore pointer to where it was */ - (void)history(h, &ev, H_SET, curr_num); + (void)FUNW(history)(h, &ev, H_SET, curr_num); return (&she); } @@ -1145,13 +1361,13 @@ history_get(int num) int add_history(const char *line) { - HistEvent ev; + TYPE(HistEvent) ev; if (h == NULL || e == NULL) rl_initialize(); - (void)history(h, &ev, H_ENTER, line); - if (history(h, &ev, H_GETSIZE) == 0) + (void)FUNW(history)(h, &ev, H_ENTER, line); + if (FUNW(history)(h, &ev, H_GETSIZE) == 0) history_length = ev.num; return (!(history_length > 0)); /* return 0 if all is okay */ @@ -1159,14 +1375,89 @@ add_history(const char *line) /* + * remove the specified entry from the history list and return it. + */ +HIST_ENTRY * +remove_history(int num) +{ + HIST_ENTRY *he; + TYPE(HistEvent) ev; + + if (h == NULL || e == NULL) + rl_initialize(); + + if ((he = malloc(sizeof(*he))) == NULL) + return NULL; + + if (FUNW(history)(h, &ev, H_DELDATA, num, &he->data) != 0) { + free(he); + return NULL; + } + + he->line = ct_encode_string(ev.str, &conv); + if (FUNW(history)(h, &ev, H_GETSIZE) == 0) + history_length = ev.num; + + return he; +} + + +/* + * replace the line and data of the num-th entry + */ +HIST_ENTRY * +replace_history_entry(int num, const char *line, histdata_t data) +{ + HIST_ENTRY *he; + TYPE(HistEvent) ev; + int curr_num; + + if (h == NULL || e == NULL) + rl_initialize(); + + /* save current position */ + if (FUNW(history)(h, &ev, H_CURR) != 0) + return NULL; + curr_num = ev.num; + + /* start from the oldest */ + if (FUNW(history)(h, &ev, H_LAST) != 0) + return NULL; /* error */ + + if ((he = malloc(sizeof(*he))) == NULL) + return NULL; + + /* look forwards for event matching specified offset */ + if (FUNW(history)(h, &ev, H_NEXT_EVDATA, num, &he->data)) + goto out; + + he->line = strdup(ct_encode_string(ev.str, &e->el_scratch)); + if (he->line == NULL) + goto out; + + if (FUNW(history)(h, &ev, H_REPLACE, line, data)) + goto out; + + /* restore pointer to where it was */ + if (FUNW(history)(h, &ev, H_SET, curr_num)) + goto out; + + return he; +out: + free(he); + return NULL; +} + +/* * clear the history list - delete all entries */ void clear_history(void) { - HistEvent ev; + TYPE(HistEvent) ev; - history(h, &ev, H_CLEAR); + FUNW(history)(h, &ev, H_CLEAR); + history_length = 0; } @@ -1176,16 +1467,16 @@ clear_history(void) int where_history(void) { - HistEvent ev; + TYPE(HistEvent) ev; int curr_num, off; - if (history(h, &ev, H_CURR) != 0) + if (FUNW(history)(h, &ev, H_CURR) != 0) return (0); curr_num = ev.num; - history(h, &ev, H_FIRST); + FUNW(history)(h, &ev, H_FIRST); off = 1; - while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) + while (ev.num != curr_num && FUNW(history)(h, &ev, H_NEXT) == 0) off++; return (off); @@ -1209,23 +1500,24 @@ current_history(void) int history_total_bytes(void) { - HistEvent ev; - int curr_num, size; + TYPE(HistEvent) ev; + int curr_num; + size_t size; - if (history(h, &ev, H_CURR) != 0) + if (FUNW(history)(h, &ev, H_CURR) != 0) return (-1); curr_num = ev.num; - history(h, &ev, H_FIRST); + FUNW(history)(h, &ev, H_FIRST); size = 0; do - size += strlen(ev.str); - while (history(h, &ev, H_NEXT) == 0); + size += Strlen(ev.str) * sizeof(*ev.str); + while (FUNW(history)(h, &ev, H_NEXT) == 0); /* get to the same position as before */ - history(h, &ev, H_PREV_EVENT, curr_num); + FUNW(history)(h, &ev, H_PREV_EVENT, curr_num); - return (size); + return (int)(size); } @@ -1235,17 +1527,21 @@ history_total_bytes(void) int history_set_pos(int pos) { - HistEvent ev; + TYPE(HistEvent) ev; int curr_num; - if (pos > history_length || pos < 0) + if (pos >= history_length || pos < 0) return (-1); - history(h, &ev, H_CURR); + FUNW(history)(h, &ev, H_CURR); curr_num = ev.num; - if (history(h, &ev, H_SET, pos)) { - history(h, &ev, H_SET, curr_num); + /* + * use H_DELDATA to set to nth history (without delete) by passing + * (void **)-1 + */ + if (FUNW(history)(h, &ev, H_DELDATA, pos, (void **)-1)) { + FUNW(history)(h, &ev, H_SET, curr_num); return(-1); } return (0); @@ -1280,21 +1576,23 @@ next_history(void) int history_search(const char *str, int direction) { - HistEvent ev; - const char *strp; + TYPE(HistEvent) ev; + const Char *strp; + const Char *wstr; int curr_num; - if (history(h, &ev, H_CURR) != 0) + if (FUNW(history)(h, &ev, H_CURR) != 0) return (-1); curr_num = ev.num; + wstr = ct_decode_string(str, &conv); for (;;) { - if ((strp = strstr(ev.str, str)) != NULL) + if ((strp = Strstr(ev.str, wstr)) != NULL) return (int) (strp - ev.str); - if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0) + if (FUNW(history)(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0) break; } - history(h, &ev, H_SET, curr_num); + FUNW(history)(h, &ev, H_SET, curr_num); return (-1); } @@ -1305,9 +1603,9 @@ history_search(const char *str, int dire int history_search_prefix(const char *str, int direction) { - HistEvent ev; + TYPE(HistEvent) ev; - return (history(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str)); + return (FUNW(history)(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str)); } @@ -1320,29 +1618,30 @@ int history_search_pos(const char *str, int direction __attribute__((__unused__)), int pos) { - HistEvent ev; + TYPE(HistEvent) ev; int curr_num, off; + const Char *wstr; off = (pos > 0) ? pos : -pos; pos = (pos > 0) ? 1 : -1; - if (history(h, &ev, H_CURR) != 0) + if (FUNW(history)(h, &ev, H_CURR) != 0) return (-1); curr_num = ev.num; - if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) + if (history_set_pos(off) != 0 || FUNW(history)(h, &ev, H_CURR) != 0) return (-1); - + wstr = ct_decode_string(str, &conv); for (;;) { - if (strstr(ev.str, str)) + if (Strstr(ev.str, wstr)) return (off); - if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) + if (FUNW(history)(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) break; } /* set "current" pointer back to previous state */ - history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); + FUNW(history)(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); return (-1); } @@ -1351,6 +1650,18 @@ history_search_pos(const char *str, /********************************/ /* completion functions */ +char * +tilde_expand(char *name) +{ + return fn_tilde_expand(name); +} + +char * +filename_completion_function(const char *name, int state) +{ + return fn_filename_completion_function(name, state); +} + /* * a completion generator for usernames; returns _first_ username * which starts with supplied text @@ -1379,9 +1690,9 @@ username_completion_function(const char if (pwd == NULL) { endpwent(); - return (NULL); + return NULL; } - return (strdup(pwd->pw_name)); + return strdup(pwd->pw_name); } @@ -1405,7 +1716,18 @@ void rl_display_match_list(char **matches, int len, int max) { - fn_display_match_list(e, matches, len, max); + fn_display_match_list(e, matches, (size_t)len, (size_t)max); +} + +static const char * +/*ARGSUSED*/ +_rl_completion_append_character_function(const char *dummy + __attribute__((__unused__))) +{ + static char buf[2]; + buf[0] = rl_completion_append_character; + buf[1] = '\0'; + return buf; } @@ -1416,6 +1738,10 @@ rl_display_match_list(char **matches, in int rl_complete(int ignore __attribute__((__unused__)), int invoking_key) { +#ifdef WIDECHAR + static ct_buffer_t wbreak_conv, sprefix_conv; +#endif + if (h == NULL || e == NULL) rl_initialize(); @@ -1431,8 +1757,10 @@ rl_complete(int ignore __attribute__((__ return fn_complete(e, (CPFunction *)rl_completion_entry_function, rl_attempted_completion_function, - rl_basic_word_break_characters, rl_special_prefixes, - rl_completion_append_character, rl_completion_query_items, + ct_decode_string(rl_basic_word_break_characters, &wbreak_conv), + ct_decode_string(rl_special_prefixes, &sprefix_conv), + _rl_completion_append_character_function, + (size_t)rl_completion_query_items, &rl_completion_type, &rl_attempted_completion_over, &rl_point, &rl_end); } @@ -1453,7 +1781,7 @@ _el_rl_complete(EditLine *el __attribute * bind key c to readline-type function func */ int -rl_bind_key(int c, int func(int, int)) +rl_bind_key(int c, rl_command_func_t *func) { int retval = -1; @@ -1520,6 +1848,20 @@ rl_insert(int count, int c) return (0); } +int +rl_insert_text(const char *text) +{ + if (!text || *text == 0) + return (0); + + if (h == NULL || e == NULL) + rl_initialize(); + + if (el_insertstr(e, text) < 0) + return (0); + return (int)strlen(text); +} + /*ARGSUSED*/ int rl_newline(int count, int c) @@ -1552,7 +1894,7 @@ int rl_add_defun(const char *name, Function *fun, int c) { char dest[8]; - if (c >= sizeof(map) / sizeof(map[0]) || c < 0) + if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0) return -1; map[(unsigned char)c] = fun; el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); @@ -1570,7 +1912,7 @@ rl_callback_read_char() if (buf == NULL || count-- <= 0) return; - if (count == 0 && buf[0] == CTRL('d')) + if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF]) done = 1; if (buf[count] == '\n' || buf[count] == '\r') done = 2; @@ -1583,19 +1925,17 @@ rl_callback_read_char() } else wbuf = NULL; (*(void (*)(const char *))rl_linefunc)(wbuf); - el_set(e, EL_UNBUFFERED, 1); + //el_set(e, EL_UNBUFFERED, 1); } } void -rl_callback_handler_install (const char *prompt, VCPFunction *linefunc) +rl_callback_handler_install(const char *prompt, VCPFunction *linefunc) { if (e == NULL) { rl_initialize(); } - if (rl_prompt) - free(rl_prompt); - rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL; + (void)rl_set_prompt(prompt); rl_linefunc = linefunc; el_set(e, EL_UNBUFFERED, 1); } @@ -1604,13 +1944,14 @@ void rl_callback_handler_remove(void) { el_set(e, EL_UNBUFFERED, 0); + rl_linefunc = NULL; } void rl_redisplay(void) { char a[2]; - a[0] = CTRL('r'); + a[0] = e->el_tty.t_c[TS_IO][C_REPRINT]; a[1] = '\0'; el_push(e, a); } @@ -1634,7 +1975,7 @@ rl_prep_terminal(int meta_flag) } void -rl_deprep_terminal() +rl_deprep_terminal(void) { el_set(e, EL_PREP_TERM, 0); } @@ -1682,9 +2023,10 @@ rl_stuff_char(int c) static int _rl_event_read_char(EditLine *el, char *cp) { - int n, num_read = 0; + int n; + ssize_t num_read = 0; - *cp = 0; + *cp = '\0'; while (rl_event_hook) { (*rl_event_hook)(); @@ -1718,7 +2060,7 @@ _rl_event_read_char(EditLine *el, char * } if (!rl_event_hook) el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); - return(num_read); + return (int)num_read; } static void @@ -1726,6 +2068,162 @@ _rl_update_pos(void) { const LineInfo *li = el_line(e); - rl_point = li->cursor - li->buffer; - rl_end = li->lastchar - li->buffer; + rl_point = (int)(li->cursor - li->buffer); + rl_end = (int)(li->lastchar - li->buffer); +} + +void +rl_get_screen_size(int *rows, int *cols) +{ + if (rows) + el_get(e, EL_GETTC, "li", rows); + if (cols) + el_get(e, EL_GETTC, "co", cols); +} + +void +rl_set_screen_size(int rows, int cols) +{ + char buf[64]; + (void)snprintf(buf, sizeof(buf), "%d", rows); + el_set(e, EL_SETTC, "li", buf); + (void)snprintf(buf, sizeof(buf), "%d", cols); + el_set(e, EL_SETTC, "co", buf); +} + +char ** +rl_completion_matches(const char *str, rl_compentry_func_t *fun) +{ + size_t len, max, i, j, min; + char **list, *match, *a, *b; + + len = 1; + max = 10; + if ((list = malloc(max * sizeof(*list))) == NULL) + return NULL; + + while ((match = (*fun)(str, (int)(len - 1))) != NULL) { + list[len++] = match; + if (len == max) { + char **nl; + max += 10; + if ((nl = realloc(list, max * sizeof(*nl))) == NULL) + goto out; + list = nl; + } + } + if (len == 1) + goto out; + list[len] = NULL; + if (len == 2) { + if ((list[0] = strdup(list[1])) == NULL) + goto out; + return list; + } + qsort(&list[1], len - 1, sizeof(*list), + (int (*)(const void *, const void *)) strcmp); + min = SIZE_T_MAX; + for (i = 1, a = list[i]; i < len - 1; i++, a = b) { + b = list[i + 1]; + for (j = 0; a[j] && a[j] == b[j]; j++) + continue; + if (min > j) + min = j; + } + if (min == 0 && *str) { + if ((list[0] = strdup(str)) == NULL) + goto out; + } else { + if ((list[0] = malloc(min + 1)) == NULL) + goto out; + (void)memcpy(list[0], list[1], min); + list[0][min] = '\0'; + } + return list; + +out: + free(list); + return NULL; +} + +char * +rl_filename_completion_function (const char *text, int state) +{ + return fn_filename_completion_function(text, state); +} + +void +rl_forced_update_display(void) +{ + el_set(e, EL_REFRESH); +} + +int +_rl_abort_internal(void) +{ + el_beep(e); + longjmp(topbuf, 1); + /*NOTREACHED*/ +} + +int +_rl_qsort_string_compare(char **s1, char **s2) +{ + return strcoll(*s1, *s2); +} + +HISTORY_STATE * +history_get_history_state(void) +{ + HISTORY_STATE *hs; + + if ((hs = malloc(sizeof(HISTORY_STATE))) == NULL) + return (NULL); + hs->length = history_length; + return (hs); +} + +int +/*ARGSUSED*/ +rl_kill_text(int from, int to) +{ + return 0; +} + +Keymap +rl_make_bare_keymap(void) +{ + return NULL; +} + +Keymap +rl_get_keymap(void) +{ + return NULL; +} + +void +/*ARGSUSED*/ +rl_set_keymap(Keymap k) +{ +} + +int +/*ARGSUSED*/ +rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k) +{ + return 0; +} + +int +/*ARGSUSED*/ +rl_bind_key_in_map(int key, rl_command_func_t *fun, Keymap k) +{ + return 0; +} + +/* unsupported, but needed by python */ +void +rl_cleanup_after_signal(void) +{ }