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