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