Annotation of src/lib/libedit/readline.c, Revision 1.136.2.2
1.136.2.2! pgoyette 1: /* $NetBSD: readline.c,v 1.140 2017/01/09 03:09:05 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.136.2.2! pgoyette 34: __RCSID("$NetBSD: readline.c,v 1.140 2017/01/09 03:09:05 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.136.2.1 pgoyette 225: i = (*rl_getc_function)(rl_instream);
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)
1.136.2.2! pgoyette 586: num = history_length - num + history_base;
1.40 christos 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.136 christos 1188: if (history_length > max)
1189: history_base = history_length - max;
1.135 christos 1190: while (history_length > max) {
1.134 christos 1191: he = remove_history(0);
1.130 christos 1192: el_free(he->data);
1193: el_free((void *)(unsigned long)he->line);
1194: el_free(he);
1195: }
1196: }
1.1 christos 1197: }
1198:
1.11 lukem 1199:
1.1 christos 1200: /*
1201: * "unlimit" size of history - set the limit to maximum allowed int value
1202: */
1203: int
1.11 lukem 1204: unstifle_history(void)
1.1 christos 1205: {
1.92 christos 1206: HistEvent ev;
1.1 christos 1207: int omax;
1208:
1.92 christos 1209: history(h, &ev, H_SETSIZE, INT_MAX);
1.1 christos 1210: omax = max_input_history;
1211: max_input_history = INT_MAX;
1.96 christos 1212: return omax; /* some value _must_ be returned */
1.1 christos 1213: }
1214:
1.11 lukem 1215:
1.1 christos 1216: int
1.11 lukem 1217: history_is_stifled(void)
1.1 christos 1218: {
1.11 lukem 1219:
1.1 christos 1220: /* cannot return true answer */
1.96 christos 1221: return max_input_history != INT_MAX;
1.1 christos 1222: }
1223:
1.85 christos 1224: static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
1225:
1226: int
1227: history_truncate_file (const char *filename, int nlines)
1228: {
1229: int ret = 0;
1230: FILE *fp, *tp;
1231: char template[sizeof(_history_tmp_template)];
1232: char buf[4096];
1233: int fd;
1234: char *cp;
1235: off_t off;
1236: int count = 0;
1237: ssize_t left = 0;
1238:
1239: if (filename == NULL && (filename = _default_history_file()) == NULL)
1240: return errno;
1241: if ((fp = fopen(filename, "r+")) == NULL)
1242: return errno;
1243: strcpy(template, _history_tmp_template);
1244: if ((fd = mkstemp(template)) == -1) {
1245: ret = errno;
1246: goto out1;
1247: }
1248:
1249: if ((tp = fdopen(fd, "r+")) == NULL) {
1250: close(fd);
1251: ret = errno;
1252: goto out2;
1253: }
1254:
1255: for(;;) {
1.98 christos 1256: if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) {
1.85 christos 1257: if (ferror(fp)) {
1258: ret = errno;
1259: break;
1260: }
1261: if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
1262: (off_t)-1) {
1263: ret = errno;
1264: break;
1265: }
1.99 christos 1266: left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp);
1.85 christos 1267: if (ferror(fp)) {
1268: ret = errno;
1269: break;
1270: }
1271: if (left == 0) {
1272: count--;
1273: left = sizeof(buf);
1.98 christos 1274: } else if (fwrite(buf, (size_t)left, (size_t)1, tp)
1275: != 1) {
1.85 christos 1276: ret = errno;
1277: break;
1278: }
1279: fflush(tp);
1280: break;
1281: }
1.98 christos 1282: if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) {
1.85 christos 1283: ret = errno;
1284: break;
1285: }
1286: count++;
1287: }
1288: if (ret)
1289: goto out3;
1290: cp = buf + left - 1;
1291: if(*cp != '\n')
1292: cp++;
1293: for(;;) {
1294: while (--cp >= buf) {
1295: if (*cp == '\n') {
1296: if (--nlines == 0) {
1297: if (++cp >= buf + sizeof(buf)) {
1298: count++;
1299: cp = buf;
1300: }
1301: break;
1302: }
1303: }
1304: }
1305: if (nlines <= 0 || count == 0)
1306: break;
1307: count--;
1308: if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
1309: ret = errno;
1310: break;
1311: }
1.98 christos 1312: if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) {
1.85 christos 1313: if (ferror(tp)) {
1314: ret = errno;
1315: break;
1316: }
1317: ret = EAGAIN;
1318: break;
1319: }
1320: cp = buf + sizeof(buf);
1321: }
1322:
1323: if (ret || nlines > 0)
1324: goto out3;
1325:
1.98 christos 1326: if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
1.85 christos 1327: ret = errno;
1328: goto out3;
1329: }
1330:
1331: if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
1332: (off_t)-1) {
1333: ret = errno;
1334: goto out3;
1335: }
1336:
1337: for(;;) {
1.99 christos 1338: if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) {
1.85 christos 1339: if (ferror(fp))
1340: ret = errno;
1341: break;
1342: }
1.98 christos 1343: if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) {
1.85 christos 1344: ret = errno;
1345: break;
1346: }
1347: }
1348: fflush(fp);
1349: if((off = ftello(fp)) > 0)
1350: (void)ftruncate(fileno(fp), off);
1351: out3:
1352: fclose(tp);
1353: out2:
1354: unlink(template);
1355: out1:
1356: fclose(fp);
1357:
1358: return ret;
1359: }
1360:
1.11 lukem 1361:
1.1 christos 1362: /*
1363: * read history from a file given
1364: */
1365: int
1.11 lukem 1366: read_history(const char *filename)
1.1 christos 1367: {
1.92 christos 1368: HistEvent ev;
1.1 christos 1369:
1370: if (h == NULL || e == NULL)
1371: rl_initialize();
1.85 christos 1372: if (filename == NULL && (filename = _default_history_file()) == NULL)
1373: return errno;
1.96 christos 1374: return history(h, &ev, H_LOAD, filename) == -1 ?
1375: (errno ? errno : EINVAL) : 0;
1.1 christos 1376: }
1377:
1.11 lukem 1378:
1.1 christos 1379: /*
1380: * write history to a file given
1381: */
1382: int
1.11 lukem 1383: write_history(const char *filename)
1.1 christos 1384: {
1.92 christos 1385: HistEvent ev;
1.1 christos 1386:
1387: if (h == NULL || e == NULL)
1388: rl_initialize();
1.85 christos 1389: if (filename == NULL && (filename = _default_history_file()) == NULL)
1390: return errno;
1.96 christos 1391: return history(h, &ev, H_SAVE, filename) == -1 ?
1392: (errno ? errno : EINVAL) : 0;
1.1 christos 1393: }
1394:
1.11 lukem 1395:
1.1 christos 1396: /*
1397: * returns history ``num''th event
1398: *
1399: * returned pointer points to static variable
1400: */
1.2 christos 1401: HIST_ENTRY *
1.11 lukem 1402: history_get(int num)
1.1 christos 1403: {
1404: static HIST_ENTRY she;
1.92 christos 1405: HistEvent ev;
1.40 christos 1406: int curr_num;
1.1 christos 1407:
1408: if (h == NULL || e == NULL)
1409: rl_initialize();
1410:
1.131 christos 1411: if (num < history_base)
1412: return NULL;
1413:
1.40 christos 1414: /* save current position */
1.92 christos 1415: if (history(h, &ev, H_CURR) != 0)
1.96 christos 1416: return NULL;
1.1 christos 1417: curr_num = ev.num;
1.40 christos 1418:
1.131 christos 1419: /*
1420: * use H_DELDATA to set to nth history (without delete) by passing
1421: * (void **)-1 -- as in history_set_pos
1422: */
1423: if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0)
1424: goto out;
1.1 christos 1425:
1.131 christos 1426: /* get current entry */
1427: if (history(h, &ev, H_CURR) != 0)
1428: goto out;
1429: if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0)
1430: goto out;
1.92 christos 1431: she.line = ev.str;
1.1 christos 1432:
1.40 christos 1433: /* restore pointer to where it was */
1.92 christos 1434: (void)history(h, &ev, H_SET, curr_num);
1.1 christos 1435:
1.96 christos 1436: return &she;
1.131 christos 1437:
1438: out:
1439: /* restore pointer to where it was */
1440: (void)history(h, &ev, H_SET, curr_num);
1441: return NULL;
1.1 christos 1442: }
1443:
1.11 lukem 1444:
1.1 christos 1445: /*
1446: * add the line to history table
1447: */
1448: int
1.11 lukem 1449: add_history(const char *line)
1.1 christos 1450: {
1.92 christos 1451: HistEvent ev;
1.1 christos 1452:
1453: if (h == NULL || e == NULL)
1454: rl_initialize();
1455:
1.135 christos 1456: if (history(h, &ev, H_ENTER, line) == -1)
1457: return 0;
1458:
1459: (void)history(h, &ev, H_GETSIZE);
1460: if (ev.num == history_length)
1461: history_base++;
1462: else
1.1 christos 1463: history_length = ev.num;
1.132 christos 1464: current_history_valid = 1;
1.135 christos 1465: return 0;
1.1 christos 1466: }
1467:
1.11 lukem 1468:
1.1 christos 1469: /*
1.58 christos 1470: * remove the specified entry from the history list and return it.
1471: */
1472: HIST_ENTRY *
1473: remove_history(int num)
1474: {
1.85 christos 1475: HIST_ENTRY *he;
1.92 christos 1476: HistEvent ev;
1.58 christos 1477:
1478: if (h == NULL || e == NULL)
1479: rl_initialize();
1480:
1.95 christos 1481: if ((he = el_malloc(sizeof(*he))) == NULL)
1.58 christos 1482: return NULL;
1483:
1.92 christos 1484: if (history(h, &ev, H_DELDATA, num, &he->data) != 0) {
1.95 christos 1485: el_free(he);
1.71 christos 1486: return NULL;
1.85 christos 1487: }
1.71 christos 1488:
1.92 christos 1489: he->line = ev.str;
1490: if (history(h, &ev, H_GETSIZE) == 0)
1.85 christos 1491: history_length = ev.num;
1.58 christos 1492:
1.85 christos 1493: return he;
1.58 christos 1494: }
1495:
1496:
1497: /*
1.85 christos 1498: * replace the line and data of the num-th entry
1499: */
1500: HIST_ENTRY *
1501: replace_history_entry(int num, const char *line, histdata_t data)
1502: {
1503: HIST_ENTRY *he;
1.92 christos 1504: HistEvent ev;
1.85 christos 1505: int curr_num;
1506:
1507: if (h == NULL || e == NULL)
1508: rl_initialize();
1509:
1510: /* save current position */
1.92 christos 1511: if (history(h, &ev, H_CURR) != 0)
1.85 christos 1512: return NULL;
1513: curr_num = ev.num;
1514:
1515: /* start from the oldest */
1.92 christos 1516: if (history(h, &ev, H_LAST) != 0)
1.85 christos 1517: return NULL; /* error */
1518:
1.95 christos 1519: if ((he = el_malloc(sizeof(*he))) == NULL)
1.85 christos 1520: return NULL;
1521:
1522: /* look forwards for event matching specified offset */
1.92 christos 1523: if (history(h, &ev, H_NEXT_EVDATA, num, &he->data))
1.85 christos 1524: goto out;
1525:
1.92 christos 1526: he->line = strdup(ev.str);
1.85 christos 1527: if (he->line == NULL)
1528: goto out;
1529:
1.92 christos 1530: if (history(h, &ev, H_REPLACE, line, data))
1.85 christos 1531: goto out;
1532:
1533: /* restore pointer to where it was */
1.92 christos 1534: if (history(h, &ev, H_SET, curr_num))
1.85 christos 1535: goto out;
1536:
1537: return he;
1538: out:
1.95 christos 1539: el_free(he);
1.85 christos 1540: return NULL;
1541: }
1542:
1543: /*
1.1 christos 1544: * clear the history list - delete all entries
1545: */
1546: void
1.11 lukem 1547: clear_history(void)
1.1 christos 1548: {
1.92 christos 1549: HistEvent ev;
1.11 lukem 1550:
1.110 christos 1551: if (h == NULL || e == NULL)
1552: rl_initialize();
1553:
1.92 christos 1554: (void)history(h, &ev, H_CLEAR);
1.85 christos 1555: history_length = 0;
1.132 christos 1556: current_history_valid = 1;
1.1 christos 1557: }
1558:
1.11 lukem 1559:
1.1 christos 1560: /*
1561: * returns offset of the current history event
1562: */
1563: int
1.11 lukem 1564: where_history(void)
1.1 christos 1565: {
1.92 christos 1566: HistEvent ev;
1.1 christos 1567: int curr_num, off;
1568:
1.92 christos 1569: if (history(h, &ev, H_CURR) != 0)
1.96 christos 1570: return 0;
1.1 christos 1571: curr_num = ev.num;
1572:
1.133 christos 1573: /* start from the oldest */
1574: (void)history(h, &ev, H_LAST);
1575:
1576: /* position is zero-based */
1577: off = 0;
1578: while (ev.num != curr_num && history(h, &ev, H_PREV) == 0)
1.1 christos 1579: off++;
1580:
1.96 christos 1581: return off;
1.1 christos 1582: }
1583:
1.11 lukem 1584:
1.1 christos 1585: /*
1586: * returns current history event or NULL if there is no such event
1587: */
1.2 christos 1588: HIST_ENTRY *
1.11 lukem 1589: current_history(void)
1.1 christos 1590: {
1.11 lukem 1591:
1.132 christos 1592: return current_history_valid ? _move_history(H_CURR) : NULL;
1.1 christos 1593: }
1594:
1.11 lukem 1595:
1.1 christos 1596: /*
1597: * returns total number of bytes history events' data are using
1598: */
1599: int
1.11 lukem 1600: history_total_bytes(void)
1.1 christos 1601: {
1.92 christos 1602: HistEvent ev;
1.80 christos 1603: int curr_num;
1604: size_t size;
1.1 christos 1605:
1.92 christos 1606: if (history(h, &ev, H_CURR) != 0)
1.96 christos 1607: return -1;
1.1 christos 1608: curr_num = ev.num;
1609:
1.92 christos 1610: (void)history(h, &ev, H_FIRST);
1.1 christos 1611: size = 0;
1612: do
1.92 christos 1613: size += strlen(ev.str) * sizeof(*ev.str);
1614: while (history(h, &ev, H_NEXT) == 0);
1.1 christos 1615:
1616: /* get to the same position as before */
1.92 christos 1617: history(h, &ev, H_PREV_EVENT, curr_num);
1.1 christos 1618:
1.96 christos 1619: return (int)size;
1.1 christos 1620: }
1621:
1.11 lukem 1622:
1.1 christos 1623: /*
1624: * sets the position in the history list to ``pos''
1625: */
1626: int
1.11 lukem 1627: history_set_pos(int pos)
1.1 christos 1628: {
1.92 christos 1629: HistEvent ev;
1.40 christos 1630: int curr_num;
1.1 christos 1631:
1.85 christos 1632: if (pos >= history_length || pos < 0)
1.129 christos 1633: return 0;
1.1 christos 1634:
1.92 christos 1635: (void)history(h, &ev, H_CURR);
1.1 christos 1636: curr_num = ev.num;
1.132 christos 1637: current_history_valid = 1;
1.1 christos 1638:
1.85 christos 1639: /*
1640: * use H_DELDATA to set to nth history (without delete) by passing
1641: * (void **)-1
1642: */
1.92 christos 1643: if (history(h, &ev, H_DELDATA, pos, (void **)-1)) {
1644: (void)history(h, &ev, H_SET, curr_num);
1.129 christos 1645: return 0;
1.1 christos 1646: }
1.129 christos 1647: return 1;
1.1 christos 1648: }
1649:
1.11 lukem 1650:
1.1 christos 1651: /*
1652: * returns previous event in history and shifts pointer accordingly
1.132 christos 1653: * Note that readline and editline define directions in opposite ways.
1.1 christos 1654: */
1.2 christos 1655: HIST_ENTRY *
1.11 lukem 1656: previous_history(void)
1.1 christos 1657: {
1.11 lukem 1658:
1.132 christos 1659: if (current_history_valid == 0) {
1660: current_history_valid = 1;
1661: return _move_history(H_CURR);
1662: }
1663: return _move_history(H_NEXT);
1.1 christos 1664: }
1665:
1.11 lukem 1666:
1.1 christos 1667: /*
1668: * returns next event in history and shifts pointer accordingly
1669: */
1.2 christos 1670: HIST_ENTRY *
1.11 lukem 1671: next_history(void)
1.1 christos 1672: {
1.132 christos 1673: HIST_ENTRY *he;
1.11 lukem 1674:
1.132 christos 1675: he = _move_history(H_PREV);
1676: if (he == NULL)
1677: current_history_valid = 0;
1678: return he;
1.1 christos 1679: }
1680:
1.11 lukem 1681:
1.1 christos 1682: /*
1.40 christos 1683: * searches for first history event containing the str
1.1 christos 1684: */
1.40 christos 1685: int
1686: history_search(const char *str, int direction)
1.11 lukem 1687: {
1.92 christos 1688: HistEvent ev;
1689: const char *strp;
1.11 lukem 1690: int curr_num;
1.1 christos 1691:
1.92 christos 1692: if (history(h, &ev, H_CURR) != 0)
1.96 christos 1693: return -1;
1.1 christos 1694: curr_num = ev.num;
1695:
1696: for (;;) {
1.92 christos 1697: if ((strp = strstr(ev.str, str)) != NULL)
1.96 christos 1698: return (int)(strp - ev.str);
1.92 christos 1699: if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
1.1 christos 1700: break;
1701: }
1.92 christos 1702: (void)history(h, &ev, H_SET, curr_num);
1.96 christos 1703: return -1;
1.1 christos 1704: }
1705:
1.11 lukem 1706:
1.1 christos 1707: /*
1708: * searches for first history event beginning with str
1709: */
1710: int
1.11 lukem 1711: history_search_prefix(const char *str, int direction)
1.1 christos 1712: {
1.92 christos 1713: HistEvent ev;
1.11 lukem 1714:
1.92 christos 1715: return (history(h, &ev, direction < 0 ?
1.88 christos 1716: H_PREV_STR : H_NEXT_STR, str));
1.1 christos 1717: }
1718:
1.11 lukem 1719:
1.1 christos 1720: /*
1721: * search for event in history containing str, starting at offset
1722: * abs(pos); continue backward, if pos<0, forward otherwise
1723: */
1.5 christos 1724: /* ARGSUSED */
1.1 christos 1725: int
1.40 christos 1726: history_search_pos(const char *str,
1.30 christos 1727: int direction __attribute__((__unused__)), int pos)
1.1 christos 1728: {
1.92 christos 1729: HistEvent ev;
1.11 lukem 1730: int curr_num, off;
1.1 christos 1731:
1732: off = (pos > 0) ? pos : -pos;
1733: pos = (pos > 0) ? 1 : -1;
1734:
1.92 christos 1735: if (history(h, &ev, H_CURR) != 0)
1.96 christos 1736: return -1;
1.1 christos 1737: curr_num = ev.num;
1738:
1.129 christos 1739: if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0)
1.96 christos 1740: return -1;
1.1 christos 1741:
1742: for (;;) {
1.92 christos 1743: if (strstr(ev.str, str))
1.96 christos 1744: return off;
1.92 christos 1745: if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
1.1 christos 1746: break;
1747: }
1748:
1749: /* set "current" pointer back to previous state */
1.92 christos 1750: (void)history(h, &ev,
1.88 christos 1751: pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
1.1 christos 1752:
1.96 christos 1753: return -1;
1.1 christos 1754: }
1755:
1756:
1757: /********************************/
1.40 christos 1758: /* completion functions */
1.1 christos 1759:
1.57 christos 1760: char *
1761: tilde_expand(char *name)
1762: {
1763: return fn_tilde_expand(name);
1764: }
1765:
1766: char *
1767: filename_completion_function(const char *name, int state)
1768: {
1769: return fn_filename_completion_function(name, state);
1770: }
1771:
1.1 christos 1772: /*
1773: * a completion generator for usernames; returns _first_ username
1774: * which starts with supplied text
1775: * text contains a partial username preceded by random character
1.94 christos 1776: * (usually '~'); state resets search from start (??? should we do that anyway)
1.113 snj 1777: * it's the caller's responsibility to free the returned value
1.1 christos 1778: */
1.11 lukem 1779: char *
1780: username_completion_function(const char *text, int state)
1.1 christos 1781: {
1.94 christos 1782: #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1783: struct passwd pwres;
1.50 christos 1784: char pwbuf[1024];
1.94 christos 1785: #endif
1786: struct passwd *pass = NULL;
1.1 christos 1787:
1788: if (text[0] == '\0')
1.96 christos 1789: return NULL;
1.1 christos 1790:
1791: if (*text == '~')
1792: text++;
1793:
1794: if (state == 0)
1795: setpwent();
1796:
1.94 christos 1797: while (
1798: #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1799: getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL
1800: #else
1801: (pass = getpwent()) != NULL
1802: #endif
1803: && text[0] == pass->pw_name[0]
1804: && strcmp(text, pass->pw_name) == 0)
1805: continue;
1.1 christos 1806:
1.94 christos 1807: if (pass == NULL) {
1.1 christos 1808: endpwent();
1.85 christos 1809: return NULL;
1.1 christos 1810: }
1.94 christos 1811: return strdup(pass->pw_name);
1.1 christos 1812: }
1813:
1.11 lukem 1814:
1.1 christos 1815: /*
1.46 christos 1816: * el-compatible wrapper to send TSTP on ^Z
1817: */
1818: /* ARGSUSED */
1819: static unsigned char
1820: _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
1821: {
1822: (void)kill(0, SIGTSTP);
1823: return CC_NORM;
1824: }
1.11 lukem 1825:
1.1 christos 1826: /*
1.12 jdolecek 1827: * Display list of strings in columnar format on readline's output stream.
1828: * 'matches' is list of strings, 'len' is number of strings in 'matches',
1829: * 'max' is maximum length of string in 'matches'.
1830: */
1831: void
1.53 dsl 1832: rl_display_match_list(char **matches, int len, int max)
1.12 jdolecek 1833: {
1834:
1.81 christos 1835: fn_display_match_list(e, matches, (size_t)len, (size_t)max);
1.1 christos 1836: }
1837:
1.56 christos 1838: static const char *
1839: /*ARGSUSED*/
1840: _rl_completion_append_character_function(const char *dummy
1841: __attribute__((__unused__)))
1842: {
1843: static char buf[2];
1.99 christos 1844: buf[0] = (char)rl_completion_append_character;
1.76 christos 1845: buf[1] = '\0';
1.56 christos 1846: return buf;
1847: }
1848:
1.11 lukem 1849:
1.1 christos 1850: /*
1851: * complete word at current point
1852: */
1.53 dsl 1853: /* ARGSUSED */
1.1 christos 1854: int
1.53 dsl 1855: rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
1.1 christos 1856: {
1.86 christos 1857: static ct_buffer_t wbreak_conv, sprefix_conv;
1.102 christos 1858: char *breakchars;
1.86 christos 1859:
1.1 christos 1860: if (h == NULL || e == NULL)
1861: rl_initialize();
1862:
1863: if (rl_inhibit_completion) {
1.47 christos 1864: char arr[2];
1865: arr[0] = (char)invoking_key;
1866: arr[1] = '\0';
1867: el_insertstr(e, arr);
1.96 christos 1868: return CC_REFRESH;
1.53 dsl 1869: }
1870:
1.102 christos 1871: if (rl_completion_word_break_hook != NULL)
1872: breakchars = (*rl_completion_word_break_hook)();
1873: else
1874: breakchars = rl_basic_word_break_characters;
1875:
1.116 christos 1876: _rl_update_pos();
1877:
1.53 dsl 1878: /* Just look at how many global variables modify this operation! */
1879: return fn_complete(e,
1.117 christos 1880: (rl_compentry_func_t *)rl_completion_entry_function,
1.53 dsl 1881: rl_attempted_completion_function,
1.86 christos 1882: ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
1.102 christos 1883: ct_decode_string(breakchars, &sprefix_conv),
1.81 christos 1884: _rl_completion_append_character_function,
1885: (size_t)rl_completion_query_items,
1.53 dsl 1886: &rl_completion_type, &rl_attempted_completion_over,
1887: &rl_point, &rl_end);
1.92 christos 1888:
1889:
1.1 christos 1890: }
1891:
1.11 lukem 1892:
1.53 dsl 1893: /* ARGSUSED */
1894: static unsigned char
1895: _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
1896: {
1897: return (unsigned char)rl_complete(0, ch);
1898: }
1899:
1.1 christos 1900: /*
1.7 simonb 1901: * misc other functions
1.1 christos 1902: */
1903:
1904: /*
1905: * bind key c to readline-type function func
1906: */
1907: int
1.85 christos 1908: rl_bind_key(int c, rl_command_func_t *func)
1.1 christos 1909: {
1.11 lukem 1910: int retval = -1;
1.1 christos 1911:
1912: if (h == NULL || e == NULL)
1913: rl_initialize();
1914:
1915: if (func == rl_insert) {
1916: /* XXX notice there is no range checking of ``c'' */
1917: e->el_map.key[c] = ED_INSERT;
1918: retval = 0;
1919: }
1.96 christos 1920: return retval;
1.1 christos 1921: }
1922:
1.11 lukem 1923:
1.1 christos 1924: /*
1925: * read one key from input - handles chars pushed back
1926: * to input stream also
1927: */
1928: int
1.11 lukem 1929: rl_read_key(void)
1.1 christos 1930: {
1.11 lukem 1931: char fooarr[2 * sizeof(int)];
1.1 christos 1932:
1933: if (e == NULL || h == NULL)
1934: rl_initialize();
1935:
1.96 christos 1936: return el_getc(e, fooarr);
1.1 christos 1937: }
1938:
1.11 lukem 1939:
1.1 christos 1940: /*
1941: * reset the terminal
1942: */
1.5 christos 1943: /* ARGSUSED */
1.1 christos 1944: void
1.30 christos 1945: rl_reset_terminal(const char *p __attribute__((__unused__)))
1.1 christos 1946: {
1.11 lukem 1947:
1.1 christos 1948: if (h == NULL || e == NULL)
1949: rl_initialize();
1950: el_reset(e);
1951: }
1952:
1.11 lukem 1953:
1.1 christos 1954: /*
1955: * insert character ``c'' back into input stream, ``count'' times
1956: */
1957: int
1.11 lukem 1958: rl_insert(int count, int c)
1.1 christos 1959: {
1.11 lukem 1960: char arr[2];
1.1 christos 1961:
1962: if (h == NULL || e == NULL)
1963: rl_initialize();
1964:
1965: /* XXX - int -> char conversion can lose on multichars */
1.99 christos 1966: arr[0] = (char)c;
1.1 christos 1967: arr[1] = '\0';
1968:
1969: for (; count > 0; count--)
1970: el_push(e, arr);
1971:
1.96 christos 1972: return 0;
1.35 christos 1973: }
1974:
1.85 christos 1975: int
1976: rl_insert_text(const char *text)
1977: {
1978: if (!text || *text == 0)
1.96 christos 1979: return 0;
1.85 christos 1980:
1981: if (h == NULL || e == NULL)
1982: rl_initialize();
1983:
1984: if (el_insertstr(e, text) < 0)
1.96 christos 1985: return 0;
1.85 christos 1986: return (int)strlen(text);
1987: }
1988:
1.35 christos 1989: /*ARGSUSED*/
1990: int
1.97 christos 1991: rl_newline(int count __attribute__((__unused__)),
1992: int c __attribute__((__unused__)))
1.35 christos 1993: {
1994: /*
1995: * Readline-4.0 appears to ignore the args.
1996: */
1997: return rl_insert(1, '\n');
1998: }
1999:
2000: /*ARGSUSED*/
2001: static unsigned char
1.97 christos 2002: rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c)
1.35 christos 2003: {
2004: if (map[c] == NULL)
2005: return CC_ERROR;
1.49 christos 2006:
2007: _rl_update_pos();
2008:
1.116 christos 2009: (*map[c])(1, c);
1.38 christos 2010:
2011: /* If rl_done was set by the above call, deal with it here */
2012: if (rl_done)
2013: return CC_EOF;
2014:
1.35 christos 2015: return CC_NORM;
2016: }
2017:
2018: int
1.116 christos 2019: rl_add_defun(const char *name, rl_command_func_t *fun, int c)
1.35 christos 2020: {
2021: char dest[8];
1.77 lukem 2022: if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
1.35 christos 2023: return -1;
2024: map[(unsigned char)c] = fun;
2025: el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
1.37 christos 2026: vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
1.106 christos 2027: el_set(e, EL_BIND, dest, name, NULL);
1.35 christos 2028: return 0;
2029: }
2030:
2031: void
1.101 matt 2032: rl_callback_read_char(void)
1.35 christos 2033: {
1.36 christos 2034: int count = 0, done = 0;
1.35 christos 2035: const char *buf = el_gets(e, &count);
2036: char *wbuf;
2037:
2038: if (buf == NULL || count-- <= 0)
2039: return;
1.61 christos 2040: if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
1.36 christos 2041: done = 1;
2042: if (buf[count] == '\n' || buf[count] == '\r')
2043: done = 2;
2044:
2045: if (done && rl_linefunc != NULL) {
1.35 christos 2046: el_set(e, EL_UNBUFFERED, 0);
1.36 christos 2047: if (done == 2) {
2048: if ((wbuf = strdup(buf)) != NULL)
2049: wbuf[count] = '\0';
2050: } else
2051: wbuf = NULL;
1.35 christos 2052: (*(void (*)(const char *))rl_linefunc)(wbuf);
1.111 christos 2053: el_set(e, EL_UNBUFFERED, 1);
1.35 christos 2054: }
2055: }
2056:
1.125 christos 2057: void
1.117 christos 2058: rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc)
1.35 christos 2059: {
2060: if (e == NULL) {
2061: rl_initialize();
2062: }
1.78 christos 2063: (void)rl_set_prompt(prompt);
1.35 christos 2064: rl_linefunc = linefunc;
2065: el_set(e, EL_UNBUFFERED, 1);
1.125 christos 2066: }
1.35 christos 2067:
1.125 christos 2068: void
1.35 christos 2069: rl_callback_handler_remove(void)
2070: {
2071: el_set(e, EL_UNBUFFERED, 0);
1.72 christos 2072: rl_linefunc = NULL;
1.35 christos 2073: }
2074:
2075: void
2076: rl_redisplay(void)
2077: {
2078: char a[2];
1.99 christos 2079: a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT];
1.35 christos 2080: a[1] = '\0';
2081: el_push(e, a);
2082: }
2083:
2084: int
2085: rl_get_previous_history(int count, int key)
2086: {
2087: char a[2];
1.99 christos 2088: a[0] = (char)key;
1.35 christos 2089: a[1] = '\0';
2090: while (count--)
2091: el_push(e, a);
2092: return 0;
1.38 christos 2093: }
2094:
2095: void
2096: /*ARGSUSED*/
1.97 christos 2097: rl_prep_terminal(int meta_flag __attribute__((__unused__)))
1.38 christos 2098: {
2099: el_set(e, EL_PREP_TERM, 1);
2100: }
2101:
2102: void
1.68 christos 2103: rl_deprep_terminal(void)
1.38 christos 2104: {
2105: el_set(e, EL_PREP_TERM, 0);
2106: }
2107:
2108: int
2109: rl_read_init_file(const char *s)
2110: {
1.96 christos 2111: return el_source(e, s);
1.38 christos 2112: }
2113:
2114: int
2115: rl_parse_and_bind(const char *line)
2116: {
2117: const char **argv;
2118: int argc;
2119: Tokenizer *tok;
2120:
2121: tok = tok_init(NULL);
1.44 lukem 2122: tok_str(tok, line, &argc, &argv);
1.38 christos 2123: argc = el_parse(e, argc, argv);
2124: tok_end(tok);
1.96 christos 2125: return argc ? 1 : 0;
1.38 christos 2126: }
2127:
1.51 christos 2128: int
2129: rl_variable_bind(const char *var, const char *value)
2130: {
2131: /*
2132: * The proper return value is undocument, but this is what the
2133: * readline source seems to do.
2134: */
1.106 christos 2135: return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0;
1.51 christos 2136: }
2137:
1.38 christos 2138: void
2139: rl_stuff_char(int c)
2140: {
2141: char buf[2];
2142:
1.99 christos 2143: buf[0] = (char)c;
1.38 christos 2144: buf[1] = '\0';
2145: el_insertstr(e, buf);
2146: }
2147:
2148: static int
1.126 christos 2149: _rl_event_read_char(EditLine *el, wchar_t *wc)
1.38 christos 2150: {
1.126 christos 2151: char ch;
1.80 christos 2152: int n;
2153: ssize_t num_read = 0;
1.38 christos 2154:
1.126 christos 2155: ch = '\0';
2156: *wc = L'\0';
1.38 christos 2157: while (rl_event_hook) {
2158:
2159: (*rl_event_hook)();
2160:
2161: #if defined(FIONREAD)
2162: if (ioctl(el->el_infd, FIONREAD, &n) < 0)
1.96 christos 2163: return -1;
1.38 christos 2164: if (n)
1.126 christos 2165: num_read = read(el->el_infd, &ch, (size_t)1);
1.38 christos 2166: else
2167: num_read = 0;
2168: #elif defined(F_SETFL) && defined(O_NDELAY)
2169: if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
1.96 christos 2170: return -1;
1.38 christos 2171: if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
1.96 christos 2172: return -1;
1.126 christos 2173: num_read = read(el->el_infd, &ch, 1);
1.38 christos 2174: if (fcntl(el->el_infd, F_SETFL, n))
1.96 christos 2175: return -1;
1.38 christos 2176: #else
2177: /* not non-blocking, but what you gonna do? */
1.126 christos 2178: num_read = read(el->el_infd, &ch, 1);
1.96 christos 2179: return -1;
1.38 christos 2180: #endif
2181:
2182: if (num_read < 0 && errno == EAGAIN)
2183: continue;
2184: if (num_read == 0)
2185: continue;
2186: break;
2187: }
2188: if (!rl_event_hook)
2189: el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
1.126 christos 2190: *wc = (wchar_t)ch;
1.80 christos 2191: return (int)num_read;
1.1 christos 2192: }
1.49 christos 2193:
2194: static void
2195: _rl_update_pos(void)
2196: {
2197: const LineInfo *li = el_line(e);
2198:
1.80 christos 2199: rl_point = (int)(li->cursor - li->buffer);
2200: rl_end = (int)(li->lastchar - li->buffer);
1.49 christos 2201: }
1.70 christos 2202:
2203: void
2204: rl_get_screen_size(int *rows, int *cols)
2205: {
2206: if (rows)
1.107 christos 2207: el_get(e, EL_GETTC, "li", rows, (void *)0);
1.70 christos 2208: if (cols)
1.107 christos 2209: el_get(e, EL_GETTC, "co", cols, (void *)0);
1.70 christos 2210: }
2211:
2212: void
2213: rl_set_screen_size(int rows, int cols)
2214: {
2215: char buf[64];
2216: (void)snprintf(buf, sizeof(buf), "%d", rows);
1.106 christos 2217: el_set(e, EL_SETTC, "li", buf, NULL);
1.70 christos 2218: (void)snprintf(buf, sizeof(buf), "%d", cols);
1.106 christos 2219: el_set(e, EL_SETTC, "co", buf, NULL);
1.70 christos 2220: }
2221:
1.71 christos 2222: char **
2223: rl_completion_matches(const char *str, rl_compentry_func_t *fun)
2224: {
2225: size_t len, max, i, j, min;
2226: char **list, *match, *a, *b;
2227:
2228: len = 1;
2229: max = 10;
1.95 christos 2230: if ((list = el_malloc(max * sizeof(*list))) == NULL)
1.71 christos 2231: return NULL;
2232:
2233: while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
1.83 christos 2234: list[len++] = match;
1.71 christos 2235: if (len == max) {
2236: char **nl;
2237: max += 10;
1.95 christos 2238: if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL)
1.71 christos 2239: goto out;
2240: list = nl;
2241: }
2242: }
2243: if (len == 1)
2244: goto out;
2245: list[len] = NULL;
2246: if (len == 2) {
2247: if ((list[0] = strdup(list[1])) == NULL)
2248: goto out;
2249: return list;
2250: }
2251: qsort(&list[1], len - 1, sizeof(*list),
2252: (int (*)(const void *, const void *)) strcmp);
1.119 christos 2253: min = SIZE_MAX;
1.71 christos 2254: for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
2255: b = list[i + 1];
2256: for (j = 0; a[j] && a[j] == b[j]; j++)
2257: continue;
2258: if (min > j)
2259: min = j;
2260: }
2261: if (min == 0 && *str) {
2262: if ((list[0] = strdup(str)) == NULL)
2263: goto out;
2264: } else {
1.95 christos 2265: if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL)
1.71 christos 2266: goto out;
2267: (void)memcpy(list[0], list[1], min);
2268: list[0][min] = '\0';
2269: }
2270: return list;
1.125 christos 2271:
1.71 christos 2272: out:
1.95 christos 2273: el_free(list);
1.71 christos 2274: return NULL;
2275: }
2276:
1.70 christos 2277: char *
2278: rl_filename_completion_function (const char *text, int state)
2279: {
2280: return fn_filename_completion_function(text, state);
2281: }
2282:
1.73 christos 2283: void
2284: rl_forced_update_display(void)
2285: {
1.74 christos 2286: el_set(e, EL_REFRESH);
1.73 christos 2287: }
2288:
1.70 christos 2289: int
2290: _rl_abort_internal(void)
2291: {
2292: el_beep(e);
2293: longjmp(topbuf, 1);
2294: /*NOTREACHED*/
2295: }
2296:
2297: int
2298: _rl_qsort_string_compare(char **s1, char **s2)
2299: {
2300: return strcoll(*s1, *s2);
2301: }
2302:
1.85 christos 2303: HISTORY_STATE *
2304: history_get_history_state(void)
2305: {
2306: HISTORY_STATE *hs;
2307:
1.95 christos 2308: if ((hs = el_malloc(sizeof(*hs))) == NULL)
1.96 christos 2309: return NULL;
1.85 christos 2310: hs->length = history_length;
1.96 christos 2311: return hs;
1.85 christos 2312: }
2313:
1.70 christos 2314: int
2315: /*ARGSUSED*/
1.97 christos 2316: rl_kill_text(int from __attribute__((__unused__)),
2317: int to __attribute__((__unused__)))
1.70 christos 2318: {
2319: return 0;
2320: }
2321:
2322: Keymap
2323: rl_make_bare_keymap(void)
2324: {
2325: return NULL;
2326: }
2327:
2328: Keymap
2329: rl_get_keymap(void)
2330: {
2331: return NULL;
2332: }
2333:
2334: void
2335: /*ARGSUSED*/
1.97 christos 2336: rl_set_keymap(Keymap k __attribute__((__unused__)))
1.70 christos 2337: {
2338: }
2339:
2340: int
2341: /*ARGSUSED*/
1.97 christos 2342: rl_generic_bind(int type __attribute__((__unused__)),
2343: const char * keyseq __attribute__((__unused__)),
2344: const char * data __attribute__((__unused__)),
2345: Keymap k __attribute__((__unused__)))
1.70 christos 2346: {
2347: return 0;
2348: }
2349:
2350: int
2351: /*ARGSUSED*/
1.97 christos 2352: rl_bind_key_in_map(int key __attribute__((__unused__)),
2353: rl_command_func_t *fun __attribute__((__unused__)),
2354: Keymap k __attribute__((__unused__)))
1.70 christos 2355: {
2356: return 0;
2357: }
1.85 christos 2358:
2359: /* unsupported, but needed by python */
2360: void
2361: rl_cleanup_after_signal(void)
2362: {
2363: }
1.90 christos 2364:
2365: int
2366: rl_on_new_line(void)
2367: {
2368: return 0;
2369: }
1.105 christos 2370:
2371: void
2372: rl_free_line_state(void)
2373: {
2374: }
1.118 christos 2375:
2376: int
2377: /*ARGSUSED*/
1.120 christos 2378: rl_set_keyboard_input_timeout(int u __attribute__((__unused__)))
1.118 christos 2379: {
2380: return 0;
2381: }
CVSweb <webmaster@jp.NetBSD.org>