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