xref: /dflybsd-src/contrib/libedit/src/readline.c (revision 698e9e6cd5f042847de67460caaa3fde98cdfe99)
1*cdf8408cSAntonio Huete Jimenez /*	$NetBSD: readline.c,v 1.176 2022/09/21 01:33:53 christos Exp $	*/
232fe07f8SJohn Marino 
332fe07f8SJohn Marino /*-
432fe07f8SJohn Marino  * Copyright (c) 1997 The NetBSD Foundation, Inc.
532fe07f8SJohn Marino  * All rights reserved.
632fe07f8SJohn Marino  *
732fe07f8SJohn Marino  * This code is derived from software contributed to The NetBSD Foundation
832fe07f8SJohn Marino  * by Jaromir Dolecek.
932fe07f8SJohn Marino  *
1032fe07f8SJohn Marino  * Redistribution and use in source and binary forms, with or without
1132fe07f8SJohn Marino  * modification, are permitted provided that the following conditions
1232fe07f8SJohn Marino  * are met:
1332fe07f8SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1432fe07f8SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1532fe07f8SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1632fe07f8SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1732fe07f8SJohn Marino  *    documentation and/or other materials provided with the distribution.
1832fe07f8SJohn Marino  *
1932fe07f8SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2032fe07f8SJohn Marino  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2132fe07f8SJohn Marino  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2232fe07f8SJohn Marino  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2332fe07f8SJohn Marino  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2432fe07f8SJohn Marino  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2532fe07f8SJohn Marino  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2632fe07f8SJohn Marino  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2732fe07f8SJohn Marino  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2832fe07f8SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2932fe07f8SJohn Marino  * POSSIBILITY OF SUCH DAMAGE.
3032fe07f8SJohn Marino  */
3132fe07f8SJohn Marino 
3232fe07f8SJohn Marino #include "config.h"
3332fe07f8SJohn Marino #if !defined(lint) && !defined(SCCSID)
34*cdf8408cSAntonio Huete Jimenez __RCSID("$NetBSD: readline.c,v 1.176 2022/09/21 01:33:53 christos Exp $");
3532fe07f8SJohn Marino #endif /* not lint && not SCCSID */
3632fe07f8SJohn Marino 
3732fe07f8SJohn Marino #include <sys/types.h>
3832fe07f8SJohn Marino #include <sys/stat.h>
3932fe07f8SJohn Marino #include <ctype.h>
4012db70c8Szrj #include <dirent.h>
4132fe07f8SJohn Marino #include <errno.h>
4232fe07f8SJohn Marino #include <fcntl.h>
4312db70c8Szrj #include <limits.h>
4412db70c8Szrj #include <pwd.h>
4532fe07f8SJohn Marino #include <setjmp.h>
46*cdf8408cSAntonio Huete Jimenez #include <stdarg.h>
4712db70c8Szrj #include <stdint.h>
4812db70c8Szrj #include <stdio.h>
4912db70c8Szrj #include <stdlib.h>
5012db70c8Szrj #include <string.h>
5112db70c8Szrj #include <unistd.h>
5232fe07f8SJohn Marino #include <vis.h>
5332fe07f8SJohn Marino 
5432fe07f8SJohn Marino #include "editline/readline.h"
5532fe07f8SJohn Marino #include "el.h"
5612db70c8Szrj #include "fcns.h"
5732fe07f8SJohn Marino #include "filecomplete.h"
5832fe07f8SJohn Marino 
5932fe07f8SJohn Marino #if !defined(SIZE_T_MAX)
6032fe07f8SJohn Marino # define SIZE_T_MAX (size_t)(-1)
6132fe07f8SJohn Marino #endif
6232fe07f8SJohn Marino 
6332fe07f8SJohn Marino void rl_prep_terminal(int);
6432fe07f8SJohn Marino void rl_deprep_terminal(void);
6532fe07f8SJohn Marino 
6632fe07f8SJohn Marino /* for rl_complete() */
6732fe07f8SJohn Marino #define TAB		'\r'
6832fe07f8SJohn Marino 
6932fe07f8SJohn Marino /* see comment at the #ifdef for sense of this */
7032fe07f8SJohn Marino /* #define GDB_411_HACK */
7132fe07f8SJohn Marino 
7232fe07f8SJohn Marino /* readline compatibility stuff - look at readline sources/documentation */
7332fe07f8SJohn Marino /* to see what these variables mean */
7432fe07f8SJohn Marino const char *rl_library_version = "EditLine wrapper";
7532fe07f8SJohn Marino int rl_readline_version = RL_READLINE_VERSION;
7632fe07f8SJohn Marino static char empty[] = { '\0' };
7732fe07f8SJohn Marino static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
7832fe07f8SJohn Marino static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
7932fe07f8SJohn Marino     '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
80ae19eda8Szrj const char *rl_readline_name = empty;
8132fe07f8SJohn Marino FILE *rl_instream = NULL;
8232fe07f8SJohn Marino FILE *rl_outstream = NULL;
8332fe07f8SJohn Marino int rl_point = 0;
8432fe07f8SJohn Marino int rl_end = 0;
8532fe07f8SJohn Marino char *rl_line_buffer = NULL;
8612db70c8Szrj rl_vcpfunc_t *rl_linefunc = NULL;
8732fe07f8SJohn Marino int rl_done = 0;
88ae19eda8Szrj rl_hook_func_t *rl_event_hook = NULL;
8932fe07f8SJohn Marino KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
9032fe07f8SJohn Marino     emacs_meta_keymap,
9132fe07f8SJohn Marino     emacs_ctlx_keymap;
9284b940c1SJohn Marino /*
9384b940c1SJohn Marino  * The following is not implemented; we always catch signals in the
9484b940c1SJohn Marino  * libedit fashion: set handlers on entry to el_gets() and clear them
9584b940c1SJohn Marino  * on the way out. This simplistic approach works for most cases; if
9684b940c1SJohn Marino  * it does not work for your application, please let us know.
9784b940c1SJohn Marino  */
9884b940c1SJohn Marino int rl_catch_signals = 1;
9984b940c1SJohn Marino int rl_catch_sigwinch = 1;
10032fe07f8SJohn Marino 
10132fe07f8SJohn Marino int history_base = 1;		/* probably never subject to change */
10232fe07f8SJohn Marino int history_length = 0;
10312db70c8Szrj int history_offset = 0;
10432fe07f8SJohn Marino int max_input_history = 0;
10532fe07f8SJohn Marino char history_expansion_char = '!';
10632fe07f8SJohn Marino char history_subst_char = '^';
10732fe07f8SJohn Marino char *history_no_expand_chars = expand_chars;
10832fe07f8SJohn Marino Function *history_inhibit_expansion_function = NULL;
10932fe07f8SJohn Marino char *history_arg_extract(int start, int end, const char *str);
11032fe07f8SJohn Marino 
11132fe07f8SJohn Marino int rl_inhibit_completion = 0;
11232fe07f8SJohn Marino int rl_attempted_completion_over = 0;
113ae19eda8Szrj const char *rl_basic_word_break_characters = break_chars;
11432fe07f8SJohn Marino char *rl_completer_word_break_characters = NULL;
11560ecde0cSDaniel Fojt const char *rl_completer_quote_characters = NULL;
116*cdf8408cSAntonio Huete Jimenez const char *rl_basic_quote_characters = "\"'";
11712db70c8Szrj rl_compentry_func_t *rl_completion_entry_function = NULL;
118c8e4d2bfSJohn Marino char *(*rl_completion_word_break_hook)(void) = NULL;
11912db70c8Szrj rl_completion_func_t *rl_attempted_completion_function = NULL;
120*cdf8408cSAntonio Huete Jimenez rl_hook_func_t *rl_pre_input_hook = NULL;
121*cdf8408cSAntonio Huete Jimenez rl_hook_func_t *rl_startup1_hook = NULL;
12232fe07f8SJohn Marino int (*rl_getc_function)(FILE *) = NULL;
12332fe07f8SJohn Marino char *rl_terminal_name = NULL;
12432fe07f8SJohn Marino int rl_already_prompted = 0;
12532fe07f8SJohn Marino int rl_filename_completion_desired = 0;
12632fe07f8SJohn Marino int rl_ignore_completion_duplicates = 0;
12732fe07f8SJohn Marino int readline_echoing_p = 1;
12832fe07f8SJohn Marino int _rl_print_completions_horizontally = 0;
12932fe07f8SJohn Marino VFunction *rl_redisplay_function = NULL;
130*cdf8408cSAntonio Huete Jimenez rl_hook_func_t *rl_startup_hook = NULL;
13132fe07f8SJohn Marino VFunction *rl_completion_display_matches_hook = NULL;
13232fe07f8SJohn Marino VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
13332fe07f8SJohn Marino VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
13432fe07f8SJohn Marino KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
135*cdf8408cSAntonio Huete Jimenez unsigned long rl_readline_state = RL_STATE_NONE;
136*cdf8408cSAntonio Huete Jimenez int _rl_complete_mark_directories;
137*cdf8408cSAntonio Huete Jimenez rl_icppfunc_t *rl_directory_completion_hook;
138*cdf8408cSAntonio Huete Jimenez int rl_completion_suppress_append;
139*cdf8408cSAntonio Huete Jimenez int rl_sort_completion_matches;
140*cdf8408cSAntonio Huete Jimenez int _rl_completion_prefix_display_length;
141*cdf8408cSAntonio Huete Jimenez int _rl_echoing_p;
142*cdf8408cSAntonio Huete Jimenez int history_max_entries;
143*cdf8408cSAntonio Huete Jimenez char *rl_display_prompt;
144*cdf8408cSAntonio Huete Jimenez int rl_erase_empty_line;
14532fe07f8SJohn Marino 
14632fe07f8SJohn Marino /*
14732fe07f8SJohn Marino  * The current prompt string.
14832fe07f8SJohn Marino  */
14932fe07f8SJohn Marino char *rl_prompt = NULL;
150*cdf8408cSAntonio Huete Jimenez char *rl_prompt_saved = NULL;
15132fe07f8SJohn Marino /*
15232fe07f8SJohn Marino  * This is set to character indicating type of completion being done by
15332fe07f8SJohn Marino  * rl_complete_internal(); this is available for application completion
15432fe07f8SJohn Marino  * functions.
15532fe07f8SJohn Marino  */
15632fe07f8SJohn Marino int rl_completion_type = 0;
15732fe07f8SJohn Marino 
15832fe07f8SJohn Marino /*
15932fe07f8SJohn Marino  * If more than this number of items results from query for possible
16032fe07f8SJohn Marino  * completions, we ask user if they are sure to really display the list.
16132fe07f8SJohn Marino  */
16232fe07f8SJohn Marino int rl_completion_query_items = 100;
16332fe07f8SJohn Marino 
16432fe07f8SJohn Marino /*
16532fe07f8SJohn Marino  * List of characters which are word break characters, but should be left
16632fe07f8SJohn Marino  * in the parsed text when it is passed to the completion function.
16732fe07f8SJohn Marino  * Shell uses this to help determine what kind of completing to do.
16832fe07f8SJohn Marino  */
169ae19eda8Szrj const char *rl_special_prefixes = NULL;
17032fe07f8SJohn Marino 
17132fe07f8SJohn Marino /*
17232fe07f8SJohn Marino  * This is the character appended to the completed words if at the end of
17332fe07f8SJohn Marino  * the line. Default is ' ' (a space).
17432fe07f8SJohn Marino  */
17532fe07f8SJohn Marino int rl_completion_append_character = ' ';
17632fe07f8SJohn Marino 
17732fe07f8SJohn Marino /* stuff below is used internally by libedit for readline emulation */
17832fe07f8SJohn Marino 
17932fe07f8SJohn Marino static History *h = NULL;
18032fe07f8SJohn Marino static EditLine *e = NULL;
18112db70c8Szrj static rl_command_func_t *map[256];
18232fe07f8SJohn Marino static jmp_buf topbuf;
18332fe07f8SJohn Marino 
18432fe07f8SJohn Marino /* internal functions */
18532fe07f8SJohn Marino static unsigned char	 _el_rl_complete(EditLine *, int);
18632fe07f8SJohn Marino static unsigned char	 _el_rl_tstp(EditLine *, int);
18732fe07f8SJohn Marino static char		*_get_prompt(EditLine *);
18812db70c8Szrj static int		 _getc_function(EditLine *, wchar_t *);
18932fe07f8SJohn Marino static int		 _history_expand_command(const char *, size_t, size_t,
19032fe07f8SJohn Marino     char **);
19132fe07f8SJohn Marino static char		*_rl_compat_sub(const char *, const char *,
19232fe07f8SJohn Marino     const char *, int);
19312db70c8Szrj static int		 _rl_event_read_char(EditLine *, wchar_t *);
19432fe07f8SJohn Marino static void		 _rl_update_pos(void);
19532fe07f8SJohn Marino 
19612db70c8Szrj static HIST_ENTRY rl_he;
19732fe07f8SJohn Marino 
19832fe07f8SJohn Marino /* ARGSUSED */
19932fe07f8SJohn Marino static char *
_get_prompt(EditLine * el)20032fe07f8SJohn Marino _get_prompt(EditLine *el __attribute__((__unused__)))
20132fe07f8SJohn Marino {
20232fe07f8SJohn Marino 	rl_already_prompted = 1;
20332fe07f8SJohn Marino 	return rl_prompt;
20432fe07f8SJohn Marino }
20532fe07f8SJohn Marino 
20632fe07f8SJohn Marino 
20732fe07f8SJohn Marino /*
20832fe07f8SJohn Marino  * read one key from user defined input function
20932fe07f8SJohn Marino  */
21032fe07f8SJohn Marino static int
21132fe07f8SJohn Marino /*ARGSUSED*/
_getc_function(EditLine * el,wchar_t * c)21212db70c8Szrj _getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c)
21332fe07f8SJohn Marino {
21432fe07f8SJohn Marino 	int i;
21532fe07f8SJohn Marino 
21612db70c8Szrj 	i = (*rl_getc_function)(rl_instream);
21732fe07f8SJohn Marino 	if (i == -1)
21832fe07f8SJohn Marino 		return 0;
21912db70c8Szrj 	*c = (wchar_t)i;
22032fe07f8SJohn Marino 	return 1;
22132fe07f8SJohn Marino }
22232fe07f8SJohn Marino 
22332fe07f8SJohn Marino static void
_resize_fun(EditLine * el,void * a)22432fe07f8SJohn Marino _resize_fun(EditLine *el, void *a)
22532fe07f8SJohn Marino {
22632fe07f8SJohn Marino 	const LineInfo *li;
227*cdf8408cSAntonio Huete Jimenez 	const char **ap = a;
22832fe07f8SJohn Marino 
22932fe07f8SJohn Marino 	li = el_line(el);
230*cdf8408cSAntonio Huete Jimenez 	*ap = li->buffer;
23132fe07f8SJohn Marino }
23232fe07f8SJohn Marino 
23332fe07f8SJohn Marino static const char *
_default_history_file(void)23432fe07f8SJohn Marino _default_history_file(void)
23532fe07f8SJohn Marino {
23632fe07f8SJohn Marino 	struct passwd *p;
23784b940c1SJohn Marino 	static char *path;
23884b940c1SJohn Marino 	size_t len;
23932fe07f8SJohn Marino 
24084b940c1SJohn Marino 	if (path)
24132fe07f8SJohn Marino 		return path;
24284b940c1SJohn Marino 
24332fe07f8SJohn Marino 	if ((p = getpwuid(getuid())) == NULL)
24432fe07f8SJohn Marino 		return NULL;
24584b940c1SJohn Marino 
24684b940c1SJohn Marino 	len = strlen(p->pw_dir) + sizeof("/.history");
24784b940c1SJohn Marino 	if ((path = malloc(len)) == NULL)
24884b940c1SJohn Marino 		return NULL;
24984b940c1SJohn Marino 
25084b940c1SJohn Marino 	(void)snprintf(path, len, "%s/.history", p->pw_dir);
25132fe07f8SJohn Marino 	return path;
25232fe07f8SJohn Marino }
25332fe07f8SJohn Marino 
25432fe07f8SJohn Marino /*
25532fe07f8SJohn Marino  * READLINE compatibility stuff
25632fe07f8SJohn Marino  */
25732fe07f8SJohn Marino 
25832fe07f8SJohn Marino /*
25932fe07f8SJohn Marino  * Set the prompt
26032fe07f8SJohn Marino  */
26132fe07f8SJohn Marino int
rl_set_prompt(const char * prompt)26232fe07f8SJohn Marino rl_set_prompt(const char *prompt)
26332fe07f8SJohn Marino {
26432fe07f8SJohn Marino 	char *p;
26532fe07f8SJohn Marino 
26632fe07f8SJohn Marino 	if (!prompt)
26732fe07f8SJohn Marino 		prompt = "";
26832fe07f8SJohn Marino 	if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
26932fe07f8SJohn Marino 		return 0;
27032fe07f8SJohn Marino 	if (rl_prompt)
27132fe07f8SJohn Marino 		el_free(rl_prompt);
27232fe07f8SJohn Marino 	rl_prompt = strdup(prompt);
27332fe07f8SJohn Marino 	if (rl_prompt == NULL)
27432fe07f8SJohn Marino 		return -1;
27532fe07f8SJohn Marino 
27660ecde0cSDaniel Fojt 	while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) {
27760ecde0cSDaniel Fojt 		/* Remove adjacent end/start markers to avoid double-escapes. */
27860ecde0cSDaniel Fojt 		if (p[1] == RL_PROMPT_START_IGNORE) {
27960ecde0cSDaniel Fojt 			memmove(p, p + 2, 1 + strlen(p + 2));
28060ecde0cSDaniel Fojt 		} else {
28132fe07f8SJohn Marino 			*p = RL_PROMPT_START_IGNORE;
28260ecde0cSDaniel Fojt 		}
28360ecde0cSDaniel Fojt 	}
28432fe07f8SJohn Marino 
28532fe07f8SJohn Marino 	return 0;
28632fe07f8SJohn Marino }
28732fe07f8SJohn Marino 
288*cdf8408cSAntonio Huete Jimenez void
rl_save_prompt(void)289*cdf8408cSAntonio Huete Jimenez rl_save_prompt(void)
290*cdf8408cSAntonio Huete Jimenez {
291*cdf8408cSAntonio Huete Jimenez 	rl_prompt_saved = strdup(rl_prompt);
292*cdf8408cSAntonio Huete Jimenez }
293*cdf8408cSAntonio Huete Jimenez 
294*cdf8408cSAntonio Huete Jimenez void
rl_restore_prompt(void)295*cdf8408cSAntonio Huete Jimenez rl_restore_prompt(void)
296*cdf8408cSAntonio Huete Jimenez {
297*cdf8408cSAntonio Huete Jimenez 	if (!rl_prompt_saved)
298*cdf8408cSAntonio Huete Jimenez 		return;
299*cdf8408cSAntonio Huete Jimenez 	rl_prompt = rl_prompt_saved;
300*cdf8408cSAntonio Huete Jimenez 	rl_prompt_saved = NULL;
301*cdf8408cSAntonio Huete Jimenez }
302*cdf8408cSAntonio Huete Jimenez 
30332fe07f8SJohn Marino /*
30432fe07f8SJohn Marino  * initialize rl compat stuff
30532fe07f8SJohn Marino  */
30632fe07f8SJohn Marino int
rl_initialize(void)30732fe07f8SJohn Marino rl_initialize(void)
30832fe07f8SJohn Marino {
30932fe07f8SJohn Marino 	HistEvent ev;
31032fe07f8SJohn Marino 	int editmode = 1;
31132fe07f8SJohn Marino 	struct termios t;
31232fe07f8SJohn Marino 
31332fe07f8SJohn Marino 	if (e != NULL)
31432fe07f8SJohn Marino 		el_end(e);
31532fe07f8SJohn Marino 	if (h != NULL)
31632fe07f8SJohn Marino 		history_end(h);
31732fe07f8SJohn Marino 
318*cdf8408cSAntonio Huete Jimenez 	RL_UNSETSTATE(RL_STATE_DONE);
319*cdf8408cSAntonio Huete Jimenez 
32032fe07f8SJohn Marino 	if (!rl_instream)
32132fe07f8SJohn Marino 		rl_instream = stdin;
32232fe07f8SJohn Marino 	if (!rl_outstream)
32332fe07f8SJohn Marino 		rl_outstream = stdout;
32432fe07f8SJohn Marino 
32532fe07f8SJohn Marino 	/*
32632fe07f8SJohn Marino 	 * See if we don't really want to run the editor
32732fe07f8SJohn Marino 	 */
32832fe07f8SJohn Marino 	if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
32932fe07f8SJohn Marino 		editmode = 0;
33032fe07f8SJohn Marino 
331ae19eda8Szrj 	e = el_init_internal(rl_readline_name, rl_instream, rl_outstream,
332ae19eda8Szrj 	    stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr),
333ae19eda8Szrj 	    NO_RESET);
33432fe07f8SJohn Marino 
33532fe07f8SJohn Marino 	if (!editmode)
33632fe07f8SJohn Marino 		el_set(e, EL_EDITMODE, 0);
33732fe07f8SJohn Marino 
33832fe07f8SJohn Marino 	h = history_init();
33932fe07f8SJohn Marino 	if (!e || !h)
34032fe07f8SJohn Marino 		return -1;
34132fe07f8SJohn Marino 
34232fe07f8SJohn Marino 	history(h, &ev, H_SETSIZE, INT_MAX);	/* unlimited */
34332fe07f8SJohn Marino 	history_length = 0;
34432fe07f8SJohn Marino 	max_input_history = INT_MAX;
34532fe07f8SJohn Marino 	el_set(e, EL_HIST, history, h);
34632fe07f8SJohn Marino 
34732fe07f8SJohn Marino 	/* Setup resize function */
34832fe07f8SJohn Marino 	el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer);
34932fe07f8SJohn Marino 
35032fe07f8SJohn Marino 	/* setup getc function if valid */
35132fe07f8SJohn Marino 	if (rl_getc_function)
35232fe07f8SJohn Marino 		el_set(e, EL_GETCFN, _getc_function);
35332fe07f8SJohn Marino 
35432fe07f8SJohn Marino 	/* for proper prompt printing in readline() */
35532fe07f8SJohn Marino 	if (rl_set_prompt("") == -1) {
35632fe07f8SJohn Marino 		history_end(h);
35732fe07f8SJohn Marino 		el_end(e);
35832fe07f8SJohn Marino 		return -1;
35932fe07f8SJohn Marino 	}
360ae19eda8Szrj 	el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE);
36132fe07f8SJohn Marino 	el_set(e, EL_SIGNAL, rl_catch_signals);
36232fe07f8SJohn Marino 
36332fe07f8SJohn Marino 	/* set default mode to "emacs"-style and read setting afterwards */
364a0c9eb18SJohn Marino 	/* so this can be overridden */
36532fe07f8SJohn Marino 	el_set(e, EL_EDITOR, "emacs");
36632fe07f8SJohn Marino 	if (rl_terminal_name != NULL)
36732fe07f8SJohn Marino 		el_set(e, EL_TERMINAL, rl_terminal_name);
36832fe07f8SJohn Marino 	else
36932fe07f8SJohn Marino 		el_get(e, EL_TERMINAL, &rl_terminal_name);
37032fe07f8SJohn Marino 
37132fe07f8SJohn Marino 	/*
37232fe07f8SJohn Marino 	 * Word completion - this has to go AFTER rebinding keys
37332fe07f8SJohn Marino 	 * to emacs-style.
37432fe07f8SJohn Marino 	 */
37532fe07f8SJohn Marino 	el_set(e, EL_ADDFN, "rl_complete",
37632fe07f8SJohn Marino 	    "ReadLine compatible completion function",
37732fe07f8SJohn Marino 	    _el_rl_complete);
37832fe07f8SJohn Marino 	el_set(e, EL_BIND, "^I", "rl_complete", NULL);
37932fe07f8SJohn Marino 
38032fe07f8SJohn Marino 	/*
38132fe07f8SJohn Marino 	 * Send TSTP when ^Z is pressed.
38232fe07f8SJohn Marino 	 */
38332fe07f8SJohn Marino 	el_set(e, EL_ADDFN, "rl_tstp",
38432fe07f8SJohn Marino 	    "ReadLine compatible suspend function",
38532fe07f8SJohn Marino 	    _el_rl_tstp);
38632fe07f8SJohn Marino 	el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
38732fe07f8SJohn Marino 
388a0c9eb18SJohn Marino 	/*
389a0c9eb18SJohn Marino 	 * Set some readline compatible key-bindings.
390a0c9eb18SJohn Marino 	 */
391a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL);
392a0c9eb18SJohn Marino 
393a0c9eb18SJohn Marino 	/*
394a0c9eb18SJohn Marino 	 * Allow the use of Home/End keys.
395a0c9eb18SJohn Marino 	 */
396a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
397a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
398a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL);
399a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL);
400a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL);
401a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL);
402a0c9eb18SJohn Marino 
403a0c9eb18SJohn Marino 	/*
404a0c9eb18SJohn Marino 	 * Allow the use of the Delete/Insert keys.
405a0c9eb18SJohn Marino 	 */
406a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
407a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[2~", "ed-quoted-insert", NULL);
408a0c9eb18SJohn Marino 
409a0c9eb18SJohn Marino 	/*
410a0c9eb18SJohn Marino 	 * Ctrl-left-arrow and Ctrl-right-arrow for word moving.
411a0c9eb18SJohn Marino 	 */
412a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
413a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
414a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL);
415a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL);
416a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
417a0c9eb18SJohn Marino 	el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
418a0c9eb18SJohn Marino 
41932fe07f8SJohn Marino 	/* read settings from configuration file */
42032fe07f8SJohn Marino 	el_source(e, NULL);
42132fe07f8SJohn Marino 
42232fe07f8SJohn Marino 	/*
42332fe07f8SJohn Marino 	 * Unfortunately, some applications really do use rl_point
42432fe07f8SJohn Marino 	 * and rl_line_buffer directly.
42532fe07f8SJohn Marino 	 */
42632fe07f8SJohn Marino 	_resize_fun(e, &rl_line_buffer);
42732fe07f8SJohn Marino 	_rl_update_pos();
42832fe07f8SJohn Marino 
429ae19eda8Szrj 	tty_end(e, TCSADRAIN);
43032fe07f8SJohn Marino 
43132fe07f8SJohn Marino 	return 0;
43232fe07f8SJohn Marino }
43332fe07f8SJohn Marino 
43432fe07f8SJohn Marino 
43532fe07f8SJohn Marino /*
43632fe07f8SJohn Marino  * read one line from input stream and return it, chomping
43732fe07f8SJohn Marino  * trailing newline (if there is any)
43832fe07f8SJohn Marino  */
43932fe07f8SJohn Marino char *
readline(const char * p)44032fe07f8SJohn Marino readline(const char *p)
44132fe07f8SJohn Marino {
44232fe07f8SJohn Marino 	HistEvent ev;
44332fe07f8SJohn Marino 	const char * volatile prompt = p;
44432fe07f8SJohn Marino 	int count;
44532fe07f8SJohn Marino 	const char *ret;
44632fe07f8SJohn Marino 	char *buf;
44732fe07f8SJohn Marino 	static int used_event_hook;
44832fe07f8SJohn Marino 
44932fe07f8SJohn Marino 	if (e == NULL || h == NULL)
45032fe07f8SJohn Marino 		rl_initialize();
451*cdf8408cSAntonio Huete Jimenez 	if (rl_startup_hook) {
452*cdf8408cSAntonio Huete Jimenez 		(*rl_startup_hook)();
453ae19eda8Szrj 	}
454ae19eda8Szrj 	tty_init(e);
455ae19eda8Szrj 
45632fe07f8SJohn Marino 
45732fe07f8SJohn Marino 	rl_done = 0;
45832fe07f8SJohn Marino 
45932fe07f8SJohn Marino 	(void)setjmp(topbuf);
460ae19eda8Szrj 	buf = NULL;
46132fe07f8SJohn Marino 
46232fe07f8SJohn Marino 	/* update prompt accordingly to what has been passed */
46332fe07f8SJohn Marino 	if (rl_set_prompt(prompt) == -1)
464ae19eda8Szrj 		goto out;
46532fe07f8SJohn Marino 
46632fe07f8SJohn Marino 	if (rl_pre_input_hook)
467*cdf8408cSAntonio Huete Jimenez 		(*rl_pre_input_hook)();
46832fe07f8SJohn Marino 
46932fe07f8SJohn Marino 	if (rl_event_hook && !(e->el_flags & NO_TTY)) {
47032fe07f8SJohn Marino 		el_set(e, EL_GETCFN, _rl_event_read_char);
47132fe07f8SJohn Marino 		used_event_hook = 1;
47232fe07f8SJohn Marino 	}
47332fe07f8SJohn Marino 
47432fe07f8SJohn Marino 	if (!rl_event_hook && used_event_hook) {
47532fe07f8SJohn Marino 		el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
47632fe07f8SJohn Marino 		used_event_hook = 0;
47732fe07f8SJohn Marino 	}
47832fe07f8SJohn Marino 
47932fe07f8SJohn Marino 	rl_already_prompted = 0;
48032fe07f8SJohn Marino 
48132fe07f8SJohn Marino 	/* get one line from input stream */
48232fe07f8SJohn Marino 	ret = el_gets(e, &count);
48332fe07f8SJohn Marino 
48432fe07f8SJohn Marino 	if (ret && count > 0) {
48532fe07f8SJohn Marino 		int lastidx;
48632fe07f8SJohn Marino 
48732fe07f8SJohn Marino 		buf = strdup(ret);
48832fe07f8SJohn Marino 		if (buf == NULL)
489ae19eda8Szrj 			goto out;
49032fe07f8SJohn Marino 		lastidx = count - 1;
49132fe07f8SJohn Marino 		if (buf[lastidx] == '\n')
49232fe07f8SJohn Marino 			buf[lastidx] = '\0';
49332fe07f8SJohn Marino 	} else
49432fe07f8SJohn Marino 		buf = NULL;
49532fe07f8SJohn Marino 
49632fe07f8SJohn Marino 	history(h, &ev, H_GETSIZE);
49732fe07f8SJohn Marino 	history_length = ev.num;
49832fe07f8SJohn Marino 
499ae19eda8Szrj out:
500ae19eda8Szrj 	tty_end(e, TCSADRAIN);
50132fe07f8SJohn Marino 	return buf;
50232fe07f8SJohn Marino }
50332fe07f8SJohn Marino 
50432fe07f8SJohn Marino /*
50532fe07f8SJohn Marino  * history functions
50632fe07f8SJohn Marino  */
50732fe07f8SJohn Marino 
50832fe07f8SJohn Marino /*
50932fe07f8SJohn Marino  * is normally called before application starts to use
51032fe07f8SJohn Marino  * history expansion functions
51132fe07f8SJohn Marino  */
51232fe07f8SJohn Marino void
using_history(void)51332fe07f8SJohn Marino using_history(void)
51432fe07f8SJohn Marino {
51532fe07f8SJohn Marino 	if (h == NULL || e == NULL)
51632fe07f8SJohn Marino 		rl_initialize();
51712db70c8Szrj 	history_offset = history_length;
51832fe07f8SJohn Marino }
51932fe07f8SJohn Marino 
52032fe07f8SJohn Marino 
52132fe07f8SJohn Marino /*
52232fe07f8SJohn Marino  * substitute ``what'' with ``with'', returning resulting string; if
52332fe07f8SJohn Marino  * globally == 1, substitutes all occurrences of what, otherwise only the
52432fe07f8SJohn Marino  * first one
52532fe07f8SJohn Marino  */
52632fe07f8SJohn Marino static char *
_rl_compat_sub(const char * str,const char * what,const char * with,int globally)52732fe07f8SJohn Marino _rl_compat_sub(const char *str, const char *what, const char *with,
52832fe07f8SJohn Marino     int globally)
52932fe07f8SJohn Marino {
53032fe07f8SJohn Marino 	const	char	*s;
53132fe07f8SJohn Marino 	char	*r, *result;
53232fe07f8SJohn Marino 	size_t	len, with_len, what_len;
53332fe07f8SJohn Marino 
53432fe07f8SJohn Marino 	len = strlen(str);
53532fe07f8SJohn Marino 	with_len = strlen(with);
53632fe07f8SJohn Marino 	what_len = strlen(what);
53732fe07f8SJohn Marino 
53832fe07f8SJohn Marino 	/* calculate length we need for result */
53932fe07f8SJohn Marino 	s = str;
54032fe07f8SJohn Marino 	while (*s) {
54132fe07f8SJohn Marino 		if (*s == *what && !strncmp(s, what, what_len)) {
54232fe07f8SJohn Marino 			len += with_len - what_len;
54332fe07f8SJohn Marino 			if (!globally)
54432fe07f8SJohn Marino 				break;
54532fe07f8SJohn Marino 			s += what_len;
54632fe07f8SJohn Marino 		} else
54732fe07f8SJohn Marino 			s++;
54832fe07f8SJohn Marino 	}
54960ecde0cSDaniel Fojt 	r = result = el_calloc(len + 1, sizeof(*r));
55032fe07f8SJohn Marino 	if (result == NULL)
55132fe07f8SJohn Marino 		return NULL;
55232fe07f8SJohn Marino 	s = str;
55332fe07f8SJohn Marino 	while (*s) {
55432fe07f8SJohn Marino 		if (*s == *what && !strncmp(s, what, what_len)) {
55560ecde0cSDaniel Fojt 			memcpy(r, with, with_len);
55632fe07f8SJohn Marino 			r += with_len;
55732fe07f8SJohn Marino 			s += what_len;
55832fe07f8SJohn Marino 			if (!globally) {
55932fe07f8SJohn Marino 				(void)strcpy(r, s);
56032fe07f8SJohn Marino 				return result;
56132fe07f8SJohn Marino 			}
56232fe07f8SJohn Marino 		} else
56332fe07f8SJohn Marino 			*r++ = *s++;
56432fe07f8SJohn Marino 	}
56532fe07f8SJohn Marino 	*r = '\0';
56632fe07f8SJohn Marino 	return result;
56732fe07f8SJohn Marino }
56832fe07f8SJohn Marino 
56932fe07f8SJohn Marino static	char	*last_search_pat;	/* last !?pat[?] search pattern */
57032fe07f8SJohn Marino static	char	*last_search_match;	/* last !?pat[?] that matched */
57132fe07f8SJohn Marino 
57232fe07f8SJohn Marino const char *
get_history_event(const char * cmd,int * cindex,int qchar)57332fe07f8SJohn Marino get_history_event(const char *cmd, int *cindex, int qchar)
57432fe07f8SJohn Marino {
57532fe07f8SJohn Marino 	int idx, sign, sub, num, begin, ret;
57632fe07f8SJohn Marino 	size_t len;
57732fe07f8SJohn Marino 	char	*pat;
57832fe07f8SJohn Marino 	const char *rptr;
57932fe07f8SJohn Marino 	HistEvent ev;
58032fe07f8SJohn Marino 
58132fe07f8SJohn Marino 	idx = *cindex;
58232fe07f8SJohn Marino 	if (cmd[idx++] != history_expansion_char)
58332fe07f8SJohn Marino 		return NULL;
58432fe07f8SJohn Marino 
58532fe07f8SJohn Marino 	/* find out which event to take */
58632fe07f8SJohn Marino 	if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
58732fe07f8SJohn Marino 		if (history(h, &ev, H_FIRST) != 0)
58832fe07f8SJohn Marino 			return NULL;
58932fe07f8SJohn Marino 		*cindex = cmd[idx]? (idx + 1):idx;
59032fe07f8SJohn Marino 		return ev.str;
59132fe07f8SJohn Marino 	}
59232fe07f8SJohn Marino 	sign = 0;
59332fe07f8SJohn Marino 	if (cmd[idx] == '-') {
59432fe07f8SJohn Marino 		sign = 1;
59532fe07f8SJohn Marino 		idx++;
59632fe07f8SJohn Marino 	}
59732fe07f8SJohn Marino 
59832fe07f8SJohn Marino 	if ('0' <= cmd[idx] && cmd[idx] <= '9') {
59912db70c8Szrj 		HIST_ENTRY *he;
60032fe07f8SJohn Marino 
60132fe07f8SJohn Marino 		num = 0;
60232fe07f8SJohn Marino 		while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
60332fe07f8SJohn Marino 			num = num * 10 + cmd[idx] - '0';
60432fe07f8SJohn Marino 			idx++;
60532fe07f8SJohn Marino 		}
60632fe07f8SJohn Marino 		if (sign)
60712db70c8Szrj 			num = history_length - num + history_base;
60832fe07f8SJohn Marino 
60912db70c8Szrj 		if (!(he = history_get(num)))
61032fe07f8SJohn Marino 			return NULL;
61132fe07f8SJohn Marino 
61232fe07f8SJohn Marino 		*cindex = idx;
61312db70c8Szrj 		return he->line;
61432fe07f8SJohn Marino 	}
61532fe07f8SJohn Marino 	sub = 0;
61632fe07f8SJohn Marino 	if (cmd[idx] == '?') {
61732fe07f8SJohn Marino 		sub = 1;
61832fe07f8SJohn Marino 		idx++;
61932fe07f8SJohn Marino 	}
62032fe07f8SJohn Marino 	begin = idx;
62132fe07f8SJohn Marino 	while (cmd[idx]) {
62232fe07f8SJohn Marino 		if (cmd[idx] == '\n')
62332fe07f8SJohn Marino 			break;
62432fe07f8SJohn Marino 		if (sub && cmd[idx] == '?')
62532fe07f8SJohn Marino 			break;
62632fe07f8SJohn Marino 		if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
62732fe07f8SJohn Marino 		    || cmd[idx] == '\t' || cmd[idx] == qchar))
62832fe07f8SJohn Marino 			break;
62932fe07f8SJohn Marino 		idx++;
63032fe07f8SJohn Marino 	}
63132fe07f8SJohn Marino 	len = (size_t)idx - (size_t)begin;
63232fe07f8SJohn Marino 	if (sub && cmd[idx] == '?')
63332fe07f8SJohn Marino 		idx++;
63432fe07f8SJohn Marino 	if (sub && len == 0 && last_search_pat && *last_search_pat)
63532fe07f8SJohn Marino 		pat = last_search_pat;
63632fe07f8SJohn Marino 	else if (len == 0)
63732fe07f8SJohn Marino 		return NULL;
63832fe07f8SJohn Marino 	else {
63960ecde0cSDaniel Fojt 		if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL)
64032fe07f8SJohn Marino 			return NULL;
64160ecde0cSDaniel Fojt 		(void)strlcpy(pat, cmd + begin, len + 1);
64232fe07f8SJohn Marino 	}
64332fe07f8SJohn Marino 
64432fe07f8SJohn Marino 	if (history(h, &ev, H_CURR) != 0) {
64532fe07f8SJohn Marino 		if (pat != last_search_pat)
64632fe07f8SJohn Marino 			el_free(pat);
64732fe07f8SJohn Marino 		return NULL;
64832fe07f8SJohn Marino 	}
64932fe07f8SJohn Marino 	num = ev.num;
65032fe07f8SJohn Marino 
65132fe07f8SJohn Marino 	if (sub) {
65232fe07f8SJohn Marino 		if (pat != last_search_pat) {
65332fe07f8SJohn Marino 			el_free(last_search_pat);
65432fe07f8SJohn Marino 			last_search_pat = pat;
65532fe07f8SJohn Marino 		}
65632fe07f8SJohn Marino 		ret = history_search(pat, -1);
65732fe07f8SJohn Marino 	} else
65832fe07f8SJohn Marino 		ret = history_search_prefix(pat, -1);
65932fe07f8SJohn Marino 
66032fe07f8SJohn Marino 	if (ret == -1) {
66132fe07f8SJohn Marino 		/* restore to end of list on failed search */
66232fe07f8SJohn Marino 		history(h, &ev, H_FIRST);
66332fe07f8SJohn Marino 		(void)fprintf(rl_outstream, "%s: Event not found\n", pat);
66432fe07f8SJohn Marino 		if (pat != last_search_pat)
66532fe07f8SJohn Marino 			el_free(pat);
66632fe07f8SJohn Marino 		return NULL;
66732fe07f8SJohn Marino 	}
66832fe07f8SJohn Marino 
66932fe07f8SJohn Marino 	if (sub && len) {
67032fe07f8SJohn Marino 		el_free(last_search_match);
671*cdf8408cSAntonio Huete Jimenez 		last_search_match = strdup(pat);
67232fe07f8SJohn Marino 	}
67332fe07f8SJohn Marino 
67432fe07f8SJohn Marino 	if (pat != last_search_pat)
67532fe07f8SJohn Marino 		el_free(pat);
67632fe07f8SJohn Marino 
67732fe07f8SJohn Marino 	if (history(h, &ev, H_CURR) != 0)
67832fe07f8SJohn Marino 		return NULL;
67932fe07f8SJohn Marino 	*cindex = idx;
68032fe07f8SJohn Marino 	rptr = ev.str;
68132fe07f8SJohn Marino 
68232fe07f8SJohn Marino 	/* roll back to original position */
68332fe07f8SJohn Marino 	(void)history(h, &ev, H_SET, num);
68432fe07f8SJohn Marino 
68532fe07f8SJohn Marino 	return rptr;
68632fe07f8SJohn Marino }
68732fe07f8SJohn Marino 
688*cdf8408cSAntonio Huete Jimenez static int
getfrom(const char ** cmdp,char ** fromp,const char * search,int delim)689*cdf8408cSAntonio Huete Jimenez getfrom(const char **cmdp, char **fromp, const char *search, int delim)
690*cdf8408cSAntonio Huete Jimenez {
691*cdf8408cSAntonio Huete Jimenez 	size_t size = 16;
692*cdf8408cSAntonio Huete Jimenez 	size_t len = 0;
693*cdf8408cSAntonio Huete Jimenez 	const char *cmd = *cmdp;
694*cdf8408cSAntonio Huete Jimenez 	char *what = el_realloc(*fromp, size * sizeof(*what));
695*cdf8408cSAntonio Huete Jimenez 	if (what == NULL){
696*cdf8408cSAntonio Huete Jimenez 		el_free(*fromp);
697*cdf8408cSAntonio Huete Jimenez 		*fromp = NULL;
698*cdf8408cSAntonio Huete Jimenez 		return 0;
699*cdf8408cSAntonio Huete Jimenez 	}
700*cdf8408cSAntonio Huete Jimenez 	for (; *cmd && *cmd != delim; cmd++) {
701*cdf8408cSAntonio Huete Jimenez 		if (*cmd == '\\' && cmd[1] == delim)
702*cdf8408cSAntonio Huete Jimenez 			cmd++;
703*cdf8408cSAntonio Huete Jimenez 		if (len - 1 >= size) {
704*cdf8408cSAntonio Huete Jimenez 			char *nwhat;
705*cdf8408cSAntonio Huete Jimenez 			nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat));
706*cdf8408cSAntonio Huete Jimenez 			if (nwhat == NULL) {
707*cdf8408cSAntonio Huete Jimenez 				el_free(what);
708*cdf8408cSAntonio Huete Jimenez 				el_free(*fromp);
709*cdf8408cSAntonio Huete Jimenez 				*cmdp = cmd;
710*cdf8408cSAntonio Huete Jimenez 				*fromp = NULL;
711*cdf8408cSAntonio Huete Jimenez 				return 0;
712*cdf8408cSAntonio Huete Jimenez 			}
713*cdf8408cSAntonio Huete Jimenez 			what = nwhat;
714*cdf8408cSAntonio Huete Jimenez 		}
715*cdf8408cSAntonio Huete Jimenez 		what[len++] = *cmd;
716*cdf8408cSAntonio Huete Jimenez 	}
717*cdf8408cSAntonio Huete Jimenez 	what[len] = '\0';
718*cdf8408cSAntonio Huete Jimenez 	*fromp = what;
719*cdf8408cSAntonio Huete Jimenez 	*cmdp = cmd;
720*cdf8408cSAntonio Huete Jimenez 	if (*what == '\0') {
721*cdf8408cSAntonio Huete Jimenez 		el_free(what);
722*cdf8408cSAntonio Huete Jimenez 		if (search) {
723*cdf8408cSAntonio Huete Jimenez 			*fromp = strdup(search);
724*cdf8408cSAntonio Huete Jimenez 			if (*fromp == NULL) {
725*cdf8408cSAntonio Huete Jimenez 				return 0;
726*cdf8408cSAntonio Huete Jimenez 			}
727*cdf8408cSAntonio Huete Jimenez 		} else {
728*cdf8408cSAntonio Huete Jimenez 			*fromp = NULL;
729*cdf8408cSAntonio Huete Jimenez 			return -1;
730*cdf8408cSAntonio Huete Jimenez 		}
731*cdf8408cSAntonio Huete Jimenez 	}
732*cdf8408cSAntonio Huete Jimenez 	if (!*cmd) {
733*cdf8408cSAntonio Huete Jimenez 		el_free(what);
734*cdf8408cSAntonio Huete Jimenez 		*fromp = NULL;
735*cdf8408cSAntonio Huete Jimenez 		return -1;
736*cdf8408cSAntonio Huete Jimenez 	}
737*cdf8408cSAntonio Huete Jimenez 
738*cdf8408cSAntonio Huete Jimenez 	cmd++;	/* shift after delim */
739*cdf8408cSAntonio Huete Jimenez 	*cmdp = cmd;
740*cdf8408cSAntonio Huete Jimenez 
741*cdf8408cSAntonio Huete Jimenez 	if (!*cmd) {
742*cdf8408cSAntonio Huete Jimenez 		el_free(what);
743*cdf8408cSAntonio Huete Jimenez 		*fromp = NULL;
744*cdf8408cSAntonio Huete Jimenez 		return -1;
745*cdf8408cSAntonio Huete Jimenez 	}
746*cdf8408cSAntonio Huete Jimenez 	return 1;
747*cdf8408cSAntonio Huete Jimenez }
748*cdf8408cSAntonio Huete Jimenez 
749*cdf8408cSAntonio Huete Jimenez static int
getto(const char ** cmdp,char ** top,const char * from,int delim)750*cdf8408cSAntonio Huete Jimenez getto(const char **cmdp, char **top, const char *from, int delim)
751*cdf8408cSAntonio Huete Jimenez {
752*cdf8408cSAntonio Huete Jimenez 	size_t size = 16;
753*cdf8408cSAntonio Huete Jimenez 	size_t len = 0;
754*cdf8408cSAntonio Huete Jimenez 	size_t from_len = strlen(from);
755*cdf8408cSAntonio Huete Jimenez 	const char *cmd = *cmdp;
756*cdf8408cSAntonio Huete Jimenez 	char *with = el_realloc(*top, size * sizeof(*with));
757*cdf8408cSAntonio Huete Jimenez 	*top = NULL;
758*cdf8408cSAntonio Huete Jimenez 	if (with == NULL)
759*cdf8408cSAntonio Huete Jimenez 		goto out;
760*cdf8408cSAntonio Huete Jimenez 
761*cdf8408cSAntonio Huete Jimenez 	for (; *cmd && *cmd != delim; cmd++) {
762*cdf8408cSAntonio Huete Jimenez 		if (len + from_len + 1 >= size) {
763*cdf8408cSAntonio Huete Jimenez 			char *nwith;
764*cdf8408cSAntonio Huete Jimenez 			size += from_len + 1;
765*cdf8408cSAntonio Huete Jimenez 			nwith = el_realloc(with, size * sizeof(*nwith));
766*cdf8408cSAntonio Huete Jimenez 			if (nwith == NULL)
767*cdf8408cSAntonio Huete Jimenez 				goto out;
768*cdf8408cSAntonio Huete Jimenez 			with = nwith;
769*cdf8408cSAntonio Huete Jimenez 		}
770*cdf8408cSAntonio Huete Jimenez 		if (*cmd == '&') {
771*cdf8408cSAntonio Huete Jimenez 			/* safe */
772*cdf8408cSAntonio Huete Jimenez 			strcpy(&with[len], from);
773*cdf8408cSAntonio Huete Jimenez 			len += from_len;
774*cdf8408cSAntonio Huete Jimenez 			continue;
775*cdf8408cSAntonio Huete Jimenez 		}
776*cdf8408cSAntonio Huete Jimenez 		if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&'))
777*cdf8408cSAntonio Huete Jimenez 			cmd++;
778*cdf8408cSAntonio Huete Jimenez 		with[len++] = *cmd;
779*cdf8408cSAntonio Huete Jimenez 	}
780*cdf8408cSAntonio Huete Jimenez 	if (!*cmd)
781*cdf8408cSAntonio Huete Jimenez 		goto out;
782*cdf8408cSAntonio Huete Jimenez 	with[len] = '\0';
783*cdf8408cSAntonio Huete Jimenez 	*top = with;
784*cdf8408cSAntonio Huete Jimenez 	*cmdp = cmd;
785*cdf8408cSAntonio Huete Jimenez 	return 1;
786*cdf8408cSAntonio Huete Jimenez out:
787*cdf8408cSAntonio Huete Jimenez 	el_free(with);
788*cdf8408cSAntonio Huete Jimenez 	el_free(*top);
789*cdf8408cSAntonio Huete Jimenez 	*top = NULL;
790*cdf8408cSAntonio Huete Jimenez 	*cmdp = cmd;
791*cdf8408cSAntonio Huete Jimenez 	return -1;
792*cdf8408cSAntonio Huete Jimenez }
793*cdf8408cSAntonio Huete Jimenez 
794*cdf8408cSAntonio Huete Jimenez static void
replace(char ** tmp,int c)795*cdf8408cSAntonio Huete Jimenez replace(char **tmp, int c)
796*cdf8408cSAntonio Huete Jimenez {
797*cdf8408cSAntonio Huete Jimenez 	char *aptr;
798*cdf8408cSAntonio Huete Jimenez 	if ((aptr = strrchr(*tmp, c)) == NULL)
799*cdf8408cSAntonio Huete Jimenez 		return;
800*cdf8408cSAntonio Huete Jimenez 	aptr = strdup(aptr + 1); // XXX: check
801*cdf8408cSAntonio Huete Jimenez 	el_free(*tmp);
802*cdf8408cSAntonio Huete Jimenez 	*tmp = aptr;
803*cdf8408cSAntonio Huete Jimenez }
804*cdf8408cSAntonio Huete Jimenez 
80532fe07f8SJohn Marino /*
80632fe07f8SJohn Marino  * the real function doing history expansion - takes as argument command
80732fe07f8SJohn Marino  * to do and data upon which the command should be executed
80832fe07f8SJohn Marino  * does expansion the way I've understood readline documentation
80932fe07f8SJohn Marino  *
81032fe07f8SJohn Marino  * returns 0 if data was not modified, 1 if it was and 2 if the string
81132fe07f8SJohn Marino  * should be only printed and not executed; in case of error,
81232fe07f8SJohn Marino  * returns -1 and *result points to NULL
813a0c9eb18SJohn Marino  * it's the caller's responsibility to free() the string returned in *result
81432fe07f8SJohn Marino  */
81532fe07f8SJohn Marino static int
_history_expand_command(const char * command,size_t offs,size_t cmdlen,char ** result)81632fe07f8SJohn Marino _history_expand_command(const char *command, size_t offs, size_t cmdlen,
81732fe07f8SJohn Marino     char **result)
81832fe07f8SJohn Marino {
819*cdf8408cSAntonio Huete Jimenez 	char *tmp, *search = NULL, *aptr, delim;
82032fe07f8SJohn Marino 	const char *ptr, *cmd;
82132fe07f8SJohn Marino 	static char *from = NULL, *to = NULL;
82232fe07f8SJohn Marino 	int start, end, idx, has_mods = 0;
823*cdf8408cSAntonio Huete Jimenez 	int p_on = 0, g_on = 0, ev;
82432fe07f8SJohn Marino 
82532fe07f8SJohn Marino 	*result = NULL;
82632fe07f8SJohn Marino 	aptr = NULL;
82732fe07f8SJohn Marino 	ptr = NULL;
82832fe07f8SJohn Marino 
82932fe07f8SJohn Marino 	/* First get event specifier */
83032fe07f8SJohn Marino 	idx = 0;
83132fe07f8SJohn Marino 
83232fe07f8SJohn Marino 	if (strchr(":^*$", command[offs + 1])) {
83332fe07f8SJohn Marino 		char str[4];
83432fe07f8SJohn Marino 		/*
83532fe07f8SJohn Marino 		* "!:" is shorthand for "!!:".
83632fe07f8SJohn Marino 		* "!^", "!*" and "!$" are shorthand for
83732fe07f8SJohn Marino 		* "!!:^", "!!:*" and "!!:$" respectively.
83832fe07f8SJohn Marino 		*/
83932fe07f8SJohn Marino 		str[0] = str[1] = '!';
84032fe07f8SJohn Marino 		str[2] = '0';
84132fe07f8SJohn Marino 		ptr = get_history_event(str, &idx, 0);
84232fe07f8SJohn Marino 		idx = (command[offs + 1] == ':')? 1:0;
84332fe07f8SJohn Marino 		has_mods = 1;
84432fe07f8SJohn Marino 	} else {
84532fe07f8SJohn Marino 		if (command[offs + 1] == '#') {
84632fe07f8SJohn Marino 			/* use command so far */
84760ecde0cSDaniel Fojt 			if ((aptr = el_calloc(offs + 1, sizeof(*aptr)))
84832fe07f8SJohn Marino 			    == NULL)
84932fe07f8SJohn Marino 				return -1;
85060ecde0cSDaniel Fojt 			(void)strlcpy(aptr, command, offs + 1);
85132fe07f8SJohn Marino 			idx = 1;
85232fe07f8SJohn Marino 		} else {
85332fe07f8SJohn Marino 			int	qchar;
85432fe07f8SJohn Marino 
855*cdf8408cSAntonio Huete Jimenez 			qchar = (offs > 0 && command[offs - 1] == '"')
856*cdf8408cSAntonio Huete Jimenez 			    ? '"' : '\0';
85732fe07f8SJohn Marino 			ptr = get_history_event(command + offs, &idx, qchar);
85832fe07f8SJohn Marino 		}
85932fe07f8SJohn Marino 		has_mods = command[offs + (size_t)idx] == ':';
86032fe07f8SJohn Marino 	}
86132fe07f8SJohn Marino 
86232fe07f8SJohn Marino 	if (ptr == NULL && aptr == NULL)
86332fe07f8SJohn Marino 		return -1;
86432fe07f8SJohn Marino 
86532fe07f8SJohn Marino 	if (!has_mods) {
86632fe07f8SJohn Marino 		*result = strdup(aptr ? aptr : ptr);
86732fe07f8SJohn Marino 		if (aptr)
86832fe07f8SJohn Marino 			el_free(aptr);
86932fe07f8SJohn Marino 		if (*result == NULL)
87032fe07f8SJohn Marino 			return -1;
87132fe07f8SJohn Marino 		return 1;
87232fe07f8SJohn Marino 	}
87332fe07f8SJohn Marino 
87432fe07f8SJohn Marino 	cmd = command + offs + idx + 1;
87532fe07f8SJohn Marino 
87632fe07f8SJohn Marino 	/* Now parse any word designators */
87732fe07f8SJohn Marino 
87832fe07f8SJohn Marino 	if (*cmd == '%')	/* last word matched by ?pat? */
87932fe07f8SJohn Marino 		tmp = strdup(last_search_match ? last_search_match : "");
88032fe07f8SJohn Marino 	else if (strchr("^*$-0123456789", *cmd)) {
88132fe07f8SJohn Marino 		start = end = -1;
88232fe07f8SJohn Marino 		if (*cmd == '^')
88332fe07f8SJohn Marino 			start = end = 1, cmd++;
88432fe07f8SJohn Marino 		else if (*cmd == '$')
88532fe07f8SJohn Marino 			start = -1, cmd++;
88632fe07f8SJohn Marino 		else if (*cmd == '*')
88732fe07f8SJohn Marino 			start = 1, cmd++;
88832fe07f8SJohn Marino 		else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
88932fe07f8SJohn Marino 			start = 0;
89032fe07f8SJohn Marino 			while (*cmd && '0' <= *cmd && *cmd <= '9')
89132fe07f8SJohn Marino 				start = start * 10 + *cmd++ - '0';
89232fe07f8SJohn Marino 
89332fe07f8SJohn Marino 			if (*cmd == '-') {
89432fe07f8SJohn Marino 				if (isdigit((unsigned char) cmd[1])) {
89532fe07f8SJohn Marino 					cmd++;
89632fe07f8SJohn Marino 					end = 0;
89732fe07f8SJohn Marino 					while (*cmd && '0' <= *cmd && *cmd <= '9')
89832fe07f8SJohn Marino 						end = end * 10 + *cmd++ - '0';
89932fe07f8SJohn Marino 				} else if (cmd[1] == '$') {
90032fe07f8SJohn Marino 					cmd += 2;
90132fe07f8SJohn Marino 					end = -1;
90232fe07f8SJohn Marino 				} else {
90332fe07f8SJohn Marino 					cmd++;
90432fe07f8SJohn Marino 					end = -2;
90532fe07f8SJohn Marino 				}
90632fe07f8SJohn Marino 			} else if (*cmd == '*')
90732fe07f8SJohn Marino 				end = -1, cmd++;
90832fe07f8SJohn Marino 			else
90932fe07f8SJohn Marino 				end = start;
91032fe07f8SJohn Marino 		}
91132fe07f8SJohn Marino 		tmp = history_arg_extract(start, end, aptr? aptr:ptr);
91232fe07f8SJohn Marino 		if (tmp == NULL) {
91332fe07f8SJohn Marino 			(void)fprintf(rl_outstream, "%s: Bad word specifier",
91432fe07f8SJohn Marino 			    command + offs + idx);
91532fe07f8SJohn Marino 			if (aptr)
91632fe07f8SJohn Marino 				el_free(aptr);
91732fe07f8SJohn Marino 			return -1;
91832fe07f8SJohn Marino 		}
91932fe07f8SJohn Marino 	} else
92032fe07f8SJohn Marino 		tmp = strdup(aptr? aptr:ptr);
92132fe07f8SJohn Marino 
92232fe07f8SJohn Marino 	if (aptr)
92332fe07f8SJohn Marino 		el_free(aptr);
92432fe07f8SJohn Marino 
92532fe07f8SJohn Marino 	if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
92632fe07f8SJohn Marino 		*result = tmp;
92732fe07f8SJohn Marino 		return 1;
92832fe07f8SJohn Marino 	}
92932fe07f8SJohn Marino 
93032fe07f8SJohn Marino 	for (; *cmd; cmd++) {
931*cdf8408cSAntonio Huete Jimenez 		switch (*cmd) {
932*cdf8408cSAntonio Huete Jimenez 		case ':':
93332fe07f8SJohn Marino 			continue;
934*cdf8408cSAntonio Huete Jimenez 		case 'h':	/* remove trailing path */
93532fe07f8SJohn Marino 			if ((aptr = strrchr(tmp, '/')) != NULL)
93632fe07f8SJohn Marino 				*aptr = '\0';
937*cdf8408cSAntonio Huete Jimenez 			continue;
938*cdf8408cSAntonio Huete Jimenez 		case 't':	/* remove leading path */
939*cdf8408cSAntonio Huete Jimenez 			replace(&tmp, '/');
940*cdf8408cSAntonio Huete Jimenez 			continue;
941*cdf8408cSAntonio Huete Jimenez 		case 'r':	/* remove trailing suffix */
94232fe07f8SJohn Marino 			if ((aptr = strrchr(tmp, '.')) != NULL)
94332fe07f8SJohn Marino 				*aptr = '\0';
944*cdf8408cSAntonio Huete Jimenez 			continue;
945*cdf8408cSAntonio Huete Jimenez 		case 'e':	/* remove all but suffix */
946*cdf8408cSAntonio Huete Jimenez 			replace(&tmp, '.');
947*cdf8408cSAntonio Huete Jimenez 			continue;
948*cdf8408cSAntonio Huete Jimenez 		case 'p':	/* print only */
94932fe07f8SJohn Marino 			p_on = 1;
950*cdf8408cSAntonio Huete Jimenez 			continue;
951*cdf8408cSAntonio Huete Jimenez 		case 'g':
95232fe07f8SJohn Marino 			g_on = 2;
95332fe07f8SJohn Marino 			continue;
954*cdf8408cSAntonio Huete Jimenez 		case '&':
955*cdf8408cSAntonio Huete Jimenez 			if (from == NULL || to == NULL)
95632fe07f8SJohn Marino 				continue;
957*cdf8408cSAntonio Huete Jimenez 			/*FALLTHROUGH*/
958*cdf8408cSAntonio Huete Jimenez 		case 's':
959*cdf8408cSAntonio Huete Jimenez 			ev = -1;
960*cdf8408cSAntonio Huete Jimenez 			delim = *++cmd;
961*cdf8408cSAntonio Huete Jimenez 			if (delim == '\0' || *++cmd == '\0')
962*cdf8408cSAntonio Huete Jimenez 				goto out;
963*cdf8408cSAntonio Huete Jimenez 			if ((ev = getfrom(&cmd, &from, search, delim)) != 1)
964*cdf8408cSAntonio Huete Jimenez 				goto out;
965*cdf8408cSAntonio Huete Jimenez 			if ((ev = getto(&cmd, &to, from, delim)) != 1)
966*cdf8408cSAntonio Huete Jimenez 				goto out;
96732fe07f8SJohn Marino 			aptr = _rl_compat_sub(tmp, from, to, g_on);
96832fe07f8SJohn Marino 			if (aptr) {
96932fe07f8SJohn Marino 				el_free(tmp);
97032fe07f8SJohn Marino 				tmp = aptr;
97132fe07f8SJohn Marino 			}
97232fe07f8SJohn Marino 			g_on = 0;
973*cdf8408cSAntonio Huete Jimenez 			cmd--;
974*cdf8408cSAntonio Huete Jimenez 			continue;
97532fe07f8SJohn Marino 		}
97632fe07f8SJohn Marino 	}
97732fe07f8SJohn Marino 	*result = tmp;
97832fe07f8SJohn Marino 	return p_on ? 2 : 1;
979*cdf8408cSAntonio Huete Jimenez out:
980*cdf8408cSAntonio Huete Jimenez 	el_free(tmp);
981*cdf8408cSAntonio Huete Jimenez 	return ev;
982*cdf8408cSAntonio Huete Jimenez 
98332fe07f8SJohn Marino }
98432fe07f8SJohn Marino 
98532fe07f8SJohn Marino 
98632fe07f8SJohn Marino /*
98732fe07f8SJohn Marino  * csh-style history expansion
98832fe07f8SJohn Marino  */
98932fe07f8SJohn Marino int
history_expand(char * str,char ** output)99032fe07f8SJohn Marino history_expand(char *str, char **output)
99132fe07f8SJohn Marino {
99232fe07f8SJohn Marino 	int ret = 0;
99332fe07f8SJohn Marino 	size_t idx, i, size;
99432fe07f8SJohn Marino 	char *tmp, *result;
99532fe07f8SJohn Marino 
99632fe07f8SJohn Marino 	if (h == NULL || e == NULL)
99732fe07f8SJohn Marino 		rl_initialize();
99832fe07f8SJohn Marino 
99932fe07f8SJohn Marino 	if (history_expansion_char == 0) {
100032fe07f8SJohn Marino 		*output = strdup(str);
100132fe07f8SJohn Marino 		return 0;
100232fe07f8SJohn Marino 	}
100332fe07f8SJohn Marino 
100432fe07f8SJohn Marino 	*output = NULL;
100532fe07f8SJohn Marino 	if (str[0] == history_subst_char) {
100632fe07f8SJohn Marino 		/* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
100760ecde0cSDaniel Fojt 		*output = el_calloc(strlen(str) + 4 + 1, sizeof(**output));
100832fe07f8SJohn Marino 		if (*output == NULL)
100932fe07f8SJohn Marino 			return 0;
101032fe07f8SJohn Marino 		(*output)[0] = (*output)[1] = history_expansion_char;
101132fe07f8SJohn Marino 		(*output)[2] = ':';
101232fe07f8SJohn Marino 		(*output)[3] = 's';
101332fe07f8SJohn Marino 		(void)strcpy((*output) + 4, str);
101432fe07f8SJohn Marino 		str = *output;
101532fe07f8SJohn Marino 	} else {
101632fe07f8SJohn Marino 		*output = strdup(str);
101732fe07f8SJohn Marino 		if (*output == NULL)
101832fe07f8SJohn Marino 			return 0;
101932fe07f8SJohn Marino 	}
102032fe07f8SJohn Marino 
102132fe07f8SJohn Marino #define ADD_STRING(what, len, fr)					\
102232fe07f8SJohn Marino 	{								\
102332fe07f8SJohn Marino 		if (idx + len + 1 > size) {				\
102432fe07f8SJohn Marino 			char *nresult = el_realloc(result,		\
102532fe07f8SJohn Marino 			    (size += len + 1) * sizeof(*nresult));	\
102632fe07f8SJohn Marino 			if (nresult == NULL) {				\
102732fe07f8SJohn Marino 				el_free(*output);			\
1028*cdf8408cSAntonio Huete Jimenez 				el_free(fr);				\
102932fe07f8SJohn Marino 				return 0;				\
103032fe07f8SJohn Marino 			}						\
103132fe07f8SJohn Marino 			result = nresult;				\
103232fe07f8SJohn Marino 		}							\
103360ecde0cSDaniel Fojt 		(void)strlcpy(&result[idx], what, len + 1);		\
103432fe07f8SJohn Marino 		idx += len;						\
103532fe07f8SJohn Marino 	}
103632fe07f8SJohn Marino 
103732fe07f8SJohn Marino 	result = NULL;
103832fe07f8SJohn Marino 	size = idx = 0;
103932fe07f8SJohn Marino 	tmp = NULL;
104032fe07f8SJohn Marino 	for (i = 0; str[i];) {
104132fe07f8SJohn Marino 		int qchar, loop_again;
104232fe07f8SJohn Marino 		size_t len, start, j;
104332fe07f8SJohn Marino 
104432fe07f8SJohn Marino 		qchar = 0;
104532fe07f8SJohn Marino 		loop_again = 1;
104632fe07f8SJohn Marino 		start = j = i;
104732fe07f8SJohn Marino loop:
104832fe07f8SJohn Marino 		for (; str[j]; j++) {
104932fe07f8SJohn Marino 			if (str[j] == '\\' &&
105032fe07f8SJohn Marino 			    str[j + 1] == history_expansion_char) {
105112db70c8Szrj 				len = strlen(&str[j + 1]) + 1;
105212db70c8Szrj 				memmove(&str[j], &str[j + 1], len);
105332fe07f8SJohn Marino 				continue;
105432fe07f8SJohn Marino 			}
105532fe07f8SJohn Marino 			if (!loop_again) {
105632fe07f8SJohn Marino 				if (isspace((unsigned char) str[j])
105732fe07f8SJohn Marino 				    || str[j] == qchar)
105832fe07f8SJohn Marino 					break;
105932fe07f8SJohn Marino 			}
106032fe07f8SJohn Marino 			if (str[j] == history_expansion_char
106132fe07f8SJohn Marino 			    && !strchr(history_no_expand_chars, str[j + 1])
106232fe07f8SJohn Marino 			    && (!history_inhibit_expansion_function ||
106332fe07f8SJohn Marino 			    (*history_inhibit_expansion_function)(str,
106432fe07f8SJohn Marino 			    (int)j) == 0))
106532fe07f8SJohn Marino 				break;
106632fe07f8SJohn Marino 		}
106732fe07f8SJohn Marino 
106832fe07f8SJohn Marino 		if (str[j] && loop_again) {
106932fe07f8SJohn Marino 			i = j;
107032fe07f8SJohn Marino 			qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
107132fe07f8SJohn Marino 			j++;
107232fe07f8SJohn Marino 			if (str[j] == history_expansion_char)
107332fe07f8SJohn Marino 				j++;
107432fe07f8SJohn Marino 			loop_again = 0;
107532fe07f8SJohn Marino 			goto loop;
107632fe07f8SJohn Marino 		}
107732fe07f8SJohn Marino 		len = i - start;
1078*cdf8408cSAntonio Huete Jimenez 		ADD_STRING(&str[start], len, NULL);
107932fe07f8SJohn Marino 
108032fe07f8SJohn Marino 		if (str[i] == '\0' || str[i] != history_expansion_char) {
108132fe07f8SJohn Marino 			len = j - i;
1082*cdf8408cSAntonio Huete Jimenez 			ADD_STRING(&str[i], len, NULL);
108332fe07f8SJohn Marino 			if (start == 0)
108432fe07f8SJohn Marino 				ret = 0;
108532fe07f8SJohn Marino 			else
108632fe07f8SJohn Marino 				ret = 1;
108732fe07f8SJohn Marino 			break;
108832fe07f8SJohn Marino 		}
108932fe07f8SJohn Marino 		ret = _history_expand_command (str, i, (j - i), &tmp);
109032fe07f8SJohn Marino 		if (ret > 0 && tmp) {
109132fe07f8SJohn Marino 			len = strlen(tmp);
1092*cdf8408cSAntonio Huete Jimenez 			ADD_STRING(tmp, len, tmp);
109332fe07f8SJohn Marino 		}
109432fe07f8SJohn Marino 		if (tmp) {
109532fe07f8SJohn Marino 			el_free(tmp);
109632fe07f8SJohn Marino 			tmp = NULL;
109732fe07f8SJohn Marino 		}
109832fe07f8SJohn Marino 		i = j;
109932fe07f8SJohn Marino 	}
110032fe07f8SJohn Marino 
110132fe07f8SJohn Marino 	/* ret is 2 for "print only" option */
110232fe07f8SJohn Marino 	if (ret == 2) {
110332fe07f8SJohn Marino 		add_history(result);
110432fe07f8SJohn Marino #ifdef GDB_411_HACK
110532fe07f8SJohn Marino 		/* gdb 4.11 has been shipped with readline, where */
110632fe07f8SJohn Marino 		/* history_expand() returned -1 when the line	  */
110732fe07f8SJohn Marino 		/* should not be executed; in readline 2.1+	  */
110832fe07f8SJohn Marino 		/* it should return 2 in such a case		  */
110932fe07f8SJohn Marino 		ret = -1;
111032fe07f8SJohn Marino #endif
111132fe07f8SJohn Marino 	}
111232fe07f8SJohn Marino 	el_free(*output);
111332fe07f8SJohn Marino 	*output = result;
111432fe07f8SJohn Marino 
111532fe07f8SJohn Marino 	return ret;
111632fe07f8SJohn Marino }
111732fe07f8SJohn Marino 
111832fe07f8SJohn Marino /*
111932fe07f8SJohn Marino * Return a string consisting of arguments of "str" from "start" to "end".
112032fe07f8SJohn Marino */
112132fe07f8SJohn Marino char *
history_arg_extract(int start,int end,const char * str)112232fe07f8SJohn Marino history_arg_extract(int start, int end, const char *str)
112332fe07f8SJohn Marino {
112432fe07f8SJohn Marino 	size_t  i, len, max;
112532fe07f8SJohn Marino 	char	**arr, *result = NULL;
112632fe07f8SJohn Marino 
112732fe07f8SJohn Marino 	arr = history_tokenize(str);
112832fe07f8SJohn Marino 	if (!arr)
112932fe07f8SJohn Marino 		return NULL;
113032fe07f8SJohn Marino 	if (arr && *arr == NULL)
113132fe07f8SJohn Marino 		goto out;
113232fe07f8SJohn Marino 
113332fe07f8SJohn Marino 	for (max = 0; arr[max]; max++)
113432fe07f8SJohn Marino 		continue;
113532fe07f8SJohn Marino 	max--;
113632fe07f8SJohn Marino 
113732fe07f8SJohn Marino 	if (start == '$')
113832fe07f8SJohn Marino 		start = (int)max;
113932fe07f8SJohn Marino 	if (end == '$')
114032fe07f8SJohn Marino 		end = (int)max;
114132fe07f8SJohn Marino 	if (end < 0)
114232fe07f8SJohn Marino 		end = (int)max + end + 1;
114332fe07f8SJohn Marino 	if (start < 0)
114432fe07f8SJohn Marino 		start = end;
114532fe07f8SJohn Marino 
114632fe07f8SJohn Marino 	if (start < 0 || end < 0 || (size_t)start > max ||
114732fe07f8SJohn Marino 	    (size_t)end > max || start > end)
114832fe07f8SJohn Marino 		goto out;
114932fe07f8SJohn Marino 
115032fe07f8SJohn Marino 	for (i = (size_t)start, len = 0; i <= (size_t)end; i++)
115132fe07f8SJohn Marino 		len += strlen(arr[i]) + 1;
115232fe07f8SJohn Marino 	len++;
115360ecde0cSDaniel Fojt 	result = el_calloc(len, sizeof(*result));
115432fe07f8SJohn Marino 	if (result == NULL)
115532fe07f8SJohn Marino 		goto out;
115632fe07f8SJohn Marino 
115732fe07f8SJohn Marino 	for (i = (size_t)start, len = 0; i <= (size_t)end; i++) {
115832fe07f8SJohn Marino 		(void)strcpy(result + len, arr[i]);
115932fe07f8SJohn Marino 		len += strlen(arr[i]);
116032fe07f8SJohn Marino 		if (i < (size_t)end)
116132fe07f8SJohn Marino 			result[len++] = ' ';
116232fe07f8SJohn Marino 	}
116332fe07f8SJohn Marino 	result[len] = '\0';
116432fe07f8SJohn Marino 
116532fe07f8SJohn Marino out:
116632fe07f8SJohn Marino 	for (i = 0; arr[i]; i++)
116732fe07f8SJohn Marino 		el_free(arr[i]);
116832fe07f8SJohn Marino 	el_free(arr);
116932fe07f8SJohn Marino 
117032fe07f8SJohn Marino 	return result;
117132fe07f8SJohn Marino }
117232fe07f8SJohn Marino 
117332fe07f8SJohn Marino /*
117432fe07f8SJohn Marino  * Parse the string into individual tokens,
117532fe07f8SJohn Marino  * similar to how shell would do it.
117632fe07f8SJohn Marino  */
117732fe07f8SJohn Marino char **
history_tokenize(const char * str)117832fe07f8SJohn Marino history_tokenize(const char *str)
117932fe07f8SJohn Marino {
118032fe07f8SJohn Marino 	int size = 1, idx = 0, i, start;
118132fe07f8SJohn Marino 	size_t len;
118232fe07f8SJohn Marino 	char **result = NULL, *temp, delim = '\0';
118332fe07f8SJohn Marino 
118432fe07f8SJohn Marino 	for (i = 0; str[i];) {
118532fe07f8SJohn Marino 		while (isspace((unsigned char) str[i]))
118632fe07f8SJohn Marino 			i++;
118732fe07f8SJohn Marino 		start = i;
118832fe07f8SJohn Marino 		for (; str[i];) {
118932fe07f8SJohn Marino 			if (str[i] == '\\') {
119032fe07f8SJohn Marino 				if (str[i+1] != '\0')
119132fe07f8SJohn Marino 					i++;
119232fe07f8SJohn Marino 			} else if (str[i] == delim)
119332fe07f8SJohn Marino 				delim = '\0';
119432fe07f8SJohn Marino 			else if (!delim &&
119532fe07f8SJohn Marino 				    (isspace((unsigned char) str[i]) ||
119632fe07f8SJohn Marino 				strchr("()<>;&|$", str[i])))
119732fe07f8SJohn Marino 				break;
119832fe07f8SJohn Marino 			else if (!delim && strchr("'`\"", str[i]))
119932fe07f8SJohn Marino 				delim = str[i];
120032fe07f8SJohn Marino 			if (str[i])
120132fe07f8SJohn Marino 				i++;
120232fe07f8SJohn Marino 		}
120332fe07f8SJohn Marino 
120432fe07f8SJohn Marino 		if (idx + 2 >= size) {
120532fe07f8SJohn Marino 			char **nresult;
120632fe07f8SJohn Marino 			size <<= 1;
120732fe07f8SJohn Marino 			nresult = el_realloc(result, (size_t)size * sizeof(*nresult));
120832fe07f8SJohn Marino 			if (nresult == NULL) {
120932fe07f8SJohn Marino 				el_free(result);
121032fe07f8SJohn Marino 				return NULL;
121132fe07f8SJohn Marino 			}
121232fe07f8SJohn Marino 			result = nresult;
121332fe07f8SJohn Marino 		}
121432fe07f8SJohn Marino 		len = (size_t)i - (size_t)start;
121560ecde0cSDaniel Fojt 		temp = el_calloc(len + 1, sizeof(*temp));
121632fe07f8SJohn Marino 		if (temp == NULL) {
121732fe07f8SJohn Marino 			for (i = 0; i < idx; i++)
121832fe07f8SJohn Marino 				el_free(result[i]);
121932fe07f8SJohn Marino 			el_free(result);
122032fe07f8SJohn Marino 			return NULL;
122132fe07f8SJohn Marino 		}
122260ecde0cSDaniel Fojt 		(void)strlcpy(temp, &str[start], len + 1);
122332fe07f8SJohn Marino 		result[idx++] = temp;
122432fe07f8SJohn Marino 		result[idx] = NULL;
122532fe07f8SJohn Marino 		if (str[i])
122632fe07f8SJohn Marino 			i++;
122732fe07f8SJohn Marino 	}
122832fe07f8SJohn Marino 	return result;
122932fe07f8SJohn Marino }
123032fe07f8SJohn Marino 
123132fe07f8SJohn Marino 
123232fe07f8SJohn Marino /*
123332fe07f8SJohn Marino  * limit size of history record to ``max'' events
123432fe07f8SJohn Marino  */
123532fe07f8SJohn Marino void
stifle_history(int max)123632fe07f8SJohn Marino stifle_history(int max)
123732fe07f8SJohn Marino {
123832fe07f8SJohn Marino 	HistEvent ev;
123912db70c8Szrj 	HIST_ENTRY *he;
124032fe07f8SJohn Marino 
124132fe07f8SJohn Marino 	if (h == NULL || e == NULL)
124232fe07f8SJohn Marino 		rl_initialize();
124332fe07f8SJohn Marino 
124412db70c8Szrj 	if (history(h, &ev, H_SETSIZE, max) == 0) {
124532fe07f8SJohn Marino 		max_input_history = max;
124612db70c8Szrj 		if (history_length > max)
124712db70c8Szrj 			history_base = history_length - max;
124812db70c8Szrj 		while (history_length > max) {
124912db70c8Szrj 			he = remove_history(0);
125012db70c8Szrj 			el_free(he->data);
125112db70c8Szrj 			el_free((void *)(unsigned long)he->line);
125212db70c8Szrj 			el_free(he);
125312db70c8Szrj 		}
125412db70c8Szrj 	}
125532fe07f8SJohn Marino }
125632fe07f8SJohn Marino 
125732fe07f8SJohn Marino 
125832fe07f8SJohn Marino /*
125932fe07f8SJohn Marino  * "unlimit" size of history - set the limit to maximum allowed int value
126032fe07f8SJohn Marino  */
126132fe07f8SJohn Marino int
unstifle_history(void)126232fe07f8SJohn Marino unstifle_history(void)
126332fe07f8SJohn Marino {
126432fe07f8SJohn Marino 	HistEvent ev;
126532fe07f8SJohn Marino 	int omax;
126632fe07f8SJohn Marino 
126732fe07f8SJohn Marino 	history(h, &ev, H_SETSIZE, INT_MAX);
126832fe07f8SJohn Marino 	omax = max_input_history;
126932fe07f8SJohn Marino 	max_input_history = INT_MAX;
127032fe07f8SJohn Marino 	return omax;		/* some value _must_ be returned */
127132fe07f8SJohn Marino }
127232fe07f8SJohn Marino 
127332fe07f8SJohn Marino 
127432fe07f8SJohn Marino int
history_is_stifled(void)127532fe07f8SJohn Marino history_is_stifled(void)
127632fe07f8SJohn Marino {
127732fe07f8SJohn Marino 
127832fe07f8SJohn Marino 	/* cannot return true answer */
127932fe07f8SJohn Marino 	return max_input_history != INT_MAX;
128032fe07f8SJohn Marino }
128132fe07f8SJohn Marino 
128232fe07f8SJohn Marino static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
128332fe07f8SJohn Marino 
128432fe07f8SJohn Marino int
history_truncate_file(const char * filename,int nlines)128532fe07f8SJohn Marino history_truncate_file (const char *filename, int nlines)
128632fe07f8SJohn Marino {
128732fe07f8SJohn Marino 	int ret = 0;
128832fe07f8SJohn Marino 	FILE *fp, *tp;
128932fe07f8SJohn Marino 	char template[sizeof(_history_tmp_template)];
129032fe07f8SJohn Marino 	char buf[4096];
129132fe07f8SJohn Marino 	int fd;
129232fe07f8SJohn Marino 	char *cp;
129332fe07f8SJohn Marino 	off_t off;
129432fe07f8SJohn Marino 	int count = 0;
129532fe07f8SJohn Marino 	ssize_t left = 0;
129632fe07f8SJohn Marino 
129732fe07f8SJohn Marino 	if (filename == NULL && (filename = _default_history_file()) == NULL)
129832fe07f8SJohn Marino 		return errno;
129932fe07f8SJohn Marino 	if ((fp = fopen(filename, "r+")) == NULL)
130032fe07f8SJohn Marino 		return errno;
130132fe07f8SJohn Marino 	strcpy(template, _history_tmp_template);
130232fe07f8SJohn Marino 	if ((fd = mkstemp(template)) == -1) {
130332fe07f8SJohn Marino 		ret = errno;
130432fe07f8SJohn Marino 		goto out1;
130532fe07f8SJohn Marino 	}
130632fe07f8SJohn Marino 
130732fe07f8SJohn Marino 	if ((tp = fdopen(fd, "r+")) == NULL) {
130832fe07f8SJohn Marino 		close(fd);
130932fe07f8SJohn Marino 		ret = errno;
131032fe07f8SJohn Marino 		goto out2;
131132fe07f8SJohn Marino 	}
131232fe07f8SJohn Marino 
131332fe07f8SJohn Marino 	for(;;) {
131432fe07f8SJohn Marino 		if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) {
131532fe07f8SJohn Marino 			if (ferror(fp)) {
131632fe07f8SJohn Marino 				ret = errno;
131732fe07f8SJohn Marino 				break;
131832fe07f8SJohn Marino 			}
131932fe07f8SJohn Marino 			if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
132032fe07f8SJohn Marino 			    (off_t)-1) {
132132fe07f8SJohn Marino 				ret = errno;
132232fe07f8SJohn Marino 				break;
132332fe07f8SJohn Marino 			}
132432fe07f8SJohn Marino 			left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp);
132532fe07f8SJohn Marino 			if (ferror(fp)) {
132632fe07f8SJohn Marino 				ret = errno;
132732fe07f8SJohn Marino 				break;
132832fe07f8SJohn Marino 			}
132932fe07f8SJohn Marino 			if (left == 0) {
133032fe07f8SJohn Marino 				count--;
133132fe07f8SJohn Marino 				left = sizeof(buf);
133232fe07f8SJohn Marino 			} else if (fwrite(buf, (size_t)left, (size_t)1, tp)
133332fe07f8SJohn Marino 			    != 1) {
133432fe07f8SJohn Marino 				ret = errno;
133532fe07f8SJohn Marino 				break;
133632fe07f8SJohn Marino 			}
133732fe07f8SJohn Marino 			fflush(tp);
133832fe07f8SJohn Marino 			break;
133932fe07f8SJohn Marino 		}
134032fe07f8SJohn Marino 		if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) {
134132fe07f8SJohn Marino 			ret = errno;
134232fe07f8SJohn Marino 			break;
134332fe07f8SJohn Marino 		}
134432fe07f8SJohn Marino 		count++;
134532fe07f8SJohn Marino 	}
134632fe07f8SJohn Marino 	if (ret)
134732fe07f8SJohn Marino 		goto out3;
134832fe07f8SJohn Marino 	cp = buf + left - 1;
134932fe07f8SJohn Marino 	if(*cp != '\n')
135032fe07f8SJohn Marino 		cp++;
135132fe07f8SJohn Marino 	for(;;) {
135232fe07f8SJohn Marino 		while (--cp >= buf) {
135332fe07f8SJohn Marino 			if (*cp == '\n') {
135432fe07f8SJohn Marino 				if (--nlines == 0) {
135532fe07f8SJohn Marino 					if (++cp >= buf + sizeof(buf)) {
135632fe07f8SJohn Marino 						count++;
135732fe07f8SJohn Marino 						cp = buf;
135832fe07f8SJohn Marino 					}
135932fe07f8SJohn Marino 					break;
136032fe07f8SJohn Marino 				}
136132fe07f8SJohn Marino 			}
136232fe07f8SJohn Marino 		}
136332fe07f8SJohn Marino 		if (nlines <= 0 || count == 0)
136432fe07f8SJohn Marino 			break;
136532fe07f8SJohn Marino 		count--;
136632fe07f8SJohn Marino 		if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
136732fe07f8SJohn Marino 			ret = errno;
136832fe07f8SJohn Marino 			break;
136932fe07f8SJohn Marino 		}
137032fe07f8SJohn Marino 		if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) {
137132fe07f8SJohn Marino 			if (ferror(tp)) {
137232fe07f8SJohn Marino 				ret = errno;
137332fe07f8SJohn Marino 				break;
137432fe07f8SJohn Marino 			}
137532fe07f8SJohn Marino 			ret = EAGAIN;
137632fe07f8SJohn Marino 			break;
137732fe07f8SJohn Marino 		}
137832fe07f8SJohn Marino 		cp = buf + sizeof(buf);
137932fe07f8SJohn Marino 	}
138032fe07f8SJohn Marino 
138132fe07f8SJohn Marino 	if (ret || nlines > 0)
138232fe07f8SJohn Marino 		goto out3;
138332fe07f8SJohn Marino 
138432fe07f8SJohn Marino 	if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
138532fe07f8SJohn Marino 		ret = errno;
138632fe07f8SJohn Marino 		goto out3;
138732fe07f8SJohn Marino 	}
138832fe07f8SJohn Marino 
138932fe07f8SJohn Marino 	if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
139032fe07f8SJohn Marino 	    (off_t)-1) {
139132fe07f8SJohn Marino 		ret = errno;
139232fe07f8SJohn Marino 		goto out3;
139332fe07f8SJohn Marino 	}
139432fe07f8SJohn Marino 
139532fe07f8SJohn Marino 	for(;;) {
139632fe07f8SJohn Marino 		if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) {
139732fe07f8SJohn Marino 			if (ferror(fp))
139832fe07f8SJohn Marino 				ret = errno;
139932fe07f8SJohn Marino 			break;
140032fe07f8SJohn Marino 		}
140132fe07f8SJohn Marino 		if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) {
140232fe07f8SJohn Marino 			ret = errno;
140332fe07f8SJohn Marino 			break;
140432fe07f8SJohn Marino 		}
140532fe07f8SJohn Marino 	}
140632fe07f8SJohn Marino 	fflush(fp);
140732fe07f8SJohn Marino 	if((off = ftello(fp)) > 0)
140832fe07f8SJohn Marino 		(void)ftruncate(fileno(fp), off);
140932fe07f8SJohn Marino out3:
141032fe07f8SJohn Marino 	fclose(tp);
141132fe07f8SJohn Marino out2:
141232fe07f8SJohn Marino 	unlink(template);
141332fe07f8SJohn Marino out1:
141432fe07f8SJohn Marino 	fclose(fp);
141532fe07f8SJohn Marino 
141632fe07f8SJohn Marino 	return ret;
141732fe07f8SJohn Marino }
141832fe07f8SJohn Marino 
141932fe07f8SJohn Marino 
142032fe07f8SJohn Marino /*
142132fe07f8SJohn Marino  * read history from a file given
142232fe07f8SJohn Marino  */
142332fe07f8SJohn Marino int
read_history(const char * filename)142432fe07f8SJohn Marino read_history(const char *filename)
142532fe07f8SJohn Marino {
142632fe07f8SJohn Marino 	HistEvent ev;
142732fe07f8SJohn Marino 
142832fe07f8SJohn Marino 	if (h == NULL || e == NULL)
142932fe07f8SJohn Marino 		rl_initialize();
143032fe07f8SJohn Marino 	if (filename == NULL && (filename = _default_history_file()) == NULL)
143132fe07f8SJohn Marino 		return errno;
1432ae19eda8Szrj 	errno = 0;
1433ae19eda8Szrj 	if (history(h, &ev, H_LOAD, filename) == -1)
1434ae19eda8Szrj 		return errno ? errno : EINVAL;
1435ae19eda8Szrj 	if (history(h, &ev, H_GETSIZE) == 0)
1436ae19eda8Szrj 		history_length = ev.num;
1437ae19eda8Szrj 	if (history_length < 0)
1438ae19eda8Szrj 		return EINVAL;
1439ae19eda8Szrj 	return 0;
144032fe07f8SJohn Marino }
144132fe07f8SJohn Marino 
144232fe07f8SJohn Marino 
144332fe07f8SJohn Marino /*
144432fe07f8SJohn Marino  * write history to a file given
144532fe07f8SJohn Marino  */
144632fe07f8SJohn Marino int
write_history(const char * filename)144732fe07f8SJohn Marino write_history(const char *filename)
144832fe07f8SJohn Marino {
144932fe07f8SJohn Marino 	HistEvent ev;
145032fe07f8SJohn Marino 
145132fe07f8SJohn Marino 	if (h == NULL || e == NULL)
145232fe07f8SJohn Marino 		rl_initialize();
145332fe07f8SJohn Marino 	if (filename == NULL && (filename = _default_history_file()) == NULL)
145432fe07f8SJohn Marino 		return errno;
145532fe07f8SJohn Marino 	return history(h, &ev, H_SAVE, filename) == -1 ?
145632fe07f8SJohn Marino 	    (errno ? errno : EINVAL) : 0;
145732fe07f8SJohn Marino }
145832fe07f8SJohn Marino 
1459ae19eda8Szrj int
append_history(int n,const char * filename)1460ae19eda8Szrj append_history(int n, const char *filename)
1461ae19eda8Szrj {
1462ae19eda8Szrj 	HistEvent ev;
1463ae19eda8Szrj 	FILE *fp;
1464ae19eda8Szrj 
1465ae19eda8Szrj 	if (h == NULL || e == NULL)
1466ae19eda8Szrj 		rl_initialize();
1467ae19eda8Szrj 	if (filename == NULL && (filename = _default_history_file()) == NULL)
1468ae19eda8Szrj 		return errno;
1469ae19eda8Szrj 
1470ae19eda8Szrj 	if ((fp = fopen(filename, "a")) == NULL)
1471ae19eda8Szrj 		return errno;
1472ae19eda8Szrj 
1473ae19eda8Szrj 	if (history(h, &ev, H_NSAVE_FP, (size_t)n,  fp) == -1) {
1474ae19eda8Szrj 		int serrno = errno ? errno : EINVAL;
1475ae19eda8Szrj 		fclose(fp);
1476ae19eda8Szrj 		return serrno;
1477ae19eda8Szrj 	}
1478ae19eda8Szrj 	fclose(fp);
1479ae19eda8Szrj 	return 0;
1480ae19eda8Szrj }
148132fe07f8SJohn Marino 
148232fe07f8SJohn Marino /*
148332fe07f8SJohn Marino  * returns history ``num''th event
148432fe07f8SJohn Marino  *
148532fe07f8SJohn Marino  * returned pointer points to static variable
148632fe07f8SJohn Marino  */
148732fe07f8SJohn Marino HIST_ENTRY *
history_get(int num)148832fe07f8SJohn Marino history_get(int num)
148932fe07f8SJohn Marino {
149032fe07f8SJohn Marino 	static HIST_ENTRY she;
149132fe07f8SJohn Marino 	HistEvent ev;
149232fe07f8SJohn Marino 	int curr_num;
149332fe07f8SJohn Marino 
149432fe07f8SJohn Marino 	if (h == NULL || e == NULL)
149532fe07f8SJohn Marino 		rl_initialize();
149632fe07f8SJohn Marino 
149712db70c8Szrj 	if (num < history_base)
149812db70c8Szrj 		return NULL;
149912db70c8Szrj 
150032fe07f8SJohn Marino 	/* save current position */
150132fe07f8SJohn Marino 	if (history(h, &ev, H_CURR) != 0)
150232fe07f8SJohn Marino 		return NULL;
150332fe07f8SJohn Marino 	curr_num = ev.num;
150432fe07f8SJohn Marino 
150512db70c8Szrj 	/*
150612db70c8Szrj 	 * use H_DELDATA to set to nth history (without delete) by passing
150712db70c8Szrj 	 * (void **)-1  -- as in history_set_pos
150812db70c8Szrj 	 */
150912db70c8Szrj 	if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0)
151012db70c8Szrj 		goto out;
151132fe07f8SJohn Marino 
151212db70c8Szrj 	/* get current entry */
151312db70c8Szrj 	if (history(h, &ev, H_CURR) != 0)
151412db70c8Szrj 		goto out;
151512db70c8Szrj 	if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0)
151612db70c8Szrj 		goto out;
151732fe07f8SJohn Marino 	she.line = ev.str;
151832fe07f8SJohn Marino 
151932fe07f8SJohn Marino 	/* restore pointer to where it was */
152032fe07f8SJohn Marino 	(void)history(h, &ev, H_SET, curr_num);
152132fe07f8SJohn Marino 
152232fe07f8SJohn Marino 	return &she;
152312db70c8Szrj 
152412db70c8Szrj out:
152512db70c8Szrj 	/* restore pointer to where it was */
152612db70c8Szrj 	(void)history(h, &ev, H_SET, curr_num);
152712db70c8Szrj 	return NULL;
152832fe07f8SJohn Marino }
152932fe07f8SJohn Marino 
153032fe07f8SJohn Marino 
153132fe07f8SJohn Marino /*
153232fe07f8SJohn Marino  * add the line to history table
153332fe07f8SJohn Marino  */
153432fe07f8SJohn Marino int
add_history(const char * line)153532fe07f8SJohn Marino add_history(const char *line)
153632fe07f8SJohn Marino {
153732fe07f8SJohn Marino 	HistEvent ev;
153832fe07f8SJohn Marino 
153932fe07f8SJohn Marino 	if (h == NULL || e == NULL)
154032fe07f8SJohn Marino 		rl_initialize();
154132fe07f8SJohn Marino 
154212db70c8Szrj 	if (history(h, &ev, H_ENTER, line) == -1)
154312db70c8Szrj 		return 0;
154432fe07f8SJohn Marino 
154512db70c8Szrj 	(void)history(h, &ev, H_GETSIZE);
154612db70c8Szrj 	if (ev.num == history_length)
154712db70c8Szrj 		history_base++;
154860ecde0cSDaniel Fojt 	else {
154960ecde0cSDaniel Fojt 		history_offset++;
155012db70c8Szrj 		history_length = ev.num;
155160ecde0cSDaniel Fojt 	}
155212db70c8Szrj 	return 0;
155332fe07f8SJohn Marino }
155432fe07f8SJohn Marino 
155532fe07f8SJohn Marino 
155632fe07f8SJohn Marino /*
155732fe07f8SJohn Marino  * remove the specified entry from the history list and return it.
155832fe07f8SJohn Marino  */
155932fe07f8SJohn Marino HIST_ENTRY *
remove_history(int num)156032fe07f8SJohn Marino remove_history(int num)
156132fe07f8SJohn Marino {
156232fe07f8SJohn Marino 	HIST_ENTRY *he;
156332fe07f8SJohn Marino 	HistEvent ev;
156432fe07f8SJohn Marino 
156532fe07f8SJohn Marino 	if (h == NULL || e == NULL)
156632fe07f8SJohn Marino 		rl_initialize();
156732fe07f8SJohn Marino 
156832fe07f8SJohn Marino 	if ((he = el_malloc(sizeof(*he))) == NULL)
156932fe07f8SJohn Marino 		return NULL;
157032fe07f8SJohn Marino 
157132fe07f8SJohn Marino 	if (history(h, &ev, H_DELDATA, num, &he->data) != 0) {
157232fe07f8SJohn Marino 		el_free(he);
157332fe07f8SJohn Marino 		return NULL;
157432fe07f8SJohn Marino 	}
157532fe07f8SJohn Marino 
157632fe07f8SJohn Marino 	he->line = ev.str;
157732fe07f8SJohn Marino 	if (history(h, &ev, H_GETSIZE) == 0)
157832fe07f8SJohn Marino 		history_length = ev.num;
157932fe07f8SJohn Marino 
158032fe07f8SJohn Marino 	return he;
158132fe07f8SJohn Marino }
158232fe07f8SJohn Marino 
158332fe07f8SJohn Marino 
158432fe07f8SJohn Marino /*
158532fe07f8SJohn Marino  * replace the line and data of the num-th entry
158632fe07f8SJohn Marino  */
158732fe07f8SJohn Marino HIST_ENTRY *
replace_history_entry(int num,const char * line,histdata_t data)158832fe07f8SJohn Marino replace_history_entry(int num, const char *line, histdata_t data)
158932fe07f8SJohn Marino {
159032fe07f8SJohn Marino 	HIST_ENTRY *he;
159132fe07f8SJohn Marino 	HistEvent ev;
159232fe07f8SJohn Marino 	int curr_num;
159332fe07f8SJohn Marino 
159432fe07f8SJohn Marino 	if (h == NULL || e == NULL)
159532fe07f8SJohn Marino 		rl_initialize();
159632fe07f8SJohn Marino 
159732fe07f8SJohn Marino 	/* save current position */
159832fe07f8SJohn Marino 	if (history(h, &ev, H_CURR) != 0)
159932fe07f8SJohn Marino 		return NULL;
160032fe07f8SJohn Marino 	curr_num = ev.num;
160132fe07f8SJohn Marino 
160232fe07f8SJohn Marino 	/* start from the oldest */
160332fe07f8SJohn Marino 	if (history(h, &ev, H_LAST) != 0)
160432fe07f8SJohn Marino 		return NULL;	/* error */
160532fe07f8SJohn Marino 
160632fe07f8SJohn Marino 	if ((he = el_malloc(sizeof(*he))) == NULL)
160732fe07f8SJohn Marino 		return NULL;
160832fe07f8SJohn Marino 
160932fe07f8SJohn Marino 	/* look forwards for event matching specified offset */
161032fe07f8SJohn Marino 	if (history(h, &ev, H_NEXT_EVDATA, num, &he->data))
161132fe07f8SJohn Marino 		goto out;
161232fe07f8SJohn Marino 
161332fe07f8SJohn Marino 	he->line = strdup(ev.str);
161432fe07f8SJohn Marino 	if (he->line == NULL)
161532fe07f8SJohn Marino 		goto out;
161632fe07f8SJohn Marino 
161732fe07f8SJohn Marino 	if (history(h, &ev, H_REPLACE, line, data))
161832fe07f8SJohn Marino 		goto out;
161932fe07f8SJohn Marino 
162032fe07f8SJohn Marino 	/* restore pointer to where it was */
162132fe07f8SJohn Marino 	if (history(h, &ev, H_SET, curr_num))
162232fe07f8SJohn Marino 		goto out;
162332fe07f8SJohn Marino 
162432fe07f8SJohn Marino 	return he;
162532fe07f8SJohn Marino out:
162632fe07f8SJohn Marino 	el_free(he);
162732fe07f8SJohn Marino 	return NULL;
162832fe07f8SJohn Marino }
162932fe07f8SJohn Marino 
163032fe07f8SJohn Marino /*
163132fe07f8SJohn Marino  * clear the history list - delete all entries
163232fe07f8SJohn Marino  */
163332fe07f8SJohn Marino void
clear_history(void)163432fe07f8SJohn Marino clear_history(void)
163532fe07f8SJohn Marino {
163632fe07f8SJohn Marino 	HistEvent ev;
163732fe07f8SJohn Marino 
163884b940c1SJohn Marino 	if (h == NULL || e == NULL)
163984b940c1SJohn Marino 		rl_initialize();
164084b940c1SJohn Marino 
164132fe07f8SJohn Marino 	(void)history(h, &ev, H_CLEAR);
164212db70c8Szrj 	history_offset = history_length = 0;
164332fe07f8SJohn Marino }
164432fe07f8SJohn Marino 
164532fe07f8SJohn Marino 
164632fe07f8SJohn Marino /*
164732fe07f8SJohn Marino  * returns offset of the current history event
164832fe07f8SJohn Marino  */
164932fe07f8SJohn Marino int
where_history(void)165032fe07f8SJohn Marino where_history(void)
165132fe07f8SJohn Marino {
165212db70c8Szrj 	return history_offset;
165332fe07f8SJohn Marino }
165432fe07f8SJohn Marino 
165512db70c8Szrj static HIST_ENTRY **_history_listp;
165612db70c8Szrj static HIST_ENTRY *_history_list;
165712db70c8Szrj 
165812db70c8Szrj HIST_ENTRY **
history_list(void)165912db70c8Szrj history_list(void)
166012db70c8Szrj {
166112db70c8Szrj 	HistEvent ev;
166212db70c8Szrj 	HIST_ENTRY **nlp, *nl;
166312db70c8Szrj 	int i;
166412db70c8Szrj 
166512db70c8Szrj 	if (history(h, &ev, H_LAST) != 0)
166612db70c8Szrj 		return NULL;
166712db70c8Szrj 
166812db70c8Szrj 	if ((nlp = el_realloc(_history_listp,
1669ae19eda8Szrj 	    ((size_t)history_length + 1) * sizeof(*nlp))) == NULL)
167012db70c8Szrj 		return NULL;
167112db70c8Szrj 	_history_listp = nlp;
167212db70c8Szrj 
167312db70c8Szrj 	if ((nl = el_realloc(_history_list,
167412db70c8Szrj 	    (size_t)history_length * sizeof(*nl))) == NULL)
167512db70c8Szrj 		return NULL;
167612db70c8Szrj 	_history_list = nl;
167712db70c8Szrj 
167812db70c8Szrj 	i = 0;
167912db70c8Szrj 	do {
168012db70c8Szrj 		_history_listp[i] = &_history_list[i];
168112db70c8Szrj 		_history_list[i].line = ev.str;
168212db70c8Szrj 		_history_list[i].data = NULL;
168312db70c8Szrj 		if (i++ == history_length)
168412db70c8Szrj 			abort();
168512db70c8Szrj 	} while (history(h, &ev, H_PREV) == 0);
1686ae19eda8Szrj 	_history_listp[i] = NULL;
168712db70c8Szrj 	return _history_listp;
168812db70c8Szrj }
168932fe07f8SJohn Marino 
169032fe07f8SJohn Marino /*
169132fe07f8SJohn Marino  * returns current history event or NULL if there is no such event
169232fe07f8SJohn Marino  */
169332fe07f8SJohn Marino HIST_ENTRY *
current_history(void)169432fe07f8SJohn Marino current_history(void)
169532fe07f8SJohn Marino {
169612db70c8Szrj 	HistEvent ev;
169732fe07f8SJohn Marino 
169812db70c8Szrj 	if (history(h, &ev, H_PREV_EVENT, history_offset + 1) != 0)
169912db70c8Szrj 		return NULL;
170012db70c8Szrj 
170112db70c8Szrj 	rl_he.line = ev.str;
170212db70c8Szrj 	rl_he.data = NULL;
170312db70c8Szrj 	return &rl_he;
170432fe07f8SJohn Marino }
170532fe07f8SJohn Marino 
170632fe07f8SJohn Marino 
170732fe07f8SJohn Marino /*
170832fe07f8SJohn Marino  * returns total number of bytes history events' data are using
170932fe07f8SJohn Marino  */
171032fe07f8SJohn Marino int
history_total_bytes(void)171132fe07f8SJohn Marino history_total_bytes(void)
171232fe07f8SJohn Marino {
171332fe07f8SJohn Marino 	HistEvent ev;
171432fe07f8SJohn Marino 	int curr_num;
171532fe07f8SJohn Marino 	size_t size;
171632fe07f8SJohn Marino 
171732fe07f8SJohn Marino 	if (history(h, &ev, H_CURR) != 0)
171832fe07f8SJohn Marino 		return -1;
171932fe07f8SJohn Marino 	curr_num = ev.num;
172032fe07f8SJohn Marino 
172132fe07f8SJohn Marino 	(void)history(h, &ev, H_FIRST);
172232fe07f8SJohn Marino 	size = 0;
172332fe07f8SJohn Marino 	do
172432fe07f8SJohn Marino 		size += strlen(ev.str) * sizeof(*ev.str);
172532fe07f8SJohn Marino 	while (history(h, &ev, H_NEXT) == 0);
172632fe07f8SJohn Marino 
172732fe07f8SJohn Marino 	/* get to the same position as before */
172832fe07f8SJohn Marino 	history(h, &ev, H_PREV_EVENT, curr_num);
172932fe07f8SJohn Marino 
173032fe07f8SJohn Marino 	return (int)size;
173132fe07f8SJohn Marino }
173232fe07f8SJohn Marino 
173332fe07f8SJohn Marino 
173432fe07f8SJohn Marino /*
173532fe07f8SJohn Marino  * sets the position in the history list to ``pos''
173632fe07f8SJohn Marino  */
173732fe07f8SJohn Marino int
history_set_pos(int pos)173832fe07f8SJohn Marino history_set_pos(int pos)
173932fe07f8SJohn Marino {
174032fe07f8SJohn Marino 	if (pos >= history_length || pos < 0)
174132fe07f8SJohn Marino 		return 0;
174212db70c8Szrj 
174312db70c8Szrj 	history_offset = pos;
174412db70c8Szrj 	return 1;
174532fe07f8SJohn Marino }
174632fe07f8SJohn Marino 
174732fe07f8SJohn Marino 
174832fe07f8SJohn Marino /*
174932fe07f8SJohn Marino  * returns previous event in history and shifts pointer accordingly
175012db70c8Szrj  * Note that readline and editline define directions in opposite ways.
175132fe07f8SJohn Marino  */
175232fe07f8SJohn Marino HIST_ENTRY *
previous_history(void)175332fe07f8SJohn Marino previous_history(void)
175432fe07f8SJohn Marino {
175512db70c8Szrj 	HistEvent ev;
175632fe07f8SJohn Marino 
175712db70c8Szrj 	if (history_offset == 0)
175812db70c8Szrj 		return NULL;
175912db70c8Szrj 
176012db70c8Szrj 	if (history(h, &ev, H_LAST) != 0)
176112db70c8Szrj 		return NULL;
176212db70c8Szrj 
176312db70c8Szrj 	history_offset--;
176412db70c8Szrj 	return current_history();
176532fe07f8SJohn Marino }
176632fe07f8SJohn Marino 
176732fe07f8SJohn Marino 
176832fe07f8SJohn Marino /*
176932fe07f8SJohn Marino  * returns next event in history and shifts pointer accordingly
177032fe07f8SJohn Marino  */
177132fe07f8SJohn Marino HIST_ENTRY *
next_history(void)177232fe07f8SJohn Marino next_history(void)
177332fe07f8SJohn Marino {
177412db70c8Szrj 	HistEvent ev;
177532fe07f8SJohn Marino 
177612db70c8Szrj 	if (history_offset >= history_length)
177712db70c8Szrj 		return NULL;
177812db70c8Szrj 
177912db70c8Szrj 	if (history(h, &ev, H_LAST) != 0)
178012db70c8Szrj 		return NULL;
178112db70c8Szrj 
178212db70c8Szrj 	history_offset++;
178312db70c8Szrj 	return current_history();
178432fe07f8SJohn Marino }
178532fe07f8SJohn Marino 
178632fe07f8SJohn Marino 
178732fe07f8SJohn Marino /*
178832fe07f8SJohn Marino  * searches for first history event containing the str
178932fe07f8SJohn Marino  */
179032fe07f8SJohn Marino int
history_search(const char * str,int direction)179132fe07f8SJohn Marino history_search(const char *str, int direction)
179232fe07f8SJohn Marino {
179332fe07f8SJohn Marino 	HistEvent ev;
179432fe07f8SJohn Marino 	const char *strp;
179532fe07f8SJohn Marino 	int curr_num;
179632fe07f8SJohn Marino 
179732fe07f8SJohn Marino 	if (history(h, &ev, H_CURR) != 0)
179832fe07f8SJohn Marino 		return -1;
179932fe07f8SJohn Marino 	curr_num = ev.num;
180032fe07f8SJohn Marino 
180132fe07f8SJohn Marino 	for (;;) {
180232fe07f8SJohn Marino 		if ((strp = strstr(ev.str, str)) != NULL)
180332fe07f8SJohn Marino 			return (int)(strp - ev.str);
180432fe07f8SJohn Marino 		if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
180532fe07f8SJohn Marino 			break;
180632fe07f8SJohn Marino 	}
180732fe07f8SJohn Marino 	(void)history(h, &ev, H_SET, curr_num);
180832fe07f8SJohn Marino 	return -1;
180932fe07f8SJohn Marino }
181032fe07f8SJohn Marino 
181132fe07f8SJohn Marino 
181232fe07f8SJohn Marino /*
181332fe07f8SJohn Marino  * searches for first history event beginning with str
181432fe07f8SJohn Marino  */
181532fe07f8SJohn Marino int
history_search_prefix(const char * str,int direction)181632fe07f8SJohn Marino history_search_prefix(const char *str, int direction)
181732fe07f8SJohn Marino {
181832fe07f8SJohn Marino 	HistEvent ev;
181932fe07f8SJohn Marino 
182032fe07f8SJohn Marino 	return (history(h, &ev, direction < 0 ?
182132fe07f8SJohn Marino 	    H_PREV_STR : H_NEXT_STR, str));
182232fe07f8SJohn Marino }
182332fe07f8SJohn Marino 
182432fe07f8SJohn Marino 
182532fe07f8SJohn Marino /*
182632fe07f8SJohn Marino  * search for event in history containing str, starting at offset
182732fe07f8SJohn Marino  * abs(pos); continue backward, if pos<0, forward otherwise
182832fe07f8SJohn Marino  */
182932fe07f8SJohn Marino /* ARGSUSED */
183032fe07f8SJohn Marino int
history_search_pos(const char * str,int direction,int pos)183132fe07f8SJohn Marino history_search_pos(const char *str,
183232fe07f8SJohn Marino 		   int direction __attribute__((__unused__)), int pos)
183332fe07f8SJohn Marino {
183432fe07f8SJohn Marino 	HistEvent ev;
183532fe07f8SJohn Marino 	int curr_num, off;
183632fe07f8SJohn Marino 
183732fe07f8SJohn Marino 	off = (pos > 0) ? pos : -pos;
183832fe07f8SJohn Marino 	pos = (pos > 0) ? 1 : -1;
183932fe07f8SJohn Marino 
184032fe07f8SJohn Marino 	if (history(h, &ev, H_CURR) != 0)
184132fe07f8SJohn Marino 		return -1;
184232fe07f8SJohn Marino 	curr_num = ev.num;
184332fe07f8SJohn Marino 
184412db70c8Szrj 	if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0)
184532fe07f8SJohn Marino 		return -1;
184632fe07f8SJohn Marino 
184732fe07f8SJohn Marino 	for (;;) {
184832fe07f8SJohn Marino 		if (strstr(ev.str, str))
184932fe07f8SJohn Marino 			return off;
185032fe07f8SJohn Marino 		if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
185132fe07f8SJohn Marino 			break;
185232fe07f8SJohn Marino 	}
185332fe07f8SJohn Marino 
185432fe07f8SJohn Marino 	/* set "current" pointer back to previous state */
185532fe07f8SJohn Marino 	(void)history(h, &ev,
185632fe07f8SJohn Marino 	    pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
185732fe07f8SJohn Marino 
185832fe07f8SJohn Marino 	return -1;
185932fe07f8SJohn Marino }
186032fe07f8SJohn Marino 
186132fe07f8SJohn Marino 
186232fe07f8SJohn Marino /********************************/
186332fe07f8SJohn Marino /* completion functions */
186432fe07f8SJohn Marino 
186532fe07f8SJohn Marino char *
tilde_expand(char * name)186632fe07f8SJohn Marino tilde_expand(char *name)
186732fe07f8SJohn Marino {
186832fe07f8SJohn Marino 	return fn_tilde_expand(name);
186932fe07f8SJohn Marino }
187032fe07f8SJohn Marino 
187132fe07f8SJohn Marino char *
filename_completion_function(const char * name,int state)187232fe07f8SJohn Marino filename_completion_function(const char *name, int state)
187332fe07f8SJohn Marino {
187432fe07f8SJohn Marino 	return fn_filename_completion_function(name, state);
187532fe07f8SJohn Marino }
187632fe07f8SJohn Marino 
187732fe07f8SJohn Marino /*
187832fe07f8SJohn Marino  * a completion generator for usernames; returns _first_ username
187932fe07f8SJohn Marino  * which starts with supplied text
188032fe07f8SJohn Marino  * text contains a partial username preceded by random character
188132fe07f8SJohn Marino  * (usually '~'); state resets search from start (??? should we do that anyway)
1882a0c9eb18SJohn Marino  * it's the caller's responsibility to free the returned value
188332fe07f8SJohn Marino  */
188432fe07f8SJohn Marino char *
username_completion_function(const char * text,int state)188532fe07f8SJohn Marino username_completion_function(const char *text, int state)
188632fe07f8SJohn Marino {
188732fe07f8SJohn Marino 	struct passwd *pass = NULL;
188832fe07f8SJohn Marino 
188932fe07f8SJohn Marino 	if (text[0] == '\0')
189032fe07f8SJohn Marino 		return NULL;
189132fe07f8SJohn Marino 
189232fe07f8SJohn Marino 	if (*text == '~')
189332fe07f8SJohn Marino 		text++;
189432fe07f8SJohn Marino 
189532fe07f8SJohn Marino 	if (state == 0)
189632fe07f8SJohn Marino 		setpwent();
189732fe07f8SJohn Marino 
189832fe07f8SJohn Marino 	while (
189932fe07f8SJohn Marino 	    (pass = getpwent()) != NULL
190032fe07f8SJohn Marino 	    && text[0] == pass->pw_name[0]
190132fe07f8SJohn Marino 	    && strcmp(text, pass->pw_name) == 0)
190232fe07f8SJohn Marino 		continue;
190332fe07f8SJohn Marino 
190432fe07f8SJohn Marino 	if (pass == NULL) {
190532fe07f8SJohn Marino 		endpwent();
190632fe07f8SJohn Marino 		return NULL;
190732fe07f8SJohn Marino 	}
190832fe07f8SJohn Marino 	return strdup(pass->pw_name);
190932fe07f8SJohn Marino }
191032fe07f8SJohn Marino 
191132fe07f8SJohn Marino 
191232fe07f8SJohn Marino /*
191332fe07f8SJohn Marino  * el-compatible wrapper to send TSTP on ^Z
191432fe07f8SJohn Marino  */
191532fe07f8SJohn Marino /* ARGSUSED */
191632fe07f8SJohn Marino static unsigned char
_el_rl_tstp(EditLine * el,int ch)191732fe07f8SJohn Marino _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
191832fe07f8SJohn Marino {
191932fe07f8SJohn Marino 	(void)kill(0, SIGTSTP);
192032fe07f8SJohn Marino 	return CC_NORM;
192132fe07f8SJohn Marino }
192232fe07f8SJohn Marino 
192332fe07f8SJohn Marino static const char *
192432fe07f8SJohn Marino /*ARGSUSED*/
_rl_completion_append_character_function(const char * dummy)192532fe07f8SJohn Marino _rl_completion_append_character_function(const char *dummy
192632fe07f8SJohn Marino     __attribute__((__unused__)))
192732fe07f8SJohn Marino {
192832fe07f8SJohn Marino 	static char buf[2];
192932fe07f8SJohn Marino 	buf[0] = (char)rl_completion_append_character;
193032fe07f8SJohn Marino 	buf[1] = '\0';
193132fe07f8SJohn Marino 	return buf;
193232fe07f8SJohn Marino }
193332fe07f8SJohn Marino 
193432fe07f8SJohn Marino 
193532fe07f8SJohn Marino /*
1936ae19eda8Szrj  * Display list of strings in columnar format on readline's output stream.
1937ae19eda8Szrj  * 'matches' is list of strings, 'len' is number of strings in 'matches',
1938ae19eda8Szrj  * 'max' is maximum length of string in 'matches'.
1939ae19eda8Szrj  */
1940ae19eda8Szrj void
rl_display_match_list(char ** matches,int len,int max)1941ae19eda8Szrj rl_display_match_list(char **matches, int len, int max)
1942ae19eda8Szrj {
1943ae19eda8Szrj 
1944ae19eda8Szrj 	fn_display_match_list(e, matches, (size_t)len, (size_t)max,
1945ae19eda8Szrj 		_rl_completion_append_character_function);
1946ae19eda8Szrj }
1947ae19eda8Szrj 
1948ae19eda8Szrj /*
194932fe07f8SJohn Marino  * complete word at current point
195032fe07f8SJohn Marino  */
195132fe07f8SJohn Marino /* ARGSUSED */
195232fe07f8SJohn Marino int
rl_complete(int ignore,int invoking_key)195332fe07f8SJohn Marino rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
195432fe07f8SJohn Marino {
195532fe07f8SJohn Marino 	static ct_buffer_t wbreak_conv, sprefix_conv;
1956ae19eda8Szrj 	const char *breakchars;
195732fe07f8SJohn Marino 
195832fe07f8SJohn Marino 	if (h == NULL || e == NULL)
195932fe07f8SJohn Marino 		rl_initialize();
196032fe07f8SJohn Marino 
196132fe07f8SJohn Marino 	if (rl_inhibit_completion) {
196232fe07f8SJohn Marino 		char arr[2];
196332fe07f8SJohn Marino 		arr[0] = (char)invoking_key;
196432fe07f8SJohn Marino 		arr[1] = '\0';
196532fe07f8SJohn Marino 		el_insertstr(e, arr);
196632fe07f8SJohn Marino 		return CC_REFRESH;
196732fe07f8SJohn Marino 	}
196832fe07f8SJohn Marino 
1969c8e4d2bfSJohn Marino 	if (rl_completion_word_break_hook != NULL)
1970c8e4d2bfSJohn Marino 		breakchars = (*rl_completion_word_break_hook)();
1971c8e4d2bfSJohn Marino 	else
1972c8e4d2bfSJohn Marino 		breakchars = rl_basic_word_break_characters;
1973c8e4d2bfSJohn Marino 
197412db70c8Szrj 	_rl_update_pos();
197512db70c8Szrj 
197632fe07f8SJohn Marino 	/* Just look at how many global variables modify this operation! */
197732fe07f8SJohn Marino 	return fn_complete(e,
197812db70c8Szrj 	    (rl_compentry_func_t *)rl_completion_entry_function,
197932fe07f8SJohn Marino 	    rl_attempted_completion_function,
198032fe07f8SJohn Marino 	    ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
1981c8e4d2bfSJohn Marino 	    ct_decode_string(breakchars, &sprefix_conv),
198232fe07f8SJohn Marino 	    _rl_completion_append_character_function,
198332fe07f8SJohn Marino 	    (size_t)rl_completion_query_items,
198432fe07f8SJohn Marino 	    &rl_completion_type, &rl_attempted_completion_over,
198532fe07f8SJohn Marino 	    &rl_point, &rl_end);
198632fe07f8SJohn Marino 
198732fe07f8SJohn Marino 
198832fe07f8SJohn Marino }
198932fe07f8SJohn Marino 
199032fe07f8SJohn Marino 
199132fe07f8SJohn Marino /* ARGSUSED */
199232fe07f8SJohn Marino static unsigned char
_el_rl_complete(EditLine * el,int ch)199332fe07f8SJohn Marino _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
199432fe07f8SJohn Marino {
199532fe07f8SJohn Marino 	return (unsigned char)rl_complete(0, ch);
199632fe07f8SJohn Marino }
199732fe07f8SJohn Marino 
199832fe07f8SJohn Marino /*
199932fe07f8SJohn Marino  * misc other functions
200032fe07f8SJohn Marino  */
200132fe07f8SJohn Marino 
200232fe07f8SJohn Marino /*
200332fe07f8SJohn Marino  * bind key c to readline-type function func
200432fe07f8SJohn Marino  */
200532fe07f8SJohn Marino int
rl_bind_key(int c,rl_command_func_t * func)200632fe07f8SJohn Marino rl_bind_key(int c, rl_command_func_t *func)
200732fe07f8SJohn Marino {
200832fe07f8SJohn Marino 	int retval = -1;
200932fe07f8SJohn Marino 
201032fe07f8SJohn Marino 	if (h == NULL || e == NULL)
201132fe07f8SJohn Marino 		rl_initialize();
201232fe07f8SJohn Marino 
201332fe07f8SJohn Marino 	if (func == rl_insert) {
201432fe07f8SJohn Marino 		/* XXX notice there is no range checking of ``c'' */
201532fe07f8SJohn Marino 		e->el_map.key[c] = ED_INSERT;
201632fe07f8SJohn Marino 		retval = 0;
201732fe07f8SJohn Marino 	}
201832fe07f8SJohn Marino 	return retval;
201932fe07f8SJohn Marino }
202032fe07f8SJohn Marino 
202132fe07f8SJohn Marino 
202232fe07f8SJohn Marino /*
202332fe07f8SJohn Marino  * read one key from input - handles chars pushed back
202432fe07f8SJohn Marino  * to input stream also
202532fe07f8SJohn Marino  */
202632fe07f8SJohn Marino int
rl_read_key(void)202732fe07f8SJohn Marino rl_read_key(void)
202832fe07f8SJohn Marino {
202932fe07f8SJohn Marino 	char fooarr[2 * sizeof(int)];
203032fe07f8SJohn Marino 
203132fe07f8SJohn Marino 	if (e == NULL || h == NULL)
203232fe07f8SJohn Marino 		rl_initialize();
203332fe07f8SJohn Marino 
203432fe07f8SJohn Marino 	return el_getc(e, fooarr);
203532fe07f8SJohn Marino }
203632fe07f8SJohn Marino 
203732fe07f8SJohn Marino 
203832fe07f8SJohn Marino /*
203932fe07f8SJohn Marino  * reset the terminal
204032fe07f8SJohn Marino  */
204132fe07f8SJohn Marino /* ARGSUSED */
2042ae19eda8Szrj int
rl_reset_terminal(const char * p)204332fe07f8SJohn Marino rl_reset_terminal(const char *p __attribute__((__unused__)))
204432fe07f8SJohn Marino {
204532fe07f8SJohn Marino 
204632fe07f8SJohn Marino 	if (h == NULL || e == NULL)
204732fe07f8SJohn Marino 		rl_initialize();
204832fe07f8SJohn Marino 	el_reset(e);
2049ae19eda8Szrj 	return 0;
205032fe07f8SJohn Marino }
205132fe07f8SJohn Marino 
205232fe07f8SJohn Marino 
205332fe07f8SJohn Marino /*
205432fe07f8SJohn Marino  * insert character ``c'' back into input stream, ``count'' times
205532fe07f8SJohn Marino  */
205632fe07f8SJohn Marino int
rl_insert(int count,int c)205732fe07f8SJohn Marino rl_insert(int count, int c)
205832fe07f8SJohn Marino {
205932fe07f8SJohn Marino 	char arr[2];
206032fe07f8SJohn Marino 
206132fe07f8SJohn Marino 	if (h == NULL || e == NULL)
206232fe07f8SJohn Marino 		rl_initialize();
206332fe07f8SJohn Marino 
206432fe07f8SJohn Marino 	/* XXX - int -> char conversion can lose on multichars */
206532fe07f8SJohn Marino 	arr[0] = (char)c;
206632fe07f8SJohn Marino 	arr[1] = '\0';
206732fe07f8SJohn Marino 
206832fe07f8SJohn Marino 	for (; count > 0; count--)
206932fe07f8SJohn Marino 		el_push(e, arr);
207032fe07f8SJohn Marino 
207132fe07f8SJohn Marino 	return 0;
207232fe07f8SJohn Marino }
207332fe07f8SJohn Marino 
207432fe07f8SJohn Marino int
rl_insert_text(const char * text)207532fe07f8SJohn Marino rl_insert_text(const char *text)
207632fe07f8SJohn Marino {
207732fe07f8SJohn Marino 	if (!text || *text == 0)
207832fe07f8SJohn Marino 		return 0;
207932fe07f8SJohn Marino 
208032fe07f8SJohn Marino 	if (h == NULL || e == NULL)
208132fe07f8SJohn Marino 		rl_initialize();
208232fe07f8SJohn Marino 
208332fe07f8SJohn Marino 	if (el_insertstr(e, text) < 0)
208432fe07f8SJohn Marino 		return 0;
208532fe07f8SJohn Marino 	return (int)strlen(text);
208632fe07f8SJohn Marino }
208732fe07f8SJohn Marino 
208832fe07f8SJohn Marino /*ARGSUSED*/
208932fe07f8SJohn Marino int
rl_newline(int count,int c)209032fe07f8SJohn Marino rl_newline(int count __attribute__((__unused__)),
209132fe07f8SJohn Marino     int c __attribute__((__unused__)))
209232fe07f8SJohn Marino {
209332fe07f8SJohn Marino 	/*
209432fe07f8SJohn Marino 	 * Readline-4.0 appears to ignore the args.
209532fe07f8SJohn Marino 	 */
209632fe07f8SJohn Marino 	return rl_insert(1, '\n');
209732fe07f8SJohn Marino }
209832fe07f8SJohn Marino 
209932fe07f8SJohn Marino /*ARGSUSED*/
210032fe07f8SJohn Marino static unsigned char
rl_bind_wrapper(EditLine * el,unsigned char c)210132fe07f8SJohn Marino rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c)
210232fe07f8SJohn Marino {
210332fe07f8SJohn Marino 	if (map[c] == NULL)
210432fe07f8SJohn Marino 		return CC_ERROR;
210532fe07f8SJohn Marino 
210632fe07f8SJohn Marino 	_rl_update_pos();
210732fe07f8SJohn Marino 
210812db70c8Szrj 	(*map[c])(1, c);
210932fe07f8SJohn Marino 
211032fe07f8SJohn Marino 	/* If rl_done was set by the above call, deal with it here */
211132fe07f8SJohn Marino 	if (rl_done)
211232fe07f8SJohn Marino 		return CC_EOF;
211332fe07f8SJohn Marino 
211432fe07f8SJohn Marino 	return CC_NORM;
211532fe07f8SJohn Marino }
211632fe07f8SJohn Marino 
211732fe07f8SJohn Marino int
rl_add_defun(const char * name,rl_command_func_t * fun,int c)211812db70c8Szrj rl_add_defun(const char *name, rl_command_func_t *fun, int c)
211932fe07f8SJohn Marino {
212032fe07f8SJohn Marino 	char dest[8];
212132fe07f8SJohn Marino 	if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
212232fe07f8SJohn Marino 		return -1;
212332fe07f8SJohn Marino 	map[(unsigned char)c] = fun;
212432fe07f8SJohn Marino 	el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
212532fe07f8SJohn Marino 	vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
2126c8e4d2bfSJohn Marino 	el_set(e, EL_BIND, dest, name, NULL);
212732fe07f8SJohn Marino 	return 0;
212832fe07f8SJohn Marino }
212932fe07f8SJohn Marino 
213032fe07f8SJohn Marino void
rl_callback_read_char(void)2131c8e4d2bfSJohn Marino rl_callback_read_char(void)
213232fe07f8SJohn Marino {
213332fe07f8SJohn Marino 	int count = 0, done = 0;
213432fe07f8SJohn Marino 	const char *buf = el_gets(e, &count);
213532fe07f8SJohn Marino 	char *wbuf;
213632fe07f8SJohn Marino 
2137*cdf8408cSAntonio Huete Jimenez 	el_set(e, EL_UNBUFFERED, 1);
213832fe07f8SJohn Marino 	if (buf == NULL || count-- <= 0)
213932fe07f8SJohn Marino 		return;
214032fe07f8SJohn Marino 	if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
214132fe07f8SJohn Marino 		done = 1;
214232fe07f8SJohn Marino 	if (buf[count] == '\n' || buf[count] == '\r')
214332fe07f8SJohn Marino 		done = 2;
214432fe07f8SJohn Marino 
214532fe07f8SJohn Marino 	if (done && rl_linefunc != NULL) {
214632fe07f8SJohn Marino 		el_set(e, EL_UNBUFFERED, 0);
214732fe07f8SJohn Marino 		if (done == 2) {
214832fe07f8SJohn Marino 			if ((wbuf = strdup(buf)) != NULL)
214932fe07f8SJohn Marino 				wbuf[count] = '\0';
2150*cdf8408cSAntonio Huete Jimenez 			RL_SETSTATE(RL_STATE_DONE);
215132fe07f8SJohn Marino 		} else
215232fe07f8SJohn Marino 			wbuf = NULL;
215332fe07f8SJohn Marino 		(*(void (*)(const char *))rl_linefunc)(wbuf);
215432fe07f8SJohn Marino 	}
2155*cdf8408cSAntonio Huete Jimenez 	_rl_update_pos();
215632fe07f8SJohn Marino }
215732fe07f8SJohn Marino 
215832fe07f8SJohn Marino void
rl_callback_handler_install(const char * prompt,rl_vcpfunc_t * linefunc)215912db70c8Szrj rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc)
216032fe07f8SJohn Marino {
216132fe07f8SJohn Marino 	if (e == NULL) {
216232fe07f8SJohn Marino 		rl_initialize();
216332fe07f8SJohn Marino 	}
216432fe07f8SJohn Marino 	(void)rl_set_prompt(prompt);
216532fe07f8SJohn Marino 	rl_linefunc = linefunc;
216632fe07f8SJohn Marino 	el_set(e, EL_UNBUFFERED, 1);
216732fe07f8SJohn Marino }
216832fe07f8SJohn Marino 
216932fe07f8SJohn Marino void
rl_callback_handler_remove(void)217032fe07f8SJohn Marino rl_callback_handler_remove(void)
217132fe07f8SJohn Marino {
2172*cdf8408cSAntonio Huete Jimenez 	el_set(e, EL_UNBUFFERED, 0);
217332fe07f8SJohn Marino 	rl_linefunc = NULL;
217432fe07f8SJohn Marino }
217532fe07f8SJohn Marino 
217632fe07f8SJohn Marino void
rl_redisplay(void)217732fe07f8SJohn Marino rl_redisplay(void)
217832fe07f8SJohn Marino {
217932fe07f8SJohn Marino 	char a[2];
218032fe07f8SJohn Marino 	a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT];
218132fe07f8SJohn Marino 	a[1] = '\0';
218232fe07f8SJohn Marino 	el_push(e, a);
2183*cdf8408cSAntonio Huete Jimenez 	rl_forced_update_display();
218432fe07f8SJohn Marino }
218532fe07f8SJohn Marino 
218632fe07f8SJohn Marino int
rl_get_previous_history(int count,int key)218732fe07f8SJohn Marino rl_get_previous_history(int count, int key)
218832fe07f8SJohn Marino {
218932fe07f8SJohn Marino 	char a[2];
219032fe07f8SJohn Marino 	a[0] = (char)key;
219132fe07f8SJohn Marino 	a[1] = '\0';
219232fe07f8SJohn Marino 	while (count--)
219332fe07f8SJohn Marino 		el_push(e, a);
219432fe07f8SJohn Marino 	return 0;
219532fe07f8SJohn Marino }
219632fe07f8SJohn Marino 
219732fe07f8SJohn Marino void
219832fe07f8SJohn Marino /*ARGSUSED*/
rl_prep_terminal(int meta_flag)219932fe07f8SJohn Marino rl_prep_terminal(int meta_flag __attribute__((__unused__)))
220032fe07f8SJohn Marino {
220132fe07f8SJohn Marino 	el_set(e, EL_PREP_TERM, 1);
220232fe07f8SJohn Marino }
220332fe07f8SJohn Marino 
220432fe07f8SJohn Marino void
rl_deprep_terminal(void)220532fe07f8SJohn Marino rl_deprep_terminal(void)
220632fe07f8SJohn Marino {
220732fe07f8SJohn Marino 	el_set(e, EL_PREP_TERM, 0);
220832fe07f8SJohn Marino }
220932fe07f8SJohn Marino 
221032fe07f8SJohn Marino int
rl_read_init_file(const char * s)221132fe07f8SJohn Marino rl_read_init_file(const char *s)
221232fe07f8SJohn Marino {
221332fe07f8SJohn Marino 	return el_source(e, s);
221432fe07f8SJohn Marino }
221532fe07f8SJohn Marino 
221632fe07f8SJohn Marino int
rl_parse_and_bind(const char * line)221732fe07f8SJohn Marino rl_parse_and_bind(const char *line)
221832fe07f8SJohn Marino {
221932fe07f8SJohn Marino 	const char **argv;
222032fe07f8SJohn Marino 	int argc;
222132fe07f8SJohn Marino 	Tokenizer *tok;
222232fe07f8SJohn Marino 
222332fe07f8SJohn Marino 	tok = tok_init(NULL);
222432fe07f8SJohn Marino 	tok_str(tok, line, &argc, &argv);
222532fe07f8SJohn Marino 	argc = el_parse(e, argc, argv);
222632fe07f8SJohn Marino 	tok_end(tok);
222732fe07f8SJohn Marino 	return argc ? 1 : 0;
222832fe07f8SJohn Marino }
222932fe07f8SJohn Marino 
223032fe07f8SJohn Marino int
rl_variable_bind(const char * var,const char * value)223132fe07f8SJohn Marino rl_variable_bind(const char *var, const char *value)
223232fe07f8SJohn Marino {
223332fe07f8SJohn Marino 	/*
223432fe07f8SJohn Marino 	 * The proper return value is undocument, but this is what the
223532fe07f8SJohn Marino 	 * readline source seems to do.
223632fe07f8SJohn Marino 	 */
2237c8e4d2bfSJohn Marino 	return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0;
223832fe07f8SJohn Marino }
223932fe07f8SJohn Marino 
2240ae19eda8Szrj int
rl_stuff_char(int c)224132fe07f8SJohn Marino rl_stuff_char(int c)
224232fe07f8SJohn Marino {
224332fe07f8SJohn Marino 	char buf[2];
224432fe07f8SJohn Marino 
224532fe07f8SJohn Marino 	buf[0] = (char)c;
224632fe07f8SJohn Marino 	buf[1] = '\0';
224732fe07f8SJohn Marino 	el_insertstr(e, buf);
2248ae19eda8Szrj 	return 1;
224932fe07f8SJohn Marino }
225032fe07f8SJohn Marino 
225132fe07f8SJohn Marino static int
_rl_event_read_char(EditLine * el,wchar_t * wc)225212db70c8Szrj _rl_event_read_char(EditLine *el, wchar_t *wc)
225332fe07f8SJohn Marino {
225412db70c8Szrj 	char	ch;
225532fe07f8SJohn Marino 	int	n;
225632fe07f8SJohn Marino 	ssize_t num_read = 0;
225732fe07f8SJohn Marino 
225812db70c8Szrj 	ch = '\0';
225912db70c8Szrj 	*wc = L'\0';
226032fe07f8SJohn Marino 	while (rl_event_hook) {
226132fe07f8SJohn Marino 
226232fe07f8SJohn Marino 		(*rl_event_hook)();
226332fe07f8SJohn Marino 
226432fe07f8SJohn Marino #if defined(FIONREAD)
226532fe07f8SJohn Marino 		if (ioctl(el->el_infd, FIONREAD, &n) < 0)
226632fe07f8SJohn Marino 			return -1;
226732fe07f8SJohn Marino 		if (n)
226812db70c8Szrj 			num_read = read(el->el_infd, &ch, (size_t)1);
226932fe07f8SJohn Marino 		else
227032fe07f8SJohn Marino 			num_read = 0;
227132fe07f8SJohn Marino #elif defined(F_SETFL) && defined(O_NDELAY)
227232fe07f8SJohn Marino 		if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
227332fe07f8SJohn Marino 			return -1;
227432fe07f8SJohn Marino 		if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
227532fe07f8SJohn Marino 			return -1;
227612db70c8Szrj 		num_read = read(el->el_infd, &ch, 1);
227732fe07f8SJohn Marino 		if (fcntl(el->el_infd, F_SETFL, n))
227832fe07f8SJohn Marino 			return -1;
227932fe07f8SJohn Marino #else
228032fe07f8SJohn Marino 		/* not non-blocking, but what you gonna do? */
228112db70c8Szrj 		num_read = read(el->el_infd, &ch, 1);
228232fe07f8SJohn Marino 		return -1;
228332fe07f8SJohn Marino #endif
228432fe07f8SJohn Marino 
228532fe07f8SJohn Marino 		if (num_read < 0 && errno == EAGAIN)
228632fe07f8SJohn Marino 			continue;
228732fe07f8SJohn Marino 		if (num_read == 0)
228832fe07f8SJohn Marino 			continue;
228932fe07f8SJohn Marino 		break;
229032fe07f8SJohn Marino 	}
229132fe07f8SJohn Marino 	if (!rl_event_hook)
229232fe07f8SJohn Marino 		el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
229312db70c8Szrj 	*wc = (wchar_t)ch;
229432fe07f8SJohn Marino 	return (int)num_read;
229532fe07f8SJohn Marino }
229632fe07f8SJohn Marino 
229732fe07f8SJohn Marino static void
_rl_update_pos(void)229832fe07f8SJohn Marino _rl_update_pos(void)
229932fe07f8SJohn Marino {
230032fe07f8SJohn Marino 	const LineInfo *li = el_line(e);
230132fe07f8SJohn Marino 
230232fe07f8SJohn Marino 	rl_point = (int)(li->cursor - li->buffer);
230332fe07f8SJohn Marino 	rl_end = (int)(li->lastchar - li->buffer);
230460ecde0cSDaniel Fojt 	rl_line_buffer[rl_end] = '\0';
230532fe07f8SJohn Marino }
230632fe07f8SJohn Marino 
2307*cdf8408cSAntonio Huete Jimenez char *
rl_copy_text(int from,int to)2308*cdf8408cSAntonio Huete Jimenez rl_copy_text(int from, int to)
2309*cdf8408cSAntonio Huete Jimenez {
2310*cdf8408cSAntonio Huete Jimenez 	const LineInfo *li;
2311*cdf8408cSAntonio Huete Jimenez 	size_t len;
2312*cdf8408cSAntonio Huete Jimenez 	char * out;
2313*cdf8408cSAntonio Huete Jimenez 
2314*cdf8408cSAntonio Huete Jimenez 	if (h == NULL || e == NULL)
2315*cdf8408cSAntonio Huete Jimenez 		rl_initialize();
2316*cdf8408cSAntonio Huete Jimenez 
2317*cdf8408cSAntonio Huete Jimenez 	li = el_line(e);
2318*cdf8408cSAntonio Huete Jimenez 
2319*cdf8408cSAntonio Huete Jimenez 	if (from > to)
2320*cdf8408cSAntonio Huete Jimenez 		return NULL;
2321*cdf8408cSAntonio Huete Jimenez 
2322*cdf8408cSAntonio Huete Jimenez 	if (li->buffer + from > li->lastchar)
2323*cdf8408cSAntonio Huete Jimenez 		from = (int)(li->lastchar - li->buffer);
2324*cdf8408cSAntonio Huete Jimenez 
2325*cdf8408cSAntonio Huete Jimenez 	if (li->buffer + to > li->lastchar)
2326*cdf8408cSAntonio Huete Jimenez 		to = (int)(li->lastchar - li->buffer);
2327*cdf8408cSAntonio Huete Jimenez 
2328*cdf8408cSAntonio Huete Jimenez 	len = (size_t)(to - from);
2329*cdf8408cSAntonio Huete Jimenez 	out = el_malloc((size_t)len + 1);
2330*cdf8408cSAntonio Huete Jimenez 	(void)strlcpy(out, li->buffer + from , len);
2331*cdf8408cSAntonio Huete Jimenez 
2332*cdf8408cSAntonio Huete Jimenez 	return out;
2333*cdf8408cSAntonio Huete Jimenez }
2334*cdf8408cSAntonio Huete Jimenez 
2335*cdf8408cSAntonio Huete Jimenez void
rl_replace_line(const char * text,int clear_undo)2336*cdf8408cSAntonio Huete Jimenez rl_replace_line(const char * text, int clear_undo __attribute__((__unused__)))
2337*cdf8408cSAntonio Huete Jimenez {
2338*cdf8408cSAntonio Huete Jimenez 	if (!text || *text == 0)
2339*cdf8408cSAntonio Huete Jimenez 		return;
2340*cdf8408cSAntonio Huete Jimenez 
2341*cdf8408cSAntonio Huete Jimenez 	if (h == NULL || e == NULL)
2342*cdf8408cSAntonio Huete Jimenez 		rl_initialize();
2343*cdf8408cSAntonio Huete Jimenez 
2344*cdf8408cSAntonio Huete Jimenez 	el_replacestr(e, text);
2345*cdf8408cSAntonio Huete Jimenez }
2346*cdf8408cSAntonio Huete Jimenez 
2347*cdf8408cSAntonio Huete Jimenez int
rl_delete_text(int start,int end)2348*cdf8408cSAntonio Huete Jimenez rl_delete_text(int start, int end)
2349*cdf8408cSAntonio Huete Jimenez {
2350*cdf8408cSAntonio Huete Jimenez 
2351*cdf8408cSAntonio Huete Jimenez 	if (h == NULL || e == NULL)
2352*cdf8408cSAntonio Huete Jimenez 		rl_initialize();
2353*cdf8408cSAntonio Huete Jimenez 
2354*cdf8408cSAntonio Huete Jimenez 	return el_deletestr1(e, start, end);
2355*cdf8408cSAntonio Huete Jimenez }
2356*cdf8408cSAntonio Huete Jimenez 
235732fe07f8SJohn Marino void
rl_get_screen_size(int * rows,int * cols)235832fe07f8SJohn Marino rl_get_screen_size(int *rows, int *cols)
235932fe07f8SJohn Marino {
236032fe07f8SJohn Marino 	if (rows)
236160ecde0cSDaniel Fojt 		el_get(e, EL_GETTC, "li", rows);
236232fe07f8SJohn Marino 	if (cols)
236360ecde0cSDaniel Fojt 		el_get(e, EL_GETTC, "co", cols);
236432fe07f8SJohn Marino }
236532fe07f8SJohn Marino 
2366*cdf8408cSAntonio Huete Jimenez #define MAX_MESSAGE 160
2367*cdf8408cSAntonio Huete Jimenez void
rl_message(const char * format,...)2368*cdf8408cSAntonio Huete Jimenez rl_message(const char *format, ...)
2369*cdf8408cSAntonio Huete Jimenez {
2370*cdf8408cSAntonio Huete Jimenez 	char msg[MAX_MESSAGE];
2371*cdf8408cSAntonio Huete Jimenez 	va_list args;
2372*cdf8408cSAntonio Huete Jimenez 
2373*cdf8408cSAntonio Huete Jimenez 	va_start(args, format);
2374*cdf8408cSAntonio Huete Jimenez 	vsnprintf(msg, sizeof(msg), format, args);
2375*cdf8408cSAntonio Huete Jimenez 	va_end(args);
2376*cdf8408cSAntonio Huete Jimenez 
2377*cdf8408cSAntonio Huete Jimenez 	rl_set_prompt(msg);
2378*cdf8408cSAntonio Huete Jimenez 	rl_forced_update_display();
2379*cdf8408cSAntonio Huete Jimenez }
2380*cdf8408cSAntonio Huete Jimenez 
238132fe07f8SJohn Marino void
rl_set_screen_size(int rows,int cols)238232fe07f8SJohn Marino rl_set_screen_size(int rows, int cols)
238332fe07f8SJohn Marino {
238432fe07f8SJohn Marino 	char buf[64];
238532fe07f8SJohn Marino 	(void)snprintf(buf, sizeof(buf), "%d", rows);
2386c8e4d2bfSJohn Marino 	el_set(e, EL_SETTC, "li", buf, NULL);
238732fe07f8SJohn Marino 	(void)snprintf(buf, sizeof(buf), "%d", cols);
2388c8e4d2bfSJohn Marino 	el_set(e, EL_SETTC, "co", buf, NULL);
238932fe07f8SJohn Marino }
239032fe07f8SJohn Marino 
239132fe07f8SJohn Marino char **
rl_completion_matches(const char * str,rl_compentry_func_t * fun)239232fe07f8SJohn Marino rl_completion_matches(const char *str, rl_compentry_func_t *fun)
239332fe07f8SJohn Marino {
239432fe07f8SJohn Marino 	size_t len, max, i, j, min;
239532fe07f8SJohn Marino 	char **list, *match, *a, *b;
239632fe07f8SJohn Marino 
239732fe07f8SJohn Marino 	len = 1;
239832fe07f8SJohn Marino 	max = 10;
239960ecde0cSDaniel Fojt 	if ((list = el_calloc(max, sizeof(*list))) == NULL)
240032fe07f8SJohn Marino 		return NULL;
240132fe07f8SJohn Marino 
240232fe07f8SJohn Marino 	while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
240332fe07f8SJohn Marino 		list[len++] = match;
240432fe07f8SJohn Marino 		if (len == max) {
240532fe07f8SJohn Marino 			char **nl;
240632fe07f8SJohn Marino 			max += 10;
240732fe07f8SJohn Marino 			if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL)
240832fe07f8SJohn Marino 				goto out;
240932fe07f8SJohn Marino 			list = nl;
241032fe07f8SJohn Marino 		}
241132fe07f8SJohn Marino 	}
241232fe07f8SJohn Marino 	if (len == 1)
241332fe07f8SJohn Marino 		goto out;
241432fe07f8SJohn Marino 	list[len] = NULL;
241532fe07f8SJohn Marino 	if (len == 2) {
241632fe07f8SJohn Marino 		if ((list[0] = strdup(list[1])) == NULL)
241732fe07f8SJohn Marino 			goto out;
241832fe07f8SJohn Marino 		return list;
241932fe07f8SJohn Marino 	}
242032fe07f8SJohn Marino 	qsort(&list[1], len - 1, sizeof(*list),
242132fe07f8SJohn Marino 	    (int (*)(const void *, const void *)) strcmp);
242212db70c8Szrj 	min = SIZE_MAX;
242332fe07f8SJohn Marino 	for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
242432fe07f8SJohn Marino 		b = list[i + 1];
242532fe07f8SJohn Marino 		for (j = 0; a[j] && a[j] == b[j]; j++)
242632fe07f8SJohn Marino 			continue;
242732fe07f8SJohn Marino 		if (min > j)
242832fe07f8SJohn Marino 			min = j;
242932fe07f8SJohn Marino 	}
243032fe07f8SJohn Marino 	if (min == 0 && *str) {
243132fe07f8SJohn Marino 		if ((list[0] = strdup(str)) == NULL)
243232fe07f8SJohn Marino 			goto out;
243332fe07f8SJohn Marino 	} else {
243460ecde0cSDaniel Fojt 		if ((list[0] = el_calloc(min + 1, sizeof(*list[0]))) == NULL)
243532fe07f8SJohn Marino 			goto out;
243632fe07f8SJohn Marino 		(void)memcpy(list[0], list[1], min);
243732fe07f8SJohn Marino 		list[0][min] = '\0';
243832fe07f8SJohn Marino 	}
243932fe07f8SJohn Marino 	return list;
244032fe07f8SJohn Marino 
244132fe07f8SJohn Marino out:
244232fe07f8SJohn Marino 	el_free(list);
244332fe07f8SJohn Marino 	return NULL;
244432fe07f8SJohn Marino }
244532fe07f8SJohn Marino 
244632fe07f8SJohn Marino char *
rl_filename_completion_function(const char * text,int state)244732fe07f8SJohn Marino rl_filename_completion_function (const char *text, int state)
244832fe07f8SJohn Marino {
244932fe07f8SJohn Marino 	return fn_filename_completion_function(text, state);
245032fe07f8SJohn Marino }
245132fe07f8SJohn Marino 
245232fe07f8SJohn Marino void
rl_forced_update_display(void)245332fe07f8SJohn Marino rl_forced_update_display(void)
245432fe07f8SJohn Marino {
245532fe07f8SJohn Marino 	el_set(e, EL_REFRESH);
245632fe07f8SJohn Marino }
245732fe07f8SJohn Marino 
245832fe07f8SJohn Marino int
_rl_abort_internal(void)245932fe07f8SJohn Marino _rl_abort_internal(void)
246032fe07f8SJohn Marino {
246132fe07f8SJohn Marino 	el_beep(e);
246232fe07f8SJohn Marino 	longjmp(topbuf, 1);
246332fe07f8SJohn Marino 	/*NOTREACHED*/
246432fe07f8SJohn Marino }
246532fe07f8SJohn Marino 
246632fe07f8SJohn Marino int
_rl_qsort_string_compare(char ** s1,char ** s2)246732fe07f8SJohn Marino _rl_qsort_string_compare(char **s1, char **s2)
246832fe07f8SJohn Marino {
246932fe07f8SJohn Marino 	return strcoll(*s1, *s2);
247032fe07f8SJohn Marino }
247132fe07f8SJohn Marino 
247232fe07f8SJohn Marino HISTORY_STATE *
history_get_history_state(void)247332fe07f8SJohn Marino history_get_history_state(void)
247432fe07f8SJohn Marino {
247532fe07f8SJohn Marino 	HISTORY_STATE *hs;
247632fe07f8SJohn Marino 
247732fe07f8SJohn Marino 	if ((hs = el_malloc(sizeof(*hs))) == NULL)
247832fe07f8SJohn Marino 		return NULL;
247932fe07f8SJohn Marino 	hs->length = history_length;
248032fe07f8SJohn Marino 	return hs;
248132fe07f8SJohn Marino }
248232fe07f8SJohn Marino 
248332fe07f8SJohn Marino int
248432fe07f8SJohn Marino /*ARGSUSED*/
rl_kill_text(int from,int to)248532fe07f8SJohn Marino rl_kill_text(int from __attribute__((__unused__)),
248632fe07f8SJohn Marino     int to __attribute__((__unused__)))
248732fe07f8SJohn Marino {
248832fe07f8SJohn Marino 	return 0;
248932fe07f8SJohn Marino }
249032fe07f8SJohn Marino 
249132fe07f8SJohn Marino Keymap
rl_make_bare_keymap(void)249232fe07f8SJohn Marino rl_make_bare_keymap(void)
249332fe07f8SJohn Marino {
249432fe07f8SJohn Marino 	return NULL;
249532fe07f8SJohn Marino }
249632fe07f8SJohn Marino 
249732fe07f8SJohn Marino Keymap
rl_get_keymap(void)249832fe07f8SJohn Marino rl_get_keymap(void)
249932fe07f8SJohn Marino {
250032fe07f8SJohn Marino 	return NULL;
250132fe07f8SJohn Marino }
250232fe07f8SJohn Marino 
250332fe07f8SJohn Marino void
250432fe07f8SJohn Marino /*ARGSUSED*/
rl_set_keymap(Keymap k)250532fe07f8SJohn Marino rl_set_keymap(Keymap k __attribute__((__unused__)))
250632fe07f8SJohn Marino {
250732fe07f8SJohn Marino }
250832fe07f8SJohn Marino 
250932fe07f8SJohn Marino int
251032fe07f8SJohn Marino /*ARGSUSED*/
rl_generic_bind(int type,const char * keyseq,const char * data,Keymap k)251132fe07f8SJohn Marino rl_generic_bind(int type __attribute__((__unused__)),
251232fe07f8SJohn Marino     const char * keyseq __attribute__((__unused__)),
251332fe07f8SJohn Marino     const char * data __attribute__((__unused__)),
251432fe07f8SJohn Marino     Keymap k __attribute__((__unused__)))
251532fe07f8SJohn Marino {
251632fe07f8SJohn Marino 	return 0;
251732fe07f8SJohn Marino }
251832fe07f8SJohn Marino 
251932fe07f8SJohn Marino int
252032fe07f8SJohn Marino /*ARGSUSED*/
rl_bind_key_in_map(int key,rl_command_func_t * fun,Keymap k)252132fe07f8SJohn Marino rl_bind_key_in_map(int key __attribute__((__unused__)),
252232fe07f8SJohn Marino     rl_command_func_t *fun __attribute__((__unused__)),
252332fe07f8SJohn Marino     Keymap k __attribute__((__unused__)))
252432fe07f8SJohn Marino {
252532fe07f8SJohn Marino 	return 0;
252632fe07f8SJohn Marino }
252732fe07f8SJohn Marino 
2528*cdf8408cSAntonio Huete Jimenez int
rl_set_key(const char * keyseq,rl_command_func_t * function,Keymap k)2529*cdf8408cSAntonio Huete Jimenez rl_set_key(const char *keyseq  __attribute__((__unused__)),
2530*cdf8408cSAntonio Huete Jimenez 	rl_command_func_t *function __attribute__((__unused__)),
2531*cdf8408cSAntonio Huete Jimenez 	Keymap k __attribute__((__unused__)))
2532*cdf8408cSAntonio Huete Jimenez {
2533*cdf8408cSAntonio Huete Jimenez 	return 0;
2534*cdf8408cSAntonio Huete Jimenez }
2535*cdf8408cSAntonio Huete Jimenez 
253632fe07f8SJohn Marino /* unsupported, but needed by python */
253732fe07f8SJohn Marino void
rl_cleanup_after_signal(void)253832fe07f8SJohn Marino rl_cleanup_after_signal(void)
253932fe07f8SJohn Marino {
254032fe07f8SJohn Marino }
254132fe07f8SJohn Marino 
254232fe07f8SJohn Marino int
rl_on_new_line(void)254332fe07f8SJohn Marino rl_on_new_line(void)
254432fe07f8SJohn Marino {
254532fe07f8SJohn Marino 	return 0;
254632fe07f8SJohn Marino }
2547c8e4d2bfSJohn Marino 
2548c8e4d2bfSJohn Marino void
rl_free_line_state(void)2549c8e4d2bfSJohn Marino rl_free_line_state(void)
2550c8e4d2bfSJohn Marino {
2551c8e4d2bfSJohn Marino }
255212db70c8Szrj 
255312db70c8Szrj int
255412db70c8Szrj /*ARGSUSED*/
rl_set_keyboard_input_timeout(int u)255512db70c8Szrj rl_set_keyboard_input_timeout(int u __attribute__((__unused__)))
255612db70c8Szrj {
255712db70c8Szrj 	return 0;
255812db70c8Szrj }
2559ae19eda8Szrj 
2560ae19eda8Szrj void
rl_resize_terminal(void)2561ae19eda8Szrj rl_resize_terminal(void)
2562ae19eda8Szrj {
2563ae19eda8Szrj 	el_resize(e);
2564ae19eda8Szrj }
2565ae19eda8Szrj 
2566ae19eda8Szrj void
rl_reset_after_signal(void)2567ae19eda8Szrj rl_reset_after_signal(void)
2568ae19eda8Szrj {
2569ae19eda8Szrj 	if (rl_prep_term_function)
2570ae19eda8Szrj 		(*rl_prep_term_function)();
2571ae19eda8Szrj }
2572ae19eda8Szrj 
2573ae19eda8Szrj void
rl_echo_signal_char(int sig)2574ae19eda8Szrj rl_echo_signal_char(int sig)
2575ae19eda8Szrj {
2576ae19eda8Szrj 	int c = tty_get_signal_character(e, sig);
2577ae19eda8Szrj 	if (c == -1)
2578ae19eda8Szrj 		return;
2579ae19eda8Szrj 	re_putc(e, c, 0);
2580ae19eda8Szrj }
2581*cdf8408cSAntonio Huete Jimenez 
2582*cdf8408cSAntonio Huete Jimenez int
rl_crlf(void)2583*cdf8408cSAntonio Huete Jimenez rl_crlf(void)
2584*cdf8408cSAntonio Huete Jimenez {
2585*cdf8408cSAntonio Huete Jimenez 	re_putc(e, '\n', 0);
2586*cdf8408cSAntonio Huete Jimenez 	return 0;
2587*cdf8408cSAntonio Huete Jimenez }
2588*cdf8408cSAntonio Huete Jimenez 
2589*cdf8408cSAntonio Huete Jimenez int
rl_ding(void)2590*cdf8408cSAntonio Huete Jimenez rl_ding(void)
2591*cdf8408cSAntonio Huete Jimenez {
2592*cdf8408cSAntonio Huete Jimenez 	re_putc(e, '\a', 0);
2593*cdf8408cSAntonio Huete Jimenez 	return 0;
2594*cdf8408cSAntonio Huete Jimenez }
2595*cdf8408cSAntonio Huete Jimenez 
2596*cdf8408cSAntonio Huete Jimenez int
rl_abort(int count,int key)2597*cdf8408cSAntonio Huete Jimenez rl_abort(int count, int key)
2598*cdf8408cSAntonio Huete Jimenez {
2599*cdf8408cSAntonio Huete Jimenez 	return count && key ? 0 : 0;
2600*cdf8408cSAntonio Huete Jimenez }
2601*cdf8408cSAntonio Huete Jimenez 
2602*cdf8408cSAntonio Huete Jimenez int
rl_set_keymap_name(const char * name,Keymap k)2603*cdf8408cSAntonio Huete Jimenez rl_set_keymap_name(const char *name, Keymap k)
2604*cdf8408cSAntonio Huete Jimenez {
2605*cdf8408cSAntonio Huete Jimenez 	return name && k ? 0 : 0;
2606*cdf8408cSAntonio Huete Jimenez }
2607*cdf8408cSAntonio Huete Jimenez 
2608*cdf8408cSAntonio Huete Jimenez histdata_t
free_history_entry(HIST_ENTRY * he)2609*cdf8408cSAntonio Huete Jimenez free_history_entry(HIST_ENTRY *he)
2610*cdf8408cSAntonio Huete Jimenez {
2611*cdf8408cSAntonio Huete Jimenez 	return he ? NULL : NULL;
2612*cdf8408cSAntonio Huete Jimenez }
2613*cdf8408cSAntonio Huete Jimenez 
2614*cdf8408cSAntonio Huete Jimenez void
_rl_erase_entire_line(void)2615*cdf8408cSAntonio Huete Jimenez _rl_erase_entire_line(void)
2616*cdf8408cSAntonio Huete Jimenez {
2617*cdf8408cSAntonio Huete Jimenez }
2618