diff options
Diffstat (limited to 'readline.c')
| -rw-r--r-- | readline.c | 628 | 
1 files changed, 484 insertions, 144 deletions
diff --git a/readline.c b/readline.c index e4a3f07b95a69..a0a390cc61f14 100644 --- a/readline.c +++ b/readline.c @@ -1,4 +1,4 @@ -/*	$NetBSD: readline.c,v 1.70 2006/11/24 00:01:17 christos Exp $	*/ +/*	$NetBSD: readline.c,v 1.89 2010/04/15 00:57:33 christos Exp $	*/  /*-   * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,9 +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. 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 @@ -34,7 +31,7 @@  #include "config.h"  #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.70 2006/11/24 00:01:17 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.89 2010/04/15 00:57:33 christos Exp $");  #endif /* not lint && not SCCSID */  #include <sys/types.h> @@ -55,13 +52,10 @@ __RCSID("$NetBSD: readline.c,v 1.70 2006/11/24 00:01:17 christos Exp $");  #else  #include "np/vis.h"  #endif -#ifdef HAVE_ALLOCA_H -#include <alloca.h> -#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); @@ -76,6 +70,7 @@ void rl_deprep_terminal(void);  /* 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', '"', '\\', '\'', '`', '@', '$', @@ -111,7 +106,7 @@ Function *rl_completion_entry_function = NULL;  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; @@ -124,6 +119,11 @@ Function *rl_startup_hook = NULL;  VFunction *rl_completion_display_matches_hook = NULL;  VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;  VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; +KEYMAP_ENTRY_ARRAY emacs_meta_keymap; + +#ifdef WIDECHAR +static ct_buffer_t conv; +#endif  /*   * The current prompt string. @@ -157,7 +157,7 @@ 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; @@ -191,13 +191,13 @@ _get_prompt(EditLine *el __attribute__((__unused__)))  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); @@ -213,25 +213,65 @@ _getc_function(EditLine *el, char *c)  {  	int i; -	i = (*rl_getc_function)(NULL, 0); +	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; @@ -239,7 +279,7 @@ rl_initialize(void)  	if (e != NULL)  		el_end(e);  	if (h != NULL) -		history_end(h); +		FUN(history,end)(h);  	if (!rl_instream)  		rl_instream = stdin; @@ -255,13 +295,13 @@ rl_initialize(void)  	e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);  	if (!editmode) -		el_set(e, EL_EDITMODE, 0); +		FUN(el,set)(e, EL_EDITMODE, 0); -	h = history_init(); +	h = FUN(history,init)();  	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); @@ -271,13 +311,12 @@ rl_initialize(void)  		el_set(e, EL_GETCFN, _getc_function);  	/* for proper prompt printing in readline() */ -	rl_prompt = strdup(""); -	if (rl_prompt == NULL) { -		history_end(h); +	if (rl_set_prompt("") == -1) { +		FUN(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 */ @@ -331,7 +370,7 @@ rl_initialize(void)  char *  readline(const char *p)  { -	HistEvent ev; +	TYPE(HistEvent) ev;  	const char * volatile prompt = p;  	int count;  	const char *ret; @@ -346,14 +385,8 @@ readline(const char *p)  	(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); @@ -385,7 +418,7 @@ readline(const char *p)  	} else  		buf = NULL; -	history(h, &ev, H_GETSIZE); +	FUNW(history)(h, &ev, H_GETSIZE);  	history_length = ev.num;  	return buf; @@ -451,7 +484,7 @@ _rl_compat_sub(const char *str, const char *what, const char *with,  		} else  			*r++ = *s++;  	} -	*r = 0; +	*r = '\0';  	return(result);  } @@ -465,18 +498,18 @@ get_history_event(const char *cmd, int *cindex, int qchar)  	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] == '-') { @@ -531,7 +564,7 @@ get_history_event(const char *cmd, int *cindex, int qchar)  		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); @@ -550,7 +583,7 @@ get_history_event(const char *cmd, int *cindex, int qchar)  	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); @@ -566,13 +599,13 @@ get_history_event(const char *cmd, int *cindex, int qchar)  	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;  } @@ -637,9 +670,11 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,  		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);  	} @@ -694,7 +729,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,  	if (aptr)  		free(aptr); -	if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) { +	if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {  		*result = tmp;  		return(1);  	} @@ -704,7 +739,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,  			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); @@ -713,7 +748,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,  			}  		} 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); @@ -966,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;  }  /* @@ -1080,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;  } @@ -1096,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 */ @@ -1114,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 @@ -1121,11 +1292,14 @@ 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) == -1); +	if (filename == NULL && (filename = _default_history_file()) == NULL) +		return errno; +	return (FUNW(history)(h, &ev, H_LOAD, filename) == -1 ? +	    (errno ? errno : EINVAL) : 0);  } @@ -1135,11 +1309,14 @@ 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) == -1); +	if (filename == NULL && (filename = _default_history_file()) == NULL) +		return errno; +	return (FUNW(history)(h, &ev, H_SAVE, filename) == -1 ? +	    (errno ? errno : EINVAL) : 0);  } @@ -1152,30 +1329,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);  } @@ -1187,13 +1363,16 @@ history_get(int num)  int  add_history(const char *line)  { -	HistEvent ev; +	TYPE(HistEvent) ev; +	const Char *wline;  	if (h == NULL || e == NULL)  		rl_initialize(); -	(void)history(h, &ev, H_ENTER, line); -	if (history(h, &ev, H_GETSIZE) == 0) +	wline = ct_decode_string(line, &conv); + +	(void)FUNW(history)(h, &ev, H_ENTER, wline); +	if (FUNW(history)(h, &ev, H_GETSIZE) == 0)  		history_length = ev.num;  	return (!(history_length > 0)); /* return 0 if all is okay */ @@ -1206,31 +1385,84 @@ add_history(const char *line)  HIST_ENTRY *  remove_history(int num)  { -	static HIST_ENTRY she; -	HistEvent ev; +	HIST_ENTRY *he; +	TYPE(HistEvent) ev;  	if (h == NULL || e == NULL)  		rl_initialize(); -	if (history(h, &ev, H_DEL, num) != 0) +	if ((he = malloc(sizeof(*he))) == NULL)  		return NULL; -	she.line = ev.str; -	she.data = NULL; +	if (FUNW(history)(h, &ev, H_DELDATA, num, &he->data) != 0) { +		free(he); +		return NULL; +	} -	return &she; +	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); +	(void)FUNW(history)(h, &ev, H_CLEAR); +	history_length = 0;  } @@ -1240,16 +1472,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); +	(void)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); @@ -1273,23 +1505,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); +	(void)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);  } @@ -1299,17 +1532,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); +	(void)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)) { +		(void)FUNW(history)(h, &ev, H_SET, curr_num);  		return(-1);  	}  	return (0); @@ -1344,21 +1581,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); +	(void)FUNW(history)(h, &ev, H_SET, curr_num);  	return (-1);  } @@ -1369,9 +1608,10 @@ history_search(const char *str, int direction)  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));  } @@ -1384,29 +1624,31 @@ 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); +	(void)FUNW(history)(h, &ev, +	    pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);  	return (-1);  } @@ -1455,9 +1697,9 @@ username_completion_function(const char *text, int state)  	if (pwd == NULL) {  		endpwent(); -		return (NULL); +		return NULL;  	} -	return (strdup(pwd->pw_name)); +	return strdup(pwd->pw_name);  } @@ -1481,7 +1723,7 @@ 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 * @@ -1490,7 +1732,8 @@ _rl_completion_append_character_function(const char *dummy      __attribute__((__unused__)))  {  	static char buf[2]; -	buf[1] = rl_completion_append_character; +	buf[0] = rl_completion_append_character; +	buf[1] = '\0';  	return buf;  } @@ -1502,6 +1745,10 @@ _rl_completion_append_character_function(const char *dummy  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(); @@ -1517,8 +1764,10 @@ rl_complete(int ignore __attribute__((__unused__)), int invoking_key)  	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_function, 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);  } @@ -1539,7 +1788,7 @@ _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)   * 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; @@ -1606,6 +1855,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) @@ -1638,7 +1901,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); @@ -1669,19 +1932,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);  }    @@ -1690,6 +1951,7 @@ void  rl_callback_handler_remove(void)  {  	el_set(e, EL_UNBUFFERED, 0); +	rl_linefunc = NULL;  }  void @@ -1768,9 +2030,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)(); @@ -1804,7 +2067,7 @@ _rl_event_read_char(EditLine *el, char *cp)  	}  	if (!rl_event_hook)  		el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); -	return(num_read); +	return (int)num_read;  }  static void @@ -1812,8 +2075,8 @@ _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 @@ -1835,12 +2098,73 @@ rl_set_screen_size(int rows, int 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)  { @@ -1855,6 +2179,17 @@ _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) @@ -1889,8 +2224,13 @@ rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k)  int  /*ARGSUSED*/ -rl_bind_key_in_map(int key, Function *fun, Keymap k) +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) +{ +}  | 
