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