1 /* $NetBSD: readline.c,v 1.25 2002/10/27 21:43:35 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include "config.h" 40 #if !defined(lint) && !defined(SCCSID) 41 __RCSID("$NetBSD: readline.c,v 1.25 2002/10/27 21:43:35 christos Exp $"); 42 #endif /* not lint && not SCCSID */ 43 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <stdio.h> 47 #include <dirent.h> 48 #include <string.h> 49 #include <pwd.h> 50 #include <ctype.h> 51 #include <stdlib.h> 52 #include <unistd.h> 53 #include <limits.h> 54 #include "histedit.h" 55 #include "readline/readline.h" 56 #include "el.h" 57 #include "fcns.h" /* for EL_NUM_FCNS */ 58 59 /* for rl_complete() */ 60 #define TAB '\r' 61 62 /* see comment at the #ifdef for sense of this */ 63 #define GDB_411_HACK 64 65 /* readline compatibility stuff - look at readline sources/documentation */ 66 /* to see what these variables mean */ 67 const char *rl_library_version = "EditLine wrapper"; 68 static char empty[] = { '\0' }; 69 static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; 70 static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', 71 '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; 72 char *rl_readline_name = empty; 73 FILE *rl_instream = NULL; 74 FILE *rl_outstream = NULL; 75 int rl_point = 0; 76 int rl_end = 0; 77 char *rl_line_buffer = NULL; 78 79 int history_base = 1; /* probably never subject to change */ 80 int history_length = 0; 81 int max_input_history = 0; 82 char history_expansion_char = '!'; 83 char history_subst_char = '^'; 84 char *history_no_expand_chars = expand_chars; 85 Function *history_inhibit_expansion_function = NULL; 86 87 int rl_inhibit_completion = 0; 88 int rl_attempted_completion_over = 0; 89 char *rl_basic_word_break_characters = break_chars; 90 char *rl_completer_word_break_characters = NULL; 91 char *rl_completer_quote_characters = NULL; 92 CPFunction *rl_completion_entry_function = NULL; 93 CPPFunction *rl_attempted_completion_function = NULL; 94 95 /* 96 * This is set to character indicating type of completion being done by 97 * rl_complete_internal(); this is available for application completion 98 * functions. 99 */ 100 int rl_completion_type = 0; 101 102 /* 103 * If more than this number of items results from query for possible 104 * completions, we ask user if they are sure to really display the list. 105 */ 106 int rl_completion_query_items = 100; 107 108 /* 109 * List of characters which are word break characters, but should be left 110 * in the parsed text when it is passed to the completion function. 111 * Shell uses this to help determine what kind of completing to do. 112 */ 113 char *rl_special_prefixes = (char *)NULL; 114 115 /* 116 * This is the character appended to the completed words if at the end of 117 * the line. Default is ' ' (a space). 118 */ 119 int rl_completion_append_character = ' '; 120 121 /* stuff below is used internally by libedit for readline emulation */ 122 123 /* if not zero, non-unique completions always show list of possible matches */ 124 static int _rl_complete_show_all = 0; 125 126 static History *h = NULL; 127 static EditLine *e = NULL; 128 static int el_rl_complete_cmdnum = 0; 129 130 /* internal functions */ 131 static unsigned char _el_rl_complete(EditLine *, int); 132 static char *_get_prompt(EditLine *); 133 static HIST_ENTRY *_move_history(int); 134 static int _history_search_gen(const char *, int, int); 135 static int _history_expand_command(const char *, size_t, char **); 136 static char *_rl_compat_sub(const char *, const char *, 137 const char *, int); 138 static int rl_complete_internal(int); 139 static int _rl_qsort_string_compare(const void *, const void *); 140 141 /* 142 * needed for prompt switching in readline() 143 */ 144 static char *el_rl_prompt = NULL; 145 146 147 /* ARGSUSED */ 148 static char * 149 _get_prompt(EditLine *el) 150 { 151 return (el_rl_prompt); 152 } 153 154 155 /* 156 * generic function for moving around history 157 */ 158 static HIST_ENTRY * 159 _move_history(int op) 160 { 161 HistEvent ev; 162 static HIST_ENTRY rl_he; 163 164 if (history(h, &ev, op) != 0) 165 return (HIST_ENTRY *) NULL; 166 167 rl_he.line = ev.str; 168 rl_he.data = ""; 169 170 return (&rl_he); 171 } 172 173 174 /* 175 * READLINE compatibility stuff 176 */ 177 178 /* 179 * initialize rl compat stuff 180 */ 181 int 182 rl_initialize(void) 183 { 184 HistEvent ev; 185 const LineInfo *li; 186 int i; 187 int editmode = 1; 188 struct termios t; 189 190 if (e != NULL) 191 el_end(e); 192 if (h != NULL) 193 history_end(h); 194 195 if (!rl_instream) 196 rl_instream = stdin; 197 if (!rl_outstream) 198 rl_outstream = stdout; 199 200 /* 201 * See if we don't really want to run the editor 202 */ 203 if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0) 204 editmode = 0; 205 206 e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr); 207 208 if (!editmode) 209 el_set(e, EL_EDITMODE, 0); 210 211 h = history_init(); 212 if (!e || !h) 213 return (-1); 214 215 history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ 216 history_length = 0; 217 max_input_history = INT_MAX; 218 el_set(e, EL_HIST, history, h); 219 220 /* for proper prompt printing in readline() */ 221 el_rl_prompt = strdup(""); 222 if (el_rl_prompt == NULL) { 223 history_end(h); 224 el_end(e); 225 return -1; 226 } 227 el_set(e, EL_PROMPT, _get_prompt); 228 el_set(e, EL_SIGNAL, 1); 229 230 /* set default mode to "emacs"-style and read setting afterwards */ 231 /* so this can be overriden */ 232 el_set(e, EL_EDITOR, "emacs"); 233 234 /* 235 * Word completition - this has to go AFTER rebinding keys 236 * to emacs-style. 237 */ 238 el_set(e, EL_ADDFN, "rl_complete", 239 "ReadLine compatible completition function", 240 _el_rl_complete); 241 el_set(e, EL_BIND, "^I", "rl_complete", NULL); 242 243 /* 244 * Find out where the rl_complete function was added; this is 245 * used later to detect that lastcmd was also rl_complete. 246 */ 247 for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) { 248 if (e->el_map.func[i] == _el_rl_complete) { 249 el_rl_complete_cmdnum = i; 250 break; 251 } 252 } 253 254 /* read settings from configuration file */ 255 el_source(e, NULL); 256 257 /* 258 * Unfortunately, some applications really do use rl_point 259 * and rl_line_buffer directly. 260 */ 261 li = el_line(e); 262 /* a cheesy way to get rid of const cast. */ 263 rl_line_buffer = memchr(li->buffer, *li->buffer, 1); 264 rl_point = rl_end = 0; 265 266 return (0); 267 } 268 269 270 /* 271 * read one line from input stream and return it, chomping 272 * trailing newline (if there is any) 273 */ 274 char * 275 readline(const char *prompt) 276 { 277 HistEvent ev; 278 int count; 279 const char *ret; 280 char *buf; 281 282 if (e == NULL || h == NULL) 283 rl_initialize(); 284 285 /* update prompt accordingly to what has been passed */ 286 if (!prompt) 287 prompt = ""; 288 if (strcmp(el_rl_prompt, prompt) != 0) { 289 free(el_rl_prompt); 290 el_rl_prompt = strdup(prompt); 291 if (el_rl_prompt == NULL) 292 return NULL; 293 } 294 /* get one line from input stream */ 295 ret = el_gets(e, &count); 296 297 if (ret && count > 0) { 298 int lastidx; 299 300 buf = strdup(ret); 301 if (buf == NULL) 302 return NULL; 303 lastidx = count - 1; 304 if (buf[lastidx] == '\n') 305 buf[lastidx] = '\0'; 306 } else 307 buf = NULL; 308 309 history(h, &ev, H_GETSIZE); 310 history_length = ev.num; 311 312 return buf; 313 } 314 315 /* 316 * history functions 317 */ 318 319 /* 320 * is normally called before application starts to use 321 * history expansion functions 322 */ 323 void 324 using_history(void) 325 { 326 if (h == NULL || e == NULL) 327 rl_initialize(); 328 } 329 330 331 /* 332 * substitute ``what'' with ``with'', returning resulting string; if 333 * globally == 1, substitutes all occurences of what, otherwise only the 334 * first one 335 */ 336 static char * 337 _rl_compat_sub(const char *str, const char *what, const char *with, 338 int globally) 339 { 340 char *result; 341 const char *temp, *new; 342 int len, with_len, what_len, add; 343 size_t size, i; 344 345 result = malloc((size = 16)); 346 if (result == NULL) 347 return NULL; 348 temp = str; 349 with_len = strlen(with); 350 what_len = strlen(what); 351 len = 0; 352 do { 353 new = strstr(temp, what); 354 if (new) { 355 i = new - temp; 356 add = i + with_len; 357 if (i + add + 1 >= size) { 358 char *nresult; 359 size += add + 1; 360 nresult = realloc(result, size); 361 if (nresult == NULL) { 362 free(result); 363 return NULL; 364 } 365 result = nresult; 366 } 367 (void) strncpy(&result[len], temp, i); 368 len += i; 369 (void) strcpy(&result[len], with); /* safe */ 370 len += with_len; 371 temp = new + what_len; 372 } else { 373 add = strlen(temp); 374 if (len + add + 1 >= size) { 375 char *nresult; 376 size += add + 1; 377 nresult = realloc(result, size); 378 if (nresult == NULL) { 379 free(result); 380 return NULL; 381 } 382 result = nresult; 383 } 384 (void) strcpy(&result[len], temp); /* safe */ 385 len += add; 386 temp = NULL; 387 } 388 } while (temp && globally); 389 result[len] = '\0'; 390 391 return (result); 392 } 393 394 395 /* 396 * the real function doing history expansion - takes as argument command 397 * to do and data upon which the command should be executed 398 * does expansion the way I've understood readline documentation 399 * word designator ``%'' isn't supported (yet ?) 400 * 401 * returns 0 if data was not modified, 1 if it was and 2 if the string 402 * should be only printed and not executed; in case of error, 403 * returns -1 and *result points to NULL 404 * it's callers responsibility to free() string returned in *result 405 */ 406 static int 407 _history_expand_command(const char *command, size_t cmdlen, char **result) 408 { 409 char **arr, *tempcmd, *line, *search = NULL, *cmd; 410 const char *event_data = NULL; 411 static char *from = NULL, *to = NULL; 412 int start = -1, end = -1, max, i, idx; 413 int h_on = 0, t_on = 0, r_on = 0, e_on = 0, p_on = 0, g_on = 0; 414 int event_num = 0, retval; 415 size_t cmdsize; 416 417 *result = NULL; 418 419 cmd = alloca(cmdlen + 1); 420 (void) strncpy(cmd, command, cmdlen); 421 cmd[cmdlen] = 0; 422 423 idx = 1; 424 /* find out which event to take */ 425 if (cmd[idx] == history_expansion_char) { 426 event_num = history_length; 427 idx++; 428 } else { 429 int off, num; 430 size_t len; 431 off = idx; 432 while (cmd[off] && !strchr(":^$*-%", cmd[off])) 433 off++; 434 num = atoi(&cmd[idx]); 435 if (num != 0) { 436 event_num = num; 437 if (num < 0) 438 event_num += history_length + 1; 439 } else { 440 int prefix = 1, curr_num; 441 HistEvent ev; 442 443 len = off - idx; 444 if (cmd[idx] == '?') { 445 idx++, len--; 446 if (cmd[off - 1] == '?') 447 len--; 448 else if (cmd[off] != '\n' && cmd[off] != '\0') 449 return (-1); 450 prefix = 0; 451 } 452 search = alloca(len + 1); 453 (void) strncpy(search, &cmd[idx], len); 454 search[len] = '\0'; 455 456 if (history(h, &ev, H_CURR) != 0) 457 return (-1); 458 curr_num = ev.num; 459 460 if (prefix) 461 retval = history_search_prefix(search, -1); 462 else 463 retval = history_search(search, -1); 464 465 if (retval == -1) { 466 fprintf(rl_outstream, "%s: Event not found\n", 467 search); 468 return (-1); 469 } 470 if (history(h, &ev, H_CURR) != 0) 471 return (-1); 472 event_data = ev.str; 473 474 /* roll back to original position */ 475 history(h, &ev, H_NEXT_EVENT, curr_num); 476 } 477 idx = off; 478 } 479 480 if (!event_data && event_num >= 0) { 481 HIST_ENTRY *rl_he; 482 rl_he = history_get(event_num); 483 if (!rl_he) 484 return (0); 485 event_data = rl_he->line; 486 } else 487 return (-1); 488 489 if (cmd[idx] != ':') 490 return (-1); 491 cmd += idx + 1; 492 493 /* recognize cmd */ 494 if (*cmd == '^') 495 start = end = 1, cmd++; 496 else if (*cmd == '$') 497 start = end = -1, cmd++; 498 else if (*cmd == '*') 499 start = 1, end = -1, cmd++; 500 else if (isdigit((unsigned char) *cmd)) { 501 const char *temp; 502 int shifted = 0; 503 504 start = atoi(cmd); 505 temp = cmd; 506 for (; isdigit((unsigned char) *cmd); cmd++); 507 if (temp != cmd) 508 shifted = 1; 509 if (shifted && *cmd == '-') { 510 if (!isdigit((unsigned char) *(cmd + 1))) 511 end = -2; 512 else { 513 end = atoi(cmd + 1); 514 for (; isdigit((unsigned char) *cmd); cmd++); 515 } 516 } else if (shifted && *cmd == '*') 517 end = -1, cmd++; 518 else if (shifted) 519 end = start; 520 } 521 if (*cmd == ':') 522 cmd++; 523 524 line = strdup(event_data); 525 if (line == NULL) 526 return NULL; 527 for (; *cmd; cmd++) { 528 if (*cmd == ':') 529 continue; 530 else if (*cmd == 'h') 531 h_on = 1 | g_on, g_on = 0; 532 else if (*cmd == 't') 533 t_on = 1 | g_on, g_on = 0; 534 else if (*cmd == 'r') 535 r_on = 1 | g_on, g_on = 0; 536 else if (*cmd == 'e') 537 e_on = 1 | g_on, g_on = 0; 538 else if (*cmd == 'p') 539 p_on = 1 | g_on, g_on = 0; 540 else if (*cmd == 'g') 541 g_on = 2; 542 else if (*cmd == 's' || *cmd == '&') { 543 char *what, *with, delim; 544 int len, from_len; 545 size_t size; 546 547 if (*cmd == '&' && (from == NULL || to == NULL)) 548 continue; 549 else if (*cmd == 's') { 550 delim = *(++cmd), cmd++; 551 size = 16; 552 what = realloc(from, size); 553 if (what == NULL) { 554 free(from); 555 return NULL; 556 } 557 len = 0; 558 for (; *cmd && *cmd != delim; cmd++) { 559 if (*cmd == '\\' 560 && *(cmd + 1) == delim) 561 cmd++; 562 if (len >= size) { 563 char *nwhat; 564 nwhat = realloc(what, 565 (size <<= 1)); 566 if (nwhat == NULL) { 567 free(what); 568 return NULL; 569 } 570 what = nwhat; 571 } 572 what[len++] = *cmd; 573 } 574 what[len] = '\0'; 575 from = what; 576 if (*what == '\0') { 577 free(what); 578 if (search) { 579 from = strdup(search); 580 if (from == NULL) 581 return NULL; 582 } else { 583 from = NULL; 584 return (-1); 585 } 586 } 587 cmd++; /* shift after delim */ 588 if (!*cmd) 589 continue; 590 591 size = 16; 592 with = realloc(to, size); 593 if (with == NULL) { 594 free(to); 595 return -1; 596 } 597 len = 0; 598 from_len = strlen(from); 599 for (; *cmd && *cmd != delim; cmd++) { 600 if (len + from_len + 1 >= size) { 601 char *nwith; 602 size += from_len + 1; 603 nwith = realloc(with, size); 604 if (nwith == NULL) { 605 free(with); 606 return -1; 607 } 608 with = nwith; 609 } 610 if (*cmd == '&') { 611 /* safe */ 612 (void) strcpy(&with[len], from); 613 len += from_len; 614 continue; 615 } 616 if (*cmd == '\\' 617 && (*(cmd + 1) == delim 618 || *(cmd + 1) == '&')) 619 cmd++; 620 with[len++] = *cmd; 621 } 622 with[len] = '\0'; 623 to = with; 624 625 tempcmd = _rl_compat_sub(line, from, to, 626 (g_on) ? 1 : 0); 627 if (tempcmd) { 628 free(line); 629 line = tempcmd; 630 } 631 g_on = 0; 632 } 633 } 634 } 635 636 arr = history_tokenize(line); 637 free(line); /* no more needed */ 638 if (arr && *arr == NULL) 639 free(arr), arr = NULL; 640 if (!arr) 641 return (-1); 642 643 /* find out max valid idx to array of array */ 644 max = 0; 645 for (i = 0; arr[i]; i++) 646 max++; 647 max--; 648 649 /* set boundaries to something relevant */ 650 if (start < 0) 651 start = 1; 652 if (end < 0) 653 end = max - ((end < -1) ? 1 : 0); 654 655 /* check boundaries ... */ 656 if (start > max || end > max || start > end) 657 return (-1); 658 659 for (i = 0; i <= max; i++) { 660 char *temp; 661 if (h_on && (i == 1 || h_on > 1) && 662 (temp = strrchr(arr[i], '/'))) 663 *(temp + 1) = '\0'; 664 if (t_on && (i == 1 || t_on > 1) && 665 (temp = strrchr(arr[i], '/'))) 666 (void) strcpy(arr[i], temp + 1); 667 if (r_on && (i == 1 || r_on > 1) && 668 (temp = strrchr(arr[i], '.'))) 669 *temp = '\0'; 670 if (e_on && (i == 1 || e_on > 1) && 671 (temp = strrchr(arr[i], '.'))) 672 (void) strcpy(arr[i], temp); 673 } 674 675 cmdsize = 1, cmdlen = 0; 676 if ((tempcmd = malloc(cmdsize)) == NULL) 677 return NULL; 678 for (i = start; start <= i && i <= end; i++) { 679 int arr_len; 680 681 arr_len = strlen(arr[i]); 682 if (cmdlen + arr_len + 1 >= cmdsize) { 683 char *ntempcmd; 684 cmdsize += arr_len + 1; 685 ntempcmd = realloc(tempcmd, cmdsize); 686 if (ntempcmd == NULL) { 687 free(tempcmd); 688 return NULL; 689 } 690 tempcmd = ntempcmd; 691 } 692 (void) strcpy(&tempcmd[cmdlen], arr[i]); /* safe */ 693 cmdlen += arr_len; 694 tempcmd[cmdlen++] = ' '; /* add a space */ 695 } 696 while (cmdlen > 0 && isspace((unsigned char) tempcmd[cmdlen - 1])) 697 cmdlen--; 698 tempcmd[cmdlen] = '\0'; 699 700 *result = tempcmd; 701 702 for (i = 0; i <= max; i++) 703 free(arr[i]); 704 free(arr), arr = (char **) NULL; 705 return (p_on) ? 2 : 1; 706 } 707 708 709 /* 710 * csh-style history expansion 711 */ 712 int 713 history_expand(char *str, char **output) 714 { 715 int i, retval = 0, idx; 716 size_t size; 717 char *temp, *result; 718 719 if (h == NULL || e == NULL) 720 rl_initialize(); 721 722 *output = strdup(str); /* do it early */ 723 if (*output == NULL) 724 return NULL; 725 726 if (str[0] == history_subst_char) { 727 /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ 728 temp = alloca(4 + strlen(str) + 1); 729 temp[0] = temp[1] = history_expansion_char; 730 temp[2] = ':'; 731 temp[3] = 's'; 732 (void) strcpy(temp + 4, str); 733 str = temp; 734 } 735 #define ADD_STRING(what, len) \ 736 { \ 737 if (idx + len + 1 > size) { \ 738 char *nresult = realloc(result, (size += len + 1));\ 739 if (nresult == NULL) { \ 740 free(*output); \ 741 return NULL; \ 742 } \ 743 result = nresult; \ 744 } \ 745 (void)strncpy(&result[idx], what, len); \ 746 idx += len; \ 747 result[idx] = '\0'; \ 748 } 749 750 result = NULL; 751 size = idx = 0; 752 for (i = 0; str[i];) { 753 int start, j, loop_again; 754 size_t len; 755 756 loop_again = 1; 757 start = j = i; 758 loop: 759 for (; str[j]; j++) { 760 if (str[j] == '\\' && 761 str[j + 1] == history_expansion_char) { 762 (void) strcpy(&str[j], &str[j + 1]); 763 continue; 764 } 765 if (!loop_again) { 766 if (str[j] == '?') { 767 while (str[j] && str[++j] != '?'); 768 if (str[j] == '?') 769 j++; 770 } else if (isspace((unsigned char) str[j])) 771 break; 772 } 773 if (str[j] == history_expansion_char 774 && !strchr(history_no_expand_chars, str[j + 1]) 775 && (!history_inhibit_expansion_function || 776 (*history_inhibit_expansion_function)(str, j) == 0)) 777 break; 778 } 779 780 if (str[j] && str[j + 1] != '#' && loop_again) { 781 i = j; 782 j++; 783 if (str[j] == history_expansion_char) 784 j++; 785 loop_again = 0; 786 goto loop; 787 } 788 len = i - start; 789 temp = &str[start]; 790 ADD_STRING(temp, len); 791 792 if (str[i] == '\0' || str[i] != history_expansion_char 793 || str[i + 1] == '#') { 794 len = j - i; 795 temp = &str[i]; 796 ADD_STRING(temp, len); 797 if (start == 0) 798 retval = 0; 799 else 800 retval = 1; 801 break; 802 } 803 retval = _history_expand_command(&str[i], (size_t) (j - i), 804 &temp); 805 if (retval != -1) { 806 len = strlen(temp); 807 ADD_STRING(temp, len); 808 } 809 i = j; 810 } /* for(i ...) */ 811 812 if (retval == 2) { 813 add_history(temp); 814 #ifdef GDB_411_HACK 815 /* gdb 4.11 has been shipped with readline, where */ 816 /* history_expand() returned -1 when the line */ 817 /* should not be executed; in readline 2.1+ */ 818 /* it should return 2 in such a case */ 819 retval = -1; 820 #endif 821 } 822 free(*output); 823 *output = result; 824 825 return (retval); 826 } 827 828 829 /* 830 * Parse the string into individual tokens, similarily to how shell would do it. 831 */ 832 char ** 833 history_tokenize(const char *str) 834 { 835 int size = 1, result_idx = 0, i, start; 836 size_t len; 837 char **result = NULL, *temp, delim = '\0'; 838 839 for (i = 0; str[i]; i++) { 840 while (isspace((unsigned char) str[i])) 841 i++; 842 start = i; 843 for (; str[i]; i++) { 844 if (str[i] == '\\') { 845 if (str[i+1] != '\0') 846 i++; 847 } else if (str[i] == delim) 848 delim = '\0'; 849 else if (!delim && 850 (isspace((unsigned char) str[i]) || 851 strchr("()<>;&|$", str[i]))) 852 break; 853 else if (!delim && strchr("'`\"", str[i])) 854 delim = str[i]; 855 } 856 857 if (result_idx + 2 >= size) { 858 char **nresult; 859 size <<= 1; 860 nresult = realloc(result, size * sizeof(char *)); 861 if (nresult == NULL) { 862 free(result); 863 return NULL; 864 } 865 result = nresult; 866 } 867 len = i - start; 868 temp = malloc(len + 1); 869 if (temp == NULL) { 870 free(result); 871 return NULL; 872 } 873 (void) strncpy(temp, &str[start], len); 874 temp[len] = '\0'; 875 result[result_idx++] = temp; 876 result[result_idx] = NULL; 877 } 878 879 return (result); 880 } 881 882 883 /* 884 * limit size of history record to ``max'' events 885 */ 886 void 887 stifle_history(int max) 888 { 889 HistEvent ev; 890 891 if (h == NULL || e == NULL) 892 rl_initialize(); 893 894 if (history(h, &ev, H_SETSIZE, max) == 0) 895 max_input_history = max; 896 } 897 898 899 /* 900 * "unlimit" size of history - set the limit to maximum allowed int value 901 */ 902 int 903 unstifle_history(void) 904 { 905 HistEvent ev; 906 int omax; 907 908 history(h, &ev, H_SETSIZE, INT_MAX); 909 omax = max_input_history; 910 max_input_history = INT_MAX; 911 return (omax); /* some value _must_ be returned */ 912 } 913 914 915 int 916 history_is_stifled(void) 917 { 918 919 /* cannot return true answer */ 920 return (max_input_history != INT_MAX); 921 } 922 923 924 /* 925 * read history from a file given 926 */ 927 int 928 read_history(const char *filename) 929 { 930 HistEvent ev; 931 932 if (h == NULL || e == NULL) 933 rl_initialize(); 934 return (history(h, &ev, H_LOAD, filename)); 935 } 936 937 938 /* 939 * write history to a file given 940 */ 941 int 942 write_history(const char *filename) 943 { 944 HistEvent ev; 945 946 if (h == NULL || e == NULL) 947 rl_initialize(); 948 return (history(h, &ev, H_SAVE, filename)); 949 } 950 951 952 /* 953 * returns history ``num''th event 954 * 955 * returned pointer points to static variable 956 */ 957 HIST_ENTRY * 958 history_get(int num) 959 { 960 static HIST_ENTRY she; 961 HistEvent ev; 962 int i = 1, curr_num; 963 964 if (h == NULL || e == NULL) 965 rl_initialize(); 966 967 /* rewind to beginning */ 968 if (history(h, &ev, H_CURR) != 0) 969 return (NULL); 970 curr_num = ev.num; 971 if (history(h, &ev, H_LAST) != 0) 972 return (NULL); /* error */ 973 while (i < num && history(h, &ev, H_PREV) == 0) 974 i++; 975 if (i != num) 976 return (NULL); /* not so many entries */ 977 978 she.line = ev.str; 979 she.data = NULL; 980 981 /* rewind history to the same event it was before */ 982 (void) history(h, &ev, H_FIRST); 983 (void) history(h, &ev, H_NEXT_EVENT, curr_num); 984 985 return (&she); 986 } 987 988 989 /* 990 * add the line to history table 991 */ 992 int 993 add_history(const char *line) 994 { 995 HistEvent ev; 996 997 if (h == NULL || e == NULL) 998 rl_initialize(); 999 1000 (void) history(h, &ev, H_ENTER, line); 1001 if (history(h, &ev, H_GETSIZE) == 0) 1002 history_length = ev.num; 1003 1004 return (!(history_length > 0)); /* return 0 if all is okay */ 1005 } 1006 1007 1008 /* 1009 * clear the history list - delete all entries 1010 */ 1011 void 1012 clear_history(void) 1013 { 1014 HistEvent ev; 1015 1016 history(h, &ev, H_CLEAR); 1017 } 1018 1019 1020 /* 1021 * returns offset of the current history event 1022 */ 1023 int 1024 where_history(void) 1025 { 1026 HistEvent ev; 1027 int curr_num, off; 1028 1029 if (history(h, &ev, H_CURR) != 0) 1030 return (0); 1031 curr_num = ev.num; 1032 1033 history(h, &ev, H_FIRST); 1034 off = 1; 1035 while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) 1036 off++; 1037 1038 return (off); 1039 } 1040 1041 1042 /* 1043 * returns current history event or NULL if there is no such event 1044 */ 1045 HIST_ENTRY * 1046 current_history(void) 1047 { 1048 1049 return (_move_history(H_CURR)); 1050 } 1051 1052 1053 /* 1054 * returns total number of bytes history events' data are using 1055 */ 1056 int 1057 history_total_bytes(void) 1058 { 1059 HistEvent ev; 1060 int curr_num, size; 1061 1062 if (history(h, &ev, H_CURR) != 0) 1063 return (-1); 1064 curr_num = ev.num; 1065 1066 history(h, &ev, H_FIRST); 1067 size = 0; 1068 do 1069 size += strlen(ev.str); 1070 while (history(h, &ev, H_NEXT) == 0); 1071 1072 /* get to the same position as before */ 1073 history(h, &ev, H_PREV_EVENT, curr_num); 1074 1075 return (size); 1076 } 1077 1078 1079 /* 1080 * sets the position in the history list to ``pos'' 1081 */ 1082 int 1083 history_set_pos(int pos) 1084 { 1085 HistEvent ev; 1086 int off, curr_num; 1087 1088 if (pos > history_length || pos < 0) 1089 return (-1); 1090 1091 history(h, &ev, H_CURR); 1092 curr_num = ev.num; 1093 history(h, &ev, H_FIRST); 1094 off = 0; 1095 while (off < pos && history(h, &ev, H_NEXT) == 0) 1096 off++; 1097 1098 if (off != pos) { /* do a rollback in case of error */ 1099 history(h, &ev, H_FIRST); 1100 history(h, &ev, H_NEXT_EVENT, curr_num); 1101 return (-1); 1102 } 1103 return (0); 1104 } 1105 1106 1107 /* 1108 * returns previous event in history and shifts pointer accordingly 1109 */ 1110 HIST_ENTRY * 1111 previous_history(void) 1112 { 1113 1114 return (_move_history(H_PREV)); 1115 } 1116 1117 1118 /* 1119 * returns next event in history and shifts pointer accordingly 1120 */ 1121 HIST_ENTRY * 1122 next_history(void) 1123 { 1124 1125 return (_move_history(H_NEXT)); 1126 } 1127 1128 1129 /* 1130 * generic history search function 1131 */ 1132 static int 1133 _history_search_gen(const char *str, int direction, int pos) 1134 { 1135 HistEvent ev; 1136 const char *strp; 1137 int curr_num; 1138 1139 if (history(h, &ev, H_CURR) != 0) 1140 return (-1); 1141 curr_num = ev.num; 1142 1143 for (;;) { 1144 strp = strstr(ev.str, str); 1145 if (strp && (pos < 0 || &ev.str[pos] == strp)) 1146 return (int) (strp - ev.str); 1147 if (history(h, &ev, direction < 0 ? H_PREV : H_NEXT) != 0) 1148 break; 1149 } 1150 1151 history(h, &ev, direction < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); 1152 1153 return (-1); 1154 } 1155 1156 1157 /* 1158 * searches for first history event containing the str 1159 */ 1160 int 1161 history_search(const char *str, int direction) 1162 { 1163 1164 return (_history_search_gen(str, direction, -1)); 1165 } 1166 1167 1168 /* 1169 * searches for first history event beginning with str 1170 */ 1171 int 1172 history_search_prefix(const char *str, int direction) 1173 { 1174 1175 return (_history_search_gen(str, direction, 0)); 1176 } 1177 1178 1179 /* 1180 * search for event in history containing str, starting at offset 1181 * abs(pos); continue backward, if pos<0, forward otherwise 1182 */ 1183 /* ARGSUSED */ 1184 int 1185 history_search_pos(const char *str, int direction, int pos) 1186 { 1187 HistEvent ev; 1188 int curr_num, off; 1189 1190 off = (pos > 0) ? pos : -pos; 1191 pos = (pos > 0) ? 1 : -1; 1192 1193 if (history(h, &ev, H_CURR) != 0) 1194 return (-1); 1195 curr_num = ev.num; 1196 1197 if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) 1198 return (-1); 1199 1200 1201 for (;;) { 1202 if (strstr(ev.str, str)) 1203 return (off); 1204 if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) 1205 break; 1206 } 1207 1208 /* set "current" pointer back to previous state */ 1209 history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); 1210 1211 return (-1); 1212 } 1213 1214 1215 /********************************/ 1216 /* completition functions */ 1217 1218 /* 1219 * does tilde expansion of strings of type ``~user/foo'' 1220 * if ``user'' isn't valid user name or ``txt'' doesn't start 1221 * w/ '~', returns pointer to strdup()ed copy of ``txt'' 1222 * 1223 * it's callers's responsibility to free() returned string 1224 */ 1225 char * 1226 tilde_expand(char *txt) 1227 { 1228 struct passwd *pass; 1229 char *temp; 1230 size_t len = 0; 1231 1232 if (txt[0] != '~') 1233 return (strdup(txt)); 1234 1235 temp = strchr(txt + 1, '/'); 1236 if (temp == NULL) { 1237 temp = strdup(txt + 1); 1238 if (temp == NULL) 1239 return NULL; 1240 } else { 1241 len = temp - txt + 1; /* text until string after slash */ 1242 temp = malloc(len); 1243 if (temp == NULL) 1244 return NULL; 1245 (void) strncpy(temp, txt + 1, len - 2); 1246 temp[len - 2] = '\0'; 1247 } 1248 pass = getpwnam(temp); 1249 free(temp); /* value no more needed */ 1250 if (pass == NULL) 1251 return (strdup(txt)); 1252 1253 /* update pointer txt to point at string immedially following */ 1254 /* first slash */ 1255 txt += len; 1256 1257 temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1); 1258 if (temp == NULL) 1259 return NULL; 1260 (void) sprintf(temp, "%s/%s", pass->pw_dir, txt); 1261 1262 return (temp); 1263 } 1264 1265 1266 /* 1267 * return first found file name starting by the ``text'' or NULL if no 1268 * such file can be found 1269 * value of ``state'' is ignored 1270 * 1271 * it's caller's responsibility to free returned string 1272 */ 1273 char * 1274 filename_completion_function(const char *text, int state) 1275 { 1276 static DIR *dir = NULL; 1277 static char *filename = NULL, *dirname = NULL; 1278 static size_t filename_len = 0; 1279 struct dirent *entry; 1280 char *temp; 1281 size_t len; 1282 1283 if (state == 0 || dir == NULL) { 1284 if (dir != NULL) { 1285 closedir(dir); 1286 dir = NULL; 1287 } 1288 temp = strrchr(text, '/'); 1289 if (temp) { 1290 char *nptr; 1291 temp++; 1292 nptr = realloc(filename, strlen(temp) + 1); 1293 if (nptr == NULL) { 1294 free(filename); 1295 return NULL; 1296 } 1297 filename = nptr; 1298 (void) strcpy(filename, temp); 1299 len = temp - text; /* including last slash */ 1300 nptr = realloc(dirname, len + 1); 1301 if (nptr == NULL) { 1302 free(filename); 1303 return NULL; 1304 } 1305 dirname = nptr; 1306 (void) strncpy(dirname, text, len); 1307 dirname[len] = '\0'; 1308 } else { 1309 filename = strdup(text); 1310 if (filename == NULL) 1311 return NULL; 1312 dirname = NULL; 1313 } 1314 1315 /* support for ``~user'' syntax */ 1316 if (dirname && *dirname == '~') { 1317 char *nptr; 1318 temp = tilde_expand(dirname); 1319 if (temp == NULL) 1320 return NULL; 1321 nptr = realloc(dirname, strlen(temp) + 1); 1322 if (nptr == NULL) { 1323 free(dirname); 1324 return NULL; 1325 } 1326 dirname = nptr; 1327 (void) strcpy(dirname, temp); /* safe */ 1328 free(temp); /* no longer needed */ 1329 } 1330 /* will be used in cycle */ 1331 filename_len = strlen(filename); 1332 if (filename_len == 0) 1333 return (NULL); /* no expansion possible */ 1334 1335 dir = opendir(dirname ? dirname : "."); 1336 if (!dir) 1337 return (NULL); /* cannot open the directory */ 1338 } 1339 /* find the match */ 1340 while ((entry = readdir(dir)) != NULL) { 1341 /* otherwise, get first entry where first */ 1342 /* filename_len characters are equal */ 1343 if (entry->d_name[0] == filename[0] 1344 #if defined(__SVR4) || defined(__linux__) 1345 && strlen(entry->d_name) >= filename_len 1346 #else 1347 && entry->d_namlen >= filename_len 1348 #endif 1349 && strncmp(entry->d_name, filename, 1350 filename_len) == 0) 1351 break; 1352 } 1353 1354 if (entry) { /* match found */ 1355 1356 struct stat stbuf; 1357 #if defined(__SVR4) || defined(__linux__) 1358 len = strlen(entry->d_name) + 1359 #else 1360 len = entry->d_namlen + 1361 #endif 1362 ((dirname) ? strlen(dirname) : 0) + 1 + 1; 1363 temp = malloc(len); 1364 if (temp == NULL) 1365 return NULL; 1366 (void) sprintf(temp, "%s%s", 1367 dirname ? dirname : "", entry->d_name); /* safe */ 1368 1369 /* test, if it's directory */ 1370 if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode)) 1371 strcat(temp, "/"); /* safe */ 1372 } else 1373 temp = NULL; 1374 1375 return (temp); 1376 } 1377 1378 1379 /* 1380 * a completion generator for usernames; returns _first_ username 1381 * which starts with supplied text 1382 * text contains a partial username preceded by random character 1383 * (usually '~'); state is ignored 1384 * it's callers responsibility to free returned value 1385 */ 1386 char * 1387 username_completion_function(const char *text, int state) 1388 { 1389 struct passwd *pwd; 1390 1391 if (text[0] == '\0') 1392 return (NULL); 1393 1394 if (*text == '~') 1395 text++; 1396 1397 if (state == 0) 1398 setpwent(); 1399 1400 while ((pwd = getpwent()) && text[0] == pwd->pw_name[0] 1401 && strcmp(text, pwd->pw_name) == 0); 1402 1403 if (pwd == NULL) { 1404 endpwent(); 1405 return (NULL); 1406 } 1407 return (strdup(pwd->pw_name)); 1408 } 1409 1410 1411 /* 1412 * el-compatible wrapper around rl_complete; needed for key binding 1413 */ 1414 /* ARGSUSED */ 1415 static unsigned char 1416 _el_rl_complete(EditLine *el, int ch) 1417 { 1418 return (unsigned char) rl_complete(0, ch); 1419 } 1420 1421 1422 /* 1423 * returns list of completitions for text given 1424 */ 1425 char ** 1426 completion_matches(const char *text, CPFunction *genfunc) 1427 { 1428 char **match_list = NULL, *retstr, *prevstr; 1429 size_t match_list_len, max_equal, which, i; 1430 int matches; 1431 1432 if (h == NULL || e == NULL) 1433 rl_initialize(); 1434 1435 matches = 0; 1436 match_list_len = 1; 1437 while ((retstr = (*genfunc) (text, matches)) != NULL) { 1438 /* allow for list terminator here */ 1439 if (matches + 2 >= match_list_len) { 1440 char **nmatch_list; 1441 match_list_len <<= 1; 1442 nmatch_list = realloc(match_list, 1443 match_list_len * sizeof(char *)); 1444 if (nmatch_list == NULL) { 1445 free(match_list); 1446 return NULL; 1447 } 1448 match_list = nmatch_list; 1449 1450 } 1451 match_list[++matches] = retstr; 1452 } 1453 1454 if (!match_list) 1455 return NULL; /* nothing found */ 1456 1457 /* find least denominator and insert it to match_list[0] */ 1458 which = 2; 1459 prevstr = match_list[1]; 1460 max_equal = strlen(prevstr); 1461 for (; which <= matches; which++) { 1462 for (i = 0; i < max_equal && 1463 prevstr[i] == match_list[which][i]; i++) 1464 continue; 1465 max_equal = i; 1466 } 1467 1468 retstr = malloc(max_equal + 1); 1469 if (retstr == NULL) { 1470 free(match_list); 1471 return NULL; 1472 } 1473 (void) strncpy(retstr, match_list[1], max_equal); 1474 retstr[max_equal] = '\0'; 1475 match_list[0] = retstr; 1476 1477 /* add NULL as last pointer to the array */ 1478 match_list[matches + 1] = (char *) NULL; 1479 1480 return (match_list); 1481 } 1482 1483 /* 1484 * Sort function for qsort(). Just wrapper around strcasecmp(). 1485 */ 1486 static int 1487 _rl_qsort_string_compare(i1, i2) 1488 const void *i1, *i2; 1489 { 1490 const char *s1 = ((const char * const *)i1)[0]; 1491 const char *s2 = ((const char * const *)i2)[0]; 1492 1493 return strcasecmp(s1, s2); 1494 } 1495 1496 /* 1497 * Display list of strings in columnar format on readline's output stream. 1498 * 'matches' is list of strings, 'len' is number of strings in 'matches', 1499 * 'max' is maximum length of string in 'matches'. 1500 */ 1501 void 1502 rl_display_match_list (matches, len, max) 1503 char **matches; 1504 int len, max; 1505 { 1506 int i, idx, limit, count; 1507 int screenwidth = e->el_term.t_size.h; 1508 1509 /* 1510 * Find out how many entries can be put on one line, count 1511 * with two spaces between strings. 1512 */ 1513 limit = screenwidth / (max + 2); 1514 if (limit == 0) 1515 limit = 1; 1516 1517 /* how many lines of output */ 1518 count = len / limit; 1519 if (count * limit < len) 1520 count++; 1521 1522 /* Sort the items if they are not already sorted. */ 1523 qsort(&matches[1], (size_t)(len - 1), sizeof(char *), 1524 _rl_qsort_string_compare); 1525 1526 idx = 1; 1527 for(; count > 0; count--) { 1528 for(i=0; i < limit && matches[idx]; i++, idx++) 1529 fprintf(e->el_outfile, "%-*s ", max, matches[idx]); 1530 fprintf(e->el_outfile, "\n"); 1531 } 1532 } 1533 1534 /* 1535 * Complete the word at or before point, called by rl_complete() 1536 * 'what_to_do' says what to do with the completion. 1537 * `?' means list the possible completions. 1538 * TAB means do standard completion. 1539 * `*' means insert all of the possible completions. 1540 * `!' means to do standard completion, and list all possible completions if 1541 * there is more than one. 1542 * 1543 * Note: '*' support is not implemented 1544 */ 1545 static int 1546 rl_complete_internal(int what_to_do) 1547 { 1548 CPFunction *complet_func; 1549 const LineInfo *li; 1550 char *temp, **matches; 1551 const char *ctemp; 1552 size_t len; 1553 1554 rl_completion_type = what_to_do; 1555 1556 if (h == NULL || e == NULL) 1557 rl_initialize(); 1558 1559 complet_func = rl_completion_entry_function; 1560 if (!complet_func) 1561 complet_func = filename_completion_function; 1562 1563 /* We now look backwards for the start of a filename/variable word */ 1564 li = el_line(e); 1565 ctemp = (const char *) li->cursor; 1566 while (ctemp > li->buffer 1567 && !strchr(rl_basic_word_break_characters, ctemp[-1]) 1568 && (!rl_special_prefixes 1569 || !strchr(rl_special_prefixes, ctemp[-1]) ) ) 1570 ctemp--; 1571 1572 len = li->cursor - ctemp; 1573 temp = alloca(len + 1); 1574 (void) strncpy(temp, ctemp, len); 1575 temp[len] = '\0'; 1576 1577 /* these can be used by function called in completion_matches() */ 1578 /* or (*rl_attempted_completion_function)() */ 1579 rl_point = li->cursor - li->buffer; 1580 rl_end = li->lastchar - li->buffer; 1581 1582 if (!rl_attempted_completion_function) 1583 matches = completion_matches(temp, complet_func); 1584 else { 1585 int end = li->cursor - li->buffer; 1586 matches = (*rl_attempted_completion_function) (temp, (int) 1587 (end - len), end); 1588 } 1589 1590 if (matches) { 1591 int i, retval = CC_REFRESH; 1592 int matches_num, maxlen, match_len, match_display=1; 1593 1594 /* 1595 * Only replace the completed string with common part of 1596 * possible matches if there is possible completion. 1597 */ 1598 if (matches[0][0] != '\0') { 1599 el_deletestr(e, (int) len); 1600 el_insertstr(e, matches[0]); 1601 } 1602 1603 if (what_to_do == '?') 1604 goto display_matches; 1605 1606 if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { 1607 /* 1608 * We found exact match. Add a space after 1609 * it, unless we do filename completition and the 1610 * object is a directory. 1611 */ 1612 size_t alen = strlen(matches[0]); 1613 if ((complet_func != filename_completion_function 1614 || (alen > 0 && (matches[0])[alen - 1] != '/')) 1615 && rl_completion_append_character) { 1616 char buf[2]; 1617 buf[0] = rl_completion_append_character; 1618 buf[1] = '\0'; 1619 el_insertstr(e, buf); 1620 } 1621 } else if (what_to_do == '!') { 1622 display_matches: 1623 /* 1624 * More than one match and requested to list possible 1625 * matches. 1626 */ 1627 1628 for(i=1, maxlen=0; matches[i]; i++) { 1629 match_len = strlen(matches[i]); 1630 if (match_len > maxlen) 1631 maxlen = match_len; 1632 } 1633 matches_num = i - 1; 1634 1635 /* newline to get on next line from command line */ 1636 fprintf(e->el_outfile, "\n"); 1637 1638 /* 1639 * If there are too many items, ask user for display 1640 * confirmation. 1641 */ 1642 if (matches_num > rl_completion_query_items) { 1643 fprintf(e->el_outfile, 1644 "Display all %d possibilities? (y or n) ", 1645 matches_num); 1646 fflush(e->el_outfile); 1647 if (getc(stdin) != 'y') 1648 match_display = 0; 1649 fprintf(e->el_outfile, "\n"); 1650 } 1651 1652 if (match_display) 1653 rl_display_match_list(matches, matches_num, 1654 maxlen); 1655 retval = CC_REDISPLAY; 1656 } else if (matches[0][0]) { 1657 /* 1658 * There was some common match, but the name was 1659 * not complete enough. Next tab will print possible 1660 * completions. 1661 */ 1662 el_beep(e); 1663 } else { 1664 /* lcd is not a valid object - further specification */ 1665 /* is needed */ 1666 el_beep(e); 1667 retval = CC_NORM; 1668 } 1669 1670 /* free elements of array and the array itself */ 1671 for (i = 0; matches[i]; i++) 1672 free(matches[i]); 1673 free(matches), matches = NULL; 1674 1675 return (retval); 1676 } 1677 return (CC_NORM); 1678 } 1679 1680 1681 /* 1682 * complete word at current point 1683 */ 1684 int 1685 rl_complete(int ignore, int invoking_key) 1686 { 1687 if (h == NULL || e == NULL) 1688 rl_initialize(); 1689 1690 if (rl_inhibit_completion) { 1691 rl_insert(ignore, invoking_key); 1692 return (CC_REFRESH); 1693 } else if (e->el_state.lastcmd == el_rl_complete_cmdnum) 1694 return rl_complete_internal('?'); 1695 else if (_rl_complete_show_all) 1696 return rl_complete_internal('!'); 1697 else 1698 return (rl_complete_internal(TAB)); 1699 } 1700 1701 1702 /* 1703 * misc other functions 1704 */ 1705 1706 /* 1707 * bind key c to readline-type function func 1708 */ 1709 int 1710 rl_bind_key(int c, int func(int, int)) 1711 { 1712 int retval = -1; 1713 1714 if (h == NULL || e == NULL) 1715 rl_initialize(); 1716 1717 if (func == rl_insert) { 1718 /* XXX notice there is no range checking of ``c'' */ 1719 e->el_map.key[c] = ED_INSERT; 1720 retval = 0; 1721 } 1722 return (retval); 1723 } 1724 1725 1726 /* 1727 * read one key from input - handles chars pushed back 1728 * to input stream also 1729 */ 1730 int 1731 rl_read_key(void) 1732 { 1733 char fooarr[2 * sizeof(int)]; 1734 1735 if (e == NULL || h == NULL) 1736 rl_initialize(); 1737 1738 return (el_getc(e, fooarr)); 1739 } 1740 1741 1742 /* 1743 * reset the terminal 1744 */ 1745 /* ARGSUSED */ 1746 void 1747 rl_reset_terminal(const char *p) 1748 { 1749 1750 if (h == NULL || e == NULL) 1751 rl_initialize(); 1752 el_reset(e); 1753 } 1754 1755 1756 /* 1757 * insert character ``c'' back into input stream, ``count'' times 1758 */ 1759 int 1760 rl_insert(int count, int c) 1761 { 1762 char arr[2]; 1763 1764 if (h == NULL || e == NULL) 1765 rl_initialize(); 1766 1767 /* XXX - int -> char conversion can lose on multichars */ 1768 arr[0] = c; 1769 arr[1] = '\0'; 1770 1771 for (; count > 0; count--) 1772 el_push(e, arr); 1773 1774 return (0); 1775 } 1776