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