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