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