version 1.123, 2016/02/16 15:53:48 |
version 1.134, 2016/05/31 19:25:17 |
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 <stdint.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> |
|
#include <stdint.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <unistd.h> |
#include <vis.h> |
#include <vis.h> |
|
|
#include "readline/readline.h" |
#include "readline/readline.h" |
#include "el.h" |
#include "el.h" |
#include "fcns.h" /* for EL_NUM_FCNS */ |
#include "fcns.h" |
#include "filecomplete.h" |
#include "filecomplete.h" |
|
|
void rl_prep_terminal(int); |
void rl_prep_terminal(int); |
Line 156 char *rl_special_prefixes = NULL; |
|
Line 156 char *rl_special_prefixes = NULL; |
|
*/ |
*/ |
int rl_completion_append_character = ' '; |
int rl_completion_append_character = ' '; |
|
|
|
/* |
|
* When the history cursor is on the newest element and next_history() |
|
* is called, GNU readline moves the cursor beyond the newest element. |
|
* The editline library does not provide data structures to express |
|
* that state, so we need a local flag. |
|
*/ |
|
static int current_history_valid = 1; |
|
|
/* stuff below is used internally by libedit for readline emulation */ |
/* stuff below is used internally by libedit for readline emulation */ |
|
|
static History *h = NULL; |
static History *h = NULL; |
Line 167 static jmp_buf topbuf; |
|
Line 175 static jmp_buf topbuf; |
|
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 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); |
|
|
|
|
Line 210 _move_history(int op) |
|
Line 218 _move_history(int op) |
|
*/ |
*/ |
static int |
static int |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
_getc_function(EditLine *el __attribute__((__unused__)), char *c) |
_getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c) |
{ |
{ |
int i; |
int i; |
|
|
i = (*rl_getc_function)(NULL); |
i = (*rl_getc_function)(NULL); |
if (i == -1) |
if (i == -1) |
return 0; |
return 0; |
*c = (char)i; |
*c = (wchar_t)i; |
return 1; |
return 1; |
} |
} |
|
|
Line 267 rl_set_prompt(const char *prompt) |
|
Line 275 rl_set_prompt(const char *prompt) |
|
|
|
if (!prompt) |
if (!prompt) |
prompt = ""; |
prompt = ""; |
if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) |
if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) |
return 0; |
return 0; |
if (rl_prompt) |
if (rl_prompt) |
el_free(rl_prompt); |
el_free(rl_prompt); |
Line 291 rl_initialize(void) |
|
Line 299 rl_initialize(void) |
|
int editmode = 1; |
int editmode = 1; |
struct termios t; |
struct termios t; |
|
|
|
current_history_valid = 1; |
|
|
if (e != NULL) |
if (e != NULL) |
el_end(e); |
el_end(e); |
if (h != NULL) |
if (h != NULL) |
Line 361 rl_initialize(void) |
|
Line 371 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. |
* Set some readline compatible key-bindings. |
*/ |
*/ |
|
|
stifle_history(int max) |
stifle_history(int max) |
{ |
{ |
HistEvent ev; |
HistEvent ev; |
|
HIST_ENTRY *he; |
|
int i, len; |
|
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
rl_initialize(); |
rl_initialize(); |
|
|
if (history(h, &ev, H_SETSIZE, max) == 0) |
len = history_length; |
|
if (history(h, &ev, H_SETSIZE, max) == 0) { |
max_input_history = max; |
max_input_history = max; |
|
if (max < len) |
|
history_base += len - max; |
|
for (i = 0; i < len - max; i++) { |
|
he = remove_history(0); |
|
el_free(he->data); |
|
el_free((void *)(unsigned long)he->line); |
|
el_free(he); |
|
} |
|
} |
} |
} |
|
|
|
|
Line 1388 history_get(int num) |
|
Line 1410 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 the oldest */ |
/* |
if (history(h, &ev, H_LAST) != 0) |
* use H_DELDATA to set to nth history (without delete) by passing |
return NULL; /* error */ |
* (void **)-1 -- as in history_set_pos |
|
*/ |
/* look forwards for event matching specified offset */ |
if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0) |
if (history(h, &ev, H_NEXT_EVDATA, num, &she.data)) |
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; |
|
|
/* 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 1427 add_history(const char *line) |
|
Line 1461 add_history(const char *line) |
|
(void)history(h, &ev, H_ENTER, line); |
(void)history(h, &ev, H_ENTER, line); |
if (history(h, &ev, H_GETSIZE) == 0) |
if (history(h, &ev, H_GETSIZE) == 0) |
history_length = ev.num; |
history_length = ev.num; |
|
current_history_valid = 1; |
|
|
return !(history_length > 0); /* return 0 if all is okay */ |
return !(history_length > 0); /* return 0 if all is okay */ |
} |
} |
Line 1519 clear_history(void) |
|
Line 1554 clear_history(void) |
|
|
|
(void)history(h, &ev, H_CLEAR); |
(void)history(h, &ev, H_CLEAR); |
history_length = 0; |
history_length = 0; |
|
current_history_valid = 1; |
} |
} |
|
|
|
|
Line 1535 where_history(void) |
|
Line 1571 where_history(void) |
|
return 0; |
return 0; |
curr_num = ev.num; |
curr_num = ev.num; |
|
|
(void)history(h, &ev, H_FIRST); |
/* start from the oldest */ |
off = 1; |
(void)history(h, &ev, H_LAST); |
while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) |
|
|
/* position is zero-based */ |
|
off = 0; |
|
while (ev.num != curr_num && history(h, &ev, H_PREV) == 0) |
off++; |
off++; |
|
|
return off; |
return off; |
|
|
current_history(void) |
current_history(void) |
{ |
{ |
|
|
return _move_history(H_CURR); |
return current_history_valid ? _move_history(H_CURR) : NULL; |
} |
} |
|
|
|
|
Line 1592 history_set_pos(int pos) |
|
Line 1631 history_set_pos(int pos) |
|
int curr_num; |
int curr_num; |
|
|
if (pos >= history_length || pos < 0) |
if (pos >= history_length || pos < 0) |
return -1; |
return 0; |
|
|
(void)history(h, &ev, H_CURR); |
(void)history(h, &ev, H_CURR); |
curr_num = ev.num; |
curr_num = ev.num; |
|
current_history_valid = 1; |
|
|
/* |
/* |
* use H_DELDATA to set to nth history (without delete) by passing |
* use H_DELDATA to set to nth history (without delete) by passing |
Line 1603 history_set_pos(int pos) |
|
Line 1643 history_set_pos(int pos) |
|
*/ |
*/ |
if (history(h, &ev, H_DELDATA, pos, (void **)-1)) { |
if (history(h, &ev, H_DELDATA, pos, (void **)-1)) { |
(void)history(h, &ev, H_SET, curr_num); |
(void)history(h, &ev, H_SET, curr_num); |
return -1; |
return 0; |
} |
} |
return 0; |
return 1; |
} |
} |
|
|
|
|
/* |
/* |
* 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) |
{ |
{ |
|
|
return _move_history(H_PREV); |
if (current_history_valid == 0) { |
|
current_history_valid = 1; |
|
return _move_history(H_CURR); |
|
} |
|
return _move_history(H_NEXT); |
} |
} |
|
|
|
|
Line 1626 previous_history(void) |
|
Line 1671 previous_history(void) |
|
HIST_ENTRY * |
HIST_ENTRY * |
next_history(void) |
next_history(void) |
{ |
{ |
|
HIST_ENTRY *he; |
|
|
return _move_history(H_NEXT); |
he = _move_history(H_PREV); |
|
if (he == NULL) |
|
current_history_valid = 0; |
|
return he; |
} |
} |
|
|
|
|
Line 1688 history_search_pos(const char *str, |
|
Line 1737 history_search_pos(const char *str, |
|
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 (;;) { |
Line 1806 _rl_completion_append_character_function |
|
Line 1855 _rl_completion_append_character_function |
|
int |
int |
rl_complete(int ignore __attribute__((__unused__)), int invoking_key) |
rl_complete(int ignore __attribute__((__unused__)), int invoking_key) |
{ |
{ |
#ifdef WIDECHAR |
|
static ct_buffer_t wbreak_conv, sprefix_conv; |
static ct_buffer_t wbreak_conv, sprefix_conv; |
#endif |
|
char *breakchars; |
char *breakchars; |
|
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
Line 2008 rl_callback_read_char(void) |
|
Line 2055 rl_callback_read_char(void) |
|
} |
} |
} |
} |
|
|
void |
void |
rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc) |
rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc) |
{ |
{ |
if (e == NULL) { |
if (e == NULL) { |
Line 2017 rl_callback_handler_install(const char * |
|
Line 2064 rl_callback_handler_install(const char * |
|
(void)rl_set_prompt(prompt); |
(void)rl_set_prompt(prompt); |
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); |
el_set(e, EL_UNBUFFERED, 0); |
Line 2100 rl_stuff_char(int c) |
|
Line 2147 rl_stuff_char(int c) |
|
} |
} |
|
|
static int |
static int |
_rl_event_read_char(EditLine *el, char *cp) |
_rl_event_read_char(EditLine *el, wchar_t *wc) |
{ |
{ |
|
char ch; |
int n; |
int n; |
ssize_t num_read = 0; |
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)(); |
Line 2114 _rl_event_read_char(EditLine *el, char * |
|
Line 2163 _rl_event_read_char(EditLine *el, char * |
|
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, (size_t)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) |
Line 2122 _rl_event_read_char(EditLine *el, char * |
|
Line 2171 _rl_event_read_char(EditLine *el, char * |
|
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 |
|
|
Line 2139 _rl_event_read_char(EditLine *el, char * |
|
Line 2188 _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); |
|
*wc = (wchar_t)ch; |
return (int)num_read; |
return (int)num_read; |
} |
} |
|
|
Line 2219 rl_completion_matches(const char *str, r |
|
Line 2269 rl_completion_matches(const char *str, r |
|
list[0][min] = '\0'; |
list[0][min] = '\0'; |
} |
} |
return list; |
return list; |
|
|
out: |
out: |
el_free(list); |
el_free(list); |
return NULL; |
return NULL; |