version 1.77, 2009/01/18 12:17:24 |
version 1.146.2.1, 2018/06/25 07:25:35 |
Line 36 __RCSID("$NetBSD$"); |
|
Line 36 __RCSID("$NetBSD$"); |
|
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <stdio.h> |
|
#include <dirent.h> |
|
#include <string.h> |
|
#include <pwd.h> |
|
#include <ctype.h> |
#include <ctype.h> |
#include <stdlib.h> |
#include <dirent.h> |
#include <unistd.h> |
|
#include <limits.h> |
|
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
|
#include <limits.h> |
|
#include <pwd.h> |
#include <setjmp.h> |
#include <setjmp.h> |
#ifdef HAVE_VIS_H |
#include <stdint.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <unistd.h> |
#include <vis.h> |
#include <vis.h> |
#else |
|
#include "np/vis.h" |
|
#endif |
|
#ifdef HAVE_ALLOCA_H |
|
#include <alloca.h> |
|
#endif |
|
#include "el.h" |
|
#include "fcns.h" /* for EL_NUM_FCNS */ |
|
#include "histedit.h" |
|
#include "readline/readline.h" |
#include "readline/readline.h" |
|
#include "el.h" |
|
#include "fcns.h" |
#include "filecomplete.h" |
#include "filecomplete.h" |
|
|
void rl_prep_terminal(int); |
void rl_prep_terminal(int); |
Line 73 void rl_deprep_terminal(void); |
|
Line 67 void rl_deprep_terminal(void); |
|
/* readline compatibility stuff - look at readline sources/documentation */ |
/* readline compatibility stuff - look at readline sources/documentation */ |
/* to see what these variables mean */ |
/* to see what these variables mean */ |
const char *rl_library_version = "EditLine wrapper"; |
const char *rl_library_version = "EditLine wrapper"; |
|
int rl_readline_version = RL_READLINE_VERSION; |
static char empty[] = { '\0' }; |
static char empty[] = { '\0' }; |
static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; |
static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; |
static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', |
static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', |
Line 83 FILE *rl_outstream = NULL; |
|
Line 78 FILE *rl_outstream = NULL; |
|
int rl_point = 0; |
int rl_point = 0; |
int rl_end = 0; |
int rl_end = 0; |
char *rl_line_buffer = NULL; |
char *rl_line_buffer = NULL; |
VCPFunction *rl_linefunc = NULL; |
rl_vcpfunc_t *rl_linefunc = NULL; |
int rl_done = 0; |
int rl_done = 0; |
VFunction *rl_event_hook = NULL; |
rl_hook_func_t *rl_event_hook = NULL; |
KEYMAP_ENTRY_ARRAY emacs_standard_keymap, |
KEYMAP_ENTRY_ARRAY emacs_standard_keymap, |
emacs_meta_keymap, |
emacs_meta_keymap, |
emacs_ctlx_keymap; |
emacs_ctlx_keymap; |
|
/* |
|
* The following is not implemented; we always catch signals in the |
|
* libedit fashion: set handlers on entry to el_gets() and clear them |
|
* on the way out. This simplistic approach works for most cases; if |
|
* it does not work for your application, please let us know. |
|
*/ |
|
int rl_catch_signals = 1; |
|
int rl_catch_sigwinch = 1; |
|
|
int history_base = 1; /* probably never subject to change */ |
int history_base = 1; /* probably never subject to change */ |
int history_length = 0; |
int history_length = 0; |
|
int history_offset = 0; |
int max_input_history = 0; |
int max_input_history = 0; |
char history_expansion_char = '!'; |
char history_expansion_char = '!'; |
char history_subst_char = '^'; |
char history_subst_char = '^'; |
Line 104 int rl_attempted_completion_over = 0; |
|
Line 108 int rl_attempted_completion_over = 0; |
|
char *rl_basic_word_break_characters = break_chars; |
char *rl_basic_word_break_characters = break_chars; |
char *rl_completer_word_break_characters = NULL; |
char *rl_completer_word_break_characters = NULL; |
char *rl_completer_quote_characters = NULL; |
char *rl_completer_quote_characters = NULL; |
Function *rl_completion_entry_function = NULL; |
rl_compentry_func_t *rl_completion_entry_function = NULL; |
CPPFunction *rl_attempted_completion_function = NULL; |
char *(*rl_completion_word_break_hook)(void) = NULL; |
|
rl_completion_func_t *rl_attempted_completion_function = NULL; |
Function *rl_pre_input_hook = NULL; |
Function *rl_pre_input_hook = NULL; |
Function *rl_startup1_hook = NULL; |
Function *rl_startup1_hook = NULL; |
int (*rl_getc_function)(FILE *) = NULL; |
int (*rl_getc_function)(FILE *) = NULL; |
Line 113 char *rl_terminal_name = NULL; |
|
Line 118 char *rl_terminal_name = NULL; |
|
int rl_already_prompted = 0; |
int rl_already_prompted = 0; |
int rl_filename_completion_desired = 0; |
int rl_filename_completion_desired = 0; |
int rl_ignore_completion_duplicates = 0; |
int rl_ignore_completion_duplicates = 0; |
int rl_catch_signals = 1; |
|
int readline_echoing_p = 1; |
int readline_echoing_p = 1; |
int _rl_print_completions_horizontally = 0; |
int _rl_print_completions_horizontally = 0; |
VFunction *rl_redisplay_function = NULL; |
VFunction *rl_redisplay_function = NULL; |
Function *rl_startup_hook = NULL; |
Function *rl_startup_hook = NULL; |
|
int rl_did_startup_hook = 0; |
VFunction *rl_completion_display_matches_hook = NULL; |
VFunction *rl_completion_display_matches_hook = NULL; |
VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; |
VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; |
VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; |
VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; |
|
KEYMAP_ENTRY_ARRAY emacs_meta_keymap; |
|
|
/* |
/* |
* The current prompt string. |
* The current prompt string. |
Line 156 int rl_completion_append_character = ' ' |
|
Line 162 int rl_completion_append_character = ' ' |
|
|
|
static History *h = NULL; |
static History *h = NULL; |
static EditLine *e = NULL; |
static EditLine *e = NULL; |
static Function *map[256]; |
static rl_command_func_t *map[256]; |
static jmp_buf topbuf; |
static jmp_buf topbuf; |
|
|
/* internal functions */ |
/* internal functions */ |
static unsigned char _el_rl_complete(EditLine *, int); |
static unsigned char _el_rl_complete(EditLine *, int); |
static unsigned char _el_rl_tstp(EditLine *, int); |
static unsigned char _el_rl_tstp(EditLine *, int); |
static char *_get_prompt(EditLine *); |
static char *_get_prompt(EditLine *); |
static int _getc_function(EditLine *, char *); |
static int _getc_function(EditLine *, wchar_t *); |
static HIST_ENTRY *_move_history(int); |
|
static int _history_expand_command(const char *, size_t, size_t, |
static int _history_expand_command(const char *, size_t, size_t, |
char **); |
char **); |
static char *_rl_compat_sub(const char *, const char *, |
static char *_rl_compat_sub(const char *, const char *, |
const char *, int); |
const char *, int); |
static int _rl_event_read_char(EditLine *, char *); |
static int _rl_event_read_char(EditLine *, wchar_t *); |
static void _rl_update_pos(void); |
static void _rl_update_pos(void); |
|
|
|
static HIST_ENTRY rl_he; |
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
static char * |
static char * |
_get_prompt(EditLine *el __attribute__((__unused__))) |
_get_prompt(EditLine *el __attribute__((__unused__))) |
{ |
{ |
rl_already_prompted = 1; |
rl_already_prompted = 1; |
return (rl_prompt); |
return rl_prompt; |
} |
|
|
|
|
|
/* |
|
* generic function for moving around history |
|
*/ |
|
static HIST_ENTRY * |
|
_move_history(int op) |
|
{ |
|
HistEvent ev; |
|
static HIST_ENTRY rl_he; |
|
|
|
if (history(h, &ev, op) != 0) |
|
return (HIST_ENTRY *) NULL; |
|
|
|
rl_he.line = ev.str; |
|
rl_he.data = NULL; |
|
|
|
return (&rl_he); |
|
} |
} |
|
|
|
|
Line 206 _move_history(int op) |
|
Line 193 _move_history(int op) |
|
*/ |
*/ |
static int |
static int |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
_getc_function(EditLine *el, char *c) |
_getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c) |
{ |
{ |
int i; |
int i; |
|
|
i = (*rl_getc_function)(NULL); |
i = (*rl_getc_function)(rl_instream); |
if (i == -1) |
if (i == -1) |
return 0; |
return 0; |
*c = i; |
*c = (wchar_t)i; |
return 1; |
return 1; |
} |
} |
|
|
|
static void |
|
_resize_fun(EditLine *el, void *a) |
|
{ |
|
const LineInfo *li; |
|
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); |
|
} |
|
|
|
static const char * |
|
_default_history_file(void) |
|
{ |
|
struct passwd *p; |
|
static char *path; |
|
size_t len; |
|
|
|
if (path) |
|
return path; |
|
|
|
if ((p = getpwuid(getuid())) == NULL) |
|
return NULL; |
|
|
|
len = strlen(p->pw_dir) + sizeof("/.history"); |
|
if ((path = malloc(len)) == NULL) |
|
return NULL; |
|
|
|
(void)snprintf(path, len, "%s/.history", p->pw_dir); |
|
return path; |
|
} |
|
|
/* |
/* |
* READLINE compatibility stuff |
* 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) |
|
el_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 |
* initialize rl compat stuff |
*/ |
*/ |
int |
int |
rl_initialize(void) |
rl_initialize(void) |
{ |
{ |
HistEvent ev; |
HistEvent ev; |
const LineInfo *li; |
|
int editmode = 1; |
int editmode = 1; |
struct termios t; |
struct termios t; |
|
|
Line 249 rl_initialize(void) |
|
Line 290 rl_initialize(void) |
|
if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0) |
if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0) |
editmode = 0; |
editmode = 0; |
|
|
e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr); |
e = el_init_internal(rl_readline_name, rl_instream, rl_outstream, |
|
stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr), |
|
NO_RESET); |
|
|
if (!editmode) |
if (!editmode) |
el_set(e, EL_EDITMODE, 0); |
el_set(e, EL_EDITMODE, 0); |
|
|
h = history_init(); |
h = history_init(); |
if (!e || !h) |
if (!e || !h) |
return (-1); |
return -1; |
|
|
history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ |
history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ |
history_length = 0; |
history_length = 0; |
max_input_history = INT_MAX; |
max_input_history = INT_MAX; |
el_set(e, EL_HIST, history, h); |
el_set(e, EL_HIST, history, h); |
|
|
|
/* Setup resize function */ |
|
el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer); |
|
|
/* setup getc function if valid */ |
/* setup getc function if valid */ |
if (rl_getc_function) |
if (rl_getc_function) |
el_set(e, EL_GETCFN, _getc_function); |
el_set(e, EL_GETCFN, _getc_function); |
|
|
/* for proper prompt printing in readline() */ |
/* for proper prompt printing in readline() */ |
rl_prompt = strdup(""); |
if (rl_set_prompt("") == -1) { |
if (rl_prompt == NULL) { |
|
history_end(h); |
history_end(h); |
el_end(e); |
el_end(e); |
return -1; |
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); |
el_set(e, EL_SIGNAL, rl_catch_signals); |
|
|
/* set default mode to "emacs"-style and read setting afterwards */ |
/* set default mode to "emacs"-style and read setting afterwards */ |
/* so this can be overriden */ |
/* so this can be overridden */ |
el_set(e, EL_EDITOR, "emacs"); |
el_set(e, EL_EDITOR, "emacs"); |
if (rl_terminal_name != NULL) |
if (rl_terminal_name != NULL) |
el_set(e, EL_TERMINAL, rl_terminal_name); |
el_set(e, EL_TERMINAL, rl_terminal_name); |
Line 301 rl_initialize(void) |
|
Line 346 rl_initialize(void) |
|
"ReadLine compatible suspend function", |
"ReadLine compatible suspend function", |
_el_rl_tstp); |
_el_rl_tstp); |
el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); |
el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); |
|
|
|
/* |
|
* Set some readline compatible key-bindings. |
|
*/ |
|
el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL); |
|
|
|
/* |
|
* Allow the use of Home/End keys. |
|
*/ |
|
el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL); |
|
el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL); |
|
el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL); |
|
el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL); |
|
el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL); |
|
el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL); |
|
|
|
/* |
|
* Allow the use of the Delete/Insert keys. |
|
*/ |
|
el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL); |
|
el_set(e, EL_BIND, "\\e[2~", "ed-quoted-insert", NULL); |
|
|
|
/* |
|
* Ctrl-left-arrow and Ctrl-right-arrow for word moving. |
|
*/ |
|
el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL); |
|
el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL); |
|
el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL); |
|
el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL); |
|
el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL); |
|
el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL); |
|
|
/* read settings from configuration file */ |
/* read settings from configuration file */ |
el_source(e, NULL); |
el_source(e, NULL); |
|
|
Line 309 rl_initialize(void) |
|
Line 385 rl_initialize(void) |
|
* Unfortunately, some applications really do use rl_point |
* Unfortunately, some applications really do use rl_point |
* and rl_line_buffer directly. |
* and rl_line_buffer directly. |
*/ |
*/ |
li = el_line(e); |
_resize_fun(e, &rl_line_buffer); |
/* a cheesy way to get rid of const cast. */ |
|
rl_line_buffer = memchr(li->buffer, *li->buffer, 1); |
|
_rl_update_pos(); |
_rl_update_pos(); |
|
|
if (rl_startup_hook) |
tty_end(e, TCSADRAIN); |
(*rl_startup_hook)(NULL, 0); |
|
|
|
return (0); |
return 0; |
} |
} |
|
|
|
|
Line 337 readline(const char *p) |
|
Line 410 readline(const char *p) |
|
|
|
if (e == NULL || h == NULL) |
if (e == NULL || h == NULL) |
rl_initialize(); |
rl_initialize(); |
|
if (rl_did_startup_hook == 0 && rl_startup_hook) { |
|
rl_did_startup_hook = 1; |
|
(*rl_startup_hook)(NULL, 0); |
|
} |
|
tty_init(e); |
|
|
|
|
rl_done = 0; |
rl_done = 0; |
|
|
(void)setjmp(topbuf); |
(void)setjmp(topbuf); |
|
buf = NULL; |
|
|
/* update prompt accordingly to what has been passed */ |
/* update prompt accordingly to what has been passed */ |
if (!prompt) |
if (rl_set_prompt(prompt) == -1) |
prompt = ""; |
goto out; |
if (strcmp(rl_prompt, prompt) != 0) { |
|
free(rl_prompt); |
|
rl_prompt = strdup(prompt); |
|
if (rl_prompt == NULL) |
|
return NULL; |
|
} |
|
|
|
if (rl_pre_input_hook) |
if (rl_pre_input_hook) |
(*rl_pre_input_hook)(NULL, 0); |
(*rl_pre_input_hook)(NULL, 0); |
|
|
if (rl_event_hook && !(e->el_flags&NO_TTY)) { |
if (rl_event_hook && !(e->el_flags & NO_TTY)) { |
el_set(e, EL_GETCFN, _rl_event_read_char); |
el_set(e, EL_GETCFN, _rl_event_read_char); |
used_event_hook = 1; |
used_event_hook = 1; |
} |
} |
Line 375 readline(const char *p) |
|
Line 449 readline(const char *p) |
|
|
|
buf = strdup(ret); |
buf = strdup(ret); |
if (buf == NULL) |
if (buf == NULL) |
return NULL; |
goto out; |
lastidx = count - 1; |
lastidx = count - 1; |
if (buf[lastidx] == '\n') |
if (buf[lastidx] == '\n') |
buf[lastidx] = '\0'; |
buf[lastidx] = '\0'; |
Line 385 readline(const char *p) |
|
Line 459 readline(const char *p) |
|
history(h, &ev, H_GETSIZE); |
history(h, &ev, H_GETSIZE); |
history_length = ev.num; |
history_length = ev.num; |
|
|
|
out: |
|
tty_end(e, TCSADRAIN); |
return buf; |
return buf; |
} |
} |
|
|
Line 401 using_history(void) |
|
Line 477 using_history(void) |
|
{ |
{ |
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
|
history_offset = history_length; |
} |
} |
|
|
|
|
Line 432 _rl_compat_sub(const char *str, const ch |
|
Line 509 _rl_compat_sub(const char *str, const ch |
|
} else |
} else |
s++; |
s++; |
} |
} |
r = result = malloc(len + 1); |
r = result = el_malloc((len + 1) * sizeof(*r)); |
if (result == NULL) |
if (result == NULL) |
return NULL; |
return NULL; |
s = str; |
s = str; |
Line 443 _rl_compat_sub(const char *str, const ch |
|
Line 520 _rl_compat_sub(const char *str, const ch |
|
s += what_len; |
s += what_len; |
if (!globally) { |
if (!globally) { |
(void)strcpy(r, s); |
(void)strcpy(r, s); |
return(result); |
return result; |
} |
} |
} else |
} else |
*r++ = *s++; |
*r++ = *s++; |
} |
} |
*r = '\0'; |
*r = '\0'; |
return(result); |
return result; |
} |
} |
|
|
static char *last_search_pat; /* last !?pat[?] search pattern */ |
static char *last_search_pat; /* last !?pat[?] search pattern */ |
Line 466 get_history_event(const char *cmd, int * |
|
Line 543 get_history_event(const char *cmd, int * |
|
|
|
idx = *cindex; |
idx = *cindex; |
if (cmd[idx++] != history_expansion_char) |
if (cmd[idx++] != history_expansion_char) |
return(NULL); |
return NULL; |
|
|
/* find out which event to take */ |
/* find out which event to take */ |
if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { |
if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { |
if (history(h, &ev, H_FIRST) != 0) |
if (history(h, &ev, H_FIRST) != 0) |
return(NULL); |
return NULL; |
*cindex = cmd[idx]? (idx + 1):idx; |
*cindex = cmd[idx]? (idx + 1):idx; |
return(ev.str); |
return ev.str; |
} |
} |
sign = 0; |
sign = 0; |
if (cmd[idx] == '-') { |
if (cmd[idx] == '-') { |
Line 482 get_history_event(const char *cmd, int * |
|
Line 559 get_history_event(const char *cmd, int * |
|
} |
} |
|
|
if ('0' <= cmd[idx] && cmd[idx] <= '9') { |
if ('0' <= cmd[idx] && cmd[idx] <= '9') { |
HIST_ENTRY *rl_he; |
HIST_ENTRY *he; |
|
|
num = 0; |
num = 0; |
while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') { |
while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') { |
Line 490 get_history_event(const char *cmd, int * |
|
Line 567 get_history_event(const char *cmd, int * |
|
idx++; |
idx++; |
} |
} |
if (sign) |
if (sign) |
num = history_length - num + 1; |
num = history_length - num + history_base; |
|
|
if (!(rl_he = history_get(num))) |
if (!(he = history_get(num))) |
return(NULL); |
return NULL; |
|
|
*cindex = idx; |
*cindex = idx; |
return(rl_he->line); |
return he->line; |
} |
} |
sub = 0; |
sub = 0; |
if (cmd[idx] == '?') { |
if (cmd[idx] == '?') { |
Line 514 get_history_event(const char *cmd, int * |
|
Line 591 get_history_event(const char *cmd, int * |
|
break; |
break; |
idx++; |
idx++; |
} |
} |
len = idx - begin; |
len = (size_t)idx - (size_t)begin; |
if (sub && cmd[idx] == '?') |
if (sub && cmd[idx] == '?') |
idx++; |
idx++; |
if (sub && len == 0 && last_search_pat && *last_search_pat) |
if (sub && len == 0 && last_search_pat && *last_search_pat) |
pat = last_search_pat; |
pat = last_search_pat; |
else if (len == 0) |
else if (len == 0) |
return(NULL); |
return NULL; |
else { |
else { |
if ((pat = malloc(len + 1)) == NULL) |
if ((pat = el_malloc((len + 1) * sizeof(*pat))) == NULL) |
return NULL; |
return NULL; |
(void)strncpy(pat, cmd + begin, len); |
(void)strncpy(pat, cmd + begin, len); |
pat[len] = '\0'; |
pat[len] = '\0'; |
Line 530 get_history_event(const char *cmd, int * |
|
Line 607 get_history_event(const char *cmd, int * |
|
|
|
if (history(h, &ev, H_CURR) != 0) { |
if (history(h, &ev, H_CURR) != 0) { |
if (pat != last_search_pat) |
if (pat != last_search_pat) |
free(pat); |
el_free(pat); |
return (NULL); |
return NULL; |
} |
} |
num = ev.num; |
num = ev.num; |
|
|
if (sub) { |
if (sub) { |
if (pat != last_search_pat) { |
if (pat != last_search_pat) { |
if (last_search_pat) |
if (last_search_pat) |
free(last_search_pat); |
el_free(last_search_pat); |
last_search_pat = pat; |
last_search_pat = pat; |
} |
} |
ret = history_search(pat, -1); |
ret = history_search(pat, -1); |
Line 550 get_history_event(const char *cmd, int * |
|
Line 627 get_history_event(const char *cmd, int * |
|
history(h, &ev, H_FIRST); |
history(h, &ev, H_FIRST); |
(void)fprintf(rl_outstream, "%s: Event not found\n", pat); |
(void)fprintf(rl_outstream, "%s: Event not found\n", pat); |
if (pat != last_search_pat) |
if (pat != last_search_pat) |
free(pat); |
el_free(pat); |
return(NULL); |
return NULL; |
} |
} |
|
|
if (sub && len) { |
if (sub && len) { |
if (last_search_match && last_search_match != pat) |
if (last_search_match && last_search_match != pat) |
free(last_search_match); |
el_free(last_search_match); |
last_search_match = pat; |
last_search_match = pat; |
} |
} |
|
|
if (pat != last_search_pat) |
if (pat != last_search_pat) |
free(pat); |
el_free(pat); |
|
|
if (history(h, &ev, H_CURR) != 0) |
if (history(h, &ev, H_CURR) != 0) |
return(NULL); |
return NULL; |
*cindex = idx; |
*cindex = idx; |
rptr = ev.str; |
rptr = ev.str; |
|
|
Line 582 get_history_event(const char *cmd, int * |
|
Line 659 get_history_event(const char *cmd, int * |
|
* returns 0 if data was not modified, 1 if it was and 2 if the string |
* returns 0 if data was not modified, 1 if it was and 2 if the string |
* should be only printed and not executed; in case of error, |
* should be only printed and not executed; in case of error, |
* returns -1 and *result points to NULL |
* returns -1 and *result points to NULL |
* it's callers responsibility to free() string returned in *result |
* it's the caller's responsibility to free() the string returned in *result |
*/ |
*/ |
static int |
static int |
_history_expand_command(const char *command, size_t offs, size_t cmdlen, |
_history_expand_command(const char *command, size_t offs, size_t cmdlen, |
Line 616 _history_expand_command(const char *comm |
|
Line 693 _history_expand_command(const char *comm |
|
} else { |
} else { |
if (command[offs + 1] == '#') { |
if (command[offs + 1] == '#') { |
/* use command so far */ |
/* use command so far */ |
if ((aptr = malloc(offs + 1)) == NULL) |
if ((aptr = el_malloc((offs + 1) * sizeof(*aptr))) |
|
== NULL) |
return -1; |
return -1; |
(void)strncpy(aptr, command, offs); |
(void)strncpy(aptr, command, offs); |
aptr[offs] = '\0'; |
aptr[offs] = '\0'; |
Line 627 _history_expand_command(const char *comm |
|
Line 705 _history_expand_command(const char *comm |
|
qchar = (offs > 0 && command[offs - 1] == '"')? '"':0; |
qchar = (offs > 0 && command[offs - 1] == '"')? '"':0; |
ptr = get_history_event(command + offs, &idx, qchar); |
ptr = get_history_event(command + offs, &idx, qchar); |
} |
} |
has_mods = command[offs + idx] == ':'; |
has_mods = command[offs + (size_t)idx] == ':'; |
} |
} |
|
|
if (ptr == NULL && aptr == NULL) |
if (ptr == NULL && aptr == NULL) |
return(-1); |
return -1; |
|
|
if (!has_mods) { |
if (!has_mods) { |
*result = strdup(aptr? aptr : ptr); |
*result = strdup(aptr ? aptr : ptr); |
if (aptr) |
if (aptr) |
free(aptr); |
el_free(aptr); |
return(1); |
if (*result == NULL) |
|
return -1; |
|
return 1; |
} |
} |
|
|
cmd = command + offs + idx + 1; |
cmd = command + offs + idx + 1; |
Line 682 _history_expand_command(const char *comm |
|
Line 762 _history_expand_command(const char *comm |
|
(void)fprintf(rl_outstream, "%s: Bad word specifier", |
(void)fprintf(rl_outstream, "%s: Bad word specifier", |
command + offs + idx); |
command + offs + idx); |
if (aptr) |
if (aptr) |
free(aptr); |
el_free(aptr); |
return(-1); |
return -1; |
} |
} |
} else |
} else |
tmp = strdup(aptr? aptr:ptr); |
tmp = strdup(aptr? aptr:ptr); |
|
|
if (aptr) |
if (aptr) |
free(aptr); |
el_free(aptr); |
|
|
if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { |
if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { |
*result = tmp; |
*result = tmp; |
return(1); |
return 1; |
} |
} |
|
|
for (; *cmd; cmd++) { |
for (; *cmd; cmd++) { |
Line 705 _history_expand_command(const char *comm |
|
Line 785 _history_expand_command(const char *comm |
|
} else if (*cmd == 't') { /* remove leading path */ |
} else if (*cmd == 't') { /* remove leading path */ |
if ((aptr = strrchr(tmp, '/')) != NULL) { |
if ((aptr = strrchr(tmp, '/')) != NULL) { |
aptr = strdup(aptr + 1); |
aptr = strdup(aptr + 1); |
free(tmp); |
el_free(tmp); |
tmp = aptr; |
tmp = aptr; |
} |
} |
} else if (*cmd == 'r') { /* remove trailing suffix */ |
} else if (*cmd == 'r') { /* remove trailing suffix */ |
Line 714 _history_expand_command(const char *comm |
|
Line 794 _history_expand_command(const char *comm |
|
} else if (*cmd == 'e') { /* remove all but suffix */ |
} else if (*cmd == 'e') { /* remove all but suffix */ |
if ((aptr = strrchr(tmp, '.')) != NULL) { |
if ((aptr = strrchr(tmp, '.')) != NULL) { |
aptr = strdup(aptr); |
aptr = strdup(aptr); |
free(tmp); |
el_free(tmp); |
tmp = aptr; |
tmp = aptr; |
} |
} |
} else if (*cmd == 'p') /* print only */ |
} else if (*cmd == 'p') /* print only */ |
Line 731 _history_expand_command(const char *comm |
|
Line 811 _history_expand_command(const char *comm |
|
else if (*cmd == 's') { |
else if (*cmd == 's') { |
delim = *(++cmd), cmd++; |
delim = *(++cmd), cmd++; |
size = 16; |
size = 16; |
what = realloc(from, size); |
what = el_realloc(from, size * sizeof(*what)); |
if (what == NULL) { |
if (what == NULL) { |
free(from); |
el_free(from); |
free(tmp); |
el_free(tmp); |
return 0; |
return 0; |
} |
} |
len = 0; |
len = 0; |
Line 743 _history_expand_command(const char *comm |
|
Line 823 _history_expand_command(const char *comm |
|
cmd++; |
cmd++; |
if (len >= size) { |
if (len >= size) { |
char *nwhat; |
char *nwhat; |
nwhat = realloc(what, |
nwhat = el_realloc(what, |
(size <<= 1)); |
(size <<= 1) * |
|
sizeof(*nwhat)); |
if (nwhat == NULL) { |
if (nwhat == NULL) { |
free(what); |
el_free(what); |
free(tmp); |
el_free(tmp); |
return 0; |
return 0; |
} |
} |
what = nwhat; |
what = nwhat; |
Line 757 _history_expand_command(const char *comm |
|
Line 838 _history_expand_command(const char *comm |
|
what[len] = '\0'; |
what[len] = '\0'; |
from = what; |
from = what; |
if (*what == '\0') { |
if (*what == '\0') { |
free(what); |
el_free(what); |
if (search) { |
if (search) { |
from = strdup(search); |
from = strdup(search); |
if (from == NULL) { |
if (from == NULL) { |
free(tmp); |
el_free(tmp); |
return 0; |
return 0; |
} |
} |
} else { |
} else { |
from = NULL; |
from = NULL; |
free(tmp); |
el_free(tmp); |
return (-1); |
return -1; |
} |
} |
} |
} |
cmd++; /* shift after delim */ |
cmd++; /* shift after delim */ |
Line 775 _history_expand_command(const char *comm |
|
Line 856 _history_expand_command(const char *comm |
|
continue; |
continue; |
|
|
size = 16; |
size = 16; |
with = realloc(to, size); |
with = el_realloc(to, size * sizeof(*with)); |
if (with == NULL) { |
if (with == NULL) { |
free(to); |
el_free(to); |
free(tmp); |
el_free(tmp); |
return -1; |
return -1; |
} |
} |
len = 0; |
len = 0; |
Line 787 _history_expand_command(const char *comm |
|
Line 868 _history_expand_command(const char *comm |
|
if (len + from_len + 1 >= size) { |
if (len + from_len + 1 >= size) { |
char *nwith; |
char *nwith; |
size += from_len + 1; |
size += from_len + 1; |
nwith = realloc(with, size); |
nwith = el_realloc(with, |
|
size * sizeof(*nwith)); |
if (nwith == NULL) { |
if (nwith == NULL) { |
free(with); |
el_free(with); |
free(tmp); |
el_free(tmp); |
return -1; |
return -1; |
} |
} |
with = nwith; |
with = nwith; |
Line 813 _history_expand_command(const char *comm |
|
Line 895 _history_expand_command(const char *comm |
|
|
|
aptr = _rl_compat_sub(tmp, from, to, g_on); |
aptr = _rl_compat_sub(tmp, from, to, g_on); |
if (aptr) { |
if (aptr) { |
free(tmp); |
el_free(tmp); |
tmp = aptr; |
tmp = aptr; |
} |
} |
g_on = 0; |
g_on = 0; |
} |
} |
} |
} |
*result = tmp; |
*result = tmp; |
return (p_on? 2:1); |
return p_on? 2:1; |
} |
} |
|
|
|
|
Line 839 history_expand(char *str, char **output) |
|
Line 921 history_expand(char *str, char **output) |
|
|
|
if (history_expansion_char == 0) { |
if (history_expansion_char == 0) { |
*output = strdup(str); |
*output = strdup(str); |
return(0); |
return 0; |
} |
} |
|
|
*output = NULL; |
*output = NULL; |
if (str[0] == history_subst_char) { |
if (str[0] == history_subst_char) { |
/* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ |
/* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ |
*output = malloc(strlen(str) + 4 + 1); |
*output = el_malloc((strlen(str) + 4 + 1) * sizeof(**output)); |
if (*output == NULL) |
if (*output == NULL) |
return 0; |
return 0; |
(*output)[0] = (*output)[1] = history_expansion_char; |
(*output)[0] = (*output)[1] = history_expansion_char; |
Line 862 history_expand(char *str, char **output) |
|
Line 944 history_expand(char *str, char **output) |
|
#define ADD_STRING(what, len, fr) \ |
#define ADD_STRING(what, len, fr) \ |
{ \ |
{ \ |
if (idx + len + 1 > size) { \ |
if (idx + len + 1 > size) { \ |
char *nresult = realloc(result, (size += len + 1));\ |
char *nresult = el_realloc(result, \ |
|
(size += len + 1) * sizeof(*nresult)); \ |
if (nresult == NULL) { \ |
if (nresult == NULL) { \ |
free(*output); \ |
el_free(*output); \ |
if (/*CONSTCOND*/fr) \ |
if (/*CONSTCOND*/fr) \ |
free(tmp); \ |
el_free(tmp); \ |
return 0; \ |
return 0; \ |
} \ |
} \ |
result = nresult; \ |
result = nresult; \ |
|
|
for (; str[j]; j++) { |
for (; str[j]; j++) { |
if (str[j] == '\\' && |
if (str[j] == '\\' && |
str[j + 1] == history_expansion_char) { |
str[j + 1] == history_expansion_char) { |
(void)strcpy(&str[j], &str[j + 1]); |
len = strlen(&str[j + 1]) + 1; |
|
memmove(&str[j], &str[j + 1], len); |
continue; |
continue; |
} |
} |
if (!loop_again) { |
if (!loop_again) { |
|
|
ADD_STRING(tmp, len, 1); |
ADD_STRING(tmp, len, 1); |
} |
} |
if (tmp) { |
if (tmp) { |
free(tmp); |
el_free(tmp); |
tmp = NULL; |
tmp = NULL; |
} |
} |
i = j; |
i = j; |
|
|
ret = -1; |
ret = -1; |
#endif |
#endif |
} |
} |
free(*output); |
el_free(*output); |
*output = result; |
*output = result; |
|
|
return (ret); |
return ret; |
} |
} |
|
|
/* |
/* |
|
|
history_arg_extract(int start, int end, const char *str) |
history_arg_extract(int start, int end, const char *str) |
{ |
{ |
size_t i, len, max; |
size_t i, len, max; |
char **arr, *result; |
char **arr, *result = NULL; |
|
|
arr = history_tokenize(str); |
arr = history_tokenize(str); |
if (!arr) |
if (!arr) |
return(NULL); |
return NULL; |
if (arr && *arr == NULL) { |
if (arr && *arr == NULL) |
free(arr); |
goto out; |
return(NULL); |
|
} |
|
|
|
for (max = 0; arr[max]; max++) |
for (max = 0; arr[max]; max++) |
continue; |
continue; |
max--; |
max--; |
|
|
if (start == '$') |
if (start == '$') |
start = max; |
start = (int)max; |
if (end == '$') |
if (end == '$') |
end = max; |
end = (int)max; |
if (end < 0) |
if (end < 0) |
end = max + end + 1; |
end = (int)max + end + 1; |
if (start < 0) |
if (start < 0) |
start = end; |
start = end; |
|
|
if (start < 0 || end < 0 || (size_t)start > max || (size_t)end > max || start > end) |
if (start < 0 || end < 0 || (size_t)start > max || |
return(NULL); |
(size_t)end > max || start > end) |
|
goto out; |
|
|
for (i = start, len = 0; i <= (size_t)end; i++) |
for (i = (size_t)start, len = 0; i <= (size_t)end; i++) |
len += strlen(arr[i]) + 1; |
len += strlen(arr[i]) + 1; |
len++; |
len++; |
result = malloc(len); |
result = el_malloc(len * sizeof(*result)); |
if (result == NULL) |
if (result == NULL) |
return NULL; |
goto out; |
|
|
for (i = start, len = 0; i <= (size_t)end; i++) { |
for (i = (size_t)start, len = 0; i <= (size_t)end; i++) { |
(void)strcpy(result + len, arr[i]); |
(void)strcpy(result + len, arr[i]); |
len += strlen(arr[i]); |
len += strlen(arr[i]); |
if (i < (size_t)end) |
if (i < (size_t)end) |
Line 1004 history_arg_extract(int start, int end, |
|
Line 1087 history_arg_extract(int start, int end, |
|
} |
} |
result[len] = '\0'; |
result[len] = '\0'; |
|
|
|
out: |
for (i = 0; arr[i]; i++) |
for (i = 0; arr[i]; i++) |
free(arr[i]); |
el_free(arr[i]); |
free(arr); |
el_free(arr); |
|
|
return(result); |
return result; |
} |
} |
|
|
/* |
/* |
Line 1045 history_tokenize(const char *str) |
|
Line 1129 history_tokenize(const char *str) |
|
if (idx + 2 >= size) { |
if (idx + 2 >= size) { |
char **nresult; |
char **nresult; |
size <<= 1; |
size <<= 1; |
nresult = realloc(result, size * sizeof(char *)); |
nresult = el_realloc(result, (size_t)size * sizeof(*nresult)); |
if (nresult == NULL) { |
if (nresult == NULL) { |
free(result); |
el_free(result); |
return NULL; |
return NULL; |
} |
} |
result = nresult; |
result = nresult; |
} |
} |
len = i - start; |
len = (size_t)i - (size_t)start; |
temp = malloc(len + 1); |
temp = el_malloc((size_t)(len + 1) * sizeof(*temp)); |
if (temp == NULL) { |
if (temp == NULL) { |
for (i = 0; i < idx; i++) |
for (i = 0; i < idx; i++) |
free(result[i]); |
el_free(result[i]); |
free(result); |
el_free(result); |
return NULL; |
return NULL; |
} |
} |
(void)strncpy(temp, &str[start], len); |
(void)strncpy(temp, &str[start], len); |
Line 1067 history_tokenize(const char *str) |
|
Line 1151 history_tokenize(const char *str) |
|
if (str[i]) |
if (str[i]) |
i++; |
i++; |
} |
} |
return (result); |
return result; |
} |
} |
|
|
|
|
|
|
stifle_history(int max) |
stifle_history(int max) |
{ |
{ |
HistEvent ev; |
HistEvent ev; |
|
HIST_ENTRY *he; |
|
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
|
|
if (history(h, &ev, H_SETSIZE, max) == 0) |
if (history(h, &ev, H_SETSIZE, max) == 0) { |
max_input_history = max; |
max_input_history = max; |
|
if (history_length > max) |
|
history_base = history_length - max; |
|
while (history_length > max) { |
|
he = remove_history(0); |
|
el_free(he->data); |
|
el_free((void *)(unsigned long)he->line); |
|
el_free(he); |
|
} |
|
} |
} |
} |
|
|
|
|
Line 1099 unstifle_history(void) |
|
Line 1193 unstifle_history(void) |
|
history(h, &ev, H_SETSIZE, INT_MAX); |
history(h, &ev, H_SETSIZE, INT_MAX); |
omax = max_input_history; |
omax = max_input_history; |
max_input_history = INT_MAX; |
max_input_history = INT_MAX; |
return (omax); /* some value _must_ be returned */ |
return omax; /* some value _must_ be returned */ |
} |
} |
|
|
|
|
Line 1108 history_is_stifled(void) |
|
Line 1202 history_is_stifled(void) |
|
{ |
{ |
|
|
/* cannot return true answer */ |
/* cannot return true answer */ |
return (max_input_history != INT_MAX); |
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), (size_t)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 = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp); |
|
if (ferror(fp)) { |
|
ret = errno; |
|
break; |
|
} |
|
if (left == 0) { |
|
count--; |
|
left = sizeof(buf); |
|
} else if (fwrite(buf, (size_t)left, (size_t)1, tp) |
|
!= 1) { |
|
ret = errno; |
|
break; |
|
} |
|
fflush(tp); |
|
break; |
|
} |
|
if (fwrite(buf, sizeof(buf), (size_t)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), (size_t)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, (off_t)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 = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) { |
|
if (ferror(fp)) |
|
ret = errno; |
|
break; |
|
} |
|
if (fwrite(buf, (size_t)left, (size_t)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; |
} |
} |
|
|
|
|
Line 1122 read_history(const char *filename) |
|
Line 1353 read_history(const char *filename) |
|
|
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
return (history(h, &ev, H_LOAD, filename) == -1); |
if (filename == NULL && (filename = _default_history_file()) == NULL) |
|
return errno; |
|
errno = 0; |
|
if (history(h, &ev, H_LOAD, filename) == -1) |
|
return errno ? errno : EINVAL; |
|
if (history(h, &ev, H_GETSIZE) == 0) |
|
history_length = ev.num; |
|
if (history_length < 0) |
|
return EINVAL; |
|
return 0; |
} |
} |
|
|
|
|
Line 1136 write_history(const char *filename) |
|
Line 1376 write_history(const char *filename) |
|
|
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
return (history(h, &ev, H_SAVE, filename) == -1); |
if (filename == NULL && (filename = _default_history_file()) == NULL) |
|
return errno; |
|
return history(h, &ev, H_SAVE, filename) == -1 ? |
|
(errno ? errno : EINVAL) : 0; |
} |
} |
|
|
|
int |
|
append_history(int n, const char *filename) |
|
{ |
|
HistEvent ev; |
|
FILE *fp; |
|
|
|
if (h == NULL || e == NULL) |
|
rl_initialize(); |
|
if (filename == NULL && (filename = _default_history_file()) == NULL) |
|
return errno; |
|
|
|
if ((fp = fopen(filename, "a")) == NULL) |
|
return errno; |
|
|
|
if (history(h, &ev, H_NSAVE_FP, (size_t)n, fp) == -1) { |
|
int serrno = errno ? errno : EINVAL; |
|
fclose(fp); |
|
return serrno; |
|
} |
|
fclose(fp); |
|
return 0; |
|
} |
|
|
/* |
/* |
* returns history ``num''th event |
* returns history ``num''th event |
Line 1155 history_get(int num) |
|
Line 1420 history_get(int num) |
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
|
|
|
if (num < history_base) |
|
return NULL; |
|
|
/* save current position */ |
/* save current position */ |
if (history(h, &ev, H_CURR) != 0) |
if (history(h, &ev, H_CURR) != 0) |
return (NULL); |
return NULL; |
curr_num = ev.num; |
curr_num = ev.num; |
|
|
/* start from most recent */ |
/* |
if (history(h, &ev, H_FIRST) != 0) |
* use H_DELDATA to set to nth history (without delete) by passing |
return (NULL); /* error */ |
* (void **)-1 -- as in history_set_pos |
|
*/ |
/* look backwards for event matching specified offset */ |
if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0) |
if (history(h, &ev, H_NEXT_EVENT, num + 1)) |
goto out; |
return (NULL); |
|
|
|
|
/* get current entry */ |
|
if (history(h, &ev, H_CURR) != 0) |
|
goto out; |
|
if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0) |
|
goto out; |
she.line = ev.str; |
she.line = ev.str; |
she.data = NULL; |
|
|
|
/* restore pointer to where it was */ |
/* restore pointer to where it was */ |
(void)history(h, &ev, H_SET, curr_num); |
(void)history(h, &ev, H_SET, curr_num); |
|
|
return (&she); |
return &she; |
|
|
|
out: |
|
/* restore pointer to where it was */ |
|
(void)history(h, &ev, H_SET, curr_num); |
|
return NULL; |
} |
} |
|
|
|
|
Line 1189 add_history(const char *line) |
|
Line 1465 add_history(const char *line) |
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
|
|
(void)history(h, &ev, H_ENTER, line); |
if (history(h, &ev, H_ENTER, line) == -1) |
if (history(h, &ev, H_GETSIZE) == 0) |
return 0; |
history_length = ev.num; |
|
|
|
return (!(history_length > 0)); /* return 0 if all is okay */ |
(void)history(h, &ev, H_GETSIZE); |
|
if (ev.num == history_length) |
|
history_base++; |
|
else |
|
history_length = ev.num; |
|
return 0; |
} |
} |
|
|
|
|
Line 1203 add_history(const char *line) |
|
Line 1483 add_history(const char *line) |
|
HIST_ENTRY * |
HIST_ENTRY * |
remove_history(int num) |
remove_history(int num) |
{ |
{ |
HIST_ENTRY *she; |
HIST_ENTRY *he; |
HistEvent ev; |
HistEvent ev; |
|
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
|
|
if (history(h, &ev, H_DEL, num) != 0) |
if ((he = el_malloc(sizeof(*he))) == NULL) |
return NULL; |
return NULL; |
|
|
if ((she = malloc(sizeof(*she))) == NULL) |
if (history(h, &ev, H_DELDATA, num, &he->data) != 0) { |
|
el_free(he); |
return NULL; |
return NULL; |
|
} |
|
|
she->line = ev.str; |
he->line = ev.str; |
she->data = NULL; |
if (history(h, &ev, H_GETSIZE) == 0) |
|
history_length = ev.num; |
|
|
return she; |
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; |
|
HistEvent ev; |
|
int curr_num; |
|
|
|
if (h == NULL || e == NULL) |
|
rl_initialize(); |
|
|
|
/* save current position */ |
|
if (history(h, &ev, H_CURR) != 0) |
|
return NULL; |
|
curr_num = ev.num; |
|
|
|
/* start from the oldest */ |
|
if (history(h, &ev, H_LAST) != 0) |
|
return NULL; /* error */ |
|
|
|
if ((he = el_malloc(sizeof(*he))) == NULL) |
|
return NULL; |
|
|
|
/* look forwards for event matching specified offset */ |
|
if (history(h, &ev, H_NEXT_EVDATA, num, &he->data)) |
|
goto out; |
|
|
|
he->line = strdup(ev.str); |
|
if (he->line == NULL) |
|
goto out; |
|
|
|
if (history(h, &ev, H_REPLACE, line, data)) |
|
goto out; |
|
|
|
/* restore pointer to where it was */ |
|
if (history(h, &ev, H_SET, curr_num)) |
|
goto out; |
|
|
|
return he; |
|
out: |
|
el_free(he); |
|
return NULL; |
|
} |
|
|
|
/* |
* clear the history list - delete all entries |
* clear the history list - delete all entries |
*/ |
*/ |
void |
void |
Line 1230 clear_history(void) |
|
Line 1559 clear_history(void) |
|
{ |
{ |
HistEvent ev; |
HistEvent ev; |
|
|
history(h, &ev, H_CLEAR); |
if (h == NULL || e == NULL) |
|
rl_initialize(); |
|
|
|
(void)history(h, &ev, H_CLEAR); |
|
history_offset = history_length = 0; |
} |
} |
|
|
|
|
Line 1240 clear_history(void) |
|
Line 1573 clear_history(void) |
|
int |
int |
where_history(void) |
where_history(void) |
{ |
{ |
|
return history_offset; |
|
} |
|
|
|
static HIST_ENTRY **_history_listp; |
|
static HIST_ENTRY *_history_list; |
|
|
|
HIST_ENTRY ** |
|
history_list(void) |
|
{ |
HistEvent ev; |
HistEvent ev; |
int curr_num, off; |
HIST_ENTRY **nlp, *nl; |
|
int i; |
|
|
if (history(h, &ev, H_CURR) != 0) |
if (history(h, &ev, H_LAST) != 0) |
return (0); |
return NULL; |
curr_num = ev.num; |
|
|
|
history(h, &ev, H_FIRST); |
if ((nlp = el_realloc(_history_listp, |
off = 1; |
(size_t)history_length * sizeof(*nlp))) == NULL) |
while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) |
return NULL; |
off++; |
_history_listp = nlp; |
|
|
return (off); |
if ((nl = el_realloc(_history_list, |
} |
(size_t)history_length * sizeof(*nl))) == NULL) |
|
return NULL; |
|
_history_list = nl; |
|
|
|
i = 0; |
|
do { |
|
_history_listp[i] = &_history_list[i]; |
|
_history_list[i].line = ev.str; |
|
_history_list[i].data = NULL; |
|
if (i++ == history_length) |
|
abort(); |
|
} while (history(h, &ev, H_PREV) == 0); |
|
return _history_listp; |
|
} |
|
|
/* |
/* |
* returns current history event or NULL if there is no such event |
* returns current history event or NULL if there is no such event |
Line 1262 where_history(void) |
|
Line 1616 where_history(void) |
|
HIST_ENTRY * |
HIST_ENTRY * |
current_history(void) |
current_history(void) |
{ |
{ |
|
HistEvent ev; |
|
|
return (_move_history(H_CURR)); |
if (history(h, &ev, H_PREV_EVENT, history_offset + 1) != 0) |
|
return NULL; |
|
|
|
rl_he.line = ev.str; |
|
rl_he.data = NULL; |
|
return &rl_he; |
} |
} |
|
|
|
|
|
|
history_total_bytes(void) |
history_total_bytes(void) |
{ |
{ |
HistEvent ev; |
HistEvent ev; |
int curr_num, size; |
int curr_num; |
|
size_t size; |
|
|
if (history(h, &ev, H_CURR) != 0) |
if (history(h, &ev, H_CURR) != 0) |
return (-1); |
return -1; |
curr_num = ev.num; |
curr_num = ev.num; |
|
|
history(h, &ev, H_FIRST); |
(void)history(h, &ev, H_FIRST); |
size = 0; |
size = 0; |
do |
do |
size += strlen(ev.str); |
size += strlen(ev.str) * sizeof(*ev.str); |
while (history(h, &ev, H_NEXT) == 0); |
while (history(h, &ev, H_NEXT) == 0); |
|
|
/* get to the same position as before */ |
/* get to the same position as before */ |
history(h, &ev, H_PREV_EVENT, curr_num); |
history(h, &ev, H_PREV_EVENT, curr_num); |
|
|
return (size); |
return (int)size; |
} |
} |
|
|
|
|
Line 1299 history_total_bytes(void) |
|
Line 1660 history_total_bytes(void) |
|
int |
int |
history_set_pos(int pos) |
history_set_pos(int pos) |
{ |
{ |
HistEvent ev; |
if (pos >= history_length || pos < 0) |
int curr_num; |
return 0; |
|
|
if (pos > history_length || pos < 0) |
|
return (-1); |
|
|
|
history(h, &ev, H_CURR); |
|
curr_num = ev.num; |
|
|
|
if (history(h, &ev, H_SET, pos)) { |
history_offset = pos; |
history(h, &ev, H_SET, curr_num); |
return 1; |
return(-1); |
|
} |
|
return (0); |
|
} |
} |
|
|
|
|
/* |
/* |
* returns previous event in history and shifts pointer accordingly |
* returns previous event in history and shifts pointer accordingly |
|
* Note that readline and editline define directions in opposite ways. |
*/ |
*/ |
HIST_ENTRY * |
HIST_ENTRY * |
previous_history(void) |
previous_history(void) |
{ |
{ |
|
HistEvent ev; |
|
|
|
if (history_offset == 0) |
|
return NULL; |
|
|
return (_move_history(H_PREV)); |
if (history(h, &ev, H_LAST) != 0) |
|
return NULL; |
|
|
|
history_offset--; |
|
return current_history(); |
} |
} |
|
|
|
|
Line 1333 previous_history(void) |
|
Line 1694 previous_history(void) |
|
HIST_ENTRY * |
HIST_ENTRY * |
next_history(void) |
next_history(void) |
{ |
{ |
|
HistEvent ev; |
|
|
|
if (history_offset >= history_length) |
|
return NULL; |
|
|
return (_move_history(H_NEXT)); |
if (history(h, &ev, H_LAST) != 0) |
|
return NULL; |
|
|
|
history_offset++; |
|
return current_history(); |
} |
} |
|
|
|
|
Line 1349 history_search(const char *str, int dire |
|
Line 1718 history_search(const char *str, int dire |
|
int curr_num; |
int curr_num; |
|
|
if (history(h, &ev, H_CURR) != 0) |
if (history(h, &ev, H_CURR) != 0) |
return (-1); |
return -1; |
curr_num = ev.num; |
curr_num = ev.num; |
|
|
for (;;) { |
for (;;) { |
if ((strp = strstr(ev.str, str)) != NULL) |
if ((strp = strstr(ev.str, str)) != NULL) |
return (int) (strp - ev.str); |
return (int)(strp - ev.str); |
if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0) |
if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0) |
break; |
break; |
} |
} |
history(h, &ev, H_SET, curr_num); |
(void)history(h, &ev, H_SET, curr_num); |
return (-1); |
return -1; |
} |
} |
|
|
|
|
Line 1371 history_search_prefix(const char *str, i |
|
Line 1740 history_search_prefix(const char *str, i |
|
{ |
{ |
HistEvent ev; |
HistEvent ev; |
|
|
return (history(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str)); |
return (history(h, &ev, direction < 0 ? |
|
H_PREV_STR : H_NEXT_STR, str)); |
} |
} |
|
|
|
|
Line 1391 history_search_pos(const char *str, |
|
Line 1761 history_search_pos(const char *str, |
|
pos = (pos > 0) ? 1 : -1; |
pos = (pos > 0) ? 1 : -1; |
|
|
if (history(h, &ev, H_CURR) != 0) |
if (history(h, &ev, H_CURR) != 0) |
return (-1); |
return -1; |
curr_num = ev.num; |
curr_num = ev.num; |
|
|
if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) |
if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0) |
return (-1); |
return -1; |
|
|
|
|
for (;;) { |
for (;;) { |
if (strstr(ev.str, str)) |
if (strstr(ev.str, str)) |
return (off); |
return off; |
if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) |
if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) |
break; |
break; |
} |
} |
|
|
/* set "current" pointer back to previous state */ |
/* set "current" pointer back to previous state */ |
history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); |
(void)history(h, &ev, |
|
pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); |
|
|
return (-1); |
return -1; |
} |
} |
|
|
|
|
Line 1431 filename_completion_function(const char |
|
Line 1801 filename_completion_function(const char |
|
* a completion generator for usernames; returns _first_ username |
* a completion generator for usernames; returns _first_ username |
* which starts with supplied text |
* which starts with supplied text |
* text contains a partial username preceded by random character |
* text contains a partial username preceded by random character |
* (usually '~'); state is ignored |
* (usually '~'); state resets search from start (??? should we do that anyway) |
* it's callers responsibility to free returned value |
* it's the caller's responsibility to free the returned value |
*/ |
*/ |
char * |
char * |
username_completion_function(const char *text, int state) |
username_completion_function(const char *text, int state) |
{ |
{ |
struct passwd *pwd, pwres; |
#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) |
|
struct passwd pwres; |
char pwbuf[1024]; |
char pwbuf[1024]; |
|
#endif |
|
struct passwd *pass = NULL; |
|
|
if (text[0] == '\0') |
if (text[0] == '\0') |
return (NULL); |
return NULL; |
|
|
if (*text == '~') |
if (*text == '~') |
text++; |
text++; |
Line 1449 username_completion_function(const char |
|
Line 1822 username_completion_function(const char |
|
if (state == 0) |
if (state == 0) |
setpwent(); |
setpwent(); |
|
|
while (getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pwd) == 0 |
while ( |
&& pwd != NULL && text[0] == pwd->pw_name[0] |
#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) |
&& strcmp(text, pwd->pw_name) == 0); |
getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL |
|
#else |
|
(pass = getpwent()) != NULL |
|
#endif |
|
&& text[0] == pass->pw_name[0] |
|
&& strcmp(text, pass->pw_name) == 0) |
|
continue; |
|
|
if (pwd == NULL) { |
if (pass == NULL) { |
endpwent(); |
endpwent(); |
return (NULL); |
return NULL; |
} |
} |
return (strdup(pwd->pw_name)); |
return strdup(pass->pw_name); |
} |
} |
|
|
|
|
Line 1472 _el_rl_tstp(EditLine *el __attribute__(( |
|
Line 1851 _el_rl_tstp(EditLine *el __attribute__(( |
|
return CC_NORM; |
return CC_NORM; |
} |
} |
|
|
/* |
|
* Display list of strings in columnar format on readline's output stream. |
|
* 'matches' is list of strings, 'len' is number of strings in 'matches', |
|
* 'max' is maximum length of string in 'matches'. |
|
*/ |
|
void |
|
rl_display_match_list(char **matches, int len, int max) |
|
{ |
|
|
|
fn_display_match_list(e, matches, len, max); |
|
} |
|
|
|
static const char * |
static const char * |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
_rl_completion_append_character_function(const char *dummy |
_rl_completion_append_character_function(const char *dummy |
__attribute__((__unused__))) |
__attribute__((__unused__))) |
{ |
{ |
static char buf[2]; |
static char buf[2]; |
buf[0] = rl_completion_append_character; |
buf[0] = (char)rl_completion_append_character; |
buf[1] = '\0'; |
buf[1] = '\0'; |
return buf; |
return buf; |
} |
} |
|
|
|
|
/* |
/* |
|
* Display list of strings in columnar format on readline's output stream. |
|
* 'matches' is list of strings, 'len' is number of strings in 'matches', |
|
* 'max' is maximum length of string in 'matches'. |
|
*/ |
|
void |
|
rl_display_match_list(char **matches, int len, int max) |
|
{ |
|
|
|
fn_display_match_list(e, matches, (size_t)len, (size_t)max, |
|
_rl_completion_append_character_function); |
|
} |
|
|
|
/* |
* complete word at current point |
* complete word at current point |
*/ |
*/ |
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
rl_complete(int ignore __attribute__((__unused__)), int invoking_key) |
rl_complete(int ignore __attribute__((__unused__)), int invoking_key) |
{ |
{ |
|
static ct_buffer_t wbreak_conv, sprefix_conv; |
|
char *breakchars; |
|
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
|
|
Line 1511 rl_complete(int ignore __attribute__((__ |
|
Line 1894 rl_complete(int ignore __attribute__((__ |
|
arr[0] = (char)invoking_key; |
arr[0] = (char)invoking_key; |
arr[1] = '\0'; |
arr[1] = '\0'; |
el_insertstr(e, arr); |
el_insertstr(e, arr); |
return (CC_REFRESH); |
return CC_REFRESH; |
} |
} |
|
|
|
if (rl_completion_word_break_hook != NULL) |
|
breakchars = (*rl_completion_word_break_hook)(); |
|
else |
|
breakchars = rl_basic_word_break_characters; |
|
|
|
_rl_update_pos(); |
|
|
/* Just look at how many global variables modify this operation! */ |
/* Just look at how many global variables modify this operation! */ |
return fn_complete(e, |
return fn_complete(e, |
(CPFunction *)rl_completion_entry_function, |
(rl_compentry_func_t *)rl_completion_entry_function, |
rl_attempted_completion_function, |
rl_attempted_completion_function, |
rl_basic_word_break_characters, rl_special_prefixes, |
ct_decode_string(rl_basic_word_break_characters, &wbreak_conv), |
_rl_completion_append_character_function, rl_completion_query_items, |
ct_decode_string(breakchars, &sprefix_conv), |
|
_rl_completion_append_character_function, |
|
(size_t)rl_completion_query_items, |
&rl_completion_type, &rl_attempted_completion_over, |
&rl_completion_type, &rl_attempted_completion_over, |
&rl_point, &rl_end); |
&rl_point, &rl_end); |
|
|
|
|
} |
} |
|
|
|
|
Line 1540 _el_rl_complete(EditLine *el __attribute |
|
Line 1934 _el_rl_complete(EditLine *el __attribute |
|
* bind key c to readline-type function func |
* bind key c to readline-type function func |
*/ |
*/ |
int |
int |
rl_bind_key(int c, int func(int, int)) |
rl_bind_key(int c, rl_command_func_t *func) |
{ |
{ |
int retval = -1; |
int retval = -1; |
|
|
Line 1552 rl_bind_key(int c, int func(int, int)) |
|
Line 1946 rl_bind_key(int c, int func(int, int)) |
|
e->el_map.key[c] = ED_INSERT; |
e->el_map.key[c] = ED_INSERT; |
retval = 0; |
retval = 0; |
} |
} |
return (retval); |
return retval; |
} |
} |
|
|
|
|
Line 1568 rl_read_key(void) |
|
Line 1962 rl_read_key(void) |
|
if (e == NULL || h == NULL) |
if (e == NULL || h == NULL) |
rl_initialize(); |
rl_initialize(); |
|
|
return (el_getc(e, fooarr)); |
return el_getc(e, fooarr); |
} |
} |
|
|
|
|
Line 1598 rl_insert(int count, int c) |
|
Line 1992 rl_insert(int count, int c) |
|
rl_initialize(); |
rl_initialize(); |
|
|
/* XXX - int -> char conversion can lose on multichars */ |
/* XXX - int -> char conversion can lose on multichars */ |
arr[0] = c; |
arr[0] = (char)c; |
arr[1] = '\0'; |
arr[1] = '\0'; |
|
|
for (; count > 0; count--) |
for (; count > 0; count--) |
el_push(e, arr); |
el_push(e, arr); |
|
|
return (0); |
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*/ |
/*ARGSUSED*/ |
int |
int |
rl_newline(int count, int c) |
rl_newline(int count __attribute__((__unused__)), |
|
int c __attribute__((__unused__))) |
{ |
{ |
/* |
/* |
* Readline-4.0 appears to ignore the args. |
* Readline-4.0 appears to ignore the args. |
Line 1619 rl_newline(int count, int c) |
|
Line 2028 rl_newline(int count, int c) |
|
|
|
/*ARGSUSED*/ |
/*ARGSUSED*/ |
static unsigned char |
static unsigned char |
rl_bind_wrapper(EditLine *el, unsigned char c) |
rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c) |
{ |
{ |
if (map[c] == NULL) |
if (map[c] == NULL) |
return CC_ERROR; |
return CC_ERROR; |
|
|
_rl_update_pos(); |
_rl_update_pos(); |
|
|
(*map[c])(NULL, c); |
(*map[c])(1, c); |
|
|
/* If rl_done was set by the above call, deal with it here */ |
/* If rl_done was set by the above call, deal with it here */ |
if (rl_done) |
if (rl_done) |
Line 1636 rl_bind_wrapper(EditLine *el, unsigned c |
|
Line 2045 rl_bind_wrapper(EditLine *el, unsigned c |
|
} |
} |
|
|
int |
int |
rl_add_defun(const char *name, Function *fun, int c) |
rl_add_defun(const char *name, rl_command_func_t *fun, int c) |
{ |
{ |
char dest[8]; |
char dest[8]; |
if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0) |
if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0) |
Line 1644 rl_add_defun(const char *name, Function |
|
Line 2053 rl_add_defun(const char *name, Function |
|
map[(unsigned char)c] = fun; |
map[(unsigned char)c] = fun; |
el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); |
el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); |
vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0); |
vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0); |
el_set(e, EL_BIND, dest, name); |
el_set(e, EL_BIND, dest, name, NULL); |
return 0; |
return 0; |
} |
} |
|
|
void |
void |
rl_callback_read_char() |
rl_callback_read_char(void) |
{ |
{ |
int count = 0, done = 0; |
int count = 0, done = 0; |
const char *buf = el_gets(e, &count); |
const char *buf = el_gets(e, &count); |
Line 1665 rl_callback_read_char() |
|
Line 2074 rl_callback_read_char() |
|
if (done && rl_linefunc != NULL) { |
if (done && rl_linefunc != NULL) { |
el_set(e, EL_UNBUFFERED, 0); |
el_set(e, EL_UNBUFFERED, 0); |
if (done == 2) { |
if (done == 2) { |
if ((wbuf = strdup(buf)) != NULL) |
if ((wbuf = strdup(buf)) != NULL) |
wbuf[count] = '\0'; |
wbuf[count] = '\0'; |
} else |
} else |
wbuf = NULL; |
wbuf = NULL; |
(*(void (*)(const char *))rl_linefunc)(wbuf); |
(*(void (*)(const char *))rl_linefunc)(wbuf); |
Line 1674 rl_callback_read_char() |
|
Line 2083 rl_callback_read_char() |
|
} |
} |
} |
} |
|
|
void |
void |
rl_callback_handler_install(const char *prompt, VCPFunction *linefunc) |
rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc) |
{ |
{ |
if (e == NULL) { |
if (e == NULL) { |
rl_initialize(); |
rl_initialize(); |
} |
} |
if (rl_prompt) |
(void)rl_set_prompt(prompt); |
free(rl_prompt); |
|
rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL; |
|
rl_linefunc = linefunc; |
rl_linefunc = linefunc; |
el_set(e, EL_UNBUFFERED, 1); |
el_set(e, EL_UNBUFFERED, 1); |
} |
} |
|
|
void |
void |
rl_callback_handler_remove(void) |
rl_callback_handler_remove(void) |
{ |
{ |
el_set(e, EL_UNBUFFERED, 0); |
|
rl_linefunc = NULL; |
rl_linefunc = NULL; |
|
el_end(e); |
|
e = NULL; |
} |
} |
|
|
void |
void |
rl_redisplay(void) |
rl_redisplay(void) |
{ |
{ |
char a[2]; |
char a[2]; |
a[0] = e->el_tty.t_c[TS_IO][C_REPRINT]; |
a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT]; |
a[1] = '\0'; |
a[1] = '\0'; |
el_push(e, a); |
el_push(e, a); |
} |
} |
|
|
rl_get_previous_history(int count, int key) |
rl_get_previous_history(int count, int key) |
{ |
{ |
char a[2]; |
char a[2]; |
a[0] = key; |
a[0] = (char)key; |
a[1] = '\0'; |
a[1] = '\0'; |
while (count--) |
while (count--) |
el_push(e, a); |
el_push(e, a); |
Line 1716 rl_get_previous_history(int count, int k |
|
Line 2124 rl_get_previous_history(int count, int k |
|
|
|
void |
void |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
rl_prep_terminal(int meta_flag) |
rl_prep_terminal(int meta_flag __attribute__((__unused__))) |
{ |
{ |
el_set(e, EL_PREP_TERM, 1); |
el_set(e, EL_PREP_TERM, 1); |
} |
} |
Line 1730 rl_deprep_terminal(void) |
|
Line 2138 rl_deprep_terminal(void) |
|
int |
int |
rl_read_init_file(const char *s) |
rl_read_init_file(const char *s) |
{ |
{ |
return(el_source(e, s)); |
return el_source(e, s); |
} |
} |
|
|
int |
int |
Line 1744 rl_parse_and_bind(const char *line) |
|
Line 2152 rl_parse_and_bind(const char *line) |
|
tok_str(tok, line, &argc, &argv); |
tok_str(tok, line, &argc, &argv); |
argc = el_parse(e, argc, argv); |
argc = el_parse(e, argc, argv); |
tok_end(tok); |
tok_end(tok); |
return (argc ? 1 : 0); |
return argc ? 1 : 0; |
} |
} |
|
|
int |
int |
Line 1754 rl_variable_bind(const char *var, const |
|
Line 2162 rl_variable_bind(const char *var, const |
|
* The proper return value is undocument, but this is what the |
* The proper return value is undocument, but this is what the |
* readline source seems to do. |
* readline source seems to do. |
*/ |
*/ |
return ((el_set(e, EL_BIND, "", var, value) == -1) ? 1 : 0); |
return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0; |
} |
} |
|
|
void |
void |
Line 1762 rl_stuff_char(int c) |
|
Line 2170 rl_stuff_char(int c) |
|
{ |
{ |
char buf[2]; |
char buf[2]; |
|
|
buf[0] = c; |
buf[0] = (char)c; |
buf[1] = '\0'; |
buf[1] = '\0'; |
el_insertstr(e, buf); |
el_insertstr(e, buf); |
} |
} |
|
|
static int |
static int |
_rl_event_read_char(EditLine *el, char *cp) |
_rl_event_read_char(EditLine *el, wchar_t *wc) |
{ |
{ |
int n, num_read = 0; |
char ch; |
|
int n; |
|
ssize_t num_read = 0; |
|
|
*cp = '\0'; |
ch = '\0'; |
|
*wc = L'\0'; |
while (rl_event_hook) { |
while (rl_event_hook) { |
|
|
(*rl_event_hook)(); |
(*rl_event_hook)(); |
|
|
#if defined(FIONREAD) |
#if defined(FIONREAD) |
if (ioctl(el->el_infd, FIONREAD, &n) < 0) |
if (ioctl(el->el_infd, FIONREAD, &n) < 0) |
return(-1); |
return -1; |
if (n) |
if (n) |
num_read = read(el->el_infd, cp, 1); |
num_read = read(el->el_infd, &ch, (size_t)1); |
else |
else |
num_read = 0; |
num_read = 0; |
#elif defined(F_SETFL) && defined(O_NDELAY) |
#elif defined(F_SETFL) && defined(O_NDELAY) |
if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0) |
if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0) |
return(-1); |
return -1; |
if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0) |
if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0) |
return(-1); |
return -1; |
num_read = read(el->el_infd, cp, 1); |
num_read = read(el->el_infd, &ch, 1); |
if (fcntl(el->el_infd, F_SETFL, n)) |
if (fcntl(el->el_infd, F_SETFL, n)) |
return(-1); |
return -1; |
#else |
#else |
/* not non-blocking, but what you gonna do? */ |
/* not non-blocking, but what you gonna do? */ |
num_read = read(el->el_infd, cp, 1); |
num_read = read(el->el_infd, &ch, 1); |
return(-1); |
return -1; |
#endif |
#endif |
|
|
if (num_read < 0 && errno == EAGAIN) |
if (num_read < 0 && errno == EAGAIN) |
Line 1806 _rl_event_read_char(EditLine *el, char * |
|
Line 2217 _rl_event_read_char(EditLine *el, char * |
|
} |
} |
if (!rl_event_hook) |
if (!rl_event_hook) |
el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); |
el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); |
return(num_read); |
*wc = (wchar_t)ch; |
|
return (int)num_read; |
} |
} |
|
|
static void |
static void |
Line 1814 _rl_update_pos(void) |
|
Line 2226 _rl_update_pos(void) |
|
{ |
{ |
const LineInfo *li = el_line(e); |
const LineInfo *li = el_line(e); |
|
|
rl_point = li->cursor - li->buffer; |
rl_point = (int)(li->cursor - li->buffer); |
rl_end = li->lastchar - li->buffer; |
rl_end = (int)(li->lastchar - li->buffer); |
} |
} |
|
|
void |
void |
rl_get_screen_size(int *rows, int *cols) |
rl_get_screen_size(int *rows, int *cols) |
{ |
{ |
if (rows) |
if (rows) |
el_get(e, EL_GETTC, "li", rows); |
el_get(e, EL_GETTC, "li", rows, (void *)0); |
if (cols) |
if (cols) |
el_get(e, EL_GETTC, "co", cols); |
el_get(e, EL_GETTC, "co", cols, (void *)0); |
} |
} |
|
|
void |
void |
Line 1832 rl_set_screen_size(int rows, int cols) |
|
Line 2244 rl_set_screen_size(int rows, int cols) |
|
{ |
{ |
char buf[64]; |
char buf[64]; |
(void)snprintf(buf, sizeof(buf), "%d", rows); |
(void)snprintf(buf, sizeof(buf), "%d", rows); |
el_set(e, EL_SETTC, "li", buf); |
el_set(e, EL_SETTC, "li", buf, NULL); |
(void)snprintf(buf, sizeof(buf), "%d", cols); |
(void)snprintf(buf, sizeof(buf), "%d", cols); |
el_set(e, EL_SETTC, "co", buf); |
el_set(e, EL_SETTC, "co", buf, NULL); |
} |
} |
|
|
char ** |
char ** |
Line 1845 rl_completion_matches(const char *str, r |
|
Line 2257 rl_completion_matches(const char *str, r |
|
|
|
len = 1; |
len = 1; |
max = 10; |
max = 10; |
if ((list = malloc(max * sizeof(*list))) == NULL) |
if ((list = el_malloc(max * sizeof(*list))) == NULL) |
return NULL; |
return NULL; |
|
|
while ((match = (*fun)(str, (int)(len - 1))) != NULL) { |
while ((match = (*fun)(str, (int)(len - 1))) != NULL) { |
|
list[len++] = match; |
if (len == max) { |
if (len == max) { |
char **nl; |
char **nl; |
max += 10; |
max += 10; |
if ((nl = realloc(list, max * sizeof(*nl))) == NULL) |
if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL) |
goto out; |
goto out; |
list = nl; |
list = nl; |
} |
} |
list[len++] = match; |
|
} |
} |
if (len == 1) |
if (len == 1) |
goto out; |
goto out; |
Line 1868 rl_completion_matches(const char *str, r |
|
Line 2280 rl_completion_matches(const char *str, r |
|
} |
} |
qsort(&list[1], len - 1, sizeof(*list), |
qsort(&list[1], len - 1, sizeof(*list), |
(int (*)(const void *, const void *)) strcmp); |
(int (*)(const void *, const void *)) strcmp); |
min = SIZE_T_MAX; |
min = SIZE_MAX; |
for (i = 1, a = list[i]; i < len - 1; i++, a = b) { |
for (i = 1, a = list[i]; i < len - 1; i++, a = b) { |
b = list[i + 1]; |
b = list[i + 1]; |
for (j = 0; a[j] && a[j] == b[j]; j++) |
for (j = 0; a[j] && a[j] == b[j]; j++) |
Line 1880 rl_completion_matches(const char *str, r |
|
Line 2292 rl_completion_matches(const char *str, r |
|
if ((list[0] = strdup(str)) == NULL) |
if ((list[0] = strdup(str)) == NULL) |
goto out; |
goto out; |
} else { |
} else { |
if ((list[0] = malloc(min + 1)) == NULL) |
if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL) |
goto out; |
goto out; |
(void)memcpy(list[0], list[1], min); |
(void)memcpy(list[0], list[1], min); |
list[0][min] = '\0'; |
list[0][min] = '\0'; |
} |
} |
return list; |
return list; |
|
|
out: |
out: |
free(list); |
el_free(list); |
return NULL; |
return NULL; |
} |
} |
|
|
Line 1918 _rl_qsort_string_compare(char **s1, char |
|
Line 2330 _rl_qsort_string_compare(char **s1, char |
|
return strcoll(*s1, *s2); |
return strcoll(*s1, *s2); |
} |
} |
|
|
|
HISTORY_STATE * |
|
history_get_history_state(void) |
|
{ |
|
HISTORY_STATE *hs; |
|
|
|
if ((hs = el_malloc(sizeof(*hs))) == NULL) |
|
return NULL; |
|
hs->length = history_length; |
|
return hs; |
|
} |
|
|
int |
int |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
rl_kill_text(int from, int to) |
rl_kill_text(int from __attribute__((__unused__)), |
|
int to __attribute__((__unused__))) |
{ |
{ |
return 0; |
return 0; |
} |
} |
Line 1939 rl_get_keymap(void) |
|
Line 2363 rl_get_keymap(void) |
|
|
|
void |
void |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
rl_set_keymap(Keymap k) |
rl_set_keymap(Keymap k __attribute__((__unused__))) |
|
{ |
|
} |
|
|
|
int |
|
/*ARGSUSED*/ |
|
rl_generic_bind(int type __attribute__((__unused__)), |
|
const char * keyseq __attribute__((__unused__)), |
|
const char * data __attribute__((__unused__)), |
|
Keymap k __attribute__((__unused__))) |
{ |
{ |
|
return 0; |
} |
} |
|
|
int |
int |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k) |
rl_bind_key_in_map(int key __attribute__((__unused__)), |
|
rl_command_func_t *fun __attribute__((__unused__)), |
|
Keymap k __attribute__((__unused__))) |
|
{ |
|
return 0; |
|
} |
|
|
|
/* unsupported, but needed by python */ |
|
void |
|
rl_cleanup_after_signal(void) |
|
{ |
|
} |
|
|
|
int |
|
rl_on_new_line(void) |
{ |
{ |
return 0; |
return 0; |
} |
} |
|
|
|
void |
|
rl_free_line_state(void) |
|
{ |
|
} |
|
|
int |
int |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
rl_bind_key_in_map(int key, Function *fun, Keymap k) |
rl_set_keyboard_input_timeout(int u __attribute__((__unused__))) |
{ |
{ |
return 0; |
return 0; |
} |
} |
|
|
|
void |
|
rl_resize_terminal(void) |
|
{ |
|
el_resize(e); |
|
} |