readline.c 36 KB

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