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