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