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