readline.c revision 1.37 1 /* $NetBSD: readline.c,v 1.37 2003/10/15 18:08:40 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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "config.h"
40 #if !defined(lint) && !defined(SCCSID)
41 __RCSID("$NetBSD: readline.c,v 1.37 2003/10/15 18:08:40 christos Exp $");
42 #endif /* not lint && not SCCSID */
43
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <stdio.h>
47 #include <dirent.h>
48 #include <string.h>
49 #include <pwd.h>
50 #include <ctype.h>
51 #include <stdlib.h>
52 #include <unistd.h>
53 #include <limits.h>
54 #include <vis.h>
55 #ifdef HAVE_ALLOCA_H
56 #include <alloca.h>
57 #endif
58 #include "histedit.h"
59 #include "readline/readline.h"
60 #include "el.h"
61 #include "fcns.h" /* for EL_NUM_FCNS */
62
63 /* for rl_complete() */
64 #define TAB '\r'
65
66 /* see comment at the #ifdef for sense of this */
67 #define GDB_411_HACK
68
69 /* readline compatibility stuff - look at readline sources/documentation */
70 /* to see what these variables mean */
71 const char *rl_library_version = "EditLine wrapper";
72 static char empty[] = { '\0' };
73 static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
74 static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
75 '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
76 char *rl_readline_name = empty;
77 FILE *rl_instream = NULL;
78 FILE *rl_outstream = NULL;
79 int rl_point = 0;
80 int rl_end = 0;
81 char *rl_line_buffer = NULL;
82 VFunction *rl_linefunc = NULL;
83
84 int history_base = 1; /* probably never subject to change */
85 int history_length = 0;
86 int max_input_history = 0;
87 char history_expansion_char = '!';
88 char history_subst_char = '^';
89 char *history_no_expand_chars = expand_chars;
90 Function *history_inhibit_expansion_function = NULL;
91
92 int rl_inhibit_completion = 0;
93 int rl_attempted_completion_over = 0;
94 char *rl_basic_word_break_characters = break_chars;
95 char *rl_completer_word_break_characters = NULL;
96 char *rl_completer_quote_characters = NULL;
97 Function *rl_completion_entry_function = NULL;
98 CPPFunction *rl_attempted_completion_function = NULL;
99 Function *rl_pre_input_hook = NULL;
100 Function *rl_startup1_hook = NULL;
101 Function *rl_getc_function = NULL;
102 char *rl_terminal_name = NULL;
103 int rl_already_prompted = 0;
104 int rl_filename_completion_desired = 0;
105 int rl_ignore_completion_duplicates = 0;
106 VFunction *rl_redisplay_function = NULL;
107 Function *rl_startup_hook = NULL;
108 VFunction *rl_completion_display_matches_hook = NULL;
109 VFunction *rl_prep_term_function = NULL;
110 VFunction *rl_deprep_term_function = NULL;
111
112 /*
113 * The current prompt string.
114 */
115 char *rl_prompt = NULL;
116 /*
117 * This is set to character indicating type of completion being done by
118 * rl_complete_internal(); this is available for application completion
119 * functions.
120 */
121 int rl_completion_type = 0;
122
123 /*
124 * If more than this number of items results from query for possible
125 * completions, we ask user if they are sure to really display the list.
126 */
127 int rl_completion_query_items = 100;
128
129 /*
130 * List of characters which are word break characters, but should be left
131 * in the parsed text when it is passed to the completion function.
132 * Shell uses this to help determine what kind of completing to do.
133 */
134 char *rl_special_prefixes = (char *)NULL;
135
136 /*
137 * This is the character appended to the completed words if at the end of
138 * the line. Default is ' ' (a space).
139 */
140 int rl_completion_append_character = ' ';
141
142 /* stuff below is used internally by libedit for readline emulation */
143
144 /* if not zero, non-unique completions always show list of possible matches */
145 static int _rl_complete_show_all = 0;
146
147 static History *h = NULL;
148 static EditLine *e = NULL;
149 static Function *map[256];
150 static int el_rl_complete_cmdnum = 0;
151
152 /* internal functions */
153 static unsigned char _el_rl_complete(EditLine *, int);
154 static char *_get_prompt(EditLine *);
155 static HIST_ENTRY *_move_history(int);
156 static int _history_search_gen(const char *, int, int);
157 static int _history_expand_command(const char *, size_t, char **);
158 static char *_rl_compat_sub(const char *, const char *,
159 const char *, int);
160 static int rl_complete_internal(int);
161 static int _rl_qsort_string_compare(const void *, const void *);
162
163
164 /* ARGSUSED */
165 static char *
166 _get_prompt(EditLine *el __attribute__((__unused__)))
167 {
168 rl_already_prompted = 1;
169 return (rl_prompt);
170 }
171
172
173 /*
174 * generic function for moving around history
175 */
176 static HIST_ENTRY *
177 _move_history(int op)
178 {
179 HistEvent ev;
180 static HIST_ENTRY rl_he;
181
182 if (history(h, &ev, op) != 0)
183 return (HIST_ENTRY *) NULL;
184
185 rl_he.line = ev.str;
186 rl_he.data = "";
187
188 return (&rl_he);
189 }
190
191
192 /*
193 * READLINE compatibility stuff
194 */
195
196 /*
197 * initialize rl compat stuff
198 */
199 int
200 rl_initialize(void)
201 {
202 HistEvent ev;
203 const LineInfo *li;
204 int i;
205 int editmode = 1;
206 struct termios t;
207
208 if (e != NULL)
209 el_end(e);
210 if (h != NULL)
211 history_end(h);
212
213 if (!rl_instream)
214 rl_instream = stdin;
215 if (!rl_outstream)
216 rl_outstream = stdout;
217
218 /*
219 * See if we don't really want to run the editor
220 */
221 if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
222 editmode = 0;
223
224 e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
225
226 if (!editmode)
227 el_set(e, EL_EDITMODE, 0);
228
229 h = history_init();
230 if (!e || !h)
231 return (-1);
232
233 history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
234 history_length = 0;
235 max_input_history = INT_MAX;
236 el_set(e, EL_HIST, history, h);
237
238 /* for proper prompt printing in readline() */
239 rl_prompt = strdup("");
240 if (rl_prompt == NULL) {
241 history_end(h);
242 el_end(e);
243 return -1;
244 }
245 el_set(e, EL_PROMPT, _get_prompt);
246 el_set(e, EL_SIGNAL, 1);
247
248 /* set default mode to "emacs"-style and read setting afterwards */
249 /* so this can be overriden */
250 el_set(e, EL_EDITOR, "emacs");
251 if (rl_terminal_name != NULL)
252 el_set(e, EL_TERMINAL, rl_terminal_name);
253 else
254 el_get(e, EL_TERMINAL, &rl_terminal_name);
255
256 /*
257 * Word completion - this has to go AFTER rebinding keys
258 * to emacs-style.
259 */
260 el_set(e, EL_ADDFN, "rl_complete",
261 "ReadLine compatible completion function",
262 _el_rl_complete);
263 el_set(e, EL_BIND, "^I", "rl_complete", NULL);
264 /*
265 * Find out where the rl_complete function was added; this is
266 * used later to detect that lastcmd was also rl_complete.
267 */
268 for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) {
269 if (e->el_map.func[i] == _el_rl_complete) {
270 el_rl_complete_cmdnum = i;
271 break;
272 }
273 }
274
275 /* read settings from configuration file */
276 el_source(e, NULL);
277
278 /*
279 * Unfortunately, some applications really do use rl_point
280 * and rl_line_buffer directly.
281 */
282 li = el_line(e);
283 /* a cheesy way to get rid of const cast. */
284 rl_line_buffer = memchr(li->buffer, *li->buffer, 1);
285 rl_point = rl_end = 0;
286
287 if (rl_startup_hook)
288 (*rl_startup_hook)(NULL, 0);
289
290 return (0);
291 }
292
293
294 /*
295 * read one line from input stream and return it, chomping
296 * trailing newline (if there is any)
297 */
298 char *
299 readline(const char *prompt)
300 {
301 HistEvent ev;
302 int count;
303 const char *ret;
304 char *buf;
305
306 if (e == NULL || h == NULL)
307 rl_initialize();
308
309 /* update prompt accordingly to what has been passed */
310 if (!prompt)
311 prompt = "";
312 if (strcmp(rl_prompt, prompt) != 0) {
313 free(rl_prompt);
314 rl_prompt = strdup(prompt);
315 if (rl_prompt == NULL)
316 return NULL;
317 }
318
319 if (rl_pre_input_hook)
320 (*rl_pre_input_hook)(NULL, 0);
321
322 rl_already_prompted = 0;
323
324 /* get one line from input stream */
325 ret = el_gets(e, &count);
326
327 if (ret && count > 0) {
328 int lastidx;
329
330 buf = strdup(ret);
331 if (buf == NULL)
332 return NULL;
333 lastidx = count - 1;
334 if (buf[lastidx] == '\n')
335 buf[lastidx] = '\0';
336 } else
337 buf = NULL;
338
339 history(h, &ev, H_GETSIZE);
340 history_length = ev.num;
341
342 return buf;
343 }
344
345 /*
346 * history functions
347 */
348
349 /*
350 * is normally called before application starts to use
351 * history expansion functions
352 */
353 void
354 using_history(void)
355 {
356 if (h == NULL || e == NULL)
357 rl_initialize();
358 }
359
360
361 /*
362 * substitute ``what'' with ``with'', returning resulting string; if
363 * globally == 1, substitutes all occurrences of what, otherwise only the
364 * first one
365 */
366 static char *
367 _rl_compat_sub(const char *str, const char *what, const char *with,
368 int globally)
369 {
370 char *result;
371 const char *temp, *new;
372 size_t len, with_len, what_len, add;
373 size_t size, i;
374
375 result = malloc((size = 16));
376 if (result == NULL)
377 return NULL;
378 temp = str;
379 with_len = strlen(with);
380 what_len = strlen(what);
381 len = 0;
382 do {
383 new = strstr(temp, what);
384 if (new) {
385 i = new - temp;
386 add = i + with_len;
387 if (i + add + 1 >= size) {
388 char *nresult;
389 size += add + 1;
390 nresult = realloc(result, size);
391 if (nresult == NULL) {
392 free(result);
393 return NULL;
394 }
395 result = nresult;
396 }
397 (void) strncpy(&result[len], temp, i);
398 len += i;
399 (void) strcpy(&result[len], with); /* safe */
400 len += with_len;
401 temp = new + what_len;
402 } else {
403 add = strlen(temp);
404 if (len + add + 1 >= size) {
405 char *nresult;
406 size += add + 1;
407 nresult = realloc(result, size);
408 if (nresult == NULL) {
409 free(result);
410 return NULL;
411 }
412 result = nresult;
413 }
414 (void) strcpy(&result[len], temp); /* safe */
415 len += add;
416 temp = NULL;
417 }
418 } while (temp && globally);
419 result[len] = '\0';
420
421 return (result);
422 }
423
424
425 /*
426 * the real function doing history expansion - takes as argument command
427 * to do and data upon which the command should be executed
428 * does expansion the way I've understood readline documentation
429 * word designator ``%'' isn't supported (yet ?)
430 *
431 * returns 0 if data was not modified, 1 if it was and 2 if the string
432 * should be only printed and not executed; in case of error,
433 * returns -1 and *result points to NULL
434 * it's callers responsibility to free() string returned in *result
435 */
436 static int
437 _history_expand_command(const char *command, size_t cmdlen, char **result)
438 {
439 char **arr, *tempcmd, *line, *search = NULL, *cmd;
440 const char *event_data = NULL;
441 static char *from = NULL, *to = NULL;
442 int start = -1, end = -1, max, i, idx;
443 int h_on = 0, t_on = 0, r_on = 0, e_on = 0, p_on = 0, g_on = 0;
444 int event_num = 0, retval;
445 size_t cmdsize;
446
447 *result = NULL;
448
449 cmd = alloca(cmdlen + 1);
450 (void) strncpy(cmd, command, cmdlen);
451 cmd[cmdlen] = 0;
452
453 idx = 1;
454 /* find out which event to take */
455 if (cmd[idx] == history_expansion_char) {
456 event_num = history_length;
457 idx++;
458 } else {
459 int off, num;
460 size_t len;
461 off = idx;
462 while (cmd[off] && !strchr(":^$*-%", cmd[off]))
463 off++;
464 num = atoi(&cmd[idx]);
465 if (num != 0) {
466 event_num = num;
467 if (num < 0)
468 event_num += history_length + 1;
469 } else {
470 int prefix = 1, curr_num;
471 HistEvent ev;
472
473 len = off - idx;
474 if (cmd[idx] == '?') {
475 idx++, len--;
476 if (cmd[off - 1] == '?')
477 len--;
478 else if (cmd[off] != '\n' && cmd[off] != '\0')
479 return (-1);
480 prefix = 0;
481 }
482 search = alloca(len + 1);
483 (void) strncpy(search, &cmd[idx], len);
484 search[len] = '\0';
485
486 if (history(h, &ev, H_CURR) != 0)
487 return (-1);
488 curr_num = ev.num;
489
490 if (prefix)
491 retval = history_search_prefix(search, -1);
492 else
493 retval = history_search(search, -1);
494
495 if (retval == -1) {
496 fprintf(rl_outstream, "%s: Event not found\n",
497 search);
498 return (-1);
499 }
500 if (history(h, &ev, H_CURR) != 0)
501 return (-1);
502 event_data = ev.str;
503
504 /* roll back to original position */
505 history(h, &ev, H_NEXT_EVENT, curr_num);
506 }
507 idx = off;
508 }
509
510 if (!event_data && event_num >= 0) {
511 HIST_ENTRY *rl_he;
512 rl_he = history_get(event_num);
513 if (!rl_he)
514 return (0);
515 event_data = rl_he->line;
516 } else
517 return (-1);
518
519 if (cmd[idx] != ':')
520 return (-1);
521 cmd += idx + 1;
522
523 /* recognize cmd */
524 if (*cmd == '^')
525 start = end = 1, cmd++;
526 else if (*cmd == '$')
527 start = end = -1, cmd++;
528 else if (*cmd == '*')
529 start = 1, end = -1, cmd++;
530 else if (isdigit((unsigned char) *cmd)) {
531 const char *temp;
532 int shifted = 0;
533
534 start = atoi(cmd);
535 temp = cmd;
536 for (; isdigit((unsigned char) *cmd); cmd++);
537 if (temp != cmd)
538 shifted = 1;
539 if (shifted && *cmd == '-') {
540 if (!isdigit((unsigned char) *(cmd + 1)))
541 end = -2;
542 else {
543 end = atoi(cmd + 1);
544 for (; isdigit((unsigned char) *cmd); cmd++);
545 }
546 } else if (shifted && *cmd == '*')
547 end = -1, cmd++;
548 else if (shifted)
549 end = start;
550 }
551 if (*cmd == ':')
552 cmd++;
553
554 line = strdup(event_data);
555 if (line == NULL)
556 return 0;
557 for (; *cmd; cmd++) {
558 if (*cmd == ':')
559 continue;
560 else if (*cmd == 'h')
561 h_on = 1 | g_on, g_on = 0;
562 else if (*cmd == 't')
563 t_on = 1 | g_on, g_on = 0;
564 else if (*cmd == 'r')
565 r_on = 1 | g_on, g_on = 0;
566 else if (*cmd == 'e')
567 e_on = 1 | g_on, g_on = 0;
568 else if (*cmd == 'p')
569 p_on = 1 | g_on, g_on = 0;
570 else if (*cmd == 'g')
571 g_on = 2;
572 else if (*cmd == 's' || *cmd == '&') {
573 char *what, *with, delim;
574 size_t len, from_len;
575 size_t size;
576
577 if (*cmd == '&' && (from == NULL || to == NULL))
578 continue;
579 else if (*cmd == 's') {
580 delim = *(++cmd), cmd++;
581 size = 16;
582 what = realloc(from, size);
583 if (what == NULL) {
584 free(from);
585 return 0;
586 }
587 len = 0;
588 for (; *cmd && *cmd != delim; cmd++) {
589 if (*cmd == '\\'
590 && *(cmd + 1) == delim)
591 cmd++;
592 if (len >= size) {
593 char *nwhat;
594 nwhat = realloc(what,
595 (size <<= 1));
596 if (nwhat == NULL) {
597 free(what);
598 return 0;
599 }
600 what = nwhat;
601 }
602 what[len++] = *cmd;
603 }
604 what[len] = '\0';
605 from = what;
606 if (*what == '\0') {
607 free(what);
608 if (search) {
609 from = strdup(search);
610 if (from == NULL)
611 return 0;
612 } else {
613 from = NULL;
614 return (-1);
615 }
616 }
617 cmd++; /* shift after delim */
618 if (!*cmd)
619 continue;
620
621 size = 16;
622 with = realloc(to, size);
623 if (with == NULL) {
624 free(to);
625 return -1;
626 }
627 len = 0;
628 from_len = strlen(from);
629 for (; *cmd && *cmd != delim; cmd++) {
630 if (len + from_len + 1 >= size) {
631 char *nwith;
632 size += from_len + 1;
633 nwith = realloc(with, size);
634 if (nwith == NULL) {
635 free(with);
636 return -1;
637 }
638 with = nwith;
639 }
640 if (*cmd == '&') {
641 /* safe */
642 (void) strcpy(&with[len], from);
643 len += from_len;
644 continue;
645 }
646 if (*cmd == '\\'
647 && (*(cmd + 1) == delim
648 || *(cmd + 1) == '&'))
649 cmd++;
650 with[len++] = *cmd;
651 }
652 with[len] = '\0';
653 to = with;
654
655 tempcmd = _rl_compat_sub(line, from, to,
656 (g_on) ? 1 : 0);
657 if (tempcmd) {
658 free(line);
659 line = tempcmd;
660 }
661 g_on = 0;
662 }
663 }
664 }
665
666 arr = history_tokenize(line);
667 free(line); /* no more needed */
668 if (arr && *arr == NULL)
669 free(arr), arr = NULL;
670 if (!arr)
671 return (-1);
672
673 /* find out max valid idx to array of array */
674 max = 0;
675 for (i = 0; arr[i]; i++)
676 max++;
677 max--;
678
679 /* set boundaries to something relevant */
680 if (start < 0)
681 start = 1;
682 if (end < 0)
683 end = max - ((end < -1) ? 1 : 0);
684
685 /* check boundaries ... */
686 if (start > max || end > max || start > end)
687 return (-1);
688
689 for (i = 0; i <= max; i++) {
690 char *temp;
691 if (h_on && (i == 1 || h_on > 1) &&
692 (temp = strrchr(arr[i], '/')))
693 *(temp + 1) = '\0';
694 if (t_on && (i == 1 || t_on > 1) &&
695 (temp = strrchr(arr[i], '/')))
696 (void) strcpy(arr[i], temp + 1);
697 if (r_on && (i == 1 || r_on > 1) &&
698 (temp = strrchr(arr[i], '.')))
699 *temp = '\0';
700 if (e_on && (i == 1 || e_on > 1) &&
701 (temp = strrchr(arr[i], '.')))
702 (void) strcpy(arr[i], temp);
703 }
704
705 cmdsize = 1, cmdlen = 0;
706 if ((tempcmd = malloc(cmdsize)) == NULL)
707 return 0;
708 for (i = start; start <= i && i <= end; i++) {
709 int arr_len;
710
711 arr_len = strlen(arr[i]);
712 if (cmdlen + arr_len + 1 >= cmdsize) {
713 char *ntempcmd;
714 cmdsize += arr_len + 1;
715 ntempcmd = realloc(tempcmd, cmdsize);
716 if (ntempcmd == NULL) {
717 free(tempcmd);
718 return 0;
719 }
720 tempcmd = ntempcmd;
721 }
722 (void) strcpy(&tempcmd[cmdlen], arr[i]); /* safe */
723 cmdlen += arr_len;
724 tempcmd[cmdlen++] = ' '; /* add a space */
725 }
726 while (cmdlen > 0 && isspace((unsigned char) tempcmd[cmdlen - 1]))
727 cmdlen--;
728 tempcmd[cmdlen] = '\0';
729
730 *result = tempcmd;
731
732 for (i = 0; i <= max; i++)
733 free(arr[i]);
734 free(arr), arr = (char **) NULL;
735 return (p_on) ? 2 : 1;
736 }
737
738
739 /*
740 * csh-style history expansion
741 */
742 int
743 history_expand(char *str, char **output)
744 {
745 int i, retval = 0, idx;
746 size_t size;
747 char *temp, *result;
748
749 if (h == NULL || e == NULL)
750 rl_initialize();
751
752 *output = strdup(str); /* do it early */
753 if (*output == NULL)
754 return 0;
755
756 if (str[0] == history_subst_char) {
757 /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
758 temp = alloca(4 + strlen(str) + 1);
759 temp[0] = temp[1] = history_expansion_char;
760 temp[2] = ':';
761 temp[3] = 's';
762 (void) strcpy(temp + 4, str);
763 str = temp;
764 }
765 #define ADD_STRING(what, len) \
766 { \
767 if (idx + len + 1 > size) { \
768 char *nresult = realloc(result, (size += len + 1));\
769 if (nresult == NULL) { \
770 free(*output); \
771 return 0; \
772 } \
773 result = nresult; \
774 } \
775 (void)strncpy(&result[idx], what, len); \
776 idx += len; \
777 result[idx] = '\0'; \
778 }
779
780 result = NULL;
781 size = idx = 0;
782 for (i = 0; str[i];) {
783 int start, j, loop_again;
784 size_t len;
785
786 loop_again = 1;
787 start = j = i;
788 loop:
789 for (; str[j]; j++) {
790 if (str[j] == '\\' &&
791 str[j + 1] == history_expansion_char) {
792 (void) strcpy(&str[j], &str[j + 1]);
793 continue;
794 }
795 if (!loop_again) {
796 if (str[j] == '?') {
797 while (str[j] && str[++j] != '?');
798 if (str[j] == '?')
799 j++;
800 } else if (isspace((unsigned char) str[j]))
801 break;
802 }
803 if (str[j] == history_expansion_char
804 && !strchr(history_no_expand_chars, str[j + 1])
805 && (!history_inhibit_expansion_function ||
806 (*history_inhibit_expansion_function)(str, j) == 0))
807 break;
808 }
809
810 if (str[j] && str[j + 1] != '#' && loop_again) {
811 i = j;
812 j++;
813 if (str[j] == history_expansion_char)
814 j++;
815 loop_again = 0;
816 goto loop;
817 }
818 len = i - start;
819 temp = &str[start];
820 ADD_STRING(temp, len);
821
822 if (str[i] == '\0' || str[i] != history_expansion_char
823 || str[i + 1] == '#') {
824 len = j - i;
825 temp = &str[i];
826 ADD_STRING(temp, len);
827 if (start == 0)
828 retval = 0;
829 else
830 retval = 1;
831 break;
832 }
833 retval = _history_expand_command(&str[i], (size_t) (j - i),
834 &temp);
835 if (retval != -1) {
836 len = strlen(temp);
837 ADD_STRING(temp, len);
838 }
839 i = j;
840 } /* for(i ...) */
841
842 if (retval == 2) {
843 add_history(temp);
844 #ifdef GDB_411_HACK
845 /* gdb 4.11 has been shipped with readline, where */
846 /* history_expand() returned -1 when the line */
847 /* should not be executed; in readline 2.1+ */
848 /* it should return 2 in such a case */
849 retval = -1;
850 #endif
851 }
852 free(*output);
853 *output = result;
854
855 return (retval);
856 }
857
858
859 /*
860 * Parse the string into individual tokens, similarily to how shell would do it.
861 */
862 char **
863 history_tokenize(const char *str)
864 {
865 int size = 1, result_idx = 0, i, start;
866 size_t len;
867 char **result = NULL, *temp, delim = '\0';
868
869 for (i = 0; str[i]; i++) {
870 while (isspace((unsigned char) str[i]))
871 i++;
872 start = i;
873 for (; str[i]; i++) {
874 if (str[i] == '\\') {
875 if (str[i+1] != '\0')
876 i++;
877 } else if (str[i] == delim)
878 delim = '\0';
879 else if (!delim &&
880 (isspace((unsigned char) str[i]) ||
881 strchr("()<>;&|$", str[i])))
882 break;
883 else if (!delim && strchr("'`\"", str[i]))
884 delim = str[i];
885 }
886
887 if (result_idx + 2 >= size) {
888 char **nresult;
889 size <<= 1;
890 nresult = realloc(result, size * sizeof(char *));
891 if (nresult == NULL) {
892 free(result);
893 return NULL;
894 }
895 result = nresult;
896 }
897 len = i - start;
898 temp = malloc(len + 1);
899 if (temp == NULL) {
900 free(result);
901 return NULL;
902 }
903 (void) strncpy(temp, &str[start], len);
904 temp[len] = '\0';
905 result[result_idx++] = temp;
906 result[result_idx] = NULL;
907 }
908
909 return (result);
910 }
911
912
913 /*
914 * limit size of history record to ``max'' events
915 */
916 void
917 stifle_history(int max)
918 {
919 HistEvent ev;
920
921 if (h == NULL || e == NULL)
922 rl_initialize();
923
924 if (history(h, &ev, H_SETSIZE, max) == 0)
925 max_input_history = max;
926 }
927
928
929 /*
930 * "unlimit" size of history - set the limit to maximum allowed int value
931 */
932 int
933 unstifle_history(void)
934 {
935 HistEvent ev;
936 int omax;
937
938 history(h, &ev, H_SETSIZE, INT_MAX);
939 omax = max_input_history;
940 max_input_history = INT_MAX;
941 return (omax); /* some value _must_ be returned */
942 }
943
944
945 int
946 history_is_stifled(void)
947 {
948
949 /* cannot return true answer */
950 return (max_input_history != INT_MAX);
951 }
952
953
954 /*
955 * read history from a file given
956 */
957 int
958 read_history(const char *filename)
959 {
960 HistEvent ev;
961
962 if (h == NULL || e == NULL)
963 rl_initialize();
964 return (history(h, &ev, H_LOAD, filename));
965 }
966
967
968 /*
969 * write history to a file given
970 */
971 int
972 write_history(const char *filename)
973 {
974 HistEvent ev;
975
976 if (h == NULL || e == NULL)
977 rl_initialize();
978 return (history(h, &ev, H_SAVE, filename));
979 }
980
981
982 /*
983 * returns history ``num''th event
984 *
985 * returned pointer points to static variable
986 */
987 HIST_ENTRY *
988 history_get(int num)
989 {
990 static HIST_ENTRY she;
991 HistEvent ev;
992 int i = 1, curr_num;
993
994 if (h == NULL || e == NULL)
995 rl_initialize();
996
997 /* rewind to beginning */
998 if (history(h, &ev, H_CURR) != 0)
999 return (NULL);
1000 curr_num = ev.num;
1001 if (history(h, &ev, H_LAST) != 0)
1002 return (NULL); /* error */
1003 while (i < num && history(h, &ev, H_PREV) == 0)
1004 i++;
1005 if (i != num)
1006 return (NULL); /* not so many entries */
1007
1008 she.line = ev.str;
1009 she.data = NULL;
1010
1011 /* rewind history to the same event it was before */
1012 (void) history(h, &ev, H_FIRST);
1013 (void) history(h, &ev, H_NEXT_EVENT, curr_num);
1014
1015 return (&she);
1016 }
1017
1018
1019 /*
1020 * add the line to history table
1021 */
1022 int
1023 add_history(const char *line)
1024 {
1025 HistEvent ev;
1026
1027 if (h == NULL || e == NULL)
1028 rl_initialize();
1029
1030 (void) history(h, &ev, H_ENTER, line);
1031 if (history(h, &ev, H_GETSIZE) == 0)
1032 history_length = ev.num;
1033
1034 return (!(history_length > 0)); /* return 0 if all is okay */
1035 }
1036
1037
1038 /*
1039 * clear the history list - delete all entries
1040 */
1041 void
1042 clear_history(void)
1043 {
1044 HistEvent ev;
1045
1046 history(h, &ev, H_CLEAR);
1047 }
1048
1049
1050 /*
1051 * returns offset of the current history event
1052 */
1053 int
1054 where_history(void)
1055 {
1056 HistEvent ev;
1057 int curr_num, off;
1058
1059 if (history(h, &ev, H_CURR) != 0)
1060 return (0);
1061 curr_num = ev.num;
1062
1063 history(h, &ev, H_FIRST);
1064 off = 1;
1065 while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
1066 off++;
1067
1068 return (off);
1069 }
1070
1071
1072 /*
1073 * returns current history event or NULL if there is no such event
1074 */
1075 HIST_ENTRY *
1076 current_history(void)
1077 {
1078
1079 return (_move_history(H_CURR));
1080 }
1081
1082
1083 /*
1084 * returns total number of bytes history events' data are using
1085 */
1086 int
1087 history_total_bytes(void)
1088 {
1089 HistEvent ev;
1090 int curr_num, size;
1091
1092 if (history(h, &ev, H_CURR) != 0)
1093 return (-1);
1094 curr_num = ev.num;
1095
1096 history(h, &ev, H_FIRST);
1097 size = 0;
1098 do
1099 size += strlen(ev.str);
1100 while (history(h, &ev, H_NEXT) == 0);
1101
1102 /* get to the same position as before */
1103 history(h, &ev, H_PREV_EVENT, curr_num);
1104
1105 return (size);
1106 }
1107
1108
1109 /*
1110 * sets the position in the history list to ``pos''
1111 */
1112 int
1113 history_set_pos(int pos)
1114 {
1115 HistEvent ev;
1116 int off, curr_num;
1117
1118 if (pos > history_length || pos < 0)
1119 return (-1);
1120
1121 history(h, &ev, H_CURR);
1122 curr_num = ev.num;
1123 history(h, &ev, H_FIRST);
1124 off = 0;
1125 while (off < pos && history(h, &ev, H_NEXT) == 0)
1126 off++;
1127
1128 if (off != pos) { /* do a rollback in case of error */
1129 history(h, &ev, H_FIRST);
1130 history(h, &ev, H_NEXT_EVENT, curr_num);
1131 return (-1);
1132 }
1133 return (0);
1134 }
1135
1136
1137 /*
1138 * returns previous event in history and shifts pointer accordingly
1139 */
1140 HIST_ENTRY *
1141 previous_history(void)
1142 {
1143
1144 return (_move_history(H_PREV));
1145 }
1146
1147
1148 /*
1149 * returns next event in history and shifts pointer accordingly
1150 */
1151 HIST_ENTRY *
1152 next_history(void)
1153 {
1154
1155 return (_move_history(H_NEXT));
1156 }
1157
1158
1159 /*
1160 * generic history search function
1161 */
1162 static int
1163 _history_search_gen(const char *str, int direction, int pos)
1164 {
1165 HistEvent ev;
1166 const char *strp;
1167 int curr_num;
1168
1169 if (history(h, &ev, H_CURR) != 0)
1170 return (-1);
1171 curr_num = ev.num;
1172
1173 for (;;) {
1174 strp = strstr(ev.str, str);
1175 if (strp && (pos < 0 || &ev.str[pos] == strp))
1176 return (int) (strp - ev.str);
1177 if (history(h, &ev, direction < 0 ? H_PREV : H_NEXT) != 0)
1178 break;
1179 }
1180
1181 history(h, &ev, direction < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
1182
1183 return (-1);
1184 }
1185
1186
1187 /*
1188 * searches for first history event containing the str
1189 */
1190 int
1191 history_search(const char *str, int direction)
1192 {
1193
1194 return (_history_search_gen(str, direction, -1));
1195 }
1196
1197
1198 /*
1199 * searches for first history event beginning with str
1200 */
1201 int
1202 history_search_prefix(const char *str, int direction)
1203 {
1204
1205 return (_history_search_gen(str, direction, 0));
1206 }
1207
1208
1209 /*
1210 * search for event in history containing str, starting at offset
1211 * abs(pos); continue backward, if pos<0, forward otherwise
1212 */
1213 /* ARGSUSED */
1214 int
1215 history_search_pos(const char *str,
1216 int direction __attribute__((__unused__)), int pos)
1217 {
1218 HistEvent ev;
1219 int curr_num, off;
1220
1221 off = (pos > 0) ? pos : -pos;
1222 pos = (pos > 0) ? 1 : -1;
1223
1224 if (history(h, &ev, H_CURR) != 0)
1225 return (-1);
1226 curr_num = ev.num;
1227
1228 if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
1229 return (-1);
1230
1231
1232 for (;;) {
1233 if (strstr(ev.str, str))
1234 return (off);
1235 if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
1236 break;
1237 }
1238
1239 /* set "current" pointer back to previous state */
1240 history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
1241
1242 return (-1);
1243 }
1244
1245
1246 /********************************/
1247 /* completion functions */
1248
1249 /*
1250 * does tilde expansion of strings of type ``~user/foo''
1251 * if ``user'' isn't valid user name or ``txt'' doesn't start
1252 * w/ '~', returns pointer to strdup()ed copy of ``txt''
1253 *
1254 * it's callers's responsibility to free() returned string
1255 */
1256 char *
1257 tilde_expand(char *txt)
1258 {
1259 struct passwd *pass;
1260 char *temp;
1261 size_t len = 0;
1262
1263 if (txt[0] != '~')
1264 return (strdup(txt));
1265
1266 temp = strchr(txt + 1, '/');
1267 if (temp == NULL) {
1268 temp = strdup(txt + 1);
1269 if (temp == NULL)
1270 return NULL;
1271 } else {
1272 len = temp - txt + 1; /* text until string after slash */
1273 temp = malloc(len);
1274 if (temp == NULL)
1275 return NULL;
1276 (void) strncpy(temp, txt + 1, len - 2);
1277 temp[len - 2] = '\0';
1278 }
1279 pass = getpwnam(temp);
1280 free(temp); /* value no more needed */
1281 if (pass == NULL)
1282 return (strdup(txt));
1283
1284 /* update pointer txt to point at string immedially following */
1285 /* first slash */
1286 txt += len;
1287
1288 temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1);
1289 if (temp == NULL)
1290 return NULL;
1291 (void) sprintf(temp, "%s/%s", pass->pw_dir, txt);
1292
1293 return (temp);
1294 }
1295
1296
1297 /*
1298 * return first found file name starting by the ``text'' or NULL if no
1299 * such file can be found
1300 * value of ``state'' is ignored
1301 *
1302 * it's caller's responsibility to free returned string
1303 */
1304 char *
1305 filename_completion_function(const char *text, int state)
1306 {
1307 static DIR *dir = NULL;
1308 static char *filename = NULL, *dirname = NULL;
1309 static size_t filename_len = 0;
1310 struct dirent *entry;
1311 char *temp;
1312 size_t len;
1313
1314 if (state == 0 || dir == NULL) {
1315 temp = strrchr(text, '/');
1316 if (temp) {
1317 char *nptr;
1318 temp++;
1319 nptr = realloc(filename, strlen(temp) + 1);
1320 if (nptr == NULL) {
1321 free(filename);
1322 return NULL;
1323 }
1324 filename = nptr;
1325 (void) strcpy(filename, temp);
1326 len = temp - text; /* including last slash */
1327 nptr = realloc(dirname, len + 1);
1328 if (nptr == NULL) {
1329 free(filename);
1330 return NULL;
1331 }
1332 dirname = nptr;
1333 (void) strncpy(dirname, text, len);
1334 dirname[len] = '\0';
1335 } else {
1336 filename = strdup(text);
1337 if (filename == NULL)
1338 return NULL;
1339 dirname = NULL;
1340 }
1341
1342 /* support for ``~user'' syntax */
1343 if (dirname && *dirname == '~') {
1344 char *nptr;
1345 temp = tilde_expand(dirname);
1346 if (temp == NULL)
1347 return NULL;
1348 nptr = realloc(dirname, strlen(temp) + 1);
1349 if (nptr == NULL) {
1350 free(dirname);
1351 return NULL;
1352 }
1353 dirname = nptr;
1354 (void) strcpy(dirname, temp); /* safe */
1355 free(temp); /* no longer needed */
1356 }
1357 /* will be used in cycle */
1358 filename_len = strlen(filename);
1359 if (filename_len == 0)
1360 return (NULL); /* no expansion possible */
1361
1362 if (dir != NULL) {
1363 (void)closedir(dir);
1364 dir = NULL;
1365 }
1366 dir = opendir(dirname ? dirname : ".");
1367 if (!dir)
1368 return (NULL); /* cannot open the directory */
1369 }
1370 /* find the match */
1371 while ((entry = readdir(dir)) != NULL) {
1372 /* otherwise, get first entry where first */
1373 /* filename_len characters are equal */
1374 if (entry->d_name[0] == filename[0]
1375 #if defined(__SVR4) || defined(__linux__)
1376 && strlen(entry->d_name) >= filename_len
1377 #else
1378 && entry->d_namlen >= filename_len
1379 #endif
1380 && strncmp(entry->d_name, filename,
1381 filename_len) == 0)
1382 break;
1383 }
1384
1385 if (entry) { /* match found */
1386
1387 struct stat stbuf;
1388 #if defined(__SVR4) || defined(__linux__)
1389 len = strlen(entry->d_name) +
1390 #else
1391 len = entry->d_namlen +
1392 #endif
1393 ((dirname) ? strlen(dirname) : 0) + 1 + 1;
1394 temp = malloc(len);
1395 if (temp == NULL)
1396 return NULL;
1397 (void) sprintf(temp, "%s%s",
1398 dirname ? dirname : "", entry->d_name); /* safe */
1399
1400 /* test, if it's directory */
1401 if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode))
1402 strcat(temp, "/"); /* safe */
1403 } else {
1404 (void)closedir(dir);
1405 dir = NULL;
1406 temp = NULL;
1407 }
1408
1409 return (temp);
1410 }
1411
1412
1413 /*
1414 * a completion generator for usernames; returns _first_ username
1415 * which starts with supplied text
1416 * text contains a partial username preceded by random character
1417 * (usually '~'); state is ignored
1418 * it's callers responsibility to free returned value
1419 */
1420 char *
1421 username_completion_function(const char *text, int state)
1422 {
1423 struct passwd *pwd;
1424
1425 if (text[0] == '\0')
1426 return (NULL);
1427
1428 if (*text == '~')
1429 text++;
1430
1431 if (state == 0)
1432 setpwent();
1433
1434 while ((pwd = getpwent()) && text[0] == pwd->pw_name[0]
1435 && strcmp(text, pwd->pw_name) == 0);
1436
1437 if (pwd == NULL) {
1438 endpwent();
1439 return (NULL);
1440 }
1441 return (strdup(pwd->pw_name));
1442 }
1443
1444
1445 /*
1446 * el-compatible wrapper around rl_complete; needed for key binding
1447 */
1448 /* ARGSUSED */
1449 static unsigned char
1450 _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
1451 {
1452 return (unsigned char) rl_complete(0, ch);
1453 }
1454
1455
1456 /*
1457 * returns list of completions for text given
1458 */
1459 char **
1460 completion_matches(const char *text, CPFunction *genfunc)
1461 {
1462 char **match_list = NULL, *retstr, *prevstr;
1463 size_t match_list_len, max_equal, which, i;
1464 size_t matches;
1465
1466 if (h == NULL || e == NULL)
1467 rl_initialize();
1468
1469 matches = 0;
1470 match_list_len = 1;
1471 while ((retstr = (*genfunc) (text, (int)matches)) != NULL) {
1472 /* allow for list terminator here */
1473 if (matches + 3 >= match_list_len) {
1474 char **nmatch_list;
1475 while (matches + 3 >= match_list_len)
1476 match_list_len <<= 1;
1477 nmatch_list = realloc(match_list,
1478 match_list_len * sizeof(char *));
1479 if (nmatch_list == NULL) {
1480 free(match_list);
1481 return NULL;
1482 }
1483 match_list = nmatch_list;
1484
1485 }
1486 match_list[++matches] = retstr;
1487 }
1488
1489 if (!match_list)
1490 return NULL; /* nothing found */
1491
1492 /* find least denominator and insert it to match_list[0] */
1493 which = 2;
1494 prevstr = match_list[1];
1495 max_equal = strlen(prevstr);
1496 for (; which <= matches; which++) {
1497 for (i = 0; i < max_equal &&
1498 prevstr[i] == match_list[which][i]; i++)
1499 continue;
1500 max_equal = i;
1501 }
1502
1503 retstr = malloc(max_equal + 1);
1504 if (retstr == NULL) {
1505 free(match_list);
1506 return NULL;
1507 }
1508 (void) strncpy(retstr, match_list[1], max_equal);
1509 retstr[max_equal] = '\0';
1510 match_list[0] = retstr;
1511
1512 /* add NULL as last pointer to the array */
1513 match_list[matches + 1] = (char *) NULL;
1514
1515 return (match_list);
1516 }
1517
1518 /*
1519 * Sort function for qsort(). Just wrapper around strcasecmp().
1520 */
1521 static int
1522 _rl_qsort_string_compare(i1, i2)
1523 const void *i1, *i2;
1524 {
1525 const char *s1 = ((const char * const *)i1)[0];
1526 const char *s2 = ((const char * const *)i2)[0];
1527
1528 return strcasecmp(s1, s2);
1529 }
1530
1531 /*
1532 * Display list of strings in columnar format on readline's output stream.
1533 * 'matches' is list of strings, 'len' is number of strings in 'matches',
1534 * 'max' is maximum length of string in 'matches'.
1535 */
1536 void
1537 rl_display_match_list (matches, len, max)
1538 char **matches;
1539 int len, max;
1540 {
1541 int i, idx, limit, count;
1542 int screenwidth = e->el_term.t_size.h;
1543
1544 /*
1545 * Find out how many entries can be put on one line, count
1546 * with two spaces between strings.
1547 */
1548 limit = screenwidth / (max + 2);
1549 if (limit == 0)
1550 limit = 1;
1551
1552 /* how many lines of output */
1553 count = len / limit;
1554 if (count * limit < len)
1555 count++;
1556
1557 /* Sort the items if they are not already sorted. */
1558 qsort(&matches[1], (size_t)(len - 1), sizeof(char *),
1559 _rl_qsort_string_compare);
1560
1561 idx = 1;
1562 for(; count > 0; count--) {
1563 for(i=0; i < limit && matches[idx]; i++, idx++)
1564 fprintf(e->el_outfile, "%-*s ", max, matches[idx]);
1565 fprintf(e->el_outfile, "\n");
1566 }
1567 }
1568
1569 /*
1570 * Complete the word at or before point, called by rl_complete()
1571 * 'what_to_do' says what to do with the completion.
1572 * `?' means list the possible completions.
1573 * TAB means do standard completion.
1574 * `*' means insert all of the possible completions.
1575 * `!' means to do standard completion, and list all possible completions if
1576 * there is more than one.
1577 *
1578 * Note: '*' support is not implemented
1579 */
1580 static int
1581 rl_complete_internal(int what_to_do)
1582 {
1583 Function *complet_func;
1584 const LineInfo *li;
1585 char *temp, **matches;
1586 const char *ctemp;
1587 size_t len;
1588
1589 rl_completion_type = what_to_do;
1590
1591 if (h == NULL || e == NULL)
1592 rl_initialize();
1593
1594 complet_func = rl_completion_entry_function;
1595 if (!complet_func)
1596 complet_func = (Function *)(void *)filename_completion_function;
1597
1598 /* We now look backwards for the start of a filename/variable word */
1599 li = el_line(e);
1600 ctemp = (const char *) li->cursor;
1601 while (ctemp > li->buffer
1602 && !strchr(rl_basic_word_break_characters, ctemp[-1])
1603 && (!rl_special_prefixes
1604 || !strchr(rl_special_prefixes, ctemp[-1]) ) )
1605 ctemp--;
1606
1607 len = li->cursor - ctemp;
1608 temp = alloca(len + 1);
1609 (void) strncpy(temp, ctemp, len);
1610 temp[len] = '\0';
1611
1612 /* these can be used by function called in completion_matches() */
1613 /* or (*rl_attempted_completion_function)() */
1614 rl_point = li->cursor - li->buffer;
1615 rl_end = li->lastchar - li->buffer;
1616
1617 if (!rl_attempted_completion_function)
1618 matches = completion_matches(temp, (CPFunction *)complet_func);
1619 else {
1620 int end = li->cursor - li->buffer;
1621 matches = (*rl_attempted_completion_function) (temp, (int)
1622 (end - len), end);
1623 }
1624
1625 if (matches) {
1626 int i, retval = CC_REFRESH;
1627 int matches_num, maxlen, match_len, match_display=1;
1628
1629 /*
1630 * Only replace the completed string with common part of
1631 * possible matches if there is possible completion.
1632 */
1633 if (matches[0][0] != '\0') {
1634 el_deletestr(e, (int) len);
1635 el_insertstr(e, matches[0]);
1636 }
1637
1638 if (what_to_do == '?')
1639 goto display_matches;
1640
1641 if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
1642 /*
1643 * We found exact match. Add a space after
1644 * it, unless we do filename completion and the
1645 * object is a directory.
1646 */
1647 size_t alen = strlen(matches[0]);
1648 if ((complet_func !=
1649 (Function *)filename_completion_function
1650 || (alen > 0 && (matches[0])[alen - 1] != '/'))
1651 && rl_completion_append_character) {
1652 char buf[2];
1653 buf[0] = rl_completion_append_character;
1654 buf[1] = '\0';
1655 el_insertstr(e, buf);
1656 }
1657 } else if (what_to_do == '!') {
1658 display_matches:
1659 /*
1660 * More than one match and requested to list possible
1661 * matches.
1662 */
1663
1664 for(i=1, maxlen=0; matches[i]; i++) {
1665 match_len = strlen(matches[i]);
1666 if (match_len > maxlen)
1667 maxlen = match_len;
1668 }
1669 matches_num = i - 1;
1670
1671 /* newline to get on next line from command line */
1672 fprintf(e->el_outfile, "\n");
1673
1674 /*
1675 * If there are too many items, ask user for display
1676 * confirmation.
1677 */
1678 if (matches_num > rl_completion_query_items) {
1679 fprintf(e->el_outfile,
1680 "Display all %d possibilities? (y or n) ",
1681 matches_num);
1682 fflush(e->el_outfile);
1683 if (getc(stdin) != 'y')
1684 match_display = 0;
1685 fprintf(e->el_outfile, "\n");
1686 }
1687
1688 if (match_display)
1689 rl_display_match_list(matches, matches_num,
1690 maxlen);
1691 retval = CC_REDISPLAY;
1692 } else if (matches[0][0]) {
1693 /*
1694 * There was some common match, but the name was
1695 * not complete enough. Next tab will print possible
1696 * completions.
1697 */
1698 el_beep(e);
1699 } else {
1700 /* lcd is not a valid object - further specification */
1701 /* is needed */
1702 el_beep(e);
1703 retval = CC_NORM;
1704 }
1705
1706 /* free elements of array and the array itself */
1707 for (i = 0; matches[i]; i++)
1708 free(matches[i]);
1709 free(matches), matches = NULL;
1710
1711 return (retval);
1712 }
1713 return (CC_NORM);
1714 }
1715
1716
1717 /*
1718 * complete word at current point
1719 */
1720 int
1721 rl_complete(int ignore, int invoking_key)
1722 {
1723 if (h == NULL || e == NULL)
1724 rl_initialize();
1725
1726 if (rl_inhibit_completion) {
1727 rl_insert(ignore, invoking_key);
1728 return (CC_REFRESH);
1729 } else if (e->el_state.lastcmd == el_rl_complete_cmdnum)
1730 return rl_complete_internal('?');
1731 else if (_rl_complete_show_all)
1732 return rl_complete_internal('!');
1733 else
1734 return (rl_complete_internal(TAB));
1735 }
1736
1737
1738 /*
1739 * misc other functions
1740 */
1741
1742 /*
1743 * bind key c to readline-type function func
1744 */
1745 int
1746 rl_bind_key(int c, int func(int, int))
1747 {
1748 int retval = -1;
1749
1750 if (h == NULL || e == NULL)
1751 rl_initialize();
1752
1753 if (func == rl_insert) {
1754 /* XXX notice there is no range checking of ``c'' */
1755 e->el_map.key[c] = ED_INSERT;
1756 retval = 0;
1757 }
1758 return (retval);
1759 }
1760
1761
1762 /*
1763 * read one key from input - handles chars pushed back
1764 * to input stream also
1765 */
1766 int
1767 rl_read_key(void)
1768 {
1769 char fooarr[2 * sizeof(int)];
1770
1771 if (e == NULL || h == NULL)
1772 rl_initialize();
1773
1774 return (el_getc(e, fooarr));
1775 }
1776
1777
1778 /*
1779 * reset the terminal
1780 */
1781 /* ARGSUSED */
1782 void
1783 rl_reset_terminal(const char *p __attribute__((__unused__)))
1784 {
1785
1786 if (h == NULL || e == NULL)
1787 rl_initialize();
1788 el_reset(e);
1789 }
1790
1791
1792 /*
1793 * insert character ``c'' back into input stream, ``count'' times
1794 */
1795 int
1796 rl_insert(int count, int c)
1797 {
1798 char arr[2];
1799
1800 if (h == NULL || e == NULL)
1801 rl_initialize();
1802
1803 /* XXX - int -> char conversion can lose on multichars */
1804 arr[0] = c;
1805 arr[1] = '\0';
1806
1807 for (; count > 0; count--)
1808 el_push(e, arr);
1809
1810 return (0);
1811 }
1812
1813 /*ARGSUSED*/
1814 int
1815 rl_newline(int count, int c)
1816 {
1817 /*
1818 * Readline-4.0 appears to ignore the args.
1819 */
1820 return rl_insert(1, '\n');
1821 }
1822
1823 /*ARGSUSED*/
1824 static unsigned char
1825 rl_bind_wrapper(EditLine *el, unsigned char c)
1826 {
1827 if (map[c] == NULL)
1828 return CC_ERROR;
1829 (*map[c])(NULL, c);
1830 return CC_NORM;
1831 }
1832
1833 int
1834 rl_add_defun(const char *name, Function *fun, int c)
1835 {
1836 char dest[8];
1837 if (c >= sizeof(map) / sizeof(map[0]) || c < 0)
1838 return -1;
1839 map[(unsigned char)c] = fun;
1840 el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
1841 vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
1842 el_set(e, EL_BIND, dest, name);
1843 return 0;
1844 }
1845
1846 void
1847 rl_callback_read_char()
1848 {
1849 int count = 0, done = 0;
1850 const char *buf = el_gets(e, &count);
1851 char *wbuf;
1852
1853 if (buf == NULL || count-- <= 0)
1854 return;
1855 if (count == 0 && buf[0] == CTRL('d'))
1856 done = 1;
1857 if (buf[count] == '\n' || buf[count] == '\r')
1858 done = 2;
1859
1860 if (done && rl_linefunc != NULL) {
1861 el_set(e, EL_UNBUFFERED, 0);
1862 if (done == 2) {
1863 if ((wbuf = strdup(buf)) != NULL)
1864 wbuf[count] = '\0';
1865 } else
1866 wbuf = NULL;
1867 (*(void (*)(const char *))rl_linefunc)(wbuf);
1868 }
1869 }
1870
1871 void
1872 rl_callback_handler_install (const char *prompt, VFunction *linefunc)
1873 {
1874 if (e == NULL) {
1875 rl_initialize();
1876 }
1877 if (rl_prompt)
1878 free(rl_prompt);
1879 rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL;
1880 rl_linefunc = linefunc;
1881 el_set(e, EL_UNBUFFERED, 1);
1882 }
1883
1884 void
1885 rl_callback_handler_remove(void)
1886 {
1887 el_set(e, EL_UNBUFFERED, 0);
1888 }
1889
1890 void
1891 rl_redisplay(void)
1892 {
1893 char a[2];
1894 a[0] = CTRL('r');
1895 a[1] = '\0';
1896 el_push(e, a);
1897 }
1898
1899 int
1900 rl_get_previous_history(int count, int key)
1901 {
1902 char a[2];
1903 a[0] = key;
1904 a[1] = '\0';
1905 while (count--)
1906 el_push(e, a);
1907 return 0;
1908 }
1909