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