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