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