1*0a6a1f1dSLionel Sambuc /* $NetBSD: readline.c,v 1.117 2015/06/02 15:35:31 christos Exp $ */
23e1db26aSLionel Sambuc
33e1db26aSLionel Sambuc /*-
43e1db26aSLionel Sambuc * Copyright (c) 1997 The NetBSD Foundation, Inc.
53e1db26aSLionel Sambuc * All rights reserved.
63e1db26aSLionel Sambuc *
73e1db26aSLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation
83e1db26aSLionel Sambuc * by Jaromir Dolecek.
93e1db26aSLionel Sambuc *
103e1db26aSLionel Sambuc * Redistribution and use in source and binary forms, with or without
113e1db26aSLionel Sambuc * modification, are permitted provided that the following conditions
123e1db26aSLionel Sambuc * are met:
133e1db26aSLionel Sambuc * 1. Redistributions of source code must retain the above copyright
143e1db26aSLionel Sambuc * notice, this list of conditions and the following disclaimer.
153e1db26aSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
163e1db26aSLionel Sambuc * notice, this list of conditions and the following disclaimer in the
173e1db26aSLionel Sambuc * documentation and/or other materials provided with the distribution.
183e1db26aSLionel Sambuc *
193e1db26aSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
203e1db26aSLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
213e1db26aSLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223e1db26aSLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
233e1db26aSLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
243e1db26aSLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
253e1db26aSLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
263e1db26aSLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
273e1db26aSLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
283e1db26aSLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
293e1db26aSLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
303e1db26aSLionel Sambuc */
313e1db26aSLionel Sambuc
323e1db26aSLionel Sambuc #include "config.h"
333e1db26aSLionel Sambuc #if !defined(lint) && !defined(SCCSID)
34*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: readline.c,v 1.117 2015/06/02 15:35:31 christos Exp $");
353e1db26aSLionel Sambuc #endif /* not lint && not SCCSID */
363e1db26aSLionel Sambuc
373e1db26aSLionel Sambuc #include <sys/types.h>
383e1db26aSLionel Sambuc #include <sys/stat.h>
393e1db26aSLionel Sambuc #include <stdio.h>
403e1db26aSLionel Sambuc #include <dirent.h>
413e1db26aSLionel Sambuc #include <string.h>
423e1db26aSLionel Sambuc #include <pwd.h>
433e1db26aSLionel Sambuc #include <ctype.h>
443e1db26aSLionel Sambuc #include <stdlib.h>
453e1db26aSLionel Sambuc #include <unistd.h>
463e1db26aSLionel Sambuc #include <limits.h>
473e1db26aSLionel Sambuc #include <errno.h>
483e1db26aSLionel Sambuc #include <fcntl.h>
493e1db26aSLionel Sambuc #include <setjmp.h>
503e1db26aSLionel Sambuc #include <vis.h>
513e1db26aSLionel Sambuc
523e1db26aSLionel Sambuc #include "readline/readline.h"
533e1db26aSLionel Sambuc #include "el.h"
543e1db26aSLionel Sambuc #include "fcns.h" /* for EL_NUM_FCNS */
553e1db26aSLionel Sambuc #include "histedit.h"
563e1db26aSLionel Sambuc #include "filecomplete.h"
573e1db26aSLionel Sambuc
583e1db26aSLionel Sambuc void rl_prep_terminal(int);
593e1db26aSLionel Sambuc void rl_deprep_terminal(void);
603e1db26aSLionel Sambuc
613e1db26aSLionel Sambuc /* for rl_complete() */
623e1db26aSLionel Sambuc #define TAB '\r'
633e1db26aSLionel Sambuc
643e1db26aSLionel Sambuc /* see comment at the #ifdef for sense of this */
653e1db26aSLionel Sambuc /* #define GDB_411_HACK */
663e1db26aSLionel Sambuc
673e1db26aSLionel Sambuc /* readline compatibility stuff - look at readline sources/documentation */
683e1db26aSLionel Sambuc /* to see what these variables mean */
693e1db26aSLionel Sambuc const char *rl_library_version = "EditLine wrapper";
703e1db26aSLionel Sambuc int rl_readline_version = RL_READLINE_VERSION;
713e1db26aSLionel Sambuc static char empty[] = { '\0' };
723e1db26aSLionel Sambuc static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
733e1db26aSLionel Sambuc static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
743e1db26aSLionel Sambuc '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
753e1db26aSLionel Sambuc char *rl_readline_name = empty;
763e1db26aSLionel Sambuc FILE *rl_instream = NULL;
773e1db26aSLionel Sambuc FILE *rl_outstream = NULL;
783e1db26aSLionel Sambuc int rl_point = 0;
793e1db26aSLionel Sambuc int rl_end = 0;
803e1db26aSLionel Sambuc char *rl_line_buffer = NULL;
81*0a6a1f1dSLionel Sambuc rl_vcpfunc_t *rl_linefunc = NULL;
823e1db26aSLionel Sambuc int rl_done = 0;
833e1db26aSLionel Sambuc VFunction *rl_event_hook = NULL;
843e1db26aSLionel Sambuc KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
853e1db26aSLionel Sambuc emacs_meta_keymap,
863e1db26aSLionel Sambuc emacs_ctlx_keymap;
8784d9c625SLionel Sambuc /*
8884d9c625SLionel Sambuc * The following is not implemented; we always catch signals in the
8984d9c625SLionel Sambuc * libedit fashion: set handlers on entry to el_gets() and clear them
9084d9c625SLionel Sambuc * on the way out. This simplistic approach works for most cases; if
9184d9c625SLionel Sambuc * it does not work for your application, please let us know.
9284d9c625SLionel Sambuc */
9384d9c625SLionel Sambuc int rl_catch_signals = 1;
9484d9c625SLionel Sambuc int rl_catch_sigwinch = 1;
953e1db26aSLionel Sambuc
963e1db26aSLionel Sambuc int history_base = 1; /* probably never subject to change */
973e1db26aSLionel Sambuc int history_length = 0;
983e1db26aSLionel Sambuc int max_input_history = 0;
993e1db26aSLionel Sambuc char history_expansion_char = '!';
1003e1db26aSLionel Sambuc char history_subst_char = '^';
1013e1db26aSLionel Sambuc char *history_no_expand_chars = expand_chars;
1023e1db26aSLionel Sambuc Function *history_inhibit_expansion_function = NULL;
1033e1db26aSLionel Sambuc char *history_arg_extract(int start, int end, const char *str);
1043e1db26aSLionel Sambuc
1053e1db26aSLionel Sambuc int rl_inhibit_completion = 0;
1063e1db26aSLionel Sambuc int rl_attempted_completion_over = 0;
1073e1db26aSLionel Sambuc char *rl_basic_word_break_characters = break_chars;
1083e1db26aSLionel Sambuc char *rl_completer_word_break_characters = NULL;
1093e1db26aSLionel Sambuc char *rl_completer_quote_characters = NULL;
110*0a6a1f1dSLionel Sambuc rl_compentry_func_t *rl_completion_entry_function = NULL;
1113e1db26aSLionel Sambuc char *(*rl_completion_word_break_hook)(void) = NULL;
112*0a6a1f1dSLionel Sambuc rl_completion_func_t *rl_attempted_completion_function = NULL;
1133e1db26aSLionel Sambuc Function *rl_pre_input_hook = NULL;
1143e1db26aSLionel Sambuc Function *rl_startup1_hook = NULL;
1153e1db26aSLionel Sambuc int (*rl_getc_function)(FILE *) = NULL;
1163e1db26aSLionel Sambuc char *rl_terminal_name = NULL;
1173e1db26aSLionel Sambuc int rl_already_prompted = 0;
1183e1db26aSLionel Sambuc int rl_filename_completion_desired = 0;
1193e1db26aSLionel Sambuc int rl_ignore_completion_duplicates = 0;
1203e1db26aSLionel Sambuc int readline_echoing_p = 1;
1213e1db26aSLionel Sambuc int _rl_print_completions_horizontally = 0;
1223e1db26aSLionel Sambuc VFunction *rl_redisplay_function = NULL;
1233e1db26aSLionel Sambuc Function *rl_startup_hook = NULL;
1243e1db26aSLionel Sambuc VFunction *rl_completion_display_matches_hook = NULL;
1253e1db26aSLionel Sambuc VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
1263e1db26aSLionel Sambuc VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
1273e1db26aSLionel Sambuc KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
1283e1db26aSLionel Sambuc
1293e1db26aSLionel Sambuc /*
1303e1db26aSLionel Sambuc * The current prompt string.
1313e1db26aSLionel Sambuc */
1323e1db26aSLionel Sambuc char *rl_prompt = NULL;
1333e1db26aSLionel Sambuc /*
1343e1db26aSLionel Sambuc * This is set to character indicating type of completion being done by
1353e1db26aSLionel Sambuc * rl_complete_internal(); this is available for application completion
1363e1db26aSLionel Sambuc * functions.
1373e1db26aSLionel Sambuc */
1383e1db26aSLionel Sambuc int rl_completion_type = 0;
1393e1db26aSLionel Sambuc
1403e1db26aSLionel Sambuc /*
1413e1db26aSLionel Sambuc * If more than this number of items results from query for possible
1423e1db26aSLionel Sambuc * completions, we ask user if they are sure to really display the list.
1433e1db26aSLionel Sambuc */
1443e1db26aSLionel Sambuc int rl_completion_query_items = 100;
1453e1db26aSLionel Sambuc
1463e1db26aSLionel Sambuc /*
1473e1db26aSLionel Sambuc * List of characters which are word break characters, but should be left
1483e1db26aSLionel Sambuc * in the parsed text when it is passed to the completion function.
1493e1db26aSLionel Sambuc * Shell uses this to help determine what kind of completing to do.
1503e1db26aSLionel Sambuc */
1513e1db26aSLionel Sambuc char *rl_special_prefixes = NULL;
1523e1db26aSLionel Sambuc
1533e1db26aSLionel Sambuc /*
1543e1db26aSLionel Sambuc * This is the character appended to the completed words if at the end of
1553e1db26aSLionel Sambuc * the line. Default is ' ' (a space).
1563e1db26aSLionel Sambuc */
1573e1db26aSLionel Sambuc int rl_completion_append_character = ' ';
1583e1db26aSLionel Sambuc
1593e1db26aSLionel Sambuc /* stuff below is used internally by libedit for readline emulation */
1603e1db26aSLionel Sambuc
1613e1db26aSLionel Sambuc static History *h = NULL;
1623e1db26aSLionel Sambuc static EditLine *e = NULL;
163*0a6a1f1dSLionel Sambuc static rl_command_func_t *map[256];
1643e1db26aSLionel Sambuc static jmp_buf topbuf;
1653e1db26aSLionel Sambuc
1663e1db26aSLionel Sambuc /* internal functions */
1673e1db26aSLionel Sambuc static unsigned char _el_rl_complete(EditLine *, int);
1683e1db26aSLionel Sambuc static unsigned char _el_rl_tstp(EditLine *, int);
1693e1db26aSLionel Sambuc static char *_get_prompt(EditLine *);
1703e1db26aSLionel Sambuc static int _getc_function(EditLine *, char *);
1713e1db26aSLionel Sambuc static HIST_ENTRY *_move_history(int);
1723e1db26aSLionel Sambuc static int _history_expand_command(const char *, size_t, size_t,
1733e1db26aSLionel Sambuc char **);
1743e1db26aSLionel Sambuc static char *_rl_compat_sub(const char *, const char *,
1753e1db26aSLionel Sambuc const char *, int);
1763e1db26aSLionel Sambuc static int _rl_event_read_char(EditLine *, char *);
1773e1db26aSLionel Sambuc static void _rl_update_pos(void);
1783e1db26aSLionel Sambuc
1793e1db26aSLionel Sambuc
1803e1db26aSLionel Sambuc /* ARGSUSED */
1813e1db26aSLionel Sambuc static char *
_get_prompt(EditLine * el)1823e1db26aSLionel Sambuc _get_prompt(EditLine *el __attribute__((__unused__)))
1833e1db26aSLionel Sambuc {
1843e1db26aSLionel Sambuc rl_already_prompted = 1;
1853e1db26aSLionel Sambuc return rl_prompt;
1863e1db26aSLionel Sambuc }
1873e1db26aSLionel Sambuc
1883e1db26aSLionel Sambuc
1893e1db26aSLionel Sambuc /*
1903e1db26aSLionel Sambuc * generic function for moving around history
1913e1db26aSLionel Sambuc */
1923e1db26aSLionel Sambuc static HIST_ENTRY *
_move_history(int op)1933e1db26aSLionel Sambuc _move_history(int op)
1943e1db26aSLionel Sambuc {
1953e1db26aSLionel Sambuc HistEvent ev;
1963e1db26aSLionel Sambuc static HIST_ENTRY rl_he;
1973e1db26aSLionel Sambuc
1983e1db26aSLionel Sambuc if (history(h, &ev, op) != 0)
1993e1db26aSLionel Sambuc return NULL;
2003e1db26aSLionel Sambuc
2013e1db26aSLionel Sambuc rl_he.line = ev.str;
2023e1db26aSLionel Sambuc rl_he.data = NULL;
2033e1db26aSLionel Sambuc
2043e1db26aSLionel Sambuc return &rl_he;
2053e1db26aSLionel Sambuc }
2063e1db26aSLionel Sambuc
2073e1db26aSLionel Sambuc
2083e1db26aSLionel Sambuc /*
2093e1db26aSLionel Sambuc * read one key from user defined input function
2103e1db26aSLionel Sambuc */
2113e1db26aSLionel Sambuc static int
2123e1db26aSLionel Sambuc /*ARGSUSED*/
_getc_function(EditLine * el,char * c)2133e1db26aSLionel Sambuc _getc_function(EditLine *el __attribute__((__unused__)), char *c)
2143e1db26aSLionel Sambuc {
2153e1db26aSLionel Sambuc int i;
2163e1db26aSLionel Sambuc
2173e1db26aSLionel Sambuc i = (*rl_getc_function)(NULL);
2183e1db26aSLionel Sambuc if (i == -1)
2193e1db26aSLionel Sambuc return 0;
2203e1db26aSLionel Sambuc *c = (char)i;
2213e1db26aSLionel Sambuc return 1;
2223e1db26aSLionel Sambuc }
2233e1db26aSLionel Sambuc
2243e1db26aSLionel Sambuc static void
_resize_fun(EditLine * el,void * a)2253e1db26aSLionel Sambuc _resize_fun(EditLine *el, void *a)
2263e1db26aSLionel Sambuc {
2273e1db26aSLionel Sambuc const LineInfo *li;
2283e1db26aSLionel Sambuc char **ap = a;
2293e1db26aSLionel Sambuc
2303e1db26aSLionel Sambuc li = el_line(el);
2313e1db26aSLionel Sambuc /* a cheesy way to get rid of const cast. */
2323e1db26aSLionel Sambuc *ap = memchr(li->buffer, *li->buffer, (size_t)1);
2333e1db26aSLionel Sambuc }
2343e1db26aSLionel Sambuc
2353e1db26aSLionel Sambuc static const char *
_default_history_file(void)2363e1db26aSLionel Sambuc _default_history_file(void)
2373e1db26aSLionel Sambuc {
2383e1db26aSLionel Sambuc struct passwd *p;
23984d9c625SLionel Sambuc static char *path;
24084d9c625SLionel Sambuc size_t len;
2413e1db26aSLionel Sambuc
24284d9c625SLionel Sambuc if (path)
2433e1db26aSLionel Sambuc return path;
24484d9c625SLionel Sambuc
2453e1db26aSLionel Sambuc if ((p = getpwuid(getuid())) == NULL)
2463e1db26aSLionel Sambuc return NULL;
24784d9c625SLionel Sambuc
24884d9c625SLionel Sambuc len = strlen(p->pw_dir) + sizeof("/.history");
24984d9c625SLionel Sambuc if ((path = malloc(len)) == NULL)
25084d9c625SLionel Sambuc return NULL;
25184d9c625SLionel Sambuc
25284d9c625SLionel Sambuc (void)snprintf(path, len, "%s/.history", p->pw_dir);
2533e1db26aSLionel Sambuc return path;
2543e1db26aSLionel Sambuc }
2553e1db26aSLionel Sambuc
2563e1db26aSLionel Sambuc /*
2573e1db26aSLionel Sambuc * READLINE compatibility stuff
2583e1db26aSLionel Sambuc */
2593e1db26aSLionel Sambuc
2603e1db26aSLionel Sambuc /*
2613e1db26aSLionel Sambuc * Set the prompt
2623e1db26aSLionel Sambuc */
2633e1db26aSLionel Sambuc int
rl_set_prompt(const char * prompt)2643e1db26aSLionel Sambuc rl_set_prompt(const char *prompt)
2653e1db26aSLionel Sambuc {
2663e1db26aSLionel Sambuc char *p;
2673e1db26aSLionel Sambuc
2683e1db26aSLionel Sambuc if (!prompt)
2693e1db26aSLionel Sambuc prompt = "";
2703e1db26aSLionel Sambuc if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
2713e1db26aSLionel Sambuc return 0;
2723e1db26aSLionel Sambuc if (rl_prompt)
2733e1db26aSLionel Sambuc el_free(rl_prompt);
2743e1db26aSLionel Sambuc rl_prompt = strdup(prompt);
2753e1db26aSLionel Sambuc if (rl_prompt == NULL)
2763e1db26aSLionel Sambuc return -1;
2773e1db26aSLionel Sambuc
2783e1db26aSLionel Sambuc while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL)
2793e1db26aSLionel Sambuc *p = RL_PROMPT_START_IGNORE;
2803e1db26aSLionel Sambuc
2813e1db26aSLionel Sambuc return 0;
2823e1db26aSLionel Sambuc }
2833e1db26aSLionel Sambuc
2843e1db26aSLionel Sambuc /*
2853e1db26aSLionel Sambuc * initialize rl compat stuff
2863e1db26aSLionel Sambuc */
2873e1db26aSLionel Sambuc int
rl_initialize(void)2883e1db26aSLionel Sambuc rl_initialize(void)
2893e1db26aSLionel Sambuc {
2903e1db26aSLionel Sambuc HistEvent ev;
2913e1db26aSLionel Sambuc int editmode = 1;
2923e1db26aSLionel Sambuc struct termios t;
2933e1db26aSLionel Sambuc
2943e1db26aSLionel Sambuc if (e != NULL)
2953e1db26aSLionel Sambuc el_end(e);
2963e1db26aSLionel Sambuc if (h != NULL)
2973e1db26aSLionel Sambuc history_end(h);
2983e1db26aSLionel Sambuc
2993e1db26aSLionel Sambuc if (!rl_instream)
3003e1db26aSLionel Sambuc rl_instream = stdin;
3013e1db26aSLionel Sambuc if (!rl_outstream)
3023e1db26aSLionel Sambuc rl_outstream = stdout;
3033e1db26aSLionel Sambuc
3043e1db26aSLionel Sambuc /*
3053e1db26aSLionel Sambuc * See if we don't really want to run the editor
3063e1db26aSLionel Sambuc */
3073e1db26aSLionel Sambuc if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
3083e1db26aSLionel Sambuc editmode = 0;
3093e1db26aSLionel Sambuc
3103e1db26aSLionel Sambuc e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
3113e1db26aSLionel Sambuc
3123e1db26aSLionel Sambuc if (!editmode)
3133e1db26aSLionel Sambuc el_set(e, EL_EDITMODE, 0);
3143e1db26aSLionel Sambuc
3153e1db26aSLionel Sambuc h = history_init();
3163e1db26aSLionel Sambuc if (!e || !h)
3173e1db26aSLionel Sambuc return -1;
3183e1db26aSLionel Sambuc
3193e1db26aSLionel Sambuc history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
3203e1db26aSLionel Sambuc history_length = 0;
3213e1db26aSLionel Sambuc max_input_history = INT_MAX;
3223e1db26aSLionel Sambuc el_set(e, EL_HIST, history, h);
3233e1db26aSLionel Sambuc
3243e1db26aSLionel Sambuc /* Setup resize function */
3253e1db26aSLionel Sambuc el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer);
3263e1db26aSLionel Sambuc
3273e1db26aSLionel Sambuc /* setup getc function if valid */
3283e1db26aSLionel Sambuc if (rl_getc_function)
3293e1db26aSLionel Sambuc el_set(e, EL_GETCFN, _getc_function);
3303e1db26aSLionel Sambuc
3313e1db26aSLionel Sambuc /* for proper prompt printing in readline() */
3323e1db26aSLionel Sambuc if (rl_set_prompt("") == -1) {
3333e1db26aSLionel Sambuc history_end(h);
3343e1db26aSLionel Sambuc el_end(e);
3353e1db26aSLionel Sambuc return -1;
3363e1db26aSLionel Sambuc }
3373e1db26aSLionel Sambuc el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE);
3383e1db26aSLionel Sambuc el_set(e, EL_SIGNAL, rl_catch_signals);
3393e1db26aSLionel Sambuc
3403e1db26aSLionel Sambuc /* set default mode to "emacs"-style and read setting afterwards */
341*0a6a1f1dSLionel Sambuc /* so this can be overridden */
3423e1db26aSLionel Sambuc el_set(e, EL_EDITOR, "emacs");
3433e1db26aSLionel Sambuc if (rl_terminal_name != NULL)
3443e1db26aSLionel Sambuc el_set(e, EL_TERMINAL, rl_terminal_name);
3453e1db26aSLionel Sambuc else
3463e1db26aSLionel Sambuc el_get(e, EL_TERMINAL, &rl_terminal_name);
3473e1db26aSLionel Sambuc
3483e1db26aSLionel Sambuc /*
3493e1db26aSLionel Sambuc * Word completion - this has to go AFTER rebinding keys
3503e1db26aSLionel Sambuc * to emacs-style.
3513e1db26aSLionel Sambuc */
3523e1db26aSLionel Sambuc el_set(e, EL_ADDFN, "rl_complete",
3533e1db26aSLionel Sambuc "ReadLine compatible completion function",
3543e1db26aSLionel Sambuc _el_rl_complete);
3553e1db26aSLionel Sambuc el_set(e, EL_BIND, "^I", "rl_complete", NULL);
3563e1db26aSLionel Sambuc
3573e1db26aSLionel Sambuc /*
3583e1db26aSLionel Sambuc * Send TSTP when ^Z is pressed.
3593e1db26aSLionel Sambuc */
3603e1db26aSLionel Sambuc el_set(e, EL_ADDFN, "rl_tstp",
3613e1db26aSLionel Sambuc "ReadLine compatible suspend function",
3623e1db26aSLionel Sambuc _el_rl_tstp);
3633e1db26aSLionel Sambuc el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
3643e1db26aSLionel Sambuc
365*0a6a1f1dSLionel Sambuc /*
366*0a6a1f1dSLionel Sambuc * Set some readline compatible key-bindings.
367*0a6a1f1dSLionel Sambuc */
368*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL);
369*0a6a1f1dSLionel Sambuc
370*0a6a1f1dSLionel Sambuc /*
371*0a6a1f1dSLionel Sambuc * Allow the use of Home/End keys.
372*0a6a1f1dSLionel Sambuc */
373*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
374*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
375*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL);
376*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL);
377*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL);
378*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL);
379*0a6a1f1dSLionel Sambuc
380*0a6a1f1dSLionel Sambuc /*
381*0a6a1f1dSLionel Sambuc * Allow the use of the Delete/Insert keys.
382*0a6a1f1dSLionel Sambuc */
383*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
384*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[2~", "ed-quoted-insert", NULL);
385*0a6a1f1dSLionel Sambuc
386*0a6a1f1dSLionel Sambuc /*
387*0a6a1f1dSLionel Sambuc * Ctrl-left-arrow and Ctrl-right-arrow for word moving.
388*0a6a1f1dSLionel Sambuc */
389*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
390*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
391*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL);
392*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL);
393*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
394*0a6a1f1dSLionel Sambuc el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
395*0a6a1f1dSLionel Sambuc
3963e1db26aSLionel Sambuc /* read settings from configuration file */
3973e1db26aSLionel Sambuc el_source(e, NULL);
3983e1db26aSLionel Sambuc
3993e1db26aSLionel Sambuc /*
4003e1db26aSLionel Sambuc * Unfortunately, some applications really do use rl_point
4013e1db26aSLionel Sambuc * and rl_line_buffer directly.
4023e1db26aSLionel Sambuc */
4033e1db26aSLionel Sambuc _resize_fun(e, &rl_line_buffer);
4043e1db26aSLionel Sambuc _rl_update_pos();
4053e1db26aSLionel Sambuc
4063e1db26aSLionel Sambuc if (rl_startup_hook)
4073e1db26aSLionel Sambuc (*rl_startup_hook)(NULL, 0);
4083e1db26aSLionel Sambuc
4093e1db26aSLionel Sambuc return 0;
4103e1db26aSLionel Sambuc }
4113e1db26aSLionel Sambuc
4123e1db26aSLionel Sambuc
4133e1db26aSLionel Sambuc /*
4143e1db26aSLionel Sambuc * read one line from input stream and return it, chomping
4153e1db26aSLionel Sambuc * trailing newline (if there is any)
4163e1db26aSLionel Sambuc */
4173e1db26aSLionel Sambuc char *
readline(const char * p)4183e1db26aSLionel Sambuc readline(const char *p)
4193e1db26aSLionel Sambuc {
4203e1db26aSLionel Sambuc HistEvent ev;
4213e1db26aSLionel Sambuc const char * volatile prompt = p;
4223e1db26aSLionel Sambuc int count;
4233e1db26aSLionel Sambuc const char *ret;
4243e1db26aSLionel Sambuc char *buf;
4253e1db26aSLionel Sambuc static int used_event_hook;
4263e1db26aSLionel Sambuc
4273e1db26aSLionel Sambuc if (e == NULL || h == NULL)
4283e1db26aSLionel Sambuc rl_initialize();
4293e1db26aSLionel Sambuc
4303e1db26aSLionel Sambuc rl_done = 0;
4313e1db26aSLionel Sambuc
4323e1db26aSLionel Sambuc (void)setjmp(topbuf);
4333e1db26aSLionel Sambuc
4343e1db26aSLionel Sambuc /* update prompt accordingly to what has been passed */
4353e1db26aSLionel Sambuc if (rl_set_prompt(prompt) == -1)
4363e1db26aSLionel Sambuc return NULL;
4373e1db26aSLionel Sambuc
4383e1db26aSLionel Sambuc if (rl_pre_input_hook)
4393e1db26aSLionel Sambuc (*rl_pre_input_hook)(NULL, 0);
4403e1db26aSLionel Sambuc
4413e1db26aSLionel Sambuc if (rl_event_hook && !(e->el_flags&NO_TTY)) {
4423e1db26aSLionel Sambuc el_set(e, EL_GETCFN, _rl_event_read_char);
4433e1db26aSLionel Sambuc used_event_hook = 1;
4443e1db26aSLionel Sambuc }
4453e1db26aSLionel Sambuc
4463e1db26aSLionel Sambuc if (!rl_event_hook && used_event_hook) {
4473e1db26aSLionel Sambuc el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
4483e1db26aSLionel Sambuc used_event_hook = 0;
4493e1db26aSLionel Sambuc }
4503e1db26aSLionel Sambuc
4513e1db26aSLionel Sambuc rl_already_prompted = 0;
4523e1db26aSLionel Sambuc
4533e1db26aSLionel Sambuc /* get one line from input stream */
4543e1db26aSLionel Sambuc ret = el_gets(e, &count);
4553e1db26aSLionel Sambuc
4563e1db26aSLionel Sambuc if (ret && count > 0) {
4573e1db26aSLionel Sambuc int lastidx;
4583e1db26aSLionel Sambuc
4593e1db26aSLionel Sambuc buf = strdup(ret);
4603e1db26aSLionel Sambuc if (buf == NULL)
4613e1db26aSLionel Sambuc return NULL;
4623e1db26aSLionel Sambuc lastidx = count - 1;
4633e1db26aSLionel Sambuc if (buf[lastidx] == '\n')
4643e1db26aSLionel Sambuc buf[lastidx] = '\0';
4653e1db26aSLionel Sambuc } else
4663e1db26aSLionel Sambuc buf = NULL;
4673e1db26aSLionel Sambuc
4683e1db26aSLionel Sambuc history(h, &ev, H_GETSIZE);
4693e1db26aSLionel Sambuc history_length = ev.num;
4703e1db26aSLionel Sambuc
4713e1db26aSLionel Sambuc return buf;
4723e1db26aSLionel Sambuc }
4733e1db26aSLionel Sambuc
4743e1db26aSLionel Sambuc /*
4753e1db26aSLionel Sambuc * history functions
4763e1db26aSLionel Sambuc */
4773e1db26aSLionel Sambuc
4783e1db26aSLionel Sambuc /*
4793e1db26aSLionel Sambuc * is normally called before application starts to use
4803e1db26aSLionel Sambuc * history expansion functions
4813e1db26aSLionel Sambuc */
4823e1db26aSLionel Sambuc void
using_history(void)4833e1db26aSLionel Sambuc using_history(void)
4843e1db26aSLionel Sambuc {
4853e1db26aSLionel Sambuc if (h == NULL || e == NULL)
4863e1db26aSLionel Sambuc rl_initialize();
4873e1db26aSLionel Sambuc }
4883e1db26aSLionel Sambuc
4893e1db26aSLionel Sambuc
4903e1db26aSLionel Sambuc /*
4913e1db26aSLionel Sambuc * substitute ``what'' with ``with'', returning resulting string; if
4923e1db26aSLionel Sambuc * globally == 1, substitutes all occurrences of what, otherwise only the
4933e1db26aSLionel Sambuc * first one
4943e1db26aSLionel Sambuc */
4953e1db26aSLionel Sambuc static char *
_rl_compat_sub(const char * str,const char * what,const char * with,int globally)4963e1db26aSLionel Sambuc _rl_compat_sub(const char *str, const char *what, const char *with,
4973e1db26aSLionel Sambuc int globally)
4983e1db26aSLionel Sambuc {
4993e1db26aSLionel Sambuc const char *s;
5003e1db26aSLionel Sambuc char *r, *result;
5013e1db26aSLionel Sambuc size_t len, with_len, what_len;
5023e1db26aSLionel Sambuc
5033e1db26aSLionel Sambuc len = strlen(str);
5043e1db26aSLionel Sambuc with_len = strlen(with);
5053e1db26aSLionel Sambuc what_len = strlen(what);
5063e1db26aSLionel Sambuc
5073e1db26aSLionel Sambuc /* calculate length we need for result */
5083e1db26aSLionel Sambuc s = str;
5093e1db26aSLionel Sambuc while (*s) {
5103e1db26aSLionel Sambuc if (*s == *what && !strncmp(s, what, what_len)) {
5113e1db26aSLionel Sambuc len += with_len - what_len;
5123e1db26aSLionel Sambuc if (!globally)
5133e1db26aSLionel Sambuc break;
5143e1db26aSLionel Sambuc s += what_len;
5153e1db26aSLionel Sambuc } else
5163e1db26aSLionel Sambuc s++;
5173e1db26aSLionel Sambuc }
5183e1db26aSLionel Sambuc r = result = el_malloc((len + 1) * sizeof(*r));
5193e1db26aSLionel Sambuc if (result == NULL)
5203e1db26aSLionel Sambuc return NULL;
5213e1db26aSLionel Sambuc s = str;
5223e1db26aSLionel Sambuc while (*s) {
5233e1db26aSLionel Sambuc if (*s == *what && !strncmp(s, what, what_len)) {
5243e1db26aSLionel Sambuc (void)strncpy(r, with, with_len);
5253e1db26aSLionel Sambuc r += with_len;
5263e1db26aSLionel Sambuc s += what_len;
5273e1db26aSLionel Sambuc if (!globally) {
5283e1db26aSLionel Sambuc (void)strcpy(r, s);
5293e1db26aSLionel Sambuc return result;
5303e1db26aSLionel Sambuc }
5313e1db26aSLionel Sambuc } else
5323e1db26aSLionel Sambuc *r++ = *s++;
5333e1db26aSLionel Sambuc }
5343e1db26aSLionel Sambuc *r = '\0';
5353e1db26aSLionel Sambuc return result;
5363e1db26aSLionel Sambuc }
5373e1db26aSLionel Sambuc
5383e1db26aSLionel Sambuc static char *last_search_pat; /* last !?pat[?] search pattern */
5393e1db26aSLionel Sambuc static char *last_search_match; /* last !?pat[?] that matched */
5403e1db26aSLionel Sambuc
5413e1db26aSLionel Sambuc const char *
get_history_event(const char * cmd,int * cindex,int qchar)5423e1db26aSLionel Sambuc get_history_event(const char *cmd, int *cindex, int qchar)
5433e1db26aSLionel Sambuc {
5443e1db26aSLionel Sambuc int idx, sign, sub, num, begin, ret;
5453e1db26aSLionel Sambuc size_t len;
5463e1db26aSLionel Sambuc char *pat;
5473e1db26aSLionel Sambuc const char *rptr;
5483e1db26aSLionel Sambuc HistEvent ev;
5493e1db26aSLionel Sambuc
5503e1db26aSLionel Sambuc idx = *cindex;
5513e1db26aSLionel Sambuc if (cmd[idx++] != history_expansion_char)
5523e1db26aSLionel Sambuc return NULL;
5533e1db26aSLionel Sambuc
5543e1db26aSLionel Sambuc /* find out which event to take */
5553e1db26aSLionel Sambuc if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
5563e1db26aSLionel Sambuc if (history(h, &ev, H_FIRST) != 0)
5573e1db26aSLionel Sambuc return NULL;
5583e1db26aSLionel Sambuc *cindex = cmd[idx]? (idx + 1):idx;
5593e1db26aSLionel Sambuc return ev.str;
5603e1db26aSLionel Sambuc }
5613e1db26aSLionel Sambuc sign = 0;
5623e1db26aSLionel Sambuc if (cmd[idx] == '-') {
5633e1db26aSLionel Sambuc sign = 1;
5643e1db26aSLionel Sambuc idx++;
5653e1db26aSLionel Sambuc }
5663e1db26aSLionel Sambuc
5673e1db26aSLionel Sambuc if ('0' <= cmd[idx] && cmd[idx] <= '9') {
5683e1db26aSLionel Sambuc HIST_ENTRY *rl_he;
5693e1db26aSLionel Sambuc
5703e1db26aSLionel Sambuc num = 0;
5713e1db26aSLionel Sambuc while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
5723e1db26aSLionel Sambuc num = num * 10 + cmd[idx] - '0';
5733e1db26aSLionel Sambuc idx++;
5743e1db26aSLionel Sambuc }
5753e1db26aSLionel Sambuc if (sign)
5763e1db26aSLionel Sambuc num = history_length - num + 1;
5773e1db26aSLionel Sambuc
5783e1db26aSLionel Sambuc if (!(rl_he = history_get(num)))
5793e1db26aSLionel Sambuc return NULL;
5803e1db26aSLionel Sambuc
5813e1db26aSLionel Sambuc *cindex = idx;
5823e1db26aSLionel Sambuc return rl_he->line;
5833e1db26aSLionel Sambuc }
5843e1db26aSLionel Sambuc sub = 0;
5853e1db26aSLionel Sambuc if (cmd[idx] == '?') {
5863e1db26aSLionel Sambuc sub = 1;
5873e1db26aSLionel Sambuc idx++;
5883e1db26aSLionel Sambuc }
5893e1db26aSLionel Sambuc begin = idx;
5903e1db26aSLionel Sambuc while (cmd[idx]) {
5913e1db26aSLionel Sambuc if (cmd[idx] == '\n')
5923e1db26aSLionel Sambuc break;
5933e1db26aSLionel Sambuc if (sub && cmd[idx] == '?')
5943e1db26aSLionel Sambuc break;
5953e1db26aSLionel Sambuc if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
5963e1db26aSLionel Sambuc || cmd[idx] == '\t' || cmd[idx] == qchar))
5973e1db26aSLionel Sambuc break;
5983e1db26aSLionel Sambuc idx++;
5993e1db26aSLionel Sambuc }
6003e1db26aSLionel Sambuc len = (size_t)idx - (size_t)begin;
6013e1db26aSLionel Sambuc if (sub && cmd[idx] == '?')
6023e1db26aSLionel Sambuc idx++;
6033e1db26aSLionel Sambuc if (sub && len == 0 && last_search_pat && *last_search_pat)
6043e1db26aSLionel Sambuc pat = last_search_pat;
6053e1db26aSLionel Sambuc else if (len == 0)
6063e1db26aSLionel Sambuc return NULL;
6073e1db26aSLionel Sambuc else {
6083e1db26aSLionel Sambuc if ((pat = el_malloc((len + 1) * sizeof(*pat))) == NULL)
6093e1db26aSLionel Sambuc return NULL;
6103e1db26aSLionel Sambuc (void)strncpy(pat, cmd + begin, len);
6113e1db26aSLionel Sambuc pat[len] = '\0';
6123e1db26aSLionel Sambuc }
6133e1db26aSLionel Sambuc
6143e1db26aSLionel Sambuc if (history(h, &ev, H_CURR) != 0) {
6153e1db26aSLionel Sambuc if (pat != last_search_pat)
6163e1db26aSLionel Sambuc el_free(pat);
6173e1db26aSLionel Sambuc return NULL;
6183e1db26aSLionel Sambuc }
6193e1db26aSLionel Sambuc num = ev.num;
6203e1db26aSLionel Sambuc
6213e1db26aSLionel Sambuc if (sub) {
6223e1db26aSLionel Sambuc if (pat != last_search_pat) {
6233e1db26aSLionel Sambuc if (last_search_pat)
6243e1db26aSLionel Sambuc el_free(last_search_pat);
6253e1db26aSLionel Sambuc last_search_pat = pat;
6263e1db26aSLionel Sambuc }
6273e1db26aSLionel Sambuc ret = history_search(pat, -1);
6283e1db26aSLionel Sambuc } else
6293e1db26aSLionel Sambuc ret = history_search_prefix(pat, -1);
6303e1db26aSLionel Sambuc
6313e1db26aSLionel Sambuc if (ret == -1) {
6323e1db26aSLionel Sambuc /* restore to end of list on failed search */
6333e1db26aSLionel Sambuc history(h, &ev, H_FIRST);
6343e1db26aSLionel Sambuc (void)fprintf(rl_outstream, "%s: Event not found\n", pat);
6353e1db26aSLionel Sambuc if (pat != last_search_pat)
6363e1db26aSLionel Sambuc el_free(pat);
6373e1db26aSLionel Sambuc return NULL;
6383e1db26aSLionel Sambuc }
6393e1db26aSLionel Sambuc
6403e1db26aSLionel Sambuc if (sub && len) {
6413e1db26aSLionel Sambuc if (last_search_match && last_search_match != pat)
6423e1db26aSLionel Sambuc el_free(last_search_match);
6433e1db26aSLionel Sambuc last_search_match = pat;
6443e1db26aSLionel Sambuc }
6453e1db26aSLionel Sambuc
6463e1db26aSLionel Sambuc if (pat != last_search_pat)
6473e1db26aSLionel Sambuc el_free(pat);
6483e1db26aSLionel Sambuc
6493e1db26aSLionel Sambuc if (history(h, &ev, H_CURR) != 0)
6503e1db26aSLionel Sambuc return NULL;
6513e1db26aSLionel Sambuc *cindex = idx;
6523e1db26aSLionel Sambuc rptr = ev.str;
6533e1db26aSLionel Sambuc
6543e1db26aSLionel Sambuc /* roll back to original position */
6553e1db26aSLionel Sambuc (void)history(h, &ev, H_SET, num);
6563e1db26aSLionel Sambuc
6573e1db26aSLionel Sambuc return rptr;
6583e1db26aSLionel Sambuc }
6593e1db26aSLionel Sambuc
6603e1db26aSLionel Sambuc /*
6613e1db26aSLionel Sambuc * the real function doing history expansion - takes as argument command
6623e1db26aSLionel Sambuc * to do and data upon which the command should be executed
6633e1db26aSLionel Sambuc * does expansion the way I've understood readline documentation
6643e1db26aSLionel Sambuc *
6653e1db26aSLionel Sambuc * returns 0 if data was not modified, 1 if it was and 2 if the string
6663e1db26aSLionel Sambuc * should be only printed and not executed; in case of error,
6673e1db26aSLionel Sambuc * returns -1 and *result points to NULL
668*0a6a1f1dSLionel Sambuc * it's the caller's responsibility to free() the string returned in *result
6693e1db26aSLionel Sambuc */
6703e1db26aSLionel Sambuc static int
_history_expand_command(const char * command,size_t offs,size_t cmdlen,char ** result)6713e1db26aSLionel Sambuc _history_expand_command(const char *command, size_t offs, size_t cmdlen,
6723e1db26aSLionel Sambuc char **result)
6733e1db26aSLionel Sambuc {
6743e1db26aSLionel Sambuc char *tmp, *search = NULL, *aptr;
6753e1db26aSLionel Sambuc const char *ptr, *cmd;
6763e1db26aSLionel Sambuc static char *from = NULL, *to = NULL;
6773e1db26aSLionel Sambuc int start, end, idx, has_mods = 0;
6783e1db26aSLionel Sambuc int p_on = 0, g_on = 0;
6793e1db26aSLionel Sambuc
6803e1db26aSLionel Sambuc *result = NULL;
6813e1db26aSLionel Sambuc aptr = NULL;
6823e1db26aSLionel Sambuc ptr = NULL;
6833e1db26aSLionel Sambuc
6843e1db26aSLionel Sambuc /* First get event specifier */
6853e1db26aSLionel Sambuc idx = 0;
6863e1db26aSLionel Sambuc
6873e1db26aSLionel Sambuc if (strchr(":^*$", command[offs + 1])) {
6883e1db26aSLionel Sambuc char str[4];
6893e1db26aSLionel Sambuc /*
6903e1db26aSLionel Sambuc * "!:" is shorthand for "!!:".
6913e1db26aSLionel Sambuc * "!^", "!*" and "!$" are shorthand for
6923e1db26aSLionel Sambuc * "!!:^", "!!:*" and "!!:$" respectively.
6933e1db26aSLionel Sambuc */
6943e1db26aSLionel Sambuc str[0] = str[1] = '!';
6953e1db26aSLionel Sambuc str[2] = '0';
6963e1db26aSLionel Sambuc ptr = get_history_event(str, &idx, 0);
6973e1db26aSLionel Sambuc idx = (command[offs + 1] == ':')? 1:0;
6983e1db26aSLionel Sambuc has_mods = 1;
6993e1db26aSLionel Sambuc } else {
7003e1db26aSLionel Sambuc if (command[offs + 1] == '#') {
7013e1db26aSLionel Sambuc /* use command so far */
7023e1db26aSLionel Sambuc if ((aptr = el_malloc((offs + 1) * sizeof(*aptr)))
7033e1db26aSLionel Sambuc == NULL)
7043e1db26aSLionel Sambuc return -1;
7053e1db26aSLionel Sambuc (void)strncpy(aptr, command, offs);
7063e1db26aSLionel Sambuc aptr[offs] = '\0';
7073e1db26aSLionel Sambuc idx = 1;
7083e1db26aSLionel Sambuc } else {
7093e1db26aSLionel Sambuc int qchar;
7103e1db26aSLionel Sambuc
7113e1db26aSLionel Sambuc qchar = (offs > 0 && command[offs - 1] == '"')? '"':0;
7123e1db26aSLionel Sambuc ptr = get_history_event(command + offs, &idx, qchar);
7133e1db26aSLionel Sambuc }
7143e1db26aSLionel Sambuc has_mods = command[offs + (size_t)idx] == ':';
7153e1db26aSLionel Sambuc }
7163e1db26aSLionel Sambuc
7173e1db26aSLionel Sambuc if (ptr == NULL && aptr == NULL)
7183e1db26aSLionel Sambuc return -1;
7193e1db26aSLionel Sambuc
7203e1db26aSLionel Sambuc if (!has_mods) {
7213e1db26aSLionel Sambuc *result = strdup(aptr ? aptr : ptr);
7223e1db26aSLionel Sambuc if (aptr)
7233e1db26aSLionel Sambuc el_free(aptr);
7243e1db26aSLionel Sambuc if (*result == NULL)
7253e1db26aSLionel Sambuc return -1;
7263e1db26aSLionel Sambuc return 1;
7273e1db26aSLionel Sambuc }
7283e1db26aSLionel Sambuc
7293e1db26aSLionel Sambuc cmd = command + offs + idx + 1;
7303e1db26aSLionel Sambuc
7313e1db26aSLionel Sambuc /* Now parse any word designators */
7323e1db26aSLionel Sambuc
7333e1db26aSLionel Sambuc if (*cmd == '%') /* last word matched by ?pat? */
7343e1db26aSLionel Sambuc tmp = strdup(last_search_match? last_search_match:"");
7353e1db26aSLionel Sambuc else if (strchr("^*$-0123456789", *cmd)) {
7363e1db26aSLionel Sambuc start = end = -1;
7373e1db26aSLionel Sambuc if (*cmd == '^')
7383e1db26aSLionel Sambuc start = end = 1, cmd++;
7393e1db26aSLionel Sambuc else if (*cmd == '$')
7403e1db26aSLionel Sambuc start = -1, cmd++;
7413e1db26aSLionel Sambuc else if (*cmd == '*')
7423e1db26aSLionel Sambuc start = 1, cmd++;
7433e1db26aSLionel Sambuc else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
7443e1db26aSLionel Sambuc start = 0;
7453e1db26aSLionel Sambuc while (*cmd && '0' <= *cmd && *cmd <= '9')
7463e1db26aSLionel Sambuc start = start * 10 + *cmd++ - '0';
7473e1db26aSLionel Sambuc
7483e1db26aSLionel Sambuc if (*cmd == '-') {
7493e1db26aSLionel Sambuc if (isdigit((unsigned char) cmd[1])) {
7503e1db26aSLionel Sambuc cmd++;
7513e1db26aSLionel Sambuc end = 0;
7523e1db26aSLionel Sambuc while (*cmd && '0' <= *cmd && *cmd <= '9')
7533e1db26aSLionel Sambuc end = end * 10 + *cmd++ - '0';
7543e1db26aSLionel Sambuc } else if (cmd[1] == '$') {
7553e1db26aSLionel Sambuc cmd += 2;
7563e1db26aSLionel Sambuc end = -1;
7573e1db26aSLionel Sambuc } else {
7583e1db26aSLionel Sambuc cmd++;
7593e1db26aSLionel Sambuc end = -2;
7603e1db26aSLionel Sambuc }
7613e1db26aSLionel Sambuc } else if (*cmd == '*')
7623e1db26aSLionel Sambuc end = -1, cmd++;
7633e1db26aSLionel Sambuc else
7643e1db26aSLionel Sambuc end = start;
7653e1db26aSLionel Sambuc }
7663e1db26aSLionel Sambuc tmp = history_arg_extract(start, end, aptr? aptr:ptr);
7673e1db26aSLionel Sambuc if (tmp == NULL) {
7683e1db26aSLionel Sambuc (void)fprintf(rl_outstream, "%s: Bad word specifier",
7693e1db26aSLionel Sambuc command + offs + idx);
7703e1db26aSLionel Sambuc if (aptr)
7713e1db26aSLionel Sambuc el_free(aptr);
7723e1db26aSLionel Sambuc return -1;
7733e1db26aSLionel Sambuc }
7743e1db26aSLionel Sambuc } else
7753e1db26aSLionel Sambuc tmp = strdup(aptr? aptr:ptr);
7763e1db26aSLionel Sambuc
7773e1db26aSLionel Sambuc if (aptr)
7783e1db26aSLionel Sambuc el_free(aptr);
7793e1db26aSLionel Sambuc
7803e1db26aSLionel Sambuc if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
7813e1db26aSLionel Sambuc *result = tmp;
7823e1db26aSLionel Sambuc return 1;
7833e1db26aSLionel Sambuc }
7843e1db26aSLionel Sambuc
7853e1db26aSLionel Sambuc for (; *cmd; cmd++) {
7863e1db26aSLionel Sambuc if (*cmd == ':')
7873e1db26aSLionel Sambuc continue;
7883e1db26aSLionel Sambuc else if (*cmd == 'h') { /* remove trailing path */
7893e1db26aSLionel Sambuc if ((aptr = strrchr(tmp, '/')) != NULL)
7903e1db26aSLionel Sambuc *aptr = '\0';
7913e1db26aSLionel Sambuc } else if (*cmd == 't') { /* remove leading path */
7923e1db26aSLionel Sambuc if ((aptr = strrchr(tmp, '/')) != NULL) {
7933e1db26aSLionel Sambuc aptr = strdup(aptr + 1);
7943e1db26aSLionel Sambuc el_free(tmp);
7953e1db26aSLionel Sambuc tmp = aptr;
7963e1db26aSLionel Sambuc }
7973e1db26aSLionel Sambuc } else if (*cmd == 'r') { /* remove trailing suffix */
7983e1db26aSLionel Sambuc if ((aptr = strrchr(tmp, '.')) != NULL)
7993e1db26aSLionel Sambuc *aptr = '\0';
8003e1db26aSLionel Sambuc } else if (*cmd == 'e') { /* remove all but suffix */
8013e1db26aSLionel Sambuc if ((aptr = strrchr(tmp, '.')) != NULL) {
8023e1db26aSLionel Sambuc aptr = strdup(aptr);
8033e1db26aSLionel Sambuc el_free(tmp);
8043e1db26aSLionel Sambuc tmp = aptr;
8053e1db26aSLionel Sambuc }
8063e1db26aSLionel Sambuc } else if (*cmd == 'p') /* print only */
8073e1db26aSLionel Sambuc p_on = 1;
8083e1db26aSLionel Sambuc else if (*cmd == 'g')
8093e1db26aSLionel Sambuc g_on = 2;
8103e1db26aSLionel Sambuc else if (*cmd == 's' || *cmd == '&') {
8113e1db26aSLionel Sambuc char *what, *with, delim;
8123e1db26aSLionel Sambuc size_t len, from_len;
8133e1db26aSLionel Sambuc size_t size;
8143e1db26aSLionel Sambuc
8153e1db26aSLionel Sambuc if (*cmd == '&' && (from == NULL || to == NULL))
8163e1db26aSLionel Sambuc continue;
8173e1db26aSLionel Sambuc else if (*cmd == 's') {
8183e1db26aSLionel Sambuc delim = *(++cmd), cmd++;
8193e1db26aSLionel Sambuc size = 16;
8203e1db26aSLionel Sambuc what = el_realloc(from, size * sizeof(*what));
8213e1db26aSLionel Sambuc if (what == NULL) {
8223e1db26aSLionel Sambuc el_free(from);
8233e1db26aSLionel Sambuc el_free(tmp);
8243e1db26aSLionel Sambuc return 0;
8253e1db26aSLionel Sambuc }
8263e1db26aSLionel Sambuc len = 0;
8273e1db26aSLionel Sambuc for (; *cmd && *cmd != delim; cmd++) {
8283e1db26aSLionel Sambuc if (*cmd == '\\' && cmd[1] == delim)
8293e1db26aSLionel Sambuc cmd++;
8303e1db26aSLionel Sambuc if (len >= size) {
8313e1db26aSLionel Sambuc char *nwhat;
8323e1db26aSLionel Sambuc nwhat = el_realloc(what,
8333e1db26aSLionel Sambuc (size <<= 1) *
8343e1db26aSLionel Sambuc sizeof(*nwhat));
8353e1db26aSLionel Sambuc if (nwhat == NULL) {
8363e1db26aSLionel Sambuc el_free(what);
8373e1db26aSLionel Sambuc el_free(tmp);
8383e1db26aSLionel Sambuc return 0;
8393e1db26aSLionel Sambuc }
8403e1db26aSLionel Sambuc what = nwhat;
8413e1db26aSLionel Sambuc }
8423e1db26aSLionel Sambuc what[len++] = *cmd;
8433e1db26aSLionel Sambuc }
8443e1db26aSLionel Sambuc what[len] = '\0';
8453e1db26aSLionel Sambuc from = what;
8463e1db26aSLionel Sambuc if (*what == '\0') {
8473e1db26aSLionel Sambuc el_free(what);
8483e1db26aSLionel Sambuc if (search) {
8493e1db26aSLionel Sambuc from = strdup(search);
8503e1db26aSLionel Sambuc if (from == NULL) {
8513e1db26aSLionel Sambuc el_free(tmp);
8523e1db26aSLionel Sambuc return 0;
8533e1db26aSLionel Sambuc }
8543e1db26aSLionel Sambuc } else {
8553e1db26aSLionel Sambuc from = NULL;
8563e1db26aSLionel Sambuc el_free(tmp);
8573e1db26aSLionel Sambuc return -1;
8583e1db26aSLionel Sambuc }
8593e1db26aSLionel Sambuc }
8603e1db26aSLionel Sambuc cmd++; /* shift after delim */
8613e1db26aSLionel Sambuc if (!*cmd)
8623e1db26aSLionel Sambuc continue;
8633e1db26aSLionel Sambuc
8643e1db26aSLionel Sambuc size = 16;
8653e1db26aSLionel Sambuc with = el_realloc(to, size * sizeof(*with));
8663e1db26aSLionel Sambuc if (with == NULL) {
8673e1db26aSLionel Sambuc el_free(to);
8683e1db26aSLionel Sambuc el_free(tmp);
8693e1db26aSLionel Sambuc return -1;
8703e1db26aSLionel Sambuc }
8713e1db26aSLionel Sambuc len = 0;
8723e1db26aSLionel Sambuc from_len = strlen(from);
8733e1db26aSLionel Sambuc for (; *cmd && *cmd != delim; cmd++) {
8743e1db26aSLionel Sambuc if (len + from_len + 1 >= size) {
8753e1db26aSLionel Sambuc char *nwith;
8763e1db26aSLionel Sambuc size += from_len + 1;
8773e1db26aSLionel Sambuc nwith = el_realloc(with,
8783e1db26aSLionel Sambuc size * sizeof(*nwith));
8793e1db26aSLionel Sambuc if (nwith == NULL) {
8803e1db26aSLionel Sambuc el_free(with);
8813e1db26aSLionel Sambuc el_free(tmp);
8823e1db26aSLionel Sambuc return -1;
8833e1db26aSLionel Sambuc }
8843e1db26aSLionel Sambuc with = nwith;
8853e1db26aSLionel Sambuc }
8863e1db26aSLionel Sambuc if (*cmd == '&') {
8873e1db26aSLionel Sambuc /* safe */
8883e1db26aSLionel Sambuc (void)strcpy(&with[len], from);
8893e1db26aSLionel Sambuc len += from_len;
8903e1db26aSLionel Sambuc continue;
8913e1db26aSLionel Sambuc }
8923e1db26aSLionel Sambuc if (*cmd == '\\'
8933e1db26aSLionel Sambuc && (*(cmd + 1) == delim
8943e1db26aSLionel Sambuc || *(cmd + 1) == '&'))
8953e1db26aSLionel Sambuc cmd++;
8963e1db26aSLionel Sambuc with[len++] = *cmd;
8973e1db26aSLionel Sambuc }
8983e1db26aSLionel Sambuc with[len] = '\0';
8993e1db26aSLionel Sambuc to = with;
9003e1db26aSLionel Sambuc }
9013e1db26aSLionel Sambuc
9023e1db26aSLionel Sambuc aptr = _rl_compat_sub(tmp, from, to, g_on);
9033e1db26aSLionel Sambuc if (aptr) {
9043e1db26aSLionel Sambuc el_free(tmp);
9053e1db26aSLionel Sambuc tmp = aptr;
9063e1db26aSLionel Sambuc }
9073e1db26aSLionel Sambuc g_on = 0;
9083e1db26aSLionel Sambuc }
9093e1db26aSLionel Sambuc }
9103e1db26aSLionel Sambuc *result = tmp;
9113e1db26aSLionel Sambuc return p_on? 2:1;
9123e1db26aSLionel Sambuc }
9133e1db26aSLionel Sambuc
9143e1db26aSLionel Sambuc
9153e1db26aSLionel Sambuc /*
9163e1db26aSLionel Sambuc * csh-style history expansion
9173e1db26aSLionel Sambuc */
9183e1db26aSLionel Sambuc int
history_expand(char * str,char ** output)9193e1db26aSLionel Sambuc history_expand(char *str, char **output)
9203e1db26aSLionel Sambuc {
9213e1db26aSLionel Sambuc int ret = 0;
9223e1db26aSLionel Sambuc size_t idx, i, size;
9233e1db26aSLionel Sambuc char *tmp, *result;
9243e1db26aSLionel Sambuc
9253e1db26aSLionel Sambuc if (h == NULL || e == NULL)
9263e1db26aSLionel Sambuc rl_initialize();
9273e1db26aSLionel Sambuc
9283e1db26aSLionel Sambuc if (history_expansion_char == 0) {
9293e1db26aSLionel Sambuc *output = strdup(str);
9303e1db26aSLionel Sambuc return 0;
9313e1db26aSLionel Sambuc }
9323e1db26aSLionel Sambuc
9333e1db26aSLionel Sambuc *output = NULL;
9343e1db26aSLionel Sambuc if (str[0] == history_subst_char) {
9353e1db26aSLionel Sambuc /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
9363e1db26aSLionel Sambuc *output = el_malloc((strlen(str) + 4 + 1) * sizeof(**output));
9373e1db26aSLionel Sambuc if (*output == NULL)
9383e1db26aSLionel Sambuc return 0;
9393e1db26aSLionel Sambuc (*output)[0] = (*output)[1] = history_expansion_char;
9403e1db26aSLionel Sambuc (*output)[2] = ':';
9413e1db26aSLionel Sambuc (*output)[3] = 's';
9423e1db26aSLionel Sambuc (void)strcpy((*output) + 4, str);
9433e1db26aSLionel Sambuc str = *output;
9443e1db26aSLionel Sambuc } else {
9453e1db26aSLionel Sambuc *output = strdup(str);
9463e1db26aSLionel Sambuc if (*output == NULL)
9473e1db26aSLionel Sambuc return 0;
9483e1db26aSLionel Sambuc }
9493e1db26aSLionel Sambuc
9503e1db26aSLionel Sambuc #define ADD_STRING(what, len, fr) \
9513e1db26aSLionel Sambuc { \
9523e1db26aSLionel Sambuc if (idx + len + 1 > size) { \
9533e1db26aSLionel Sambuc char *nresult = el_realloc(result, \
9543e1db26aSLionel Sambuc (size += len + 1) * sizeof(*nresult)); \
9553e1db26aSLionel Sambuc if (nresult == NULL) { \
9563e1db26aSLionel Sambuc el_free(*output); \
9573e1db26aSLionel Sambuc if (/*CONSTCOND*/fr) \
9583e1db26aSLionel Sambuc el_free(tmp); \
9593e1db26aSLionel Sambuc return 0; \
9603e1db26aSLionel Sambuc } \
9613e1db26aSLionel Sambuc result = nresult; \
9623e1db26aSLionel Sambuc } \
9633e1db26aSLionel Sambuc (void)strncpy(&result[idx], what, len); \
9643e1db26aSLionel Sambuc idx += len; \
9653e1db26aSLionel Sambuc result[idx] = '\0'; \
9663e1db26aSLionel Sambuc }
9673e1db26aSLionel Sambuc
9683e1db26aSLionel Sambuc result = NULL;
9693e1db26aSLionel Sambuc size = idx = 0;
9703e1db26aSLionel Sambuc tmp = NULL;
9713e1db26aSLionel Sambuc for (i = 0; str[i];) {
9723e1db26aSLionel Sambuc int qchar, loop_again;
9733e1db26aSLionel Sambuc size_t len, start, j;
9743e1db26aSLionel Sambuc
9753e1db26aSLionel Sambuc qchar = 0;
9763e1db26aSLionel Sambuc loop_again = 1;
9773e1db26aSLionel Sambuc start = j = i;
9783e1db26aSLionel Sambuc loop:
9793e1db26aSLionel Sambuc for (; str[j]; j++) {
9803e1db26aSLionel Sambuc if (str[j] == '\\' &&
9813e1db26aSLionel Sambuc str[j + 1] == history_expansion_char) {
982*0a6a1f1dSLionel Sambuc len = strlen(&str[j + 1]) + 1;
983*0a6a1f1dSLionel Sambuc memmove(&str[j], &str[j + 1], len);
9843e1db26aSLionel Sambuc continue;
9853e1db26aSLionel Sambuc }
9863e1db26aSLionel Sambuc if (!loop_again) {
9873e1db26aSLionel Sambuc if (isspace((unsigned char) str[j])
9883e1db26aSLionel Sambuc || str[j] == qchar)
9893e1db26aSLionel Sambuc break;
9903e1db26aSLionel Sambuc }
9913e1db26aSLionel Sambuc if (str[j] == history_expansion_char
9923e1db26aSLionel Sambuc && !strchr(history_no_expand_chars, str[j + 1])
9933e1db26aSLionel Sambuc && (!history_inhibit_expansion_function ||
9943e1db26aSLionel Sambuc (*history_inhibit_expansion_function)(str,
9953e1db26aSLionel Sambuc (int)j) == 0))
9963e1db26aSLionel Sambuc break;
9973e1db26aSLionel Sambuc }
9983e1db26aSLionel Sambuc
9993e1db26aSLionel Sambuc if (str[j] && loop_again) {
10003e1db26aSLionel Sambuc i = j;
10013e1db26aSLionel Sambuc qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
10023e1db26aSLionel Sambuc j++;
10033e1db26aSLionel Sambuc if (str[j] == history_expansion_char)
10043e1db26aSLionel Sambuc j++;
10053e1db26aSLionel Sambuc loop_again = 0;
10063e1db26aSLionel Sambuc goto loop;
10073e1db26aSLionel Sambuc }
10083e1db26aSLionel Sambuc len = i - start;
10093e1db26aSLionel Sambuc ADD_STRING(&str[start], len, 0);
10103e1db26aSLionel Sambuc
10113e1db26aSLionel Sambuc if (str[i] == '\0' || str[i] != history_expansion_char) {
10123e1db26aSLionel Sambuc len = j - i;
10133e1db26aSLionel Sambuc ADD_STRING(&str[i], len, 0);
10143e1db26aSLionel Sambuc if (start == 0)
10153e1db26aSLionel Sambuc ret = 0;
10163e1db26aSLionel Sambuc else
10173e1db26aSLionel Sambuc ret = 1;
10183e1db26aSLionel Sambuc break;
10193e1db26aSLionel Sambuc }
10203e1db26aSLionel Sambuc ret = _history_expand_command (str, i, (j - i), &tmp);
10213e1db26aSLionel Sambuc if (ret > 0 && tmp) {
10223e1db26aSLionel Sambuc len = strlen(tmp);
10233e1db26aSLionel Sambuc ADD_STRING(tmp, len, 1);
10243e1db26aSLionel Sambuc }
10253e1db26aSLionel Sambuc if (tmp) {
10263e1db26aSLionel Sambuc el_free(tmp);
10273e1db26aSLionel Sambuc tmp = NULL;
10283e1db26aSLionel Sambuc }
10293e1db26aSLionel Sambuc i = j;
10303e1db26aSLionel Sambuc }
10313e1db26aSLionel Sambuc
10323e1db26aSLionel Sambuc /* ret is 2 for "print only" option */
10333e1db26aSLionel Sambuc if (ret == 2) {
10343e1db26aSLionel Sambuc add_history(result);
10353e1db26aSLionel Sambuc #ifdef GDB_411_HACK
10363e1db26aSLionel Sambuc /* gdb 4.11 has been shipped with readline, where */
10373e1db26aSLionel Sambuc /* history_expand() returned -1 when the line */
10383e1db26aSLionel Sambuc /* should not be executed; in readline 2.1+ */
10393e1db26aSLionel Sambuc /* it should return 2 in such a case */
10403e1db26aSLionel Sambuc ret = -1;
10413e1db26aSLionel Sambuc #endif
10423e1db26aSLionel Sambuc }
10433e1db26aSLionel Sambuc el_free(*output);
10443e1db26aSLionel Sambuc *output = result;
10453e1db26aSLionel Sambuc
10463e1db26aSLionel Sambuc return ret;
10473e1db26aSLionel Sambuc }
10483e1db26aSLionel Sambuc
10493e1db26aSLionel Sambuc /*
10503e1db26aSLionel Sambuc * Return a string consisting of arguments of "str" from "start" to "end".
10513e1db26aSLionel Sambuc */
10523e1db26aSLionel Sambuc char *
history_arg_extract(int start,int end,const char * str)10533e1db26aSLionel Sambuc history_arg_extract(int start, int end, const char *str)
10543e1db26aSLionel Sambuc {
10553e1db26aSLionel Sambuc size_t i, len, max;
10563e1db26aSLionel Sambuc char **arr, *result = NULL;
10573e1db26aSLionel Sambuc
10583e1db26aSLionel Sambuc arr = history_tokenize(str);
10593e1db26aSLionel Sambuc if (!arr)
10603e1db26aSLionel Sambuc return NULL;
10613e1db26aSLionel Sambuc if (arr && *arr == NULL)
10623e1db26aSLionel Sambuc goto out;
10633e1db26aSLionel Sambuc
10643e1db26aSLionel Sambuc for (max = 0; arr[max]; max++)
10653e1db26aSLionel Sambuc continue;
10663e1db26aSLionel Sambuc max--;
10673e1db26aSLionel Sambuc
10683e1db26aSLionel Sambuc if (start == '$')
10693e1db26aSLionel Sambuc start = (int)max;
10703e1db26aSLionel Sambuc if (end == '$')
10713e1db26aSLionel Sambuc end = (int)max;
10723e1db26aSLionel Sambuc if (end < 0)
10733e1db26aSLionel Sambuc end = (int)max + end + 1;
10743e1db26aSLionel Sambuc if (start < 0)
10753e1db26aSLionel Sambuc start = end;
10763e1db26aSLionel Sambuc
10773e1db26aSLionel Sambuc if (start < 0 || end < 0 || (size_t)start > max ||
10783e1db26aSLionel Sambuc (size_t)end > max || start > end)
10793e1db26aSLionel Sambuc goto out;
10803e1db26aSLionel Sambuc
10813e1db26aSLionel Sambuc for (i = (size_t)start, len = 0; i <= (size_t)end; i++)
10823e1db26aSLionel Sambuc len += strlen(arr[i]) + 1;
10833e1db26aSLionel Sambuc len++;
10843e1db26aSLionel Sambuc result = el_malloc(len * sizeof(*result));
10853e1db26aSLionel Sambuc if (result == NULL)
10863e1db26aSLionel Sambuc goto out;
10873e1db26aSLionel Sambuc
10883e1db26aSLionel Sambuc for (i = (size_t)start, len = 0; i <= (size_t)end; i++) {
10893e1db26aSLionel Sambuc (void)strcpy(result + len, arr[i]);
10903e1db26aSLionel Sambuc len += strlen(arr[i]);
10913e1db26aSLionel Sambuc if (i < (size_t)end)
10923e1db26aSLionel Sambuc result[len++] = ' ';
10933e1db26aSLionel Sambuc }
10943e1db26aSLionel Sambuc result[len] = '\0';
10953e1db26aSLionel Sambuc
10963e1db26aSLionel Sambuc out:
10973e1db26aSLionel Sambuc for (i = 0; arr[i]; i++)
10983e1db26aSLionel Sambuc el_free(arr[i]);
10993e1db26aSLionel Sambuc el_free(arr);
11003e1db26aSLionel Sambuc
11013e1db26aSLionel Sambuc return result;
11023e1db26aSLionel Sambuc }
11033e1db26aSLionel Sambuc
11043e1db26aSLionel Sambuc /*
11053e1db26aSLionel Sambuc * Parse the string into individual tokens,
11063e1db26aSLionel Sambuc * similar to how shell would do it.
11073e1db26aSLionel Sambuc */
11083e1db26aSLionel Sambuc char **
history_tokenize(const char * str)11093e1db26aSLionel Sambuc history_tokenize(const char *str)
11103e1db26aSLionel Sambuc {
11113e1db26aSLionel Sambuc int size = 1, idx = 0, i, start;
11123e1db26aSLionel Sambuc size_t len;
11133e1db26aSLionel Sambuc char **result = NULL, *temp, delim = '\0';
11143e1db26aSLionel Sambuc
11153e1db26aSLionel Sambuc for (i = 0; str[i];) {
11163e1db26aSLionel Sambuc while (isspace((unsigned char) str[i]))
11173e1db26aSLionel Sambuc i++;
11183e1db26aSLionel Sambuc start = i;
11193e1db26aSLionel Sambuc for (; str[i];) {
11203e1db26aSLionel Sambuc if (str[i] == '\\') {
11213e1db26aSLionel Sambuc if (str[i+1] != '\0')
11223e1db26aSLionel Sambuc i++;
11233e1db26aSLionel Sambuc } else if (str[i] == delim)
11243e1db26aSLionel Sambuc delim = '\0';
11253e1db26aSLionel Sambuc else if (!delim &&
11263e1db26aSLionel Sambuc (isspace((unsigned char) str[i]) ||
11273e1db26aSLionel Sambuc strchr("()<>;&|$", str[i])))
11283e1db26aSLionel Sambuc break;
11293e1db26aSLionel Sambuc else if (!delim && strchr("'`\"", str[i]))
11303e1db26aSLionel Sambuc delim = str[i];
11313e1db26aSLionel Sambuc if (str[i])
11323e1db26aSLionel Sambuc i++;
11333e1db26aSLionel Sambuc }
11343e1db26aSLionel Sambuc
11353e1db26aSLionel Sambuc if (idx + 2 >= size) {
11363e1db26aSLionel Sambuc char **nresult;
11373e1db26aSLionel Sambuc size <<= 1;
11383e1db26aSLionel Sambuc nresult = el_realloc(result, (size_t)size * sizeof(*nresult));
11393e1db26aSLionel Sambuc if (nresult == NULL) {
11403e1db26aSLionel Sambuc el_free(result);
11413e1db26aSLionel Sambuc return NULL;
11423e1db26aSLionel Sambuc }
11433e1db26aSLionel Sambuc result = nresult;
11443e1db26aSLionel Sambuc }
11453e1db26aSLionel Sambuc len = (size_t)i - (size_t)start;
11463e1db26aSLionel Sambuc temp = el_malloc((size_t)(len + 1) * sizeof(*temp));
11473e1db26aSLionel Sambuc if (temp == NULL) {
11483e1db26aSLionel Sambuc for (i = 0; i < idx; i++)
11493e1db26aSLionel Sambuc el_free(result[i]);
11503e1db26aSLionel Sambuc el_free(result);
11513e1db26aSLionel Sambuc return NULL;
11523e1db26aSLionel Sambuc }
11533e1db26aSLionel Sambuc (void)strncpy(temp, &str[start], len);
11543e1db26aSLionel Sambuc temp[len] = '\0';
11553e1db26aSLionel Sambuc result[idx++] = temp;
11563e1db26aSLionel Sambuc result[idx] = NULL;
11573e1db26aSLionel Sambuc if (str[i])
11583e1db26aSLionel Sambuc i++;
11593e1db26aSLionel Sambuc }
11603e1db26aSLionel Sambuc return result;
11613e1db26aSLionel Sambuc }
11623e1db26aSLionel Sambuc
11633e1db26aSLionel Sambuc
11643e1db26aSLionel Sambuc /*
11653e1db26aSLionel Sambuc * limit size of history record to ``max'' events
11663e1db26aSLionel Sambuc */
11673e1db26aSLionel Sambuc void
stifle_history(int max)11683e1db26aSLionel Sambuc stifle_history(int max)
11693e1db26aSLionel Sambuc {
11703e1db26aSLionel Sambuc HistEvent ev;
11713e1db26aSLionel Sambuc
11723e1db26aSLionel Sambuc if (h == NULL || e == NULL)
11733e1db26aSLionel Sambuc rl_initialize();
11743e1db26aSLionel Sambuc
11753e1db26aSLionel Sambuc if (history(h, &ev, H_SETSIZE, max) == 0)
11763e1db26aSLionel Sambuc max_input_history = max;
11773e1db26aSLionel Sambuc }
11783e1db26aSLionel Sambuc
11793e1db26aSLionel Sambuc
11803e1db26aSLionel Sambuc /*
11813e1db26aSLionel Sambuc * "unlimit" size of history - set the limit to maximum allowed int value
11823e1db26aSLionel Sambuc */
11833e1db26aSLionel Sambuc int
unstifle_history(void)11843e1db26aSLionel Sambuc unstifle_history(void)
11853e1db26aSLionel Sambuc {
11863e1db26aSLionel Sambuc HistEvent ev;
11873e1db26aSLionel Sambuc int omax;
11883e1db26aSLionel Sambuc
11893e1db26aSLionel Sambuc history(h, &ev, H_SETSIZE, INT_MAX);
11903e1db26aSLionel Sambuc omax = max_input_history;
11913e1db26aSLionel Sambuc max_input_history = INT_MAX;
11923e1db26aSLionel Sambuc return omax; /* some value _must_ be returned */
11933e1db26aSLionel Sambuc }
11943e1db26aSLionel Sambuc
11953e1db26aSLionel Sambuc
11963e1db26aSLionel Sambuc int
history_is_stifled(void)11973e1db26aSLionel Sambuc history_is_stifled(void)
11983e1db26aSLionel Sambuc {
11993e1db26aSLionel Sambuc
12003e1db26aSLionel Sambuc /* cannot return true answer */
12013e1db26aSLionel Sambuc return max_input_history != INT_MAX;
12023e1db26aSLionel Sambuc }
12033e1db26aSLionel Sambuc
12043e1db26aSLionel Sambuc static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
12053e1db26aSLionel Sambuc
12063e1db26aSLionel Sambuc int
history_truncate_file(const char * filename,int nlines)12073e1db26aSLionel Sambuc history_truncate_file (const char *filename, int nlines)
12083e1db26aSLionel Sambuc {
12093e1db26aSLionel Sambuc int ret = 0;
12103e1db26aSLionel Sambuc FILE *fp, *tp;
12113e1db26aSLionel Sambuc char template[sizeof(_history_tmp_template)];
12123e1db26aSLionel Sambuc char buf[4096];
12133e1db26aSLionel Sambuc int fd;
12143e1db26aSLionel Sambuc char *cp;
12153e1db26aSLionel Sambuc off_t off;
12163e1db26aSLionel Sambuc int count = 0;
12173e1db26aSLionel Sambuc ssize_t left = 0;
12183e1db26aSLionel Sambuc
12193e1db26aSLionel Sambuc if (filename == NULL && (filename = _default_history_file()) == NULL)
12203e1db26aSLionel Sambuc return errno;
12213e1db26aSLionel Sambuc if ((fp = fopen(filename, "r+")) == NULL)
12223e1db26aSLionel Sambuc return errno;
12233e1db26aSLionel Sambuc strcpy(template, _history_tmp_template);
12243e1db26aSLionel Sambuc if ((fd = mkstemp(template)) == -1) {
12253e1db26aSLionel Sambuc ret = errno;
12263e1db26aSLionel Sambuc goto out1;
12273e1db26aSLionel Sambuc }
12283e1db26aSLionel Sambuc
12293e1db26aSLionel Sambuc if ((tp = fdopen(fd, "r+")) == NULL) {
12303e1db26aSLionel Sambuc close(fd);
12313e1db26aSLionel Sambuc ret = errno;
12323e1db26aSLionel Sambuc goto out2;
12333e1db26aSLionel Sambuc }
12343e1db26aSLionel Sambuc
12353e1db26aSLionel Sambuc for(;;) {
12363e1db26aSLionel Sambuc if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) {
12373e1db26aSLionel Sambuc if (ferror(fp)) {
12383e1db26aSLionel Sambuc ret = errno;
12393e1db26aSLionel Sambuc break;
12403e1db26aSLionel Sambuc }
12413e1db26aSLionel Sambuc if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
12423e1db26aSLionel Sambuc (off_t)-1) {
12433e1db26aSLionel Sambuc ret = errno;
12443e1db26aSLionel Sambuc break;
12453e1db26aSLionel Sambuc }
12463e1db26aSLionel Sambuc left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp);
12473e1db26aSLionel Sambuc if (ferror(fp)) {
12483e1db26aSLionel Sambuc ret = errno;
12493e1db26aSLionel Sambuc break;
12503e1db26aSLionel Sambuc }
12513e1db26aSLionel Sambuc if (left == 0) {
12523e1db26aSLionel Sambuc count--;
12533e1db26aSLionel Sambuc left = sizeof(buf);
12543e1db26aSLionel Sambuc } else if (fwrite(buf, (size_t)left, (size_t)1, tp)
12553e1db26aSLionel Sambuc != 1) {
12563e1db26aSLionel Sambuc ret = errno;
12573e1db26aSLionel Sambuc break;
12583e1db26aSLionel Sambuc }
12593e1db26aSLionel Sambuc fflush(tp);
12603e1db26aSLionel Sambuc break;
12613e1db26aSLionel Sambuc }
12623e1db26aSLionel Sambuc if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) {
12633e1db26aSLionel Sambuc ret = errno;
12643e1db26aSLionel Sambuc break;
12653e1db26aSLionel Sambuc }
12663e1db26aSLionel Sambuc count++;
12673e1db26aSLionel Sambuc }
12683e1db26aSLionel Sambuc if (ret)
12693e1db26aSLionel Sambuc goto out3;
12703e1db26aSLionel Sambuc cp = buf + left - 1;
12713e1db26aSLionel Sambuc if(*cp != '\n')
12723e1db26aSLionel Sambuc cp++;
12733e1db26aSLionel Sambuc for(;;) {
12743e1db26aSLionel Sambuc while (--cp >= buf) {
12753e1db26aSLionel Sambuc if (*cp == '\n') {
12763e1db26aSLionel Sambuc if (--nlines == 0) {
12773e1db26aSLionel Sambuc if (++cp >= buf + sizeof(buf)) {
12783e1db26aSLionel Sambuc count++;
12793e1db26aSLionel Sambuc cp = buf;
12803e1db26aSLionel Sambuc }
12813e1db26aSLionel Sambuc break;
12823e1db26aSLionel Sambuc }
12833e1db26aSLionel Sambuc }
12843e1db26aSLionel Sambuc }
12853e1db26aSLionel Sambuc if (nlines <= 0 || count == 0)
12863e1db26aSLionel Sambuc break;
12873e1db26aSLionel Sambuc count--;
12883e1db26aSLionel Sambuc if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
12893e1db26aSLionel Sambuc ret = errno;
12903e1db26aSLionel Sambuc break;
12913e1db26aSLionel Sambuc }
12923e1db26aSLionel Sambuc if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) {
12933e1db26aSLionel Sambuc if (ferror(tp)) {
12943e1db26aSLionel Sambuc ret = errno;
12953e1db26aSLionel Sambuc break;
12963e1db26aSLionel Sambuc }
12973e1db26aSLionel Sambuc ret = EAGAIN;
12983e1db26aSLionel Sambuc break;
12993e1db26aSLionel Sambuc }
13003e1db26aSLionel Sambuc cp = buf + sizeof(buf);
13013e1db26aSLionel Sambuc }
13023e1db26aSLionel Sambuc
13033e1db26aSLionel Sambuc if (ret || nlines > 0)
13043e1db26aSLionel Sambuc goto out3;
13053e1db26aSLionel Sambuc
13063e1db26aSLionel Sambuc if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
13073e1db26aSLionel Sambuc ret = errno;
13083e1db26aSLionel Sambuc goto out3;
13093e1db26aSLionel Sambuc }
13103e1db26aSLionel Sambuc
13113e1db26aSLionel Sambuc if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
13123e1db26aSLionel Sambuc (off_t)-1) {
13133e1db26aSLionel Sambuc ret = errno;
13143e1db26aSLionel Sambuc goto out3;
13153e1db26aSLionel Sambuc }
13163e1db26aSLionel Sambuc
13173e1db26aSLionel Sambuc for(;;) {
13183e1db26aSLionel Sambuc if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) {
13193e1db26aSLionel Sambuc if (ferror(fp))
13203e1db26aSLionel Sambuc ret = errno;
13213e1db26aSLionel Sambuc break;
13223e1db26aSLionel Sambuc }
13233e1db26aSLionel Sambuc if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) {
13243e1db26aSLionel Sambuc ret = errno;
13253e1db26aSLionel Sambuc break;
13263e1db26aSLionel Sambuc }
13273e1db26aSLionel Sambuc }
13283e1db26aSLionel Sambuc fflush(fp);
13293e1db26aSLionel Sambuc if((off = ftello(fp)) > 0)
13303e1db26aSLionel Sambuc (void)ftruncate(fileno(fp), off);
13313e1db26aSLionel Sambuc out3:
13323e1db26aSLionel Sambuc fclose(tp);
13333e1db26aSLionel Sambuc out2:
13343e1db26aSLionel Sambuc unlink(template);
13353e1db26aSLionel Sambuc out1:
13363e1db26aSLionel Sambuc fclose(fp);
13373e1db26aSLionel Sambuc
13383e1db26aSLionel Sambuc return ret;
13393e1db26aSLionel Sambuc }
13403e1db26aSLionel Sambuc
13413e1db26aSLionel Sambuc
13423e1db26aSLionel Sambuc /*
13433e1db26aSLionel Sambuc * read history from a file given
13443e1db26aSLionel Sambuc */
13453e1db26aSLionel Sambuc int
read_history(const char * filename)13463e1db26aSLionel Sambuc read_history(const char *filename)
13473e1db26aSLionel Sambuc {
13483e1db26aSLionel Sambuc HistEvent ev;
13493e1db26aSLionel Sambuc
13503e1db26aSLionel Sambuc if (h == NULL || e == NULL)
13513e1db26aSLionel Sambuc rl_initialize();
13523e1db26aSLionel Sambuc if (filename == NULL && (filename = _default_history_file()) == NULL)
13533e1db26aSLionel Sambuc return errno;
13543e1db26aSLionel Sambuc return history(h, &ev, H_LOAD, filename) == -1 ?
13553e1db26aSLionel Sambuc (errno ? errno : EINVAL) : 0;
13563e1db26aSLionel Sambuc }
13573e1db26aSLionel Sambuc
13583e1db26aSLionel Sambuc
13593e1db26aSLionel Sambuc /*
13603e1db26aSLionel Sambuc * write history to a file given
13613e1db26aSLionel Sambuc */
13623e1db26aSLionel Sambuc int
write_history(const char * filename)13633e1db26aSLionel Sambuc write_history(const char *filename)
13643e1db26aSLionel Sambuc {
13653e1db26aSLionel Sambuc HistEvent ev;
13663e1db26aSLionel Sambuc
13673e1db26aSLionel Sambuc if (h == NULL || e == NULL)
13683e1db26aSLionel Sambuc rl_initialize();
13693e1db26aSLionel Sambuc if (filename == NULL && (filename = _default_history_file()) == NULL)
13703e1db26aSLionel Sambuc return errno;
13713e1db26aSLionel Sambuc return history(h, &ev, H_SAVE, filename) == -1 ?
13723e1db26aSLionel Sambuc (errno ? errno : EINVAL) : 0;
13733e1db26aSLionel Sambuc }
13743e1db26aSLionel Sambuc
13753e1db26aSLionel Sambuc
13763e1db26aSLionel Sambuc /*
13773e1db26aSLionel Sambuc * returns history ``num''th event
13783e1db26aSLionel Sambuc *
13793e1db26aSLionel Sambuc * returned pointer points to static variable
13803e1db26aSLionel Sambuc */
13813e1db26aSLionel Sambuc HIST_ENTRY *
history_get(int num)13823e1db26aSLionel Sambuc history_get(int num)
13833e1db26aSLionel Sambuc {
13843e1db26aSLionel Sambuc static HIST_ENTRY she;
13853e1db26aSLionel Sambuc HistEvent ev;
13863e1db26aSLionel Sambuc int curr_num;
13873e1db26aSLionel Sambuc
13883e1db26aSLionel Sambuc if (h == NULL || e == NULL)
13893e1db26aSLionel Sambuc rl_initialize();
13903e1db26aSLionel Sambuc
13913e1db26aSLionel Sambuc /* save current position */
13923e1db26aSLionel Sambuc if (history(h, &ev, H_CURR) != 0)
13933e1db26aSLionel Sambuc return NULL;
13943e1db26aSLionel Sambuc curr_num = ev.num;
13953e1db26aSLionel Sambuc
13963e1db26aSLionel Sambuc /* start from the oldest */
13973e1db26aSLionel Sambuc if (history(h, &ev, H_LAST) != 0)
13983e1db26aSLionel Sambuc return NULL; /* error */
13993e1db26aSLionel Sambuc
14003e1db26aSLionel Sambuc /* look forwards for event matching specified offset */
14013e1db26aSLionel Sambuc if (history(h, &ev, H_NEXT_EVDATA, num, &she.data))
14023e1db26aSLionel Sambuc return NULL;
14033e1db26aSLionel Sambuc
14043e1db26aSLionel Sambuc she.line = ev.str;
14053e1db26aSLionel Sambuc
14063e1db26aSLionel Sambuc /* restore pointer to where it was */
14073e1db26aSLionel Sambuc (void)history(h, &ev, H_SET, curr_num);
14083e1db26aSLionel Sambuc
14093e1db26aSLionel Sambuc return &she;
14103e1db26aSLionel Sambuc }
14113e1db26aSLionel Sambuc
14123e1db26aSLionel Sambuc
14133e1db26aSLionel Sambuc /*
14143e1db26aSLionel Sambuc * add the line to history table
14153e1db26aSLionel Sambuc */
14163e1db26aSLionel Sambuc int
add_history(const char * line)14173e1db26aSLionel Sambuc add_history(const char *line)
14183e1db26aSLionel Sambuc {
14193e1db26aSLionel Sambuc HistEvent ev;
14203e1db26aSLionel Sambuc
14213e1db26aSLionel Sambuc if (line == NULL)
14223e1db26aSLionel Sambuc return 0;
14233e1db26aSLionel Sambuc
14243e1db26aSLionel Sambuc if (h == NULL || e == NULL)
14253e1db26aSLionel Sambuc rl_initialize();
14263e1db26aSLionel Sambuc
14273e1db26aSLionel Sambuc (void)history(h, &ev, H_ENTER, line);
14283e1db26aSLionel Sambuc if (history(h, &ev, H_GETSIZE) == 0)
14293e1db26aSLionel Sambuc history_length = ev.num;
14303e1db26aSLionel Sambuc
14313e1db26aSLionel Sambuc return !(history_length > 0); /* return 0 if all is okay */
14323e1db26aSLionel Sambuc }
14333e1db26aSLionel Sambuc
14343e1db26aSLionel Sambuc
14353e1db26aSLionel Sambuc /*
14363e1db26aSLionel Sambuc * remove the specified entry from the history list and return it.
14373e1db26aSLionel Sambuc */
14383e1db26aSLionel Sambuc HIST_ENTRY *
remove_history(int num)14393e1db26aSLionel Sambuc remove_history(int num)
14403e1db26aSLionel Sambuc {
14413e1db26aSLionel Sambuc HIST_ENTRY *he;
14423e1db26aSLionel Sambuc HistEvent ev;
14433e1db26aSLionel Sambuc
14443e1db26aSLionel Sambuc if (h == NULL || e == NULL)
14453e1db26aSLionel Sambuc rl_initialize();
14463e1db26aSLionel Sambuc
14473e1db26aSLionel Sambuc if ((he = el_malloc(sizeof(*he))) == NULL)
14483e1db26aSLionel Sambuc return NULL;
14493e1db26aSLionel Sambuc
14503e1db26aSLionel Sambuc if (history(h, &ev, H_DELDATA, num, &he->data) != 0) {
14513e1db26aSLionel Sambuc el_free(he);
14523e1db26aSLionel Sambuc return NULL;
14533e1db26aSLionel Sambuc }
14543e1db26aSLionel Sambuc
14553e1db26aSLionel Sambuc he->line = ev.str;
14563e1db26aSLionel Sambuc if (history(h, &ev, H_GETSIZE) == 0)
14573e1db26aSLionel Sambuc history_length = ev.num;
14583e1db26aSLionel Sambuc
14593e1db26aSLionel Sambuc return he;
14603e1db26aSLionel Sambuc }
14613e1db26aSLionel Sambuc
14623e1db26aSLionel Sambuc
14633e1db26aSLionel Sambuc /*
14643e1db26aSLionel Sambuc * replace the line and data of the num-th entry
14653e1db26aSLionel Sambuc */
14663e1db26aSLionel Sambuc HIST_ENTRY *
replace_history_entry(int num,const char * line,histdata_t data)14673e1db26aSLionel Sambuc replace_history_entry(int num, const char *line, histdata_t data)
14683e1db26aSLionel Sambuc {
14693e1db26aSLionel Sambuc HIST_ENTRY *he;
14703e1db26aSLionel Sambuc HistEvent ev;
14713e1db26aSLionel Sambuc int curr_num;
14723e1db26aSLionel Sambuc
14733e1db26aSLionel Sambuc if (h == NULL || e == NULL)
14743e1db26aSLionel Sambuc rl_initialize();
14753e1db26aSLionel Sambuc
14763e1db26aSLionel Sambuc /* save current position */
14773e1db26aSLionel Sambuc if (history(h, &ev, H_CURR) != 0)
14783e1db26aSLionel Sambuc return NULL;
14793e1db26aSLionel Sambuc curr_num = ev.num;
14803e1db26aSLionel Sambuc
14813e1db26aSLionel Sambuc /* start from the oldest */
14823e1db26aSLionel Sambuc if (history(h, &ev, H_LAST) != 0)
14833e1db26aSLionel Sambuc return NULL; /* error */
14843e1db26aSLionel Sambuc
14853e1db26aSLionel Sambuc if ((he = el_malloc(sizeof(*he))) == NULL)
14863e1db26aSLionel Sambuc return NULL;
14873e1db26aSLionel Sambuc
14883e1db26aSLionel Sambuc /* look forwards for event matching specified offset */
14893e1db26aSLionel Sambuc if (history(h, &ev, H_NEXT_EVDATA, num, &he->data))
14903e1db26aSLionel Sambuc goto out;
14913e1db26aSLionel Sambuc
14923e1db26aSLionel Sambuc he->line = strdup(ev.str);
14933e1db26aSLionel Sambuc if (he->line == NULL)
14943e1db26aSLionel Sambuc goto out;
14953e1db26aSLionel Sambuc
14963e1db26aSLionel Sambuc if (history(h, &ev, H_REPLACE, line, data))
14973e1db26aSLionel Sambuc goto out;
14983e1db26aSLionel Sambuc
14993e1db26aSLionel Sambuc /* restore pointer to where it was */
15003e1db26aSLionel Sambuc if (history(h, &ev, H_SET, curr_num))
15013e1db26aSLionel Sambuc goto out;
15023e1db26aSLionel Sambuc
15033e1db26aSLionel Sambuc return he;
15043e1db26aSLionel Sambuc out:
15053e1db26aSLionel Sambuc el_free(he);
15063e1db26aSLionel Sambuc return NULL;
15073e1db26aSLionel Sambuc }
15083e1db26aSLionel Sambuc
15093e1db26aSLionel Sambuc /*
15103e1db26aSLionel Sambuc * clear the history list - delete all entries
15113e1db26aSLionel Sambuc */
15123e1db26aSLionel Sambuc void
clear_history(void)15133e1db26aSLionel Sambuc clear_history(void)
15143e1db26aSLionel Sambuc {
15153e1db26aSLionel Sambuc HistEvent ev;
15163e1db26aSLionel Sambuc
1517*0a6a1f1dSLionel Sambuc if (h == NULL || e == NULL)
1518*0a6a1f1dSLionel Sambuc rl_initialize();
1519*0a6a1f1dSLionel Sambuc
15203e1db26aSLionel Sambuc (void)history(h, &ev, H_CLEAR);
15213e1db26aSLionel Sambuc history_length = 0;
15223e1db26aSLionel Sambuc }
15233e1db26aSLionel Sambuc
15243e1db26aSLionel Sambuc
15253e1db26aSLionel Sambuc /*
15263e1db26aSLionel Sambuc * returns offset of the current history event
15273e1db26aSLionel Sambuc */
15283e1db26aSLionel Sambuc int
where_history(void)15293e1db26aSLionel Sambuc where_history(void)
15303e1db26aSLionel Sambuc {
15313e1db26aSLionel Sambuc HistEvent ev;
15323e1db26aSLionel Sambuc int curr_num, off;
15333e1db26aSLionel Sambuc
15343e1db26aSLionel Sambuc if (history(h, &ev, H_CURR) != 0)
15353e1db26aSLionel Sambuc return 0;
15363e1db26aSLionel Sambuc curr_num = ev.num;
15373e1db26aSLionel Sambuc
15383e1db26aSLionel Sambuc (void)history(h, &ev, H_FIRST);
15393e1db26aSLionel Sambuc off = 1;
15403e1db26aSLionel Sambuc while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
15413e1db26aSLionel Sambuc off++;
15423e1db26aSLionel Sambuc
15433e1db26aSLionel Sambuc return off;
15443e1db26aSLionel Sambuc }
15453e1db26aSLionel Sambuc
15463e1db26aSLionel Sambuc
15473e1db26aSLionel Sambuc /*
15483e1db26aSLionel Sambuc * returns current history event or NULL if there is no such event
15493e1db26aSLionel Sambuc */
15503e1db26aSLionel Sambuc HIST_ENTRY *
current_history(void)15513e1db26aSLionel Sambuc current_history(void)
15523e1db26aSLionel Sambuc {
15533e1db26aSLionel Sambuc
15543e1db26aSLionel Sambuc return _move_history(H_CURR);
15553e1db26aSLionel Sambuc }
15563e1db26aSLionel Sambuc
15573e1db26aSLionel Sambuc
15583e1db26aSLionel Sambuc /*
15593e1db26aSLionel Sambuc * returns total number of bytes history events' data are using
15603e1db26aSLionel Sambuc */
15613e1db26aSLionel Sambuc int
history_total_bytes(void)15623e1db26aSLionel Sambuc history_total_bytes(void)
15633e1db26aSLionel Sambuc {
15643e1db26aSLionel Sambuc HistEvent ev;
15653e1db26aSLionel Sambuc int curr_num;
15663e1db26aSLionel Sambuc size_t size;
15673e1db26aSLionel Sambuc
15683e1db26aSLionel Sambuc if (history(h, &ev, H_CURR) != 0)
15693e1db26aSLionel Sambuc return -1;
15703e1db26aSLionel Sambuc curr_num = ev.num;
15713e1db26aSLionel Sambuc
15723e1db26aSLionel Sambuc (void)history(h, &ev, H_FIRST);
15733e1db26aSLionel Sambuc size = 0;
15743e1db26aSLionel Sambuc do
15753e1db26aSLionel Sambuc size += strlen(ev.str) * sizeof(*ev.str);
15763e1db26aSLionel Sambuc while (history(h, &ev, H_NEXT) == 0);
15773e1db26aSLionel Sambuc
15783e1db26aSLionel Sambuc /* get to the same position as before */
15793e1db26aSLionel Sambuc history(h, &ev, H_PREV_EVENT, curr_num);
15803e1db26aSLionel Sambuc
15813e1db26aSLionel Sambuc return (int)size;
15823e1db26aSLionel Sambuc }
15833e1db26aSLionel Sambuc
15843e1db26aSLionel Sambuc
15853e1db26aSLionel Sambuc /*
15863e1db26aSLionel Sambuc * sets the position in the history list to ``pos''
15873e1db26aSLionel Sambuc */
15883e1db26aSLionel Sambuc int
history_set_pos(int pos)15893e1db26aSLionel Sambuc history_set_pos(int pos)
15903e1db26aSLionel Sambuc {
15913e1db26aSLionel Sambuc HistEvent ev;
15923e1db26aSLionel Sambuc int curr_num;
15933e1db26aSLionel Sambuc
15943e1db26aSLionel Sambuc if (pos >= history_length || pos < 0)
15953e1db26aSLionel Sambuc return -1;
15963e1db26aSLionel Sambuc
15973e1db26aSLionel Sambuc (void)history(h, &ev, H_CURR);
15983e1db26aSLionel Sambuc curr_num = ev.num;
15993e1db26aSLionel Sambuc
16003e1db26aSLionel Sambuc /*
16013e1db26aSLionel Sambuc * use H_DELDATA to set to nth history (without delete) by passing
16023e1db26aSLionel Sambuc * (void **)-1
16033e1db26aSLionel Sambuc */
16043e1db26aSLionel Sambuc if (history(h, &ev, H_DELDATA, pos, (void **)-1)) {
16053e1db26aSLionel Sambuc (void)history(h, &ev, H_SET, curr_num);
16063e1db26aSLionel Sambuc return -1;
16073e1db26aSLionel Sambuc }
16083e1db26aSLionel Sambuc return 0;
16093e1db26aSLionel Sambuc }
16103e1db26aSLionel Sambuc
16113e1db26aSLionel Sambuc
16123e1db26aSLionel Sambuc /*
16133e1db26aSLionel Sambuc * returns previous event in history and shifts pointer accordingly
16143e1db26aSLionel Sambuc */
16153e1db26aSLionel Sambuc HIST_ENTRY *
previous_history(void)16163e1db26aSLionel Sambuc previous_history(void)
16173e1db26aSLionel Sambuc {
16183e1db26aSLionel Sambuc
16193e1db26aSLionel Sambuc return _move_history(H_PREV);
16203e1db26aSLionel Sambuc }
16213e1db26aSLionel Sambuc
16223e1db26aSLionel Sambuc
16233e1db26aSLionel Sambuc /*
16243e1db26aSLionel Sambuc * returns next event in history and shifts pointer accordingly
16253e1db26aSLionel Sambuc */
16263e1db26aSLionel Sambuc HIST_ENTRY *
next_history(void)16273e1db26aSLionel Sambuc next_history(void)
16283e1db26aSLionel Sambuc {
16293e1db26aSLionel Sambuc
16303e1db26aSLionel Sambuc return _move_history(H_NEXT);
16313e1db26aSLionel Sambuc }
16323e1db26aSLionel Sambuc
16333e1db26aSLionel Sambuc
16343e1db26aSLionel Sambuc /*
16353e1db26aSLionel Sambuc * searches for first history event containing the str
16363e1db26aSLionel Sambuc */
16373e1db26aSLionel Sambuc int
history_search(const char * str,int direction)16383e1db26aSLionel Sambuc history_search(const char *str, int direction)
16393e1db26aSLionel Sambuc {
16403e1db26aSLionel Sambuc HistEvent ev;
16413e1db26aSLionel Sambuc const char *strp;
16423e1db26aSLionel Sambuc int curr_num;
16433e1db26aSLionel Sambuc
16443e1db26aSLionel Sambuc if (history(h, &ev, H_CURR) != 0)
16453e1db26aSLionel Sambuc return -1;
16463e1db26aSLionel Sambuc curr_num = ev.num;
16473e1db26aSLionel Sambuc
16483e1db26aSLionel Sambuc for (;;) {
16493e1db26aSLionel Sambuc if ((strp = strstr(ev.str, str)) != NULL)
16503e1db26aSLionel Sambuc return (int)(strp - ev.str);
16513e1db26aSLionel Sambuc if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
16523e1db26aSLionel Sambuc break;
16533e1db26aSLionel Sambuc }
16543e1db26aSLionel Sambuc (void)history(h, &ev, H_SET, curr_num);
16553e1db26aSLionel Sambuc return -1;
16563e1db26aSLionel Sambuc }
16573e1db26aSLionel Sambuc
16583e1db26aSLionel Sambuc
16593e1db26aSLionel Sambuc /*
16603e1db26aSLionel Sambuc * searches for first history event beginning with str
16613e1db26aSLionel Sambuc */
16623e1db26aSLionel Sambuc int
history_search_prefix(const char * str,int direction)16633e1db26aSLionel Sambuc history_search_prefix(const char *str, int direction)
16643e1db26aSLionel Sambuc {
16653e1db26aSLionel Sambuc HistEvent ev;
16663e1db26aSLionel Sambuc
16673e1db26aSLionel Sambuc return (history(h, &ev, direction < 0 ?
16683e1db26aSLionel Sambuc H_PREV_STR : H_NEXT_STR, str));
16693e1db26aSLionel Sambuc }
16703e1db26aSLionel Sambuc
16713e1db26aSLionel Sambuc
16723e1db26aSLionel Sambuc /*
16733e1db26aSLionel Sambuc * search for event in history containing str, starting at offset
16743e1db26aSLionel Sambuc * abs(pos); continue backward, if pos<0, forward otherwise
16753e1db26aSLionel Sambuc */
16763e1db26aSLionel Sambuc /* ARGSUSED */
16773e1db26aSLionel Sambuc int
history_search_pos(const char * str,int direction,int pos)16783e1db26aSLionel Sambuc history_search_pos(const char *str,
16793e1db26aSLionel Sambuc int direction __attribute__((__unused__)), int pos)
16803e1db26aSLionel Sambuc {
16813e1db26aSLionel Sambuc HistEvent ev;
16823e1db26aSLionel Sambuc int curr_num, off;
16833e1db26aSLionel Sambuc
16843e1db26aSLionel Sambuc off = (pos > 0) ? pos : -pos;
16853e1db26aSLionel Sambuc pos = (pos > 0) ? 1 : -1;
16863e1db26aSLionel Sambuc
16873e1db26aSLionel Sambuc if (history(h, &ev, H_CURR) != 0)
16883e1db26aSLionel Sambuc return -1;
16893e1db26aSLionel Sambuc curr_num = ev.num;
16903e1db26aSLionel Sambuc
16913e1db26aSLionel Sambuc if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
16923e1db26aSLionel Sambuc return -1;
16933e1db26aSLionel Sambuc
16943e1db26aSLionel Sambuc for (;;) {
16953e1db26aSLionel Sambuc if (strstr(ev.str, str))
16963e1db26aSLionel Sambuc return off;
16973e1db26aSLionel Sambuc if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
16983e1db26aSLionel Sambuc break;
16993e1db26aSLionel Sambuc }
17003e1db26aSLionel Sambuc
17013e1db26aSLionel Sambuc /* set "current" pointer back to previous state */
17023e1db26aSLionel Sambuc (void)history(h, &ev,
17033e1db26aSLionel Sambuc pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
17043e1db26aSLionel Sambuc
17053e1db26aSLionel Sambuc return -1;
17063e1db26aSLionel Sambuc }
17073e1db26aSLionel Sambuc
17083e1db26aSLionel Sambuc
17093e1db26aSLionel Sambuc /********************************/
17103e1db26aSLionel Sambuc /* completion functions */
17113e1db26aSLionel Sambuc
17123e1db26aSLionel Sambuc char *
tilde_expand(char * name)17133e1db26aSLionel Sambuc tilde_expand(char *name)
17143e1db26aSLionel Sambuc {
17153e1db26aSLionel Sambuc return fn_tilde_expand(name);
17163e1db26aSLionel Sambuc }
17173e1db26aSLionel Sambuc
17183e1db26aSLionel Sambuc char *
filename_completion_function(const char * name,int state)17193e1db26aSLionel Sambuc filename_completion_function(const char *name, int state)
17203e1db26aSLionel Sambuc {
17213e1db26aSLionel Sambuc return fn_filename_completion_function(name, state);
17223e1db26aSLionel Sambuc }
17233e1db26aSLionel Sambuc
17243e1db26aSLionel Sambuc /*
17253e1db26aSLionel Sambuc * a completion generator for usernames; returns _first_ username
17263e1db26aSLionel Sambuc * which starts with supplied text
17273e1db26aSLionel Sambuc * text contains a partial username preceded by random character
17283e1db26aSLionel Sambuc * (usually '~'); state resets search from start (??? should we do that anyway)
1729*0a6a1f1dSLionel Sambuc * it's the caller's responsibility to free the returned value
17303e1db26aSLionel Sambuc */
17313e1db26aSLionel Sambuc char *
username_completion_function(const char * text,int state)17323e1db26aSLionel Sambuc username_completion_function(const char *text, int state)
17333e1db26aSLionel Sambuc {
17343e1db26aSLionel Sambuc #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
17353e1db26aSLionel Sambuc struct passwd pwres;
17363e1db26aSLionel Sambuc char pwbuf[1024];
17373e1db26aSLionel Sambuc #endif
17383e1db26aSLionel Sambuc struct passwd *pass = NULL;
17393e1db26aSLionel Sambuc
17403e1db26aSLionel Sambuc if (text[0] == '\0')
17413e1db26aSLionel Sambuc return NULL;
17423e1db26aSLionel Sambuc
17433e1db26aSLionel Sambuc if (*text == '~')
17443e1db26aSLionel Sambuc text++;
17453e1db26aSLionel Sambuc
17463e1db26aSLionel Sambuc if (state == 0)
17473e1db26aSLionel Sambuc setpwent();
17483e1db26aSLionel Sambuc
17493e1db26aSLionel Sambuc while (
17503e1db26aSLionel Sambuc #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
17513e1db26aSLionel Sambuc getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL
17523e1db26aSLionel Sambuc #else
17533e1db26aSLionel Sambuc (pass = getpwent()) != NULL
17543e1db26aSLionel Sambuc #endif
17553e1db26aSLionel Sambuc && text[0] == pass->pw_name[0]
17563e1db26aSLionel Sambuc && strcmp(text, pass->pw_name) == 0)
17573e1db26aSLionel Sambuc continue;
17583e1db26aSLionel Sambuc
17593e1db26aSLionel Sambuc if (pass == NULL) {
17603e1db26aSLionel Sambuc endpwent();
17613e1db26aSLionel Sambuc return NULL;
17623e1db26aSLionel Sambuc }
17633e1db26aSLionel Sambuc return strdup(pass->pw_name);
17643e1db26aSLionel Sambuc }
17653e1db26aSLionel Sambuc
17663e1db26aSLionel Sambuc
17673e1db26aSLionel Sambuc /*
17683e1db26aSLionel Sambuc * el-compatible wrapper to send TSTP on ^Z
17693e1db26aSLionel Sambuc */
17703e1db26aSLionel Sambuc /* ARGSUSED */
17713e1db26aSLionel Sambuc static unsigned char
_el_rl_tstp(EditLine * el,int ch)17723e1db26aSLionel Sambuc _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
17733e1db26aSLionel Sambuc {
17743e1db26aSLionel Sambuc (void)kill(0, SIGTSTP);
17753e1db26aSLionel Sambuc return CC_NORM;
17763e1db26aSLionel Sambuc }
17773e1db26aSLionel Sambuc
17783e1db26aSLionel Sambuc /*
17793e1db26aSLionel Sambuc * Display list of strings in columnar format on readline's output stream.
17803e1db26aSLionel Sambuc * 'matches' is list of strings, 'len' is number of strings in 'matches',
17813e1db26aSLionel Sambuc * 'max' is maximum length of string in 'matches'.
17823e1db26aSLionel Sambuc */
17833e1db26aSLionel Sambuc void
rl_display_match_list(char ** matches,int len,int max)17843e1db26aSLionel Sambuc rl_display_match_list(char **matches, int len, int max)
17853e1db26aSLionel Sambuc {
17863e1db26aSLionel Sambuc
17873e1db26aSLionel Sambuc fn_display_match_list(e, matches, (size_t)len, (size_t)max);
17883e1db26aSLionel Sambuc }
17893e1db26aSLionel Sambuc
17903e1db26aSLionel Sambuc static const char *
17913e1db26aSLionel Sambuc /*ARGSUSED*/
_rl_completion_append_character_function(const char * dummy)17923e1db26aSLionel Sambuc _rl_completion_append_character_function(const char *dummy
17933e1db26aSLionel Sambuc __attribute__((__unused__)))
17943e1db26aSLionel Sambuc {
17953e1db26aSLionel Sambuc static char buf[2];
17963e1db26aSLionel Sambuc buf[0] = (char)rl_completion_append_character;
17973e1db26aSLionel Sambuc buf[1] = '\0';
17983e1db26aSLionel Sambuc return buf;
17993e1db26aSLionel Sambuc }
18003e1db26aSLionel Sambuc
18013e1db26aSLionel Sambuc
18023e1db26aSLionel Sambuc /*
18033e1db26aSLionel Sambuc * complete word at current point
18043e1db26aSLionel Sambuc */
18053e1db26aSLionel Sambuc /* ARGSUSED */
18063e1db26aSLionel Sambuc int
rl_complete(int ignore,int invoking_key)18073e1db26aSLionel Sambuc rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
18083e1db26aSLionel Sambuc {
18093e1db26aSLionel Sambuc #ifdef WIDECHAR
18103e1db26aSLionel Sambuc static ct_buffer_t wbreak_conv, sprefix_conv;
18113e1db26aSLionel Sambuc #endif
18123e1db26aSLionel Sambuc char *breakchars;
18133e1db26aSLionel Sambuc
18143e1db26aSLionel Sambuc if (h == NULL || e == NULL)
18153e1db26aSLionel Sambuc rl_initialize();
18163e1db26aSLionel Sambuc
18173e1db26aSLionel Sambuc if (rl_inhibit_completion) {
18183e1db26aSLionel Sambuc char arr[2];
18193e1db26aSLionel Sambuc arr[0] = (char)invoking_key;
18203e1db26aSLionel Sambuc arr[1] = '\0';
18213e1db26aSLionel Sambuc el_insertstr(e, arr);
18223e1db26aSLionel Sambuc return CC_REFRESH;
18233e1db26aSLionel Sambuc }
18243e1db26aSLionel Sambuc
18253e1db26aSLionel Sambuc if (rl_completion_word_break_hook != NULL)
18263e1db26aSLionel Sambuc breakchars = (*rl_completion_word_break_hook)();
18273e1db26aSLionel Sambuc else
18283e1db26aSLionel Sambuc breakchars = rl_basic_word_break_characters;
18293e1db26aSLionel Sambuc
1830*0a6a1f1dSLionel Sambuc _rl_update_pos();
1831*0a6a1f1dSLionel Sambuc
18323e1db26aSLionel Sambuc /* Just look at how many global variables modify this operation! */
18333e1db26aSLionel Sambuc return fn_complete(e,
1834*0a6a1f1dSLionel Sambuc (rl_compentry_func_t *)rl_completion_entry_function,
18353e1db26aSLionel Sambuc rl_attempted_completion_function,
18363e1db26aSLionel Sambuc ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
18373e1db26aSLionel Sambuc ct_decode_string(breakchars, &sprefix_conv),
18383e1db26aSLionel Sambuc _rl_completion_append_character_function,
18393e1db26aSLionel Sambuc (size_t)rl_completion_query_items,
18403e1db26aSLionel Sambuc &rl_completion_type, &rl_attempted_completion_over,
18413e1db26aSLionel Sambuc &rl_point, &rl_end);
18423e1db26aSLionel Sambuc
18433e1db26aSLionel Sambuc
18443e1db26aSLionel Sambuc }
18453e1db26aSLionel Sambuc
18463e1db26aSLionel Sambuc
18473e1db26aSLionel Sambuc /* ARGSUSED */
18483e1db26aSLionel Sambuc static unsigned char
_el_rl_complete(EditLine * el,int ch)18493e1db26aSLionel Sambuc _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
18503e1db26aSLionel Sambuc {
18513e1db26aSLionel Sambuc return (unsigned char)rl_complete(0, ch);
18523e1db26aSLionel Sambuc }
18533e1db26aSLionel Sambuc
18543e1db26aSLionel Sambuc /*
18553e1db26aSLionel Sambuc * misc other functions
18563e1db26aSLionel Sambuc */
18573e1db26aSLionel Sambuc
18583e1db26aSLionel Sambuc /*
18593e1db26aSLionel Sambuc * bind key c to readline-type function func
18603e1db26aSLionel Sambuc */
18613e1db26aSLionel Sambuc int
rl_bind_key(int c,rl_command_func_t * func)18623e1db26aSLionel Sambuc rl_bind_key(int c, rl_command_func_t *func)
18633e1db26aSLionel Sambuc {
18643e1db26aSLionel Sambuc int retval = -1;
18653e1db26aSLionel Sambuc
18663e1db26aSLionel Sambuc if (h == NULL || e == NULL)
18673e1db26aSLionel Sambuc rl_initialize();
18683e1db26aSLionel Sambuc
18693e1db26aSLionel Sambuc if (func == rl_insert) {
18703e1db26aSLionel Sambuc /* XXX notice there is no range checking of ``c'' */
18713e1db26aSLionel Sambuc e->el_map.key[c] = ED_INSERT;
18723e1db26aSLionel Sambuc retval = 0;
18733e1db26aSLionel Sambuc }
18743e1db26aSLionel Sambuc return retval;
18753e1db26aSLionel Sambuc }
18763e1db26aSLionel Sambuc
18773e1db26aSLionel Sambuc
18783e1db26aSLionel Sambuc /*
18793e1db26aSLionel Sambuc * read one key from input - handles chars pushed back
18803e1db26aSLionel Sambuc * to input stream also
18813e1db26aSLionel Sambuc */
18823e1db26aSLionel Sambuc int
rl_read_key(void)18833e1db26aSLionel Sambuc rl_read_key(void)
18843e1db26aSLionel Sambuc {
18853e1db26aSLionel Sambuc char fooarr[2 * sizeof(int)];
18863e1db26aSLionel Sambuc
18873e1db26aSLionel Sambuc if (e == NULL || h == NULL)
18883e1db26aSLionel Sambuc rl_initialize();
18893e1db26aSLionel Sambuc
18903e1db26aSLionel Sambuc return el_getc(e, fooarr);
18913e1db26aSLionel Sambuc }
18923e1db26aSLionel Sambuc
18933e1db26aSLionel Sambuc
18943e1db26aSLionel Sambuc /*
18953e1db26aSLionel Sambuc * reset the terminal
18963e1db26aSLionel Sambuc */
18973e1db26aSLionel Sambuc /* ARGSUSED */
18983e1db26aSLionel Sambuc void
rl_reset_terminal(const char * p)18993e1db26aSLionel Sambuc rl_reset_terminal(const char *p __attribute__((__unused__)))
19003e1db26aSLionel Sambuc {
19013e1db26aSLionel Sambuc
19023e1db26aSLionel Sambuc if (h == NULL || e == NULL)
19033e1db26aSLionel Sambuc rl_initialize();
19043e1db26aSLionel Sambuc el_reset(e);
19053e1db26aSLionel Sambuc }
19063e1db26aSLionel Sambuc
19073e1db26aSLionel Sambuc
19083e1db26aSLionel Sambuc /*
19093e1db26aSLionel Sambuc * insert character ``c'' back into input stream, ``count'' times
19103e1db26aSLionel Sambuc */
19113e1db26aSLionel Sambuc int
rl_insert(int count,int c)19123e1db26aSLionel Sambuc rl_insert(int count, int c)
19133e1db26aSLionel Sambuc {
19143e1db26aSLionel Sambuc char arr[2];
19153e1db26aSLionel Sambuc
19163e1db26aSLionel Sambuc if (h == NULL || e == NULL)
19173e1db26aSLionel Sambuc rl_initialize();
19183e1db26aSLionel Sambuc
19193e1db26aSLionel Sambuc /* XXX - int -> char conversion can lose on multichars */
19203e1db26aSLionel Sambuc arr[0] = (char)c;
19213e1db26aSLionel Sambuc arr[1] = '\0';
19223e1db26aSLionel Sambuc
19233e1db26aSLionel Sambuc for (; count > 0; count--)
19243e1db26aSLionel Sambuc el_push(e, arr);
19253e1db26aSLionel Sambuc
19263e1db26aSLionel Sambuc return 0;
19273e1db26aSLionel Sambuc }
19283e1db26aSLionel Sambuc
19293e1db26aSLionel Sambuc int
rl_insert_text(const char * text)19303e1db26aSLionel Sambuc rl_insert_text(const char *text)
19313e1db26aSLionel Sambuc {
19323e1db26aSLionel Sambuc if (!text || *text == 0)
19333e1db26aSLionel Sambuc return 0;
19343e1db26aSLionel Sambuc
19353e1db26aSLionel Sambuc if (h == NULL || e == NULL)
19363e1db26aSLionel Sambuc rl_initialize();
19373e1db26aSLionel Sambuc
19383e1db26aSLionel Sambuc if (el_insertstr(e, text) < 0)
19393e1db26aSLionel Sambuc return 0;
19403e1db26aSLionel Sambuc return (int)strlen(text);
19413e1db26aSLionel Sambuc }
19423e1db26aSLionel Sambuc
19433e1db26aSLionel Sambuc /*ARGSUSED*/
19443e1db26aSLionel Sambuc int
rl_newline(int count,int c)19453e1db26aSLionel Sambuc rl_newline(int count __attribute__((__unused__)),
19463e1db26aSLionel Sambuc int c __attribute__((__unused__)))
19473e1db26aSLionel Sambuc {
19483e1db26aSLionel Sambuc /*
19493e1db26aSLionel Sambuc * Readline-4.0 appears to ignore the args.
19503e1db26aSLionel Sambuc */
19513e1db26aSLionel Sambuc return rl_insert(1, '\n');
19523e1db26aSLionel Sambuc }
19533e1db26aSLionel Sambuc
19543e1db26aSLionel Sambuc /*ARGSUSED*/
19553e1db26aSLionel Sambuc static unsigned char
rl_bind_wrapper(EditLine * el,unsigned char c)19563e1db26aSLionel Sambuc rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c)
19573e1db26aSLionel Sambuc {
19583e1db26aSLionel Sambuc if (map[c] == NULL)
19593e1db26aSLionel Sambuc return CC_ERROR;
19603e1db26aSLionel Sambuc
19613e1db26aSLionel Sambuc _rl_update_pos();
19623e1db26aSLionel Sambuc
1963*0a6a1f1dSLionel Sambuc (*map[c])(1, c);
19643e1db26aSLionel Sambuc
19653e1db26aSLionel Sambuc /* If rl_done was set by the above call, deal with it here */
19663e1db26aSLionel Sambuc if (rl_done)
19673e1db26aSLionel Sambuc return CC_EOF;
19683e1db26aSLionel Sambuc
19693e1db26aSLionel Sambuc return CC_NORM;
19703e1db26aSLionel Sambuc }
19713e1db26aSLionel Sambuc
19723e1db26aSLionel Sambuc int
rl_add_defun(const char * name,rl_command_func_t * fun,int c)1973*0a6a1f1dSLionel Sambuc rl_add_defun(const char *name, rl_command_func_t *fun, int c)
19743e1db26aSLionel Sambuc {
19753e1db26aSLionel Sambuc char dest[8];
19763e1db26aSLionel Sambuc if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
19773e1db26aSLionel Sambuc return -1;
19783e1db26aSLionel Sambuc map[(unsigned char)c] = fun;
19793e1db26aSLionel Sambuc el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
19803e1db26aSLionel Sambuc vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
19813e1db26aSLionel Sambuc el_set(e, EL_BIND, dest, name, NULL);
19823e1db26aSLionel Sambuc return 0;
19833e1db26aSLionel Sambuc }
19843e1db26aSLionel Sambuc
19853e1db26aSLionel Sambuc void
rl_callback_read_char(void)19863e1db26aSLionel Sambuc rl_callback_read_char(void)
19873e1db26aSLionel Sambuc {
19883e1db26aSLionel Sambuc int count = 0, done = 0;
19893e1db26aSLionel Sambuc const char *buf = el_gets(e, &count);
19903e1db26aSLionel Sambuc char *wbuf;
19913e1db26aSLionel Sambuc
19923e1db26aSLionel Sambuc if (buf == NULL || count-- <= 0)
19933e1db26aSLionel Sambuc return;
19943e1db26aSLionel Sambuc if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
19953e1db26aSLionel Sambuc done = 1;
19963e1db26aSLionel Sambuc if (buf[count] == '\n' || buf[count] == '\r')
19973e1db26aSLionel Sambuc done = 2;
19983e1db26aSLionel Sambuc
19993e1db26aSLionel Sambuc if (done && rl_linefunc != NULL) {
20003e1db26aSLionel Sambuc el_set(e, EL_UNBUFFERED, 0);
20013e1db26aSLionel Sambuc if (done == 2) {
20023e1db26aSLionel Sambuc if ((wbuf = strdup(buf)) != NULL)
20033e1db26aSLionel Sambuc wbuf[count] = '\0';
20043e1db26aSLionel Sambuc } else
20053e1db26aSLionel Sambuc wbuf = NULL;
20063e1db26aSLionel Sambuc (*(void (*)(const char *))rl_linefunc)(wbuf);
2007*0a6a1f1dSLionel Sambuc el_set(e, EL_UNBUFFERED, 1);
20083e1db26aSLionel Sambuc }
20093e1db26aSLionel Sambuc }
20103e1db26aSLionel Sambuc
20113e1db26aSLionel Sambuc void
rl_callback_handler_install(const char * prompt,rl_vcpfunc_t * linefunc)2012*0a6a1f1dSLionel Sambuc rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc)
20133e1db26aSLionel Sambuc {
20143e1db26aSLionel Sambuc if (e == NULL) {
20153e1db26aSLionel Sambuc rl_initialize();
20163e1db26aSLionel Sambuc }
20173e1db26aSLionel Sambuc (void)rl_set_prompt(prompt);
20183e1db26aSLionel Sambuc rl_linefunc = linefunc;
20193e1db26aSLionel Sambuc el_set(e, EL_UNBUFFERED, 1);
20203e1db26aSLionel Sambuc }
20213e1db26aSLionel Sambuc
20223e1db26aSLionel Sambuc void
rl_callback_handler_remove(void)20233e1db26aSLionel Sambuc rl_callback_handler_remove(void)
20243e1db26aSLionel Sambuc {
20253e1db26aSLionel Sambuc el_set(e, EL_UNBUFFERED, 0);
20263e1db26aSLionel Sambuc rl_linefunc = NULL;
20273e1db26aSLionel Sambuc }
20283e1db26aSLionel Sambuc
20293e1db26aSLionel Sambuc void
rl_redisplay(void)20303e1db26aSLionel Sambuc rl_redisplay(void)
20313e1db26aSLionel Sambuc {
20323e1db26aSLionel Sambuc char a[2];
20333e1db26aSLionel Sambuc a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT];
20343e1db26aSLionel Sambuc a[1] = '\0';
20353e1db26aSLionel Sambuc el_push(e, a);
20363e1db26aSLionel Sambuc }
20373e1db26aSLionel Sambuc
20383e1db26aSLionel Sambuc int
rl_get_previous_history(int count,int key)20393e1db26aSLionel Sambuc rl_get_previous_history(int count, int key)
20403e1db26aSLionel Sambuc {
20413e1db26aSLionel Sambuc char a[2];
20423e1db26aSLionel Sambuc a[0] = (char)key;
20433e1db26aSLionel Sambuc a[1] = '\0';
20443e1db26aSLionel Sambuc while (count--)
20453e1db26aSLionel Sambuc el_push(e, a);
20463e1db26aSLionel Sambuc return 0;
20473e1db26aSLionel Sambuc }
20483e1db26aSLionel Sambuc
20493e1db26aSLionel Sambuc void
20503e1db26aSLionel Sambuc /*ARGSUSED*/
rl_prep_terminal(int meta_flag)20513e1db26aSLionel Sambuc rl_prep_terminal(int meta_flag __attribute__((__unused__)))
20523e1db26aSLionel Sambuc {
20533e1db26aSLionel Sambuc el_set(e, EL_PREP_TERM, 1);
20543e1db26aSLionel Sambuc }
20553e1db26aSLionel Sambuc
20563e1db26aSLionel Sambuc void
rl_deprep_terminal(void)20573e1db26aSLionel Sambuc rl_deprep_terminal(void)
20583e1db26aSLionel Sambuc {
20593e1db26aSLionel Sambuc el_set(e, EL_PREP_TERM, 0);
20603e1db26aSLionel Sambuc }
20613e1db26aSLionel Sambuc
20623e1db26aSLionel Sambuc int
rl_read_init_file(const char * s)20633e1db26aSLionel Sambuc rl_read_init_file(const char *s)
20643e1db26aSLionel Sambuc {
20653e1db26aSLionel Sambuc return el_source(e, s);
20663e1db26aSLionel Sambuc }
20673e1db26aSLionel Sambuc
20683e1db26aSLionel Sambuc int
rl_parse_and_bind(const char * line)20693e1db26aSLionel Sambuc rl_parse_and_bind(const char *line)
20703e1db26aSLionel Sambuc {
20713e1db26aSLionel Sambuc const char **argv;
20723e1db26aSLionel Sambuc int argc;
20733e1db26aSLionel Sambuc Tokenizer *tok;
20743e1db26aSLionel Sambuc
20753e1db26aSLionel Sambuc tok = tok_init(NULL);
20763e1db26aSLionel Sambuc tok_str(tok, line, &argc, &argv);
20773e1db26aSLionel Sambuc argc = el_parse(e, argc, argv);
20783e1db26aSLionel Sambuc tok_end(tok);
20793e1db26aSLionel Sambuc return argc ? 1 : 0;
20803e1db26aSLionel Sambuc }
20813e1db26aSLionel Sambuc
20823e1db26aSLionel Sambuc int
rl_variable_bind(const char * var,const char * value)20833e1db26aSLionel Sambuc rl_variable_bind(const char *var, const char *value)
20843e1db26aSLionel Sambuc {
20853e1db26aSLionel Sambuc /*
20863e1db26aSLionel Sambuc * The proper return value is undocument, but this is what the
20873e1db26aSLionel Sambuc * readline source seems to do.
20883e1db26aSLionel Sambuc */
20893e1db26aSLionel Sambuc return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0;
20903e1db26aSLionel Sambuc }
20913e1db26aSLionel Sambuc
20923e1db26aSLionel Sambuc void
rl_stuff_char(int c)20933e1db26aSLionel Sambuc rl_stuff_char(int c)
20943e1db26aSLionel Sambuc {
20953e1db26aSLionel Sambuc char buf[2];
20963e1db26aSLionel Sambuc
20973e1db26aSLionel Sambuc buf[0] = (char)c;
20983e1db26aSLionel Sambuc buf[1] = '\0';
20993e1db26aSLionel Sambuc el_insertstr(e, buf);
21003e1db26aSLionel Sambuc }
21013e1db26aSLionel Sambuc
21023e1db26aSLionel Sambuc static int
_rl_event_read_char(EditLine * el,char * cp)21033e1db26aSLionel Sambuc _rl_event_read_char(EditLine *el, char *cp)
21043e1db26aSLionel Sambuc {
21053e1db26aSLionel Sambuc int n;
21063e1db26aSLionel Sambuc ssize_t num_read = 0;
21073e1db26aSLionel Sambuc
21083e1db26aSLionel Sambuc *cp = '\0';
21093e1db26aSLionel Sambuc while (rl_event_hook) {
21103e1db26aSLionel Sambuc
21113e1db26aSLionel Sambuc (*rl_event_hook)();
21123e1db26aSLionel Sambuc
21133e1db26aSLionel Sambuc #if defined(FIONREAD)
21143e1db26aSLionel Sambuc if (ioctl(el->el_infd, FIONREAD, &n) < 0)
21153e1db26aSLionel Sambuc return -1;
21163e1db26aSLionel Sambuc if (n)
21173e1db26aSLionel Sambuc num_read = read(el->el_infd, cp, (size_t)1);
21183e1db26aSLionel Sambuc else
21193e1db26aSLionel Sambuc num_read = 0;
21203e1db26aSLionel Sambuc #elif defined(F_SETFL) && defined(O_NDELAY)
21213e1db26aSLionel Sambuc if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
21223e1db26aSLionel Sambuc return -1;
21233e1db26aSLionel Sambuc if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
21243e1db26aSLionel Sambuc return -1;
21253e1db26aSLionel Sambuc num_read = read(el->el_infd, cp, 1);
21263e1db26aSLionel Sambuc if (fcntl(el->el_infd, F_SETFL, n))
21273e1db26aSLionel Sambuc return -1;
21283e1db26aSLionel Sambuc #else
21293e1db26aSLionel Sambuc /* not non-blocking, but what you gonna do? */
21303e1db26aSLionel Sambuc num_read = read(el->el_infd, cp, 1);
21313e1db26aSLionel Sambuc return -1;
21323e1db26aSLionel Sambuc #endif
21333e1db26aSLionel Sambuc
21343e1db26aSLionel Sambuc if (num_read < 0 && errno == EAGAIN)
21353e1db26aSLionel Sambuc continue;
21363e1db26aSLionel Sambuc if (num_read == 0)
21373e1db26aSLionel Sambuc continue;
21383e1db26aSLionel Sambuc break;
21393e1db26aSLionel Sambuc }
21403e1db26aSLionel Sambuc if (!rl_event_hook)
21413e1db26aSLionel Sambuc el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
21423e1db26aSLionel Sambuc return (int)num_read;
21433e1db26aSLionel Sambuc }
21443e1db26aSLionel Sambuc
21453e1db26aSLionel Sambuc static void
_rl_update_pos(void)21463e1db26aSLionel Sambuc _rl_update_pos(void)
21473e1db26aSLionel Sambuc {
21483e1db26aSLionel Sambuc const LineInfo *li = el_line(e);
21493e1db26aSLionel Sambuc
21503e1db26aSLionel Sambuc rl_point = (int)(li->cursor - li->buffer);
21513e1db26aSLionel Sambuc rl_end = (int)(li->lastchar - li->buffer);
21523e1db26aSLionel Sambuc }
21533e1db26aSLionel Sambuc
21543e1db26aSLionel Sambuc void
rl_get_screen_size(int * rows,int * cols)21553e1db26aSLionel Sambuc rl_get_screen_size(int *rows, int *cols)
21563e1db26aSLionel Sambuc {
21573e1db26aSLionel Sambuc if (rows)
215884d9c625SLionel Sambuc el_get(e, EL_GETTC, "li", rows, (void *)0);
21593e1db26aSLionel Sambuc if (cols)
216084d9c625SLionel Sambuc el_get(e, EL_GETTC, "co", cols, (void *)0);
21613e1db26aSLionel Sambuc }
21623e1db26aSLionel Sambuc
21633e1db26aSLionel Sambuc void
rl_set_screen_size(int rows,int cols)21643e1db26aSLionel Sambuc rl_set_screen_size(int rows, int cols)
21653e1db26aSLionel Sambuc {
21663e1db26aSLionel Sambuc char buf[64];
21673e1db26aSLionel Sambuc (void)snprintf(buf, sizeof(buf), "%d", rows);
21683e1db26aSLionel Sambuc el_set(e, EL_SETTC, "li", buf, NULL);
21693e1db26aSLionel Sambuc (void)snprintf(buf, sizeof(buf), "%d", cols);
21703e1db26aSLionel Sambuc el_set(e, EL_SETTC, "co", buf, NULL);
21713e1db26aSLionel Sambuc }
21723e1db26aSLionel Sambuc
21733e1db26aSLionel Sambuc char **
rl_completion_matches(const char * str,rl_compentry_func_t * fun)21743e1db26aSLionel Sambuc rl_completion_matches(const char *str, rl_compentry_func_t *fun)
21753e1db26aSLionel Sambuc {
21763e1db26aSLionel Sambuc size_t len, max, i, j, min;
21773e1db26aSLionel Sambuc char **list, *match, *a, *b;
21783e1db26aSLionel Sambuc
21793e1db26aSLionel Sambuc len = 1;
21803e1db26aSLionel Sambuc max = 10;
21813e1db26aSLionel Sambuc if ((list = el_malloc(max * sizeof(*list))) == NULL)
21823e1db26aSLionel Sambuc return NULL;
21833e1db26aSLionel Sambuc
21843e1db26aSLionel Sambuc while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
21853e1db26aSLionel Sambuc list[len++] = match;
21863e1db26aSLionel Sambuc if (len == max) {
21873e1db26aSLionel Sambuc char **nl;
21883e1db26aSLionel Sambuc max += 10;
21893e1db26aSLionel Sambuc if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL)
21903e1db26aSLionel Sambuc goto out;
21913e1db26aSLionel Sambuc list = nl;
21923e1db26aSLionel Sambuc }
21933e1db26aSLionel Sambuc }
21943e1db26aSLionel Sambuc if (len == 1)
21953e1db26aSLionel Sambuc goto out;
21963e1db26aSLionel Sambuc list[len] = NULL;
21973e1db26aSLionel Sambuc if (len == 2) {
21983e1db26aSLionel Sambuc if ((list[0] = strdup(list[1])) == NULL)
21993e1db26aSLionel Sambuc goto out;
22003e1db26aSLionel Sambuc return list;
22013e1db26aSLionel Sambuc }
22023e1db26aSLionel Sambuc qsort(&list[1], len - 1, sizeof(*list),
22033e1db26aSLionel Sambuc (int (*)(const void *, const void *)) strcmp);
22043e1db26aSLionel Sambuc min = SIZE_T_MAX;
22053e1db26aSLionel Sambuc for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
22063e1db26aSLionel Sambuc b = list[i + 1];
22073e1db26aSLionel Sambuc for (j = 0; a[j] && a[j] == b[j]; j++)
22083e1db26aSLionel Sambuc continue;
22093e1db26aSLionel Sambuc if (min > j)
22103e1db26aSLionel Sambuc min = j;
22113e1db26aSLionel Sambuc }
22123e1db26aSLionel Sambuc if (min == 0 && *str) {
22133e1db26aSLionel Sambuc if ((list[0] = strdup(str)) == NULL)
22143e1db26aSLionel Sambuc goto out;
22153e1db26aSLionel Sambuc } else {
22163e1db26aSLionel Sambuc if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL)
22173e1db26aSLionel Sambuc goto out;
22183e1db26aSLionel Sambuc (void)memcpy(list[0], list[1], min);
22193e1db26aSLionel Sambuc list[0][min] = '\0';
22203e1db26aSLionel Sambuc }
22213e1db26aSLionel Sambuc return list;
22223e1db26aSLionel Sambuc
22233e1db26aSLionel Sambuc out:
22243e1db26aSLionel Sambuc el_free(list);
22253e1db26aSLionel Sambuc return NULL;
22263e1db26aSLionel Sambuc }
22273e1db26aSLionel Sambuc
22283e1db26aSLionel Sambuc char *
rl_filename_completion_function(const char * text,int state)22293e1db26aSLionel Sambuc rl_filename_completion_function (const char *text, int state)
22303e1db26aSLionel Sambuc {
22313e1db26aSLionel Sambuc return fn_filename_completion_function(text, state);
22323e1db26aSLionel Sambuc }
22333e1db26aSLionel Sambuc
22343e1db26aSLionel Sambuc void
rl_forced_update_display(void)22353e1db26aSLionel Sambuc rl_forced_update_display(void)
22363e1db26aSLionel Sambuc {
22373e1db26aSLionel Sambuc el_set(e, EL_REFRESH);
22383e1db26aSLionel Sambuc }
22393e1db26aSLionel Sambuc
22403e1db26aSLionel Sambuc int
_rl_abort_internal(void)22413e1db26aSLionel Sambuc _rl_abort_internal(void)
22423e1db26aSLionel Sambuc {
22433e1db26aSLionel Sambuc el_beep(e);
22443e1db26aSLionel Sambuc longjmp(topbuf, 1);
22453e1db26aSLionel Sambuc /*NOTREACHED*/
22463e1db26aSLionel Sambuc }
22473e1db26aSLionel Sambuc
22483e1db26aSLionel Sambuc int
_rl_qsort_string_compare(char ** s1,char ** s2)22493e1db26aSLionel Sambuc _rl_qsort_string_compare(char **s1, char **s2)
22503e1db26aSLionel Sambuc {
22513e1db26aSLionel Sambuc return strcoll(*s1, *s2);
22523e1db26aSLionel Sambuc }
22533e1db26aSLionel Sambuc
22543e1db26aSLionel Sambuc HISTORY_STATE *
history_get_history_state(void)22553e1db26aSLionel Sambuc history_get_history_state(void)
22563e1db26aSLionel Sambuc {
22573e1db26aSLionel Sambuc HISTORY_STATE *hs;
22583e1db26aSLionel Sambuc
22593e1db26aSLionel Sambuc if ((hs = el_malloc(sizeof(*hs))) == NULL)
22603e1db26aSLionel Sambuc return NULL;
22613e1db26aSLionel Sambuc hs->length = history_length;
22623e1db26aSLionel Sambuc return hs;
22633e1db26aSLionel Sambuc }
22643e1db26aSLionel Sambuc
22653e1db26aSLionel Sambuc int
22663e1db26aSLionel Sambuc /*ARGSUSED*/
rl_kill_text(int from,int to)22673e1db26aSLionel Sambuc rl_kill_text(int from __attribute__((__unused__)),
22683e1db26aSLionel Sambuc int to __attribute__((__unused__)))
22693e1db26aSLionel Sambuc {
22703e1db26aSLionel Sambuc return 0;
22713e1db26aSLionel Sambuc }
22723e1db26aSLionel Sambuc
22733e1db26aSLionel Sambuc Keymap
rl_make_bare_keymap(void)22743e1db26aSLionel Sambuc rl_make_bare_keymap(void)
22753e1db26aSLionel Sambuc {
22763e1db26aSLionel Sambuc return NULL;
22773e1db26aSLionel Sambuc }
22783e1db26aSLionel Sambuc
22793e1db26aSLionel Sambuc Keymap
rl_get_keymap(void)22803e1db26aSLionel Sambuc rl_get_keymap(void)
22813e1db26aSLionel Sambuc {
22823e1db26aSLionel Sambuc return NULL;
22833e1db26aSLionel Sambuc }
22843e1db26aSLionel Sambuc
22853e1db26aSLionel Sambuc void
22863e1db26aSLionel Sambuc /*ARGSUSED*/
rl_set_keymap(Keymap k)22873e1db26aSLionel Sambuc rl_set_keymap(Keymap k __attribute__((__unused__)))
22883e1db26aSLionel Sambuc {
22893e1db26aSLionel Sambuc }
22903e1db26aSLionel Sambuc
22913e1db26aSLionel Sambuc int
22923e1db26aSLionel Sambuc /*ARGSUSED*/
rl_generic_bind(int type,const char * keyseq,const char * data,Keymap k)22933e1db26aSLionel Sambuc rl_generic_bind(int type __attribute__((__unused__)),
22943e1db26aSLionel Sambuc const char * keyseq __attribute__((__unused__)),
22953e1db26aSLionel Sambuc const char * data __attribute__((__unused__)),
22963e1db26aSLionel Sambuc Keymap k __attribute__((__unused__)))
22973e1db26aSLionel Sambuc {
22983e1db26aSLionel Sambuc return 0;
22993e1db26aSLionel Sambuc }
23003e1db26aSLionel Sambuc
23013e1db26aSLionel Sambuc int
23023e1db26aSLionel Sambuc /*ARGSUSED*/
rl_bind_key_in_map(int key,rl_command_func_t * fun,Keymap k)23033e1db26aSLionel Sambuc rl_bind_key_in_map(int key __attribute__((__unused__)),
23043e1db26aSLionel Sambuc rl_command_func_t *fun __attribute__((__unused__)),
23053e1db26aSLionel Sambuc Keymap k __attribute__((__unused__)))
23063e1db26aSLionel Sambuc {
23073e1db26aSLionel Sambuc return 0;
23083e1db26aSLionel Sambuc }
23093e1db26aSLionel Sambuc
23103e1db26aSLionel Sambuc /* unsupported, but needed by python */
23113e1db26aSLionel Sambuc void
rl_cleanup_after_signal(void)23123e1db26aSLionel Sambuc rl_cleanup_after_signal(void)
23133e1db26aSLionel Sambuc {
23143e1db26aSLionel Sambuc }
23153e1db26aSLionel Sambuc
23163e1db26aSLionel Sambuc int
rl_on_new_line(void)23173e1db26aSLionel Sambuc rl_on_new_line(void)
23183e1db26aSLionel Sambuc {
23193e1db26aSLionel Sambuc return 0;
23203e1db26aSLionel Sambuc }
23213e1db26aSLionel Sambuc
23223e1db26aSLionel Sambuc void
rl_free_line_state(void)23233e1db26aSLionel Sambuc rl_free_line_state(void)
23243e1db26aSLionel Sambuc {
23253e1db26aSLionel Sambuc }
2326