1 /*        $NetBSD: readline.c,v 1.182 2024/03/26 18:02:04 christos Exp $        */
2 
3 /*-
4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jaromir Dolecek.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "config.h"
33 #if !defined(lint) && !defined(SCCSID)
34 __RCSID("$NetBSD: readline.c,v 1.182 2024/03/26 18:02:04 christos Exp $");
35 #endif /* not lint && not SCCSID */
36 
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <ctype.h>
40 #include <dirent.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <limits.h>
44 #include <pwd.h>
45 #include <setjmp.h>
46 #include <stdarg.h>
47 #include <stdint.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <vis.h>
53 
54 #define completion_matches xxx_completion_matches
55 #include "readline/readline.h"
56 #undef completion_matches
57 #include "el.h"
58 #include "fcns.h"
59 #include "filecomplete.h"
60 
61 void rl_prep_terminal(int);
62 void rl_deprep_terminal(void);
63 
64 /* for rl_complete() */
65 #define TAB                   '\r'
66 
67 /* see comment at the #ifdef for sense of this */
68 /* #define GDB_411_HACK */
69 
70 /* readline compatibility stuff - look at readline sources/documentation */
71 /* to see what these variables mean */
72 const char *rl_library_version = "EditLine wrapper";
73 int rl_readline_version = RL_READLINE_VERSION;
74 static char empty[] = { '\0' };
75 static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
76 static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
77     '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
78 const char *rl_readline_name = empty;
79 FILE *rl_instream = NULL;
80 FILE *rl_outstream = NULL;
81 int rl_point = 0;
82 int rl_end = 0;
83 char *rl_line_buffer = NULL;
84 rl_vcpfunc_t *rl_linefunc = NULL;
85 int rl_done = 0;
86 rl_hook_func_t *rl_event_hook = NULL;
87 KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
88     emacs_meta_keymap,
89     emacs_ctlx_keymap;
90 /*
91  * The following is not implemented; we always catch signals in the
92  * libedit fashion: set handlers on entry to el_gets() and clear them
93  * on the way out. This simplistic approach works for most cases; if
94  * it does not work for your application, please let us know.
95  */
96 int rl_catch_signals = 1;
97 int rl_catch_sigwinch = 1;
98 
99 int history_base = 1;                   /* probably never subject to change */
100 int history_length = 0;
101 int history_offset = 0;
102 int max_input_history = 0;
103 char history_expansion_char = '!';
104 char history_subst_char = '^';
105 char *history_no_expand_chars = expand_chars;
106 rl_linebuf_func_t *history_inhibit_expansion_function = NULL;
107 char *history_arg_extract(int start, int end, const char *str);
108 
109 int rl_inhibit_completion = 0;
110 int rl_attempted_completion_over = 0;
111 const char *rl_basic_word_break_characters = break_chars;
112 char *rl_completer_word_break_characters = NULL;
113 const char *rl_completer_quote_characters = NULL;
114 const char *rl_basic_quote_characters = "\"'";
115 rl_compentry_func_t *rl_completion_entry_function = NULL;
116 char *(*rl_completion_word_break_hook)(void) = NULL;
117 rl_completion_func_t *rl_attempted_completion_function = NULL;
118 rl_hook_func_t *rl_pre_input_hook = NULL;
119 rl_hook_func_t *rl_startup1_hook = NULL;
120 int (*rl_getc_function)(FILE *) = NULL;
121 char *rl_terminal_name = NULL;
122 int rl_already_prompted = 0;
123 int rl_filename_completion_desired = 0;
124 int rl_ignore_completion_duplicates = 0;
125 int readline_echoing_p = 1;
126 int _rl_print_completions_horizontally = 0;
127 rl_voidfunc_t *rl_redisplay_function = NULL;
128 rl_hook_func_t *rl_startup_hook = NULL;
129 rl_compdisp_func_t *rl_completion_display_matches_hook = NULL;
130 rl_vintfunc_t *rl_prep_term_function = (rl_vintfunc_t *)rl_prep_terminal;
131 rl_voidfunc_t *rl_deprep_term_function = (rl_voidfunc_t *)rl_deprep_terminal;
132 KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
133 unsigned long rl_readline_state = RL_STATE_NONE;
134 int _rl_complete_mark_directories;
135 rl_icppfunc_t *rl_directory_completion_hook;
136 int rl_completion_suppress_append;
137 int rl_sort_completion_matches;
138 int _rl_completion_prefix_display_length;
139 int _rl_echoing_p;
140 int history_max_entries;
141 char *rl_display_prompt;
142 int rl_erase_empty_line;
143 
144 /*
145  * The current prompt string.
146  */
147 char *rl_prompt = NULL;
148 char *rl_prompt_saved = NULL;
149 /*
150  * This is set to character indicating type of completion being done by
151  * rl_complete_internal(); this is available for application completion
152  * functions.
153  */
154 int rl_completion_type = 0;
155 
156 /*
157  * If more than this number of items results from query for possible
158  * completions, we ask user if they are sure to really display the list.
159  */
160 int rl_completion_query_items = 100;
161 
162 /*
163  * List of characters which are word break characters, but should be left
164  * in the parsed text when it is passed to the completion function.
165  * Shell uses this to help determine what kind of completing to do.
166  */
167 const char *rl_special_prefixes = NULL;
168 
169 /*
170  * This is the character appended to the completed words if at the end of
171  * the line. Default is ' ' (a space).
172  */
173 int rl_completion_append_character = ' ';
174 
175 /* stuff below is used internally by libedit for readline emulation */
176 
177 static History *h = NULL;
178 static EditLine *e = NULL;
179 static rl_command_func_t *map[256];
180 static jmp_buf topbuf;
181 
182 /* internal functions */
183 static unsigned char           _el_rl_complete(EditLine *, int);
184 static unsigned char           _el_rl_tstp(EditLine *, int);
185 static char                   *_get_prompt(EditLine *);
186 static int                     _getc_function(EditLine *, wchar_t *);
187 static int                     _history_expand_command(const char *, size_t, size_t,
188     char **);
189 static char                   *_rl_compat_sub(const char *, const char *,
190     const char *, int);
191 static int                     _rl_event_read_char(EditLine *, wchar_t *);
192 static void                    _rl_update_pos(void);
193 
194 static HIST_ENTRY rl_he;
195 
196 /* ARGSUSED */
197 static char *
_get_prompt(EditLine * el)198 _get_prompt(EditLine *el __attribute__((__unused__)))
199 {
200           rl_already_prompted = 1;
201           return rl_prompt;
202 }
203 
204 
205 /*
206  * read one key from user defined input function
207  */
208 static int
209 /*ARGSUSED*/
_getc_function(EditLine * el,wchar_t * c)210 _getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c)
211 {
212           int i;
213 
214           i = (*rl_getc_function)(rl_instream);
215           if (i == -1)
216                     return 0;
217           *c = (wchar_t)i;
218           return 1;
219 }
220 
221 static void
_resize_fun(EditLine * el,void * a)222 _resize_fun(EditLine *el, void *a)
223 {
224           const LineInfo *li;
225           const char **ap = a;
226 
227           li = el_line(el);
228           *ap = li->buffer;
229 }
230 
231 static const char *
_default_history_file(void)232 _default_history_file(void)
233 {
234           struct passwd *p;
235           static char *path;
236           size_t len;
237 
238           if (path)
239                     return path;
240 
241           if ((p = getpwuid(getuid())) == NULL)
242                     return NULL;
243 
244           len = strlen(p->pw_dir) + sizeof("/.history");
245           if ((path = el_malloc(len)) == NULL)
246                     return NULL;
247 
248           (void)snprintf(path, len, "%s/.history", p->pw_dir);
249           return path;
250 }
251 
252 /*
253  * READLINE compatibility stuff
254  */
255 
256 /*
257  * Set the prompt
258  */
259 int
rl_set_prompt(const char * prompt)260 rl_set_prompt(const char *prompt)
261 {
262           char *p;
263 
264           if (!prompt)
265                     prompt = "";
266           if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
267                     return 0;
268           if (rl_prompt)
269                     el_free(rl_prompt);
270           rl_prompt = strdup(prompt);
271           if (rl_prompt == NULL)
272                     return -1;
273 
274           while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) {
275                     /* Remove adjacent end/start markers to avoid double-escapes. */
276                     if (p[1] == RL_PROMPT_START_IGNORE) {
277                               memmove(p, p + 2, 1 + strlen(p + 2));
278                     } else {
279                               *p = RL_PROMPT_START_IGNORE;
280                     }
281           }
282 
283           return 0;
284 }
285 
286 void
rl_save_prompt(void)287 rl_save_prompt(void)
288 {
289           rl_prompt_saved = strdup(rl_prompt);
290 }
291 
292 void
rl_restore_prompt(void)293 rl_restore_prompt(void)
294 {
295           if (!rl_prompt_saved)
296                     return;
297           rl_prompt = rl_prompt_saved;
298           rl_prompt_saved = NULL;
299 }
300 
301 /*
302  * initialize rl compat stuff
303  */
304 int
rl_initialize(void)305 rl_initialize(void)
306 {
307           HistEvent ev;
308           int editmode = 1;
309           struct termios t;
310 
311           if (e != NULL)
312                     el_end(e);
313           if (h != NULL)
314                     history_end(h);
315 
316           RL_UNSETSTATE(RL_STATE_DONE);
317 
318           if (!rl_instream)
319                     rl_instream = stdin;
320           if (!rl_outstream)
321                     rl_outstream = stdout;
322 
323           /*
324            * See if we don't really want to run the editor
325            */
326           if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
327                     editmode = 0;
328 
329           e = el_init_internal(rl_readline_name, rl_instream, rl_outstream,
330               stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr),
331               NO_RESET);
332 
333           if (!editmode)
334                     el_set(e, EL_EDITMODE, 0);
335 
336           h = history_init();
337           if (!e || !h)
338                     return -1;
339 
340           history(h, &ev, H_SETSIZE, INT_MAX);    /* unlimited */
341           history_length = 0;
342           max_input_history = INT_MAX;
343           el_set(e, EL_HIST, history, h);
344 
345           /* Setup resize function */
346           el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer);
347 
348           /* setup getc function if valid */
349           if (rl_getc_function)
350                     el_set(e, EL_GETCFN, _getc_function);
351 
352           /* for proper prompt printing in readline() */
353           if (rl_set_prompt("") == -1) {
354                     history_end(h);
355                     el_end(e);
356                     return -1;
357           }
358           el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE);
359           el_set(e, EL_SIGNAL, rl_catch_signals);
360 
361           /* set default mode to "emacs"-style and read setting afterwards */
362           /* so this can be overridden */
363           el_set(e, EL_EDITOR, "emacs");
364           if (rl_terminal_name != NULL)
365                     el_set(e, EL_TERMINAL, rl_terminal_name);
366           else
367                     el_get(e, EL_TERMINAL, &rl_terminal_name);
368 
369           /*
370            * Word completion - this has to go AFTER rebinding keys
371            * to emacs-style.
372            */
373           el_set(e, EL_ADDFN, "rl_complete",
374               "ReadLine compatible completion function",
375               _el_rl_complete);
376           el_set(e, EL_BIND, "^I", "rl_complete", NULL);
377 
378           /*
379            * Send TSTP when ^Z is pressed.
380            */
381           el_set(e, EL_ADDFN, "rl_tstp",
382               "ReadLine compatible suspend function",
383               _el_rl_tstp);
384           el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
385 
386           /*
387            * Set some readline compatible key-bindings.
388            */
389           el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL);
390 
391           /*
392            * Allow the use of Home/End keys.
393            */
394           el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
395           el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
396           el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL);
397           el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL);
398           el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL);
399           el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL);
400 
401           /*
402            * Allow the use of the Delete/Insert keys.
403            */
404           el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
405           el_set(e, EL_BIND, "\\e[2~", "em-toggle-overwrite", NULL);
406 
407           /*
408            * Ctrl-left-arrow and Ctrl-right-arrow for word moving.
409            */
410           el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
411           el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
412           el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL);
413           el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL);
414           el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
415           el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
416 
417           /* read settings from configuration file */
418           el_source(e, NULL);
419 
420           /*
421            * Unfortunately, some applications really do use rl_point
422            * and rl_line_buffer directly.
423            */
424           _resize_fun(e, &rl_line_buffer);
425           _rl_update_pos();
426 
427           tty_end(e, TCSADRAIN);
428 
429           return 0;
430 }
431 
432 
433 /*
434  * read one line from input stream and return it, chomping
435  * trailing newline (if there is any)
436  */
437 char *
readline(const char * p)438 readline(const char *p)
439 {
440           HistEvent ev;
441           const char * volatile prompt = p;
442           int count;
443           const char *ret;
444           char *buf;
445           static int used_event_hook;
446 
447           if (e == NULL || h == NULL)
448                     rl_initialize();
449           if (rl_startup_hook) {
450                     (*rl_startup_hook)();
451           }
452           tty_init(e);
453 
454 
455           rl_done = 0;
456 
457           (void)setjmp(topbuf);
458           buf = NULL;
459 
460           /* update prompt accordingly to what has been passed */
461           if (rl_set_prompt(prompt) == -1)
462                     goto out;
463 
464           if (rl_pre_input_hook)
465                     (*rl_pre_input_hook)();
466 
467           if (rl_event_hook && !(e->el_flags & NO_TTY)) {
468                     el_set(e, EL_GETCFN, _rl_event_read_char);
469                     used_event_hook = 1;
470           }
471 
472           if (!rl_event_hook && used_event_hook) {
473                     el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
474                     used_event_hook = 0;
475           }
476 
477           rl_already_prompted = 0;
478 
479           /* get one line from input stream */
480           ret = el_gets(e, &count);
481 
482           if (ret && count > 0) {
483                     int lastidx;
484 
485                     buf = strdup(ret);
486                     if (buf == NULL)
487                               goto out;
488                     lastidx = count - 1;
489                     if (buf[lastidx] == '\n')
490                               buf[lastidx] = '\0';
491           } else
492                     buf = NULL;
493 
494           history(h, &ev, H_GETSIZE);
495           history_length = ev.num;
496 
497 out:
498           tty_end(e, TCSADRAIN);
499           return buf;
500 }
501 
502 /*
503  * history functions
504  */
505 
506 /*
507  * is normally called before application starts to use
508  * history expansion functions
509  */
510 void
using_history(void)511 using_history(void)
512 {
513           if (h == NULL || e == NULL)
514                     rl_initialize();
515           history_offset = history_length;
516 }
517 
518 
519 /*
520  * substitute ``what'' with ``with'', returning resulting string; if
521  * globally == 1, substitutes all occurrences of what, otherwise only the
522  * first one
523  */
524 static char *
_rl_compat_sub(const char * str,const char * what,const char * with,int globally)525 _rl_compat_sub(const char *str, const char *what, const char *with,
526     int globally)
527 {
528           const     char      *s;
529           char      *r, *result;
530           size_t    len, with_len, what_len;
531 
532           len = strlen(str);
533           with_len = strlen(with);
534           what_len = strlen(what);
535 
536           /* calculate length we need for result */
537           s = str;
538           while (*s) {
539                     if (*s == *what && !strncmp(s, what, what_len)) {
540                               len += with_len - what_len;
541                               if (!globally)
542                                         break;
543                               s += what_len;
544                     } else
545                               s++;
546           }
547           r = result = el_calloc(len + 1, sizeof(*r));
548           if (result == NULL)
549                     return NULL;
550           s = str;
551           while (*s) {
552                     if (*s == *what && !strncmp(s, what, what_len)) {
553                               memcpy(r, with, with_len);
554                               r += with_len;
555                               s += what_len;
556                               if (!globally) {
557                                         (void)strcpy(r, s);
558                                         return result;
559                               }
560                     } else
561                               *r++ = *s++;
562           }
563           *r = '\0';
564           return result;
565 }
566 
567 static    char      *last_search_pat;   /* last !?pat[?] search pattern */
568 static    char      *last_search_match; /* last !?pat[?] that matched */
569 
570 const char *
get_history_event(const char * cmd,int * cindex,int qchar)571 get_history_event(const char *cmd, int *cindex, int qchar)
572 {
573           int idx, sign, sub, num, begin, ret;
574           size_t len;
575           char      *pat;
576           const char *rptr;
577           HistEvent ev;
578 
579           idx = *cindex;
580           if (cmd[idx++] != history_expansion_char)
581                     return NULL;
582 
583           /* find out which event to take */
584           if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
585                     if (history(h, &ev, H_FIRST) != 0)
586                               return NULL;
587                     *cindex = cmd[idx]? (idx + 1):idx;
588                     return ev.str;
589           }
590           sign = 0;
591           if (cmd[idx] == '-') {
592                     sign = 1;
593                     idx++;
594           }
595 
596           if ('0' <= cmd[idx] && cmd[idx] <= '9') {
597                     HIST_ENTRY *he;
598 
599                     num = 0;
600                     while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
601                               num = num * 10 + cmd[idx] - '0';
602                               idx++;
603                     }
604                     if (sign)
605                               num = history_length - num + history_base;
606 
607                     if (!(he = history_get(num)))
608                               return NULL;
609 
610                     *cindex = idx;
611                     return he->line;
612           }
613           sub = 0;
614           if (cmd[idx] == '?') {
615                     sub = 1;
616                     idx++;
617           }
618           begin = idx;
619           while (cmd[idx]) {
620                     if (cmd[idx] == '\n')
621                               break;
622                     if (sub && cmd[idx] == '?')
623                               break;
624                     if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
625                         || cmd[idx] == '\t' || cmd[idx] == qchar))
626                               break;
627                     idx++;
628           }
629           len = (size_t)idx - (size_t)begin;
630           if (sub && cmd[idx] == '?')
631                     idx++;
632           if (sub && len == 0 && last_search_pat && *last_search_pat)
633                     pat = last_search_pat;
634           else if (len == 0)
635                     return NULL;
636           else {
637                     if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL)
638                               return NULL;
639                     (void)strlcpy(pat, cmd + begin, len + 1);
640           }
641 
642           if (history(h, &ev, H_CURR) != 0) {
643                     if (pat != last_search_pat)
644                               el_free(pat);
645                     return NULL;
646           }
647           num = ev.num;
648 
649           if (sub) {
650                     if (pat != last_search_pat) {
651                               el_free(last_search_pat);
652                               last_search_pat = pat;
653                     }
654                     ret = history_search(pat, -1);
655           } else
656                     ret = history_search_prefix(pat, -1);
657 
658           if (ret == -1) {
659                     /* restore to end of list on failed search */
660                     history(h, &ev, H_FIRST);
661                     (void)fprintf(rl_outstream, "%s: Event not found\n", pat);
662                     if (pat != last_search_pat)
663                               el_free(pat);
664                     return NULL;
665           }
666 
667           if (sub && len) {
668                     el_free(last_search_match);
669                     last_search_match = strdup(pat);
670           }
671 
672           if (pat != last_search_pat)
673                     el_free(pat);
674 
675           if (history(h, &ev, H_CURR) != 0)
676                     return NULL;
677           *cindex = idx;
678           rptr = ev.str;
679 
680           /* roll back to original position */
681           (void)history(h, &ev, H_SET, num);
682 
683           return rptr;
684 }
685 
686 static int
getfrom(const char ** cmdp,char ** fromp,const char * search,int delim)687 getfrom(const char **cmdp, char **fromp, const char *search, int delim)
688 {
689           size_t size = 16;
690           size_t len = 0;
691           const char *cmd = *cmdp;
692           char *what = el_realloc(*fromp, size * sizeof(*what));
693           if (what == NULL){
694                     el_free(*fromp);
695                     *fromp = NULL;
696                     return 0;
697           }
698           for (; *cmd && *cmd != delim; cmd++) {
699                     if (*cmd == '\\' && cmd[1] == delim)
700                               cmd++;
701                     if (len - 1 >= size) {
702                               char *nwhat;
703                               nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat));
704                               if (nwhat == NULL) {
705                                         el_free(what);
706                                         el_free(*fromp);
707                                         *cmdp = cmd;
708                                         *fromp = NULL;
709                                         return 0;
710                               }
711                               what = nwhat;
712                     }
713                     what[len++] = *cmd;
714           }
715           what[len] = '\0';
716           *fromp = what;
717           *cmdp = cmd;
718           if (*what == '\0') {
719                     el_free(what);
720                     if (search) {
721                               *fromp = strdup(search);
722                               if (*fromp == NULL) {
723                                         return 0;
724                               }
725                     } else {
726                               *fromp = NULL;
727                               return -1;
728                     }
729           }
730           if (!*cmd) {
731                     el_free(what);
732                     *fromp = NULL;
733                     return -1;
734           }
735 
736           cmd++;    /* shift after delim */
737           *cmdp = cmd;
738 
739           if (!*cmd) {
740                     el_free(what);
741                     *fromp = NULL;
742                     return -1;
743           }
744           return 1;
745 }
746 
747 static int
getto(const char ** cmdp,char ** top,const char * from,int delim)748 getto(const char **cmdp, char **top, const char *from, int delim)
749 {
750           size_t size = 16;
751           size_t len = 0;
752           size_t from_len = strlen(from);
753           const char *cmd = *cmdp;
754           char *with = el_realloc(*top, size * sizeof(*with));
755           *top = NULL;
756           if (with == NULL)
757                     goto out;
758 
759           for (; *cmd && *cmd != delim; cmd++) {
760                     if (len + from_len + 1 >= size) {
761                               char *nwith;
762                               size += from_len + 1;
763                               nwith = el_realloc(with, size * sizeof(*nwith));
764                               if (nwith == NULL)
765                                         goto out;
766                               with = nwith;
767                     }
768                     if (*cmd == '&') {
769                               /* safe */
770                               strcpy(&with[len], from);
771                               len += from_len;
772                               continue;
773                     }
774                     if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&'))
775                               cmd++;
776                     with[len++] = *cmd;
777           }
778           if (!*cmd)
779                     goto out;
780           with[len] = '\0';
781           *top = with;
782           *cmdp = cmd;
783           return 1;
784 out:
785           el_free(with);
786           el_free(*top);
787           *top = NULL;
788           *cmdp = cmd;
789           return -1;
790 }
791 
792 static void
replace(char ** tmp,int c)793 replace(char **tmp, int c)
794 {
795           char *aptr;
796           if ((aptr = strrchr(*tmp, c)) == NULL)
797                     return;
798           aptr = strdup(aptr + 1); // XXX: check
799           el_free(*tmp);
800           *tmp = aptr;
801 }
802 
803 /*
804  * the real function doing history expansion - takes as argument command
805  * to do and data upon which the command should be executed
806  * does expansion the way I've understood readline documentation
807  *
808  * returns 0 if data was not modified, 1 if it was and 2 if the string
809  * should be only printed and not executed; in case of error,
810  * returns -1 and *result points to NULL
811  * it's the caller's responsibility to free() the string returned in *result
812  */
813 static int
_history_expand_command(const char * command,size_t offs,size_t cmdlen,char ** result)814 _history_expand_command(const char *command, size_t offs, size_t cmdlen,
815     char **result)
816 {
817           char *tmp, *search = NULL, *aptr, delim;
818           const char *ptr, *cmd;
819           static char *from = NULL, *to = NULL;
820           int start, end, idx, has_mods = 0;
821           int p_on = 0, g_on = 0, ev;
822 
823           *result = NULL;
824           aptr = NULL;
825           ptr = NULL;
826 
827           /* First get event specifier */
828           idx = 0;
829 
830           if (strchr(":^*$", command[offs + 1])) {
831                     char str[4];
832                     /*
833                     * "!:" is shorthand for "!!:".
834                     * "!^", "!*" and "!$" are shorthand for
835                     * "!!:^", "!!:*" and "!!:$" respectively.
836                     */
837                     str[0] = str[1] = '!';
838                     str[2] = '0';
839                     ptr = get_history_event(str, &idx, 0);
840                     idx = (command[offs + 1] == ':')? 1:0;
841                     has_mods = 1;
842           } else {
843                     if (command[offs + 1] == '#') {
844                               /* use command so far */
845                               if ((aptr = el_calloc(offs + 1, sizeof(*aptr)))
846                                   == NULL)
847                                         return -1;
848                               (void)strlcpy(aptr, command, offs + 1);
849                               idx = 1;
850                     } else {
851                               int       qchar;
852 
853                               qchar = (offs > 0 && command[offs - 1] == '"')
854                                   ? '"' : '\0';
855                               ptr = get_history_event(command + offs, &idx, qchar);
856                     }
857                     has_mods = command[offs + (size_t)idx] == ':';
858           }
859 
860           if (ptr == NULL && aptr == NULL)
861                     return -1;
862 
863           if (!has_mods) {
864                     *result = strdup(aptr ? aptr : ptr);
865                     if (aptr)
866                               el_free(aptr);
867                     if (*result == NULL)
868                               return -1;
869                     return 1;
870           }
871 
872           cmd = command + offs + idx + 1;
873 
874           /* Now parse any word designators */
875 
876           if (*cmd == '%')    /* last word matched by ?pat? */
877                     tmp = strdup(last_search_match ? last_search_match : "");
878           else if (strchr("^*$-0123456789", *cmd)) {
879                     start = end = -1;
880                     if (*cmd == '^')
881                               start = end = 1, cmd++;
882                     else if (*cmd == '$')
883                               start = -1, cmd++;
884                     else if (*cmd == '*')
885                               start = 1, cmd++;
886                     else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
887                               start = 0;
888                               while (*cmd && '0' <= *cmd && *cmd <= '9')
889                                         start = start * 10 + *cmd++ - '0';
890 
891                               if (*cmd == '-') {
892                                         if (isdigit((unsigned char) cmd[1])) {
893                                                   cmd++;
894                                                   end = 0;
895                                                   while (*cmd && '0' <= *cmd && *cmd <= '9')
896                                                             end = end * 10 + *cmd++ - '0';
897                                         } else if (cmd[1] == '$') {
898                                                   cmd += 2;
899                                                   end = -1;
900                                         } else {
901                                                   cmd++;
902                                                   end = -2;
903                                         }
904                               } else if (*cmd == '*')
905                                         end = -1, cmd++;
906                               else
907                                         end = start;
908                     }
909                     tmp = history_arg_extract(start, end, aptr? aptr:ptr);
910                     if (tmp == NULL) {
911                               (void)fprintf(rl_outstream, "%s: Bad word specifier",
912                                   command + offs + idx);
913                               if (aptr)
914                                         el_free(aptr);
915                               return -1;
916                     }
917           } else
918                     tmp = strdup(aptr? aptr:ptr);
919 
920           if (aptr)
921                     el_free(aptr);
922 
923           if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
924                     *result = tmp;
925                     return 1;
926           }
927 
928           for (; *cmd; cmd++) {
929                     switch (*cmd) {
930                     case ':':
931                               continue;
932                     case 'h': /* remove trailing path */
933                               if ((aptr = strrchr(tmp, '/')) != NULL)
934                                         *aptr = '\0';
935                               continue;
936                     case 't': /* remove leading path */
937                               replace(&tmp, '/');
938                               continue;
939                     case 'r': /* remove trailing suffix */
940                               if ((aptr = strrchr(tmp, '.')) != NULL)
941                                         *aptr = '\0';
942                               continue;
943                     case 'e': /* remove all but suffix */
944                               replace(&tmp, '.');
945                               continue;
946                     case 'p': /* print only */
947                               p_on = 1;
948                               continue;
949                     case 'g':
950                               g_on = 2;
951                               continue;
952                     case '&':
953                               if (from == NULL || to == NULL)
954                                         continue;
955                               /*FALLTHROUGH*/
956                     case 's':
957                               ev = -1;
958                               delim = *++cmd;
959                               if (delim == '\0' || *++cmd == '\0')
960                                         goto out;
961                               if ((ev = getfrom(&cmd, &from, search, delim)) != 1)
962                                         goto out;
963                               if ((ev = getto(&cmd, &to, from, delim)) != 1)
964                                         goto out;
965                               aptr = _rl_compat_sub(tmp, from, to, g_on);
966                               if (aptr) {
967                                         el_free(tmp);
968                                         tmp = aptr;
969                               }
970                               g_on = 0;
971                               cmd--;
972                               continue;
973                     }
974           }
975           *result = tmp;
976           return p_on ? 2 : 1;
977 out:
978           el_free(tmp);
979           return ev;
980 
981 }
982 
983 
984 /*
985  * csh-style history expansion
986  */
987 int
history_expand(char * str,char ** output)988 history_expand(char *str, char **output)
989 {
990           int ret = 0;
991           size_t idx, i, size;
992           char *tmp, *result;
993 
994           if (h == NULL || e == NULL)
995                     rl_initialize();
996 
997           if (history_expansion_char == 0) {
998                     *output = strdup(str);
999                     return 0;
1000           }
1001 
1002           *output = NULL;
1003           if (str[0] == history_subst_char) {
1004                     /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
1005                     *output = el_calloc(strlen(str) + 4 + 1, sizeof(**output));
1006                     if (*output == NULL)
1007                               return 0;
1008                     (*output)[0] = (*output)[1] = history_expansion_char;
1009                     (*output)[2] = ':';
1010                     (*output)[3] = 's';
1011                     (void)strcpy((*output) + 4, str);
1012                     str = *output;
1013           } else {
1014                     *output = strdup(str);
1015                     if (*output == NULL)
1016                               return 0;
1017           }
1018 
1019 #define ADD_STRING(what, len, fr)                                               \
1020           {                                                                               \
1021                     if (idx + len + 1 > size) {                                 \
1022                               char *nresult = el_realloc(result,                \
1023                                   (size += len + 1) * sizeof(*nresult));        \
1024                               if (nresult == NULL) {                                      \
1025                                         el_free(*output);                       \
1026                                         el_free(fr);                                      \
1027                                         return 0;                               \
1028                               }                                                           \
1029                               result = nresult;                                 \
1030                     }                                                                     \
1031                     (void)strlcpy(&result[idx], what, len + 1);                 \
1032                     idx += len;                                                           \
1033           }
1034 
1035           result = NULL;
1036           size = idx = 0;
1037           tmp = NULL;
1038           for (i = 0; str[i];) {
1039                     int qchar, loop_again;
1040                     size_t len, start, j;
1041 
1042                     qchar = 0;
1043                     loop_again = 1;
1044                     start = j = i;
1045 loop:
1046                     for (; str[j]; j++) {
1047                               if (str[j] == '\\' &&
1048                                   str[j + 1] == history_expansion_char) {
1049                                         len = strlen(&str[j + 1]) + 1;
1050                                         memmove(&str[j], &str[j + 1], len);
1051                                         continue;
1052                               }
1053                               if (!loop_again) {
1054                                         if (isspace((unsigned char) str[j])
1055                                             || str[j] == qchar)
1056                                                   break;
1057                               }
1058                               if (str[j] == history_expansion_char
1059                                   && !strchr(history_no_expand_chars, str[j + 1])
1060                                   && (!history_inhibit_expansion_function ||
1061                                   (*history_inhibit_expansion_function)(str,
1062                                   (int)j) == 0))
1063                                         break;
1064                     }
1065 
1066                     if (str[j] && loop_again) {
1067                               i = j;
1068                               qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
1069                               j++;
1070                               if (str[j] == history_expansion_char)
1071                                         j++;
1072                               loop_again = 0;
1073                               goto loop;
1074                     }
1075                     len = i - start;
1076                     ADD_STRING(&str[start], len, NULL);
1077 
1078                     if (str[i] == '\0' || str[i] != history_expansion_char) {
1079                               len = j - i;
1080                               ADD_STRING(&str[i], len, NULL);
1081                               if (start == 0)
1082                                         ret = 0;
1083                               else
1084                                         ret = 1;
1085                               break;
1086                     }
1087                     ret = _history_expand_command (str, i, (j - i), &tmp);
1088                     if (ret > 0 && tmp) {
1089                               len = strlen(tmp);
1090                               ADD_STRING(tmp, len, tmp);
1091                     }
1092                     if (tmp) {
1093                               el_free(tmp);
1094                               tmp = NULL;
1095                     }
1096                     i = j;
1097           }
1098 
1099           /* ret is 2 for "print only" option */
1100           if (ret == 2) {
1101                     add_history(result);
1102 #ifdef GDB_411_HACK
1103                     /* gdb 4.11 has been shipped with readline, where */
1104                     /* history_expand() returned -1 when the line       */
1105                     /* should not be executed; in readline 2.1+         */
1106                     /* it should return 2 in such a case                */
1107                     ret = -1;
1108 #endif
1109           }
1110           el_free(*output);
1111           *output = result;
1112 
1113           return ret;
1114 }
1115 
1116 /*
1117 * Return a string consisting of arguments of "str" from "start" to "end".
1118 */
1119 char *
history_arg_extract(int start,int end,const char * str)1120 history_arg_extract(int start, int end, const char *str)
1121 {
1122           size_t  i, len, max;
1123           char      **arr, *result = NULL;
1124 
1125           arr = history_tokenize(str);
1126           if (!arr)
1127                     return NULL;
1128           if (arr && *arr == NULL)
1129                     goto out;
1130 
1131           for (max = 0; arr[max]; max++)
1132                     continue;
1133           max--;
1134 
1135           if (start == '$')
1136                     start = (int)max;
1137           if (end == '$')
1138                     end = (int)max;
1139           if (end < 0)
1140                     end = (int)max + end + 1;
1141           if (start < 0)
1142                     start = end;
1143 
1144           if (start < 0 || end < 0 || (size_t)start > max ||
1145               (size_t)end > max || start > end)
1146                     goto out;
1147 
1148           for (i = (size_t)start, len = 0; i <= (size_t)end; i++)
1149                     len += strlen(arr[i]) + 1;
1150           len++;
1151           result = el_calloc(len, sizeof(*result));
1152           if (result == NULL)
1153                     goto out;
1154 
1155           for (i = (size_t)start, len = 0; i <= (size_t)end; i++) {
1156                     (void)strcpy(result + len, arr[i]);
1157                     len += strlen(arr[i]);
1158                     if (i < (size_t)end)
1159                               result[len++] = ' ';
1160           }
1161           result[len] = '\0';
1162 
1163 out:
1164           for (i = 0; arr[i]; i++)
1165                     el_free(arr[i]);
1166           el_free(arr);
1167 
1168           return result;
1169 }
1170 
1171 /*
1172  * Parse the string into individual tokens,
1173  * similar to how shell would do it.
1174  */
1175 char **
history_tokenize(const char * str)1176 history_tokenize(const char *str)
1177 {
1178           int size = 1, idx = 0, i, start;
1179           size_t len;
1180           char **result = NULL, *temp, delim = '\0';
1181 
1182           for (i = 0; str[i];) {
1183                     while (isspace((unsigned char) str[i]))
1184                               i++;
1185                     start = i;
1186                     for (; str[i];) {
1187                               if (str[i] == '\\') {
1188                                         if (str[i+1] != '\0')
1189                                                   i++;
1190                               } else if (str[i] == delim)
1191                                         delim = '\0';
1192                               else if (!delim &&
1193                                             (isspace((unsigned char) str[i]) ||
1194                                         strchr("()<>;&|$", str[i])))
1195                                         break;
1196                               else if (!delim && strchr("'`\"", str[i]))
1197                                         delim = str[i];
1198                               if (str[i])
1199                                         i++;
1200                     }
1201 
1202                     if (idx + 2 >= size) {
1203                               char **nresult;
1204                               size <<= 1;
1205                               nresult = el_realloc(result, (size_t)size * sizeof(*nresult));
1206                               if (nresult == NULL) {
1207                                         el_free(result);
1208                                         return NULL;
1209                               }
1210                               result = nresult;
1211                     }
1212                     len = (size_t)i - (size_t)start;
1213                     temp = el_calloc(len + 1, sizeof(*temp));
1214                     if (temp == NULL) {
1215                               for (i = 0; i < idx; i++)
1216                                         el_free(result[i]);
1217                               el_free(result);
1218                               return NULL;
1219                     }
1220                     (void)strlcpy(temp, &str[start], len + 1);
1221                     result[idx++] = temp;
1222                     result[idx] = NULL;
1223                     if (str[i])
1224                               i++;
1225           }
1226           return result;
1227 }
1228 
1229 
1230 /*
1231  * limit size of history record to ``max'' events
1232  */
1233 void
stifle_history(int max)1234 stifle_history(int max)
1235 {
1236           HistEvent ev;
1237           HIST_ENTRY *he;
1238 
1239           if (h == NULL || e == NULL)
1240                     rl_initialize();
1241 
1242           if (history(h, &ev, H_SETSIZE, max) == 0) {
1243                     max_input_history = max;
1244                     if (history_length > max)
1245                               history_base = history_length - max;
1246                     while (history_length > max) {
1247                               he = remove_history(0);
1248                               el_free(he->data);
1249                               el_free((void *)(unsigned long)he->line);
1250                               el_free(he);
1251                     }
1252           }
1253 }
1254 
1255 
1256 /*
1257  * "unlimit" size of history - set the limit to maximum allowed int value
1258  */
1259 int
unstifle_history(void)1260 unstifle_history(void)
1261 {
1262           HistEvent ev;
1263           int omax;
1264 
1265           history(h, &ev, H_SETSIZE, INT_MAX);
1266           omax = max_input_history;
1267           max_input_history = INT_MAX;
1268           return omax;                  /* some value _must_ be returned */
1269 }
1270 
1271 
1272 int
history_is_stifled(void)1273 history_is_stifled(void)
1274 {
1275 
1276           /* cannot return true answer */
1277           return max_input_history != INT_MAX;
1278 }
1279 
1280 static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
1281 
1282 int
history_truncate_file(const char * filename,int nlines)1283 history_truncate_file (const char *filename, int nlines)
1284 {
1285           int ret = 0;
1286           FILE *fp, *tp;
1287           char template[sizeof(_history_tmp_template)];
1288           char buf[4096];
1289           int fd;
1290           char *cp;
1291           off_t off;
1292           int count = 0;
1293           ssize_t left = 0;
1294 
1295           if (filename == NULL && (filename = _default_history_file()) == NULL)
1296                     return errno;
1297           if ((fp = fopen(filename, "r+")) == NULL)
1298                     return errno;
1299           strcpy(template, _history_tmp_template);
1300           if ((fd = mkstemp(template)) == -1) {
1301                     ret = errno;
1302                     goto out1;
1303           }
1304 
1305           if ((tp = fdopen(fd, "r+")) == NULL) {
1306                     close(fd);
1307                     ret = errno;
1308                     goto out2;
1309           }
1310 
1311           for(;;) {
1312                     if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) {
1313                               if (ferror(fp)) {
1314                                         ret = errno;
1315                                         break;
1316                               }
1317                               if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
1318                                   (off_t)-1) {
1319                                         ret = errno;
1320                                         break;
1321                               }
1322                               left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp);
1323                               if (ferror(fp)) {
1324                                         ret = errno;
1325                                         break;
1326                               }
1327                               if (left == 0) {
1328                                         count--;
1329                                         left = sizeof(buf);
1330                               } else if (fwrite(buf, (size_t)left, (size_t)1, tp)
1331                                   != 1) {
1332                                         ret = errno;
1333                                         break;
1334                               }
1335                               fflush(tp);
1336                               break;
1337                     }
1338                     if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) {
1339                               ret = errno;
1340                               break;
1341                     }
1342                     count++;
1343           }
1344           if (ret)
1345                     goto out3;
1346           cp = buf + left - 1;
1347           if(*cp != '\n')
1348                     cp++;
1349           for(;;) {
1350                     while (--cp >= buf) {
1351                               if (*cp == '\n') {
1352                                         if (--nlines == 0) {
1353                                                   if (++cp >= buf + sizeof(buf)) {
1354                                                             count++;
1355                                                             cp = buf;
1356                                                   }
1357                                                   break;
1358                                         }
1359                               }
1360                     }
1361                     if (nlines <= 0 || count == 0)
1362                               break;
1363                     count--;
1364                     if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
1365                               ret = errno;
1366                               break;
1367                     }
1368                     if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) {
1369                               if (ferror(tp)) {
1370                                         ret = errno;
1371                                         break;
1372                               }
1373                               ret = EAGAIN;
1374                               break;
1375                     }
1376                     cp = buf + sizeof(buf);
1377           }
1378 
1379           if (ret || nlines > 0)
1380                     goto out3;
1381 
1382           if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
1383                     ret = errno;
1384                     goto out3;
1385           }
1386 
1387           if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
1388               (off_t)-1) {
1389                     ret = errno;
1390                     goto out3;
1391           }
1392 
1393           for(;;) {
1394                     if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) {
1395                               if (ferror(fp))
1396                                         ret = errno;
1397                               break;
1398                     }
1399                     if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) {
1400                               ret = errno;
1401                               break;
1402                     }
1403           }
1404           fflush(fp);
1405           if((off = ftello(fp)) > 0)
1406                     (void)ftruncate(fileno(fp), off);
1407 out3:
1408           fclose(tp);
1409 out2:
1410           unlink(template);
1411 out1:
1412           fclose(fp);
1413 
1414           return ret;
1415 }
1416 
1417 
1418 /*
1419  * read history from a file given
1420  */
1421 int
read_history(const char * filename)1422 read_history(const char *filename)
1423 {
1424           HistEvent ev;
1425 
1426           if (h == NULL || e == NULL)
1427                     rl_initialize();
1428           if (filename == NULL && (filename = _default_history_file()) == NULL)
1429                     return errno;
1430           errno = 0;
1431           if (history(h, &ev, H_LOAD, filename) == -1)
1432                     return errno ? errno : EINVAL;
1433           if (history(h, &ev, H_GETSIZE) == 0)
1434                     history_length = ev.num;
1435           if (history_length < 0)
1436                     return EINVAL;
1437           return 0;
1438 }
1439 
1440 
1441 /*
1442  * write history to a file given
1443  */
1444 int
write_history(const char * filename)1445 write_history(const char *filename)
1446 {
1447           HistEvent ev;
1448 
1449           if (h == NULL || e == NULL)
1450                     rl_initialize();
1451           if (filename == NULL && (filename = _default_history_file()) == NULL)
1452                     return errno;
1453           return history(h, &ev, H_SAVE, filename) == -1 ?
1454               (errno ? errno : EINVAL) : 0;
1455 }
1456 
1457 int
append_history(int n,const char * filename)1458 append_history(int n, const char *filename)
1459 {
1460           HistEvent ev;
1461           FILE *fp;
1462 
1463           if (h == NULL || e == NULL)
1464                     rl_initialize();
1465           if (filename == NULL && (filename = _default_history_file()) == NULL)
1466                     return errno;
1467 
1468           if ((fp = fopen(filename, "a")) == NULL)
1469                     return errno;
1470 
1471           if (history(h, &ev, H_NSAVE_FP, (size_t)n,  fp) == -1) {
1472                     int serrno = errno ? errno : EINVAL;
1473                     fclose(fp);
1474                     return serrno;
1475           }
1476           fclose(fp);
1477           return 0;
1478 }
1479 
1480 /*
1481  * returns history ``num''th event
1482  *
1483  * returned pointer points to static variable
1484  */
1485 HIST_ENTRY *
history_get(int num)1486 history_get(int num)
1487 {
1488           static HIST_ENTRY she;
1489           HistEvent ev;
1490           int curr_num;
1491 
1492           if (h == NULL || e == NULL)
1493                     rl_initialize();
1494 
1495           if (num < history_base)
1496                     return NULL;
1497 
1498           /* save current position */
1499           if (history(h, &ev, H_CURR) != 0)
1500                     return NULL;
1501           curr_num = ev.num;
1502 
1503           /*
1504            * use H_DELDATA to set to nth history (without delete) by passing
1505            * (void **)-1  -- as in history_set_pos
1506            */
1507           if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0)
1508                     goto out;
1509 
1510           /* get current entry */
1511           if (history(h, &ev, H_CURR) != 0)
1512                     goto out;
1513           if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0)
1514                     goto out;
1515           she.line = ev.str;
1516 
1517           /* restore pointer to where it was */
1518           (void)history(h, &ev, H_SET, curr_num);
1519 
1520           return &she;
1521 
1522 out:
1523           /* restore pointer to where it was */
1524           (void)history(h, &ev, H_SET, curr_num);
1525           return NULL;
1526 }
1527 
1528 
1529 /*
1530  * add the line to history table
1531  */
1532 int
add_history(const char * line)1533 add_history(const char *line)
1534 {
1535           HistEvent ev;
1536 
1537           if (h == NULL || e == NULL)
1538                     rl_initialize();
1539 
1540           if (history(h, &ev, H_ENTER, line) == -1)
1541                     return 0;
1542 
1543           (void)history(h, &ev, H_GETSIZE);
1544           if (ev.num == history_length)
1545                     history_base++;
1546           else {
1547                     history_offset++;
1548                     history_length = ev.num;
1549           }
1550           return 0;
1551 }
1552 
1553 
1554 /*
1555  * remove the specified entry from the history list and return it.
1556  */
1557 HIST_ENTRY *
remove_history(int num)1558 remove_history(int num)
1559 {
1560           HIST_ENTRY *he;
1561           HistEvent ev;
1562 
1563           if (h == NULL || e == NULL)
1564                     rl_initialize();
1565 
1566           if ((he = el_malloc(sizeof(*he))) == NULL)
1567                     return NULL;
1568 
1569           if (history(h, &ev, H_DELDATA, num, &he->data) != 0) {
1570                     el_free(he);
1571                     return NULL;
1572           }
1573 
1574           he->line = ev.str;
1575           if (history(h, &ev, H_GETSIZE) == 0)
1576                     history_length = ev.num;
1577 
1578           return he;
1579 }
1580 
1581 
1582 /*
1583  * replace the line and data of the num-th entry
1584  */
1585 HIST_ENTRY *
replace_history_entry(int num,const char * line,histdata_t data)1586 replace_history_entry(int num, const char *line, histdata_t data)
1587 {
1588           HIST_ENTRY *he;
1589           HistEvent ev;
1590           int curr_num;
1591 
1592           if (h == NULL || e == NULL)
1593                     rl_initialize();
1594 
1595           /* save current position */
1596           if (history(h, &ev, H_CURR) != 0)
1597                     return NULL;
1598           curr_num = ev.num;
1599 
1600           /* start from the oldest */
1601           if (history(h, &ev, H_LAST) != 0)
1602                     return NULL;        /* error */
1603 
1604           if ((he = el_malloc(sizeof(*he))) == NULL)
1605                     return NULL;
1606 
1607           /* look forwards for event matching specified offset */
1608           if (history(h, &ev, H_NEXT_EVDATA, num, &he->data))
1609                     goto out;
1610 
1611           he->line = ev.str;
1612           if (he->line == NULL)
1613                     goto out;
1614 
1615           if (history(h, &ev, H_REPLACE, line, data))
1616                     goto out;
1617 
1618           /* restore pointer to where it was */
1619           if (history(h, &ev, H_SET, curr_num))
1620                     goto out;
1621 
1622           return he;
1623 out:
1624           el_free(he);
1625           return NULL;
1626 }
1627 
1628 /*
1629  * clear the history list - delete all entries
1630  */
1631 void
clear_history(void)1632 clear_history(void)
1633 {
1634           HistEvent ev;
1635 
1636           if (h == NULL || e == NULL)
1637                     rl_initialize();
1638 
1639           (void)history(h, &ev, H_CLEAR);
1640           history_offset = history_length = 0;
1641 }
1642 
1643 
1644 /*
1645  * returns offset of the current history event
1646  */
1647 int
where_history(void)1648 where_history(void)
1649 {
1650           return history_offset;
1651 }
1652 
1653 static HIST_ENTRY **_history_listp;
1654 static HIST_ENTRY *_history_list;
1655 
1656 HIST_ENTRY **
history_list(void)1657 history_list(void)
1658 {
1659           HistEvent ev;
1660           HIST_ENTRY **nlp, *nl;
1661           int i;
1662 
1663           if (history(h, &ev, H_LAST) != 0)
1664                     return NULL;
1665 
1666           if ((nlp = el_realloc(_history_listp,
1667               ((size_t)history_length + 1) * sizeof(*nlp))) == NULL)
1668                     return NULL;
1669           _history_listp = nlp;
1670 
1671           if ((nl = el_realloc(_history_list,
1672               (size_t)history_length * sizeof(*nl))) == NULL)
1673                     return NULL;
1674           _history_list = nl;
1675 
1676           i = 0;
1677           do {
1678                     _history_listp[i] = &_history_list[i];
1679                     _history_list[i].line = ev.str;
1680                     _history_list[i].data = NULL;
1681                     if (i++ == history_length)
1682                               abort();
1683           } while (history(h, &ev, H_PREV) == 0);
1684           _history_listp[i] = NULL;
1685           return _history_listp;
1686 }
1687 
1688 /*
1689  * returns current history event or NULL if there is no such event
1690  */
1691 HIST_ENTRY *
current_history(void)1692 current_history(void)
1693 {
1694           HistEvent ev;
1695 
1696           if (history(h, &ev, H_PREV_EVENT, history_offset + 1) != 0)
1697                     return NULL;
1698 
1699           rl_he.line = ev.str;
1700           rl_he.data = NULL;
1701           return &rl_he;
1702 }
1703 
1704 
1705 /*
1706  * returns total number of bytes history events' data are using
1707  */
1708 int
history_total_bytes(void)1709 history_total_bytes(void)
1710 {
1711           HistEvent ev;
1712           int curr_num;
1713           size_t size;
1714 
1715           if (history(h, &ev, H_CURR) != 0)
1716                     return -1;
1717           curr_num = ev.num;
1718 
1719           (void)history(h, &ev, H_FIRST);
1720           size = 0;
1721           do
1722                     size += strlen(ev.str) * sizeof(*ev.str);
1723           while (history(h, &ev, H_NEXT) == 0);
1724 
1725           /* get to the same position as before */
1726           history(h, &ev, H_PREV_EVENT, curr_num);
1727 
1728           return (int)size;
1729 }
1730 
1731 
1732 /*
1733  * sets the position in the history list to ``pos''
1734  */
1735 int
history_set_pos(int pos)1736 history_set_pos(int pos)
1737 {
1738           if (pos >= history_length || pos < 0)
1739                     return 0;
1740 
1741           history_offset = pos;
1742           return 1;
1743 }
1744 
1745 
1746 /*
1747  * returns previous event in history and shifts pointer accordingly
1748  * Note that readline and editline define directions in opposite ways.
1749  */
1750 HIST_ENTRY *
previous_history(void)1751 previous_history(void)
1752 {
1753           HistEvent ev;
1754 
1755           if (history_offset == 0)
1756                     return NULL;
1757 
1758           if (history(h, &ev, H_LAST) != 0)
1759                     return NULL;
1760 
1761           history_offset--;
1762           return current_history();
1763 }
1764 
1765 
1766 /*
1767  * returns next event in history and shifts pointer accordingly
1768  */
1769 HIST_ENTRY *
next_history(void)1770 next_history(void)
1771 {
1772           HistEvent ev;
1773 
1774           if (history_offset >= history_length)
1775                     return NULL;
1776 
1777           if (history(h, &ev, H_LAST) != 0)
1778                     return NULL;
1779 
1780           history_offset++;
1781           return current_history();
1782 }
1783 
1784 
1785 /*
1786  * searches for first history event containing the str
1787  */
1788 int
history_search(const char * str,int direction)1789 history_search(const char *str, int direction)
1790 {
1791           HistEvent ev;
1792           const char *strp;
1793           int curr_num;
1794 
1795           if (history(h, &ev, H_CURR) != 0)
1796                     return -1;
1797           curr_num = ev.num;
1798 
1799           for (;;) {
1800                     if ((strp = strstr(ev.str, str)) != NULL)
1801                               return (int)(strp - ev.str);
1802                     if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
1803                               break;
1804           }
1805           (void)history(h, &ev, H_SET, curr_num);
1806           return -1;
1807 }
1808 
1809 
1810 /*
1811  * searches for first history event beginning with str
1812  */
1813 int
history_search_prefix(const char * str,int direction)1814 history_search_prefix(const char *str, int direction)
1815 {
1816           HistEvent ev;
1817 
1818           return (history(h, &ev, direction < 0 ?
1819               H_PREV_STR : H_NEXT_STR, str));
1820 }
1821 
1822 
1823 /*
1824  * search for event in history containing str, starting at offset
1825  * abs(pos); continue backward, if pos<0, forward otherwise
1826  */
1827 /* ARGSUSED */
1828 int
history_search_pos(const char * str,int direction,int pos)1829 history_search_pos(const char *str,
1830                        int direction __attribute__((__unused__)), int pos)
1831 {
1832           HistEvent ev;
1833           int curr_num, off;
1834 
1835           off = (pos > 0) ? pos : -pos;
1836           pos = (pos > 0) ? 1 : -1;
1837 
1838           if (history(h, &ev, H_CURR) != 0)
1839                     return -1;
1840           curr_num = ev.num;
1841 
1842           if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0)
1843                     return -1;
1844 
1845           for (;;) {
1846                     if (strstr(ev.str, str))
1847                               return off;
1848                     if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
1849                               break;
1850           }
1851 
1852           /* set "current" pointer back to previous state */
1853           (void)history(h, &ev,
1854               pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
1855 
1856           return -1;
1857 }
1858 
1859 
1860 /********************************/
1861 /* completion functions */
1862 
1863 char *
tilde_expand(char * name)1864 tilde_expand(char *name)
1865 {
1866           return fn_tilde_expand(name);
1867 }
1868 
1869 char *
filename_completion_function(const char * name,int state)1870 filename_completion_function(const char *name, int state)
1871 {
1872           return fn_filename_completion_function(name, state);
1873 }
1874 
1875 /*
1876  * a completion generator for usernames; returns _first_ username
1877  * which starts with supplied text
1878  * text contains a partial username preceded by random character
1879  * (usually '~'); state resets search from start (??? should we do that anyway)
1880  * it's the caller's responsibility to free the returned value
1881  */
1882 char *
username_completion_function(const char * text,int state)1883 username_completion_function(const char *text, int state)
1884 {
1885 #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1886           struct passwd pwres;
1887           char pwbuf[1024];
1888 #endif
1889           struct passwd *pass = NULL;
1890 
1891           if (text[0] == '\0')
1892                     return NULL;
1893 
1894           if (*text == '~')
1895                     text++;
1896 
1897           if (state == 0)
1898                     setpwent();
1899 
1900           while (
1901 #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1902               getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL
1903 #else
1904               (pass = getpwent()) != NULL
1905 #endif
1906               && text[0] == pass->pw_name[0]
1907               && strcmp(text, pass->pw_name) == 0)
1908                     continue;
1909 
1910           if (pass == NULL) {
1911                     endpwent();
1912                     return NULL;
1913           }
1914           return strdup(pass->pw_name);
1915 }
1916 
1917 
1918 /*
1919  * el-compatible wrapper to send TSTP on ^Z
1920  */
1921 /* ARGSUSED */
1922 static unsigned char
_el_rl_tstp(EditLine * el,int ch)1923 _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
1924 {
1925           (void)kill(0, SIGTSTP);
1926           return CC_NORM;
1927 }
1928 
1929 static const char *
1930 /*ARGSUSED*/
_rl_completion_append_character_function(const char * dummy)1931 _rl_completion_append_character_function(const char *dummy
1932     __attribute__((__unused__)))
1933 {
1934           static char buf[2];
1935           buf[0] = (char)rl_completion_append_character;
1936           buf[1] = '\0';
1937           return buf;
1938 }
1939 
1940 
1941 /*
1942  * Display list of strings in columnar format on readline's output stream.
1943  * 'matches' is list of strings, 'len' is number of strings in 'matches',
1944  * 'max' is maximum length of string in 'matches'.
1945  */
1946 void
rl_display_match_list(char ** matches,int len,int max)1947 rl_display_match_list(char **matches, int len, int max)
1948 {
1949 
1950           fn_display_match_list(e, matches, (size_t)len, (size_t)max,
1951                     _rl_completion_append_character_function);
1952 }
1953 
1954 /*
1955  * complete word at current point
1956  */
1957 /* ARGSUSED */
1958 int
rl_complete(int ignore,int invoking_key)1959 rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
1960 {
1961           static ct_buffer_t wbreak_conv, sprefix_conv;
1962           const char *breakchars;
1963 
1964           if (h == NULL || e == NULL)
1965                     rl_initialize();
1966 
1967           if (rl_inhibit_completion) {
1968                     char arr[2];
1969                     arr[0] = (char)invoking_key;
1970                     arr[1] = '\0';
1971                     el_insertstr(e, arr);
1972                     return CC_REFRESH;
1973           }
1974 
1975           if (rl_completion_word_break_hook != NULL)
1976                     breakchars = (*rl_completion_word_break_hook)();
1977           else
1978                     breakchars = rl_basic_word_break_characters;
1979 
1980           _rl_update_pos();
1981 
1982           /* Just look at how many global variables modify this operation! */
1983           return fn_complete2(e,
1984               (rl_compentry_func_t *)rl_completion_entry_function,
1985               rl_attempted_completion_function,
1986               ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
1987               ct_decode_string(breakchars, &sprefix_conv),
1988               _rl_completion_append_character_function,
1989               (size_t)rl_completion_query_items,
1990               &rl_completion_type, &rl_attempted_completion_over,
1991               &rl_point, &rl_end, 0);
1992 
1993 
1994 }
1995 
1996 
1997 /* ARGSUSED */
1998 static unsigned char
_el_rl_complete(EditLine * el,int ch)1999 _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
2000 {
2001           return (unsigned char)rl_complete(0, ch);
2002 }
2003 
2004 /*
2005  * misc other functions
2006  */
2007 
2008 /*
2009  * bind key c to readline-type function func
2010  */
2011 int
rl_bind_key(int c,rl_command_func_t * func)2012 rl_bind_key(int c, rl_command_func_t *func)
2013 {
2014           int retval = -1;
2015 
2016           if (h == NULL || e == NULL)
2017                     rl_initialize();
2018 
2019           if (func == rl_insert) {
2020                     /* XXX notice there is no range checking of ``c'' */
2021                     e->el_map.key[c] = ED_INSERT;
2022                     retval = 0;
2023           }
2024           return retval;
2025 }
2026 
2027 
2028 /*
2029  * read one key from input - handles chars pushed back
2030  * to input stream also
2031  */
2032 int
rl_read_key(void)2033 rl_read_key(void)
2034 {
2035           char fooarr[2 * sizeof(int)];
2036 
2037           if (e == NULL || h == NULL)
2038                     rl_initialize();
2039 
2040           return el_getc(e, fooarr);
2041 }
2042 
2043 
2044 /*
2045  * reset the terminal
2046  */
2047 /* ARGSUSED */
2048 int
rl_reset_terminal(const char * p)2049 rl_reset_terminal(const char *p __attribute__((__unused__)))
2050 {
2051 
2052           if (h == NULL || e == NULL)
2053                     rl_initialize();
2054           el_reset(e);
2055           return 0;
2056 }
2057 
2058 
2059 /*
2060  * insert character ``c'' back into input stream, ``count'' times
2061  */
2062 int
rl_insert(int count,int c)2063 rl_insert(int count, int c)
2064 {
2065           char arr[2];
2066 
2067           if (h == NULL || e == NULL)
2068                     rl_initialize();
2069 
2070           /* XXX - int -> char conversion can lose on multichars */
2071           arr[0] = (char)c;
2072           arr[1] = '\0';
2073 
2074           for (; count > 0; count--)
2075                     el_push(e, arr);
2076 
2077           return 0;
2078 }
2079 
2080 int
rl_insert_text(const char * text)2081 rl_insert_text(const char *text)
2082 {
2083           if (!text || *text == 0)
2084                     return 0;
2085 
2086           if (h == NULL || e == NULL)
2087                     rl_initialize();
2088 
2089           if (el_insertstr(e, text) < 0)
2090                     return 0;
2091           return (int)strlen(text);
2092 }
2093 
2094 /*ARGSUSED*/
2095 int
rl_newline(int count,int c)2096 rl_newline(int count __attribute__((__unused__)),
2097     int c __attribute__((__unused__)))
2098 {
2099           /*
2100            * Readline-4.0 appears to ignore the args.
2101            */
2102           return rl_insert(1, '\n');
2103 }
2104 
2105 /*ARGSUSED*/
2106 static unsigned char
rl_bind_wrapper(EditLine * el,unsigned char c)2107 rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c)
2108 {
2109           if (map[c] == NULL)
2110                     return CC_ERROR;
2111 
2112           _rl_update_pos();
2113 
2114           (*map[c])(1, c);
2115 
2116           /* If rl_done was set by the above call, deal with it here */
2117           if (rl_done)
2118                     return CC_EOF;
2119 
2120           return CC_NORM;
2121 }
2122 
2123 int
rl_add_defun(const char * name,rl_command_func_t * fun,int c)2124 rl_add_defun(const char *name, rl_command_func_t *fun, int c)
2125 {
2126           char dest[8];
2127           if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
2128                     return -1;
2129           map[(unsigned char)c] = fun;
2130           el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
2131           vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
2132           el_set(e, EL_BIND, dest, name, NULL);
2133           return 0;
2134 }
2135 
2136 void
rl_callback_read_char(void)2137 rl_callback_read_char(void)
2138 {
2139           int count = 0, done = 0;
2140           const char *buf = el_gets(e, &count);
2141           char *wbuf;
2142 
2143           el_set(e, EL_UNBUFFERED, 1);
2144           if (buf == NULL || count-- <= 0)
2145                     return;
2146           if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
2147                     done = 1;
2148           if (buf[count] == '\n' || buf[count] == '\r')
2149                     done = 2;
2150 
2151           if (done && rl_linefunc != NULL) {
2152                     el_set(e, EL_UNBUFFERED, 0);
2153                     if (done == 2) {
2154                               if ((wbuf = strdup(buf)) != NULL)
2155                                         wbuf[count] = '\0';
2156                               RL_SETSTATE(RL_STATE_DONE);
2157                     } else
2158                               wbuf = NULL;
2159                     (*(void (*)(const char *))rl_linefunc)(wbuf);
2160           }
2161           _rl_update_pos();
2162 }
2163 
2164 void
rl_callback_handler_install(const char * prompt,rl_vcpfunc_t * linefunc)2165 rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc)
2166 {
2167           if (e == NULL) {
2168                     rl_initialize();
2169           }
2170           (void)rl_set_prompt(prompt);
2171           rl_linefunc = linefunc;
2172           el_set(e, EL_UNBUFFERED, 1);
2173 }
2174 
2175 void
rl_callback_handler_remove(void)2176 rl_callback_handler_remove(void)
2177 {
2178           el_set(e, EL_UNBUFFERED, 0);
2179           rl_linefunc = NULL;
2180 }
2181 
2182 void
rl_redisplay(void)2183 rl_redisplay(void)
2184 {
2185           char a[2];
2186           a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT];
2187           a[1] = '\0';
2188           el_push(e, a);
2189           rl_forced_update_display();
2190 }
2191 
2192 int
rl_get_previous_history(int count,int key)2193 rl_get_previous_history(int count, int key)
2194 {
2195           char a[2];
2196           a[0] = (char)key;
2197           a[1] = '\0';
2198           while (count--)
2199                     el_push(e, a);
2200           return 0;
2201 }
2202 
2203 void
2204 /*ARGSUSED*/
rl_prep_terminal(int meta_flag)2205 rl_prep_terminal(int meta_flag __attribute__((__unused__)))
2206 {
2207           el_set(e, EL_PREP_TERM, 1);
2208 }
2209 
2210 void
rl_deprep_terminal(void)2211 rl_deprep_terminal(void)
2212 {
2213           el_set(e, EL_PREP_TERM, 0);
2214 }
2215 
2216 int
rl_read_init_file(const char * s)2217 rl_read_init_file(const char *s)
2218 {
2219           return el_source(e, s);
2220 }
2221 
2222 int
rl_parse_and_bind(const char * line)2223 rl_parse_and_bind(const char *line)
2224 {
2225           const char **argv;
2226           int argc;
2227           Tokenizer *tok;
2228 
2229           tok = tok_init(NULL);
2230           tok_str(tok, line, &argc, &argv);
2231           argc = el_parse(e, argc, argv);
2232           tok_end(tok);
2233           return argc ? 1 : 0;
2234 }
2235 
2236 int
rl_variable_bind(const char * var,const char * value)2237 rl_variable_bind(const char *var, const char *value)
2238 {
2239           /*
2240            * The proper return value is undocument, but this is what the
2241            * readline source seems to do.
2242            */
2243           return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0;
2244 }
2245 
2246 int
rl_stuff_char(int c)2247 rl_stuff_char(int c)
2248 {
2249           char buf[2];
2250 
2251           buf[0] = (char)c;
2252           buf[1] = '\0';
2253           el_insertstr(e, buf);
2254           return 1;
2255 }
2256 
2257 static int
_rl_event_read_char(EditLine * el,wchar_t * wc)2258 _rl_event_read_char(EditLine *el, wchar_t *wc)
2259 {
2260           char      ch;
2261           int       n;
2262           ssize_t num_read = 0;
2263 
2264           ch = '\0';
2265           *wc = L'\0';
2266           while (rl_event_hook) {
2267 
2268                     (*rl_event_hook)();
2269 
2270 #if defined(FIONREAD)
2271                     if (ioctl(el->el_infd, FIONREAD, &n) < 0)
2272                               return -1;
2273                     if (n)
2274                               num_read = read(el->el_infd, &ch, (size_t)1);
2275                     else
2276                               num_read = 0;
2277 #elif defined(F_SETFL) && defined(O_NDELAY)
2278                     if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
2279                               return -1;
2280                     if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
2281                               return -1;
2282                     num_read = read(el->el_infd, &ch, 1);
2283                     if (fcntl(el->el_infd, F_SETFL, n))
2284                               return -1;
2285 #else
2286                     /* not non-blocking, but what you gonna do? */
2287                     num_read = read(el->el_infd, &ch, 1);
2288                     return -1;
2289 #endif
2290 
2291                     if (num_read < 0 && errno == EAGAIN)
2292                               continue;
2293                     if (num_read == 0)
2294                               continue;
2295                     break;
2296           }
2297           if (!rl_event_hook)
2298                     el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
2299           *wc = (wchar_t)ch;
2300           return (int)num_read;
2301 }
2302 
2303 static void
_rl_update_pos(void)2304 _rl_update_pos(void)
2305 {
2306           const LineInfo *li = el_line(e);
2307 
2308           rl_point = (int)(li->cursor - li->buffer);
2309           rl_end = (int)(li->lastchar - li->buffer);
2310           rl_line_buffer[rl_end] = '\0';
2311 }
2312 
2313 char *
rl_copy_text(int from,int to)2314 rl_copy_text(int from, int to)
2315 {
2316           const LineInfo *li;
2317           size_t len;
2318           char * out;
2319 
2320           if (h == NULL || e == NULL)
2321                     rl_initialize();
2322 
2323           li = el_line(e);
2324 
2325           if (from > to)
2326                     return NULL;
2327 
2328           if (li->buffer + from > li->lastchar)
2329                     from = (int)(li->lastchar - li->buffer);
2330 
2331           if (li->buffer + to > li->lastchar)
2332                     to = (int)(li->lastchar - li->buffer);
2333 
2334           len = (size_t)(to - from);
2335           out = el_malloc((size_t)len + 1);
2336           if (out == NULL)
2337                     return NULL;
2338           (void)strlcpy(out, li->buffer + from , len);
2339 
2340           return out;
2341 }
2342 
2343 void
rl_replace_line(const char * text,int clear_undo)2344 rl_replace_line(const char * text, int clear_undo __attribute__((__unused__)))
2345 {
2346           if (!text || *text == 0)
2347                     return;
2348 
2349           if (h == NULL || e == NULL)
2350                     rl_initialize();
2351 
2352           el_replacestr(e, text);
2353 }
2354 
2355 int
rl_delete_text(int start,int end)2356 rl_delete_text(int start, int end)
2357 {
2358 
2359           if (h == NULL || e == NULL)
2360                     rl_initialize();
2361 
2362           return el_deletestr1(e, start, end);
2363 }
2364 
2365 void
rl_get_screen_size(int * rows,int * cols)2366 rl_get_screen_size(int *rows, int *cols)
2367 {
2368           if (rows)
2369                     el_get(e, EL_GETTC, "li", rows);
2370           if (cols)
2371                     el_get(e, EL_GETTC, "co", cols);
2372 }
2373 
2374 #define MAX_MESSAGE 160
2375 void
rl_message(const char * format,...)2376 rl_message(const char *format, ...)
2377 {
2378           char msg[MAX_MESSAGE];
2379           va_list args;
2380 
2381           va_start(args, format);
2382           vsnprintf(msg, sizeof(msg), format, args);
2383           va_end(args);
2384 
2385           rl_set_prompt(msg);
2386           rl_forced_update_display();
2387 }
2388 
2389 void
rl_set_screen_size(int rows,int cols)2390 rl_set_screen_size(int rows, int cols)
2391 {
2392           char buf[64];
2393           (void)snprintf(buf, sizeof(buf), "%d", rows);
2394           el_set(e, EL_SETTC, "li", buf, NULL);
2395           (void)snprintf(buf, sizeof(buf), "%d", cols);
2396           el_set(e, EL_SETTC, "co", buf, NULL);
2397 }
2398 
2399 char **
rl_completion_matches(const char * str,rl_compentry_func_t * fun)2400 rl_completion_matches(const char *str, rl_compentry_func_t *fun)
2401 {
2402           size_t len, max, i, j, min;
2403           char **list, *match, *a, *b;
2404 
2405           len = 1;
2406           max = 10;
2407           if ((list = el_calloc(max, sizeof(*list))) == NULL)
2408                     return NULL;
2409 
2410           while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
2411                     list[len++] = match;
2412                     if (len == max) {
2413                               char **nl;
2414                               max += 10;
2415                               if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL)
2416                                         goto out;
2417                               list = nl;
2418                     }
2419           }
2420           if (len == 1)
2421                     goto out;
2422           list[len] = NULL;
2423           if (len == 2) {
2424                     if ((list[0] = strdup(list[1])) == NULL)
2425                               goto out;
2426                     return list;
2427           }
2428           qsort(&list[1], len - 1, sizeof(*list),
2429               (int (*)(const void *, const void *)) strcmp);
2430           min = SIZE_MAX;
2431           for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
2432                     b = list[i + 1];
2433                     for (j = 0; a[j] && a[j] == b[j]; j++)
2434                               continue;
2435                     if (min > j)
2436                               min = j;
2437           }
2438           if (min == 0 && *str) {
2439                     if ((list[0] = strdup(str)) == NULL)
2440                               goto out;
2441           } else {
2442                     if ((list[0] = el_calloc(min + 1, sizeof(*list[0]))) == NULL)
2443                               goto out;
2444                     (void)memcpy(list[0], list[1], min);
2445                     list[0][min] = '\0';
2446           }
2447           return list;
2448 
2449 out:
2450           el_free(list);
2451           return NULL;
2452 }
2453 
2454 char *
rl_filename_completion_function(const char * text,int state)2455 rl_filename_completion_function (const char *text, int state)
2456 {
2457           return fn_filename_completion_function(text, state);
2458 }
2459 
2460 void
rl_forced_update_display(void)2461 rl_forced_update_display(void)
2462 {
2463           el_set(e, EL_REFRESH);
2464 }
2465 
2466 int
_rl_abort_internal(void)2467 _rl_abort_internal(void)
2468 {
2469           el_beep(e);
2470           longjmp(topbuf, 1);
2471           /*NOTREACHED*/
2472 }
2473 
2474 int
_rl_qsort_string_compare(char ** s1,char ** s2)2475 _rl_qsort_string_compare(char **s1, char **s2)
2476 {
2477           return strcoll(*s1, *s2);
2478 }
2479 
2480 HISTORY_STATE *
history_get_history_state(void)2481 history_get_history_state(void)
2482 {
2483           HISTORY_STATE *hs;
2484 
2485           if ((hs = el_malloc(sizeof(*hs))) == NULL)
2486                     return NULL;
2487           hs->length = history_length;
2488           return hs;
2489 }
2490 
2491 int
2492 /*ARGSUSED*/
rl_kill_text(int from,int to)2493 rl_kill_text(int from __attribute__((__unused__)),
2494     int to __attribute__((__unused__)))
2495 {
2496           return 0;
2497 }
2498 
2499 Keymap
rl_make_bare_keymap(void)2500 rl_make_bare_keymap(void)
2501 {
2502           return NULL;
2503 }
2504 
2505 Keymap
rl_get_keymap(void)2506 rl_get_keymap(void)
2507 {
2508           return NULL;
2509 }
2510 
2511 void
2512 /*ARGSUSED*/
rl_set_keymap(Keymap k)2513 rl_set_keymap(Keymap k __attribute__((__unused__)))
2514 {
2515 }
2516 
2517 int
2518 /*ARGSUSED*/
rl_generic_bind(int type,const char * keyseq,const char * data,Keymap k)2519 rl_generic_bind(int type __attribute__((__unused__)),
2520     const char * keyseq __attribute__((__unused__)),
2521     const char * data __attribute__((__unused__)),
2522     Keymap k __attribute__((__unused__)))
2523 {
2524           return 0;
2525 }
2526 
2527 int
2528 /*ARGSUSED*/
rl_bind_key_in_map(int key,rl_command_func_t * fun,Keymap k)2529 rl_bind_key_in_map(int key __attribute__((__unused__)),
2530     rl_command_func_t *fun __attribute__((__unused__)),
2531     Keymap k __attribute__((__unused__)))
2532 {
2533           return 0;
2534 }
2535 
2536 int
rl_set_key(const char * keyseq,rl_command_func_t * function,Keymap k)2537 rl_set_key(const char *keyseq  __attribute__((__unused__)),
2538           rl_command_func_t *function __attribute__((__unused__)),
2539           Keymap k __attribute__((__unused__)))
2540 {
2541           return 0;
2542 }
2543 
2544 /* unsupported, but needed by python */
2545 void
rl_cleanup_after_signal(void)2546 rl_cleanup_after_signal(void)
2547 {
2548 }
2549 
2550 int
rl_on_new_line(void)2551 rl_on_new_line(void)
2552 {
2553           return 0;
2554 }
2555 
2556 void
rl_free_line_state(void)2557 rl_free_line_state(void)
2558 {
2559 }
2560 
2561 int
2562 /*ARGSUSED*/
rl_set_keyboard_input_timeout(int u)2563 rl_set_keyboard_input_timeout(int u __attribute__((__unused__)))
2564 {
2565           return 0;
2566 }
2567 
2568 void
rl_resize_terminal(void)2569 rl_resize_terminal(void)
2570 {
2571           el_resize(e);
2572 }
2573 
2574 void
rl_reset_after_signal(void)2575 rl_reset_after_signal(void)
2576 {
2577           if (rl_prep_term_function)
2578                     (*rl_prep_term_function)(1);
2579 }
2580 
2581 void
rl_echo_signal_char(int sig)2582 rl_echo_signal_char(int sig)
2583 {
2584           int c = tty_get_signal_character(e, sig);
2585           if (c == -1)
2586                     return;
2587           re_putc(e, c, 0);
2588 }
2589 
2590 int
rl_crlf(void)2591 rl_crlf(void)
2592 {
2593           re_putc(e, '\n', 0);
2594           return 0;
2595 }
2596 
2597 int
rl_ding(void)2598 rl_ding(void)
2599 {
2600           re_putc(e, '\a', 0);
2601           return 0;
2602 }
2603 
2604 int
rl_abort(int count,int key)2605 rl_abort(int count, int key)
2606 {
2607           return count && key ? 0 : 0;
2608 }
2609 
2610 int
rl_set_keymap_name(const char * name,Keymap k)2611 rl_set_keymap_name(const char *name, Keymap k)
2612 {
2613           return name && k ? 0 : 0;
2614 }
2615 
2616 histdata_t
free_history_entry(HIST_ENTRY * he)2617 free_history_entry(HIST_ENTRY *he)
2618 {
2619           return he ? NULL : NULL;
2620 }
2621 
2622 void
_rl_erase_entire_line(void)2623 _rl_erase_entire_line(void)
2624 {
2625 }
2626