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