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