1 /* pcomplete.c - functions to generate lists of matches for programmable completion. */
2 
3 /* Copyright (C) 1999-2020 Free Software Foundation, Inc.
4 
5    This file is part of GNU Bash, the Bourne Again SHell.
6 
7    Bash is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    Bash is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include <config.h>
22 
23 #if defined (PROGRAMMABLE_COMPLETION)
24 
25 #include "bashtypes.h"
26 #include "posixstat.h"
27 
28 #if defined (HAVE_UNISTD_H)
29 #  include <unistd.h>
30 #endif
31 
32 #include <signal.h>
33 
34 #if defined (PREFER_STDARG)
35 #  include <stdarg.h>
36 #else
37 #  include <varargs.h>
38 #endif
39 
40 #include "posixtime.h"
41 
42 #include <stdio.h>
43 #include "bashansi.h"
44 #include "bashintl.h"
45 
46 #include "shell.h"
47 #include "pcomplete.h"
48 #include "alias.h"
49 #include "bashline.h"
50 #include "execute_cmd.h"
51 #include "pathexp.h"
52 
53 #if defined (JOB_CONTROL)
54 #  include "jobs.h"
55 #endif
56 
57 #if !defined (NSIG)
58 #  include "trap.h"
59 #endif
60 
61 #include "shmbutil.h"
62 
63 #include "builtins.h"
64 #include "builtins/common.h"
65 #include "builtins/builtext.h"
66 
67 #include <glob/glob.h>
68 #include <glob/strmatch.h>
69 
70 #include <readline/rlconf.h>
71 #include <readline/readline.h>
72 #include <readline/history.h>
73 
74 #ifdef STRDUP
75 #  undef STRDUP
76 #endif
77 #define STRDUP(x)	((x) ? savestring (x) : (char *)NULL)
78 
79 typedef SHELL_VAR **SVFUNC ();
80 
81 #ifndef HAVE_STRPBRK
82 extern char *strpbrk PARAMS((char *, char *));
83 #endif
84 
85 extern STRING_INT_ALIST word_token_alist[];
86 extern char *signal_names[];
87 
88 #if defined (DEBUG)
89 #if defined (PREFER_STDARG)
90 static void debug_printf (const char *, ...)  __attribute__((__format__ (printf, 1, 2)));
91 #endif
92 #endif /* DEBUG */
93 
94 static int it_init_joblist PARAMS((ITEMLIST *, int));
95 
96 static int it_init_aliases PARAMS((ITEMLIST *));
97 static int it_init_arrayvars PARAMS((ITEMLIST *));
98 static int it_init_bindings PARAMS((ITEMLIST *));
99 static int it_init_builtins PARAMS((ITEMLIST *));
100 static int it_init_disabled PARAMS((ITEMLIST *));
101 static int it_init_enabled PARAMS((ITEMLIST *));
102 static int it_init_exported PARAMS((ITEMLIST *));
103 static int it_init_functions PARAMS((ITEMLIST *));
104 static int it_init_helptopics PARAMS((ITEMLIST *));
105 static int it_init_hostnames PARAMS((ITEMLIST *));
106 static int it_init_jobs PARAMS((ITEMLIST *));
107 static int it_init_running PARAMS((ITEMLIST *));
108 static int it_init_stopped PARAMS((ITEMLIST *));
109 static int it_init_keywords PARAMS((ITEMLIST *));
110 static int it_init_signals PARAMS((ITEMLIST *));
111 static int it_init_variables PARAMS((ITEMLIST *));
112 static int it_init_setopts PARAMS((ITEMLIST *));
113 static int it_init_shopts PARAMS((ITEMLIST *));
114 
115 static int shouldexp_filterpat PARAMS((char *));
116 static char *preproc_filterpat PARAMS((char *, const char *));
117 
118 static void init_itemlist_from_varlist PARAMS((ITEMLIST *, SVFUNC *));
119 
120 static STRINGLIST *gen_matches_from_itemlist PARAMS((ITEMLIST *, const char *));
121 static STRINGLIST *gen_action_completions PARAMS((COMPSPEC *, const char *));
122 static STRINGLIST *gen_globpat_matches PARAMS((COMPSPEC *, const char *));
123 static STRINGLIST *gen_wordlist_matches PARAMS((COMPSPEC *, const char *));
124 static STRINGLIST *gen_shell_function_matches PARAMS((COMPSPEC *, const char *,
125 						   const char *,
126 						   char *, int, WORD_LIST *,
127 						   int, int, int *));
128 static STRINGLIST *gen_command_matches PARAMS((COMPSPEC *, const char *,
129 					    const char *,
130 					    char *, int, WORD_LIST *,
131 					    int, int));
132 
133 static STRINGLIST *gen_progcomp_completions PARAMS((const char *, const char *,
134 						 const char *,
135 						 int, int, int *, int *,
136 						 COMPSPEC **));
137 
138 static char *pcomp_filename_completion_function PARAMS((const char *, int));
139 
140 #if defined (ARRAY_VARS)
141 static SHELL_VAR *bind_comp_words PARAMS((WORD_LIST *));
142 #endif
143 static void bind_compfunc_variables PARAMS((char *, int, WORD_LIST *, int, int));
144 static void unbind_compfunc_variables PARAMS((int));
145 static WORD_LIST *build_arg_list PARAMS((char *, const char *, const char *, WORD_LIST *, int));
146 static WORD_LIST *command_line_to_word_list PARAMS((char *, int, int, int *, int *));
147 
148 #ifdef DEBUG
149 static int progcomp_debug = 0;
150 #endif
151 
152 int prog_completion_enabled = 1;
153 
154 #ifdef ALIAS
155 int progcomp_alias = 0;	/* unavailable to user code for now */
156 #endif
157 
158 /* These are used to manage the arrays of strings for possible completions. */
159 ITEMLIST it_aliases = { 0, it_init_aliases, (STRINGLIST *)0 };
160 ITEMLIST it_arrayvars  = { LIST_DYNAMIC, it_init_arrayvars, (STRINGLIST *)0 };
161 ITEMLIST it_bindings  = { 0, it_init_bindings, (STRINGLIST *)0 };
162 ITEMLIST it_builtins  = { 0, it_init_builtins, (STRINGLIST *)0 };
163 ITEMLIST it_commands = { LIST_DYNAMIC };	/* unused */
164 ITEMLIST it_directories = { LIST_DYNAMIC };	/* unused */
165 ITEMLIST it_disabled = { 0, it_init_disabled, (STRINGLIST *)0 };
166 ITEMLIST it_enabled = { 0, it_init_enabled, (STRINGLIST *)0 };
167 ITEMLIST it_exports  = { LIST_DYNAMIC, it_init_exported, (STRINGLIST *)0 };
168 ITEMLIST it_files = { LIST_DYNAMIC };		/* unused */
169 ITEMLIST it_functions  = { 0, it_init_functions, (STRINGLIST *)0 };
170 ITEMLIST it_helptopics  = { 0, it_init_helptopics, (STRINGLIST *)0 };
171 ITEMLIST it_hostnames  = { LIST_DYNAMIC, it_init_hostnames, (STRINGLIST *)0 };
172 ITEMLIST it_groups = { LIST_DYNAMIC };		/* unused */
173 ITEMLIST it_jobs = { LIST_DYNAMIC, it_init_jobs, (STRINGLIST *)0 };
174 ITEMLIST it_keywords = { 0, it_init_keywords, (STRINGLIST *)0 };
175 ITEMLIST it_running = { LIST_DYNAMIC, it_init_running, (STRINGLIST *)0 };
176 ITEMLIST it_services = { LIST_DYNAMIC };	/* unused */
177 ITEMLIST it_setopts = { 0, it_init_setopts, (STRINGLIST *)0 };
178 ITEMLIST it_shopts = { 0, it_init_shopts, (STRINGLIST *)0 };
179 ITEMLIST it_signals = { 0, it_init_signals, (STRINGLIST *)0 };
180 ITEMLIST it_stopped = { LIST_DYNAMIC, it_init_stopped, (STRINGLIST *)0 };
181 ITEMLIST it_users = { LIST_DYNAMIC };		/* unused */
182 ITEMLIST it_variables = { LIST_DYNAMIC, it_init_variables, (STRINGLIST *)0 };
183 
184 COMPSPEC *pcomp_curcs;
185 const char *pcomp_curcmd;
186 const char *pcomp_curtxt;
187 
188 char *pcomp_line;
189 int pcomp_ind;
190 
191 #ifdef DEBUG
192 /* Debugging code */
193 static void
194 #if defined (PREFER_STDARG)
debug_printf(const char * format,...)195 debug_printf (const char *format, ...)
196 #else
197 debug_printf (format, va_alist)
198      const char *format;
199      va_dcl
200 #endif
201 {
202   va_list args;
203 
204   if (progcomp_debug == 0)
205     return;
206 
207   SH_VA_START (args, format);
208 
209   fprintf (stdout, "DEBUG: ");
210   vfprintf (stdout, format, args);
211   fprintf (stdout, "\n");
212 
213   rl_on_new_line ();
214 
215   va_end (args);
216 }
217 #endif
218 
219 /* Functions to manage the item lists */
220 
221 void
set_itemlist_dirty(it)222 set_itemlist_dirty (it)
223      ITEMLIST *it;
224 {
225   it->flags |= LIST_DIRTY;
226 }
227 
228 void
initialize_itemlist(itp)229 initialize_itemlist (itp)
230      ITEMLIST *itp;
231 {
232   (*itp->list_getter) (itp);
233   itp->flags |= LIST_INITIALIZED;
234   itp->flags &= ~LIST_DIRTY;
235 }
236 
237 void
clean_itemlist(itp)238 clean_itemlist (itp)
239      ITEMLIST *itp;
240 {
241   STRINGLIST *sl;
242 
243   sl = itp->slist;
244   if (sl)
245     {
246       if ((itp->flags & (LIST_DONTFREEMEMBERS|LIST_DONTFREE)) == 0)
247 	strvec_flush (sl->list);
248       if ((itp->flags & LIST_DONTFREE) == 0)
249 	free (sl->list);
250       free (sl);
251     }
252   itp->slist = (STRINGLIST *)NULL;
253   itp->flags &= ~(LIST_DONTFREE|LIST_DONTFREEMEMBERS|LIST_INITIALIZED|LIST_DIRTY);
254 }
255 
256 
257 static int
shouldexp_filterpat(s)258 shouldexp_filterpat (s)
259      char *s;
260 {
261   register char *p;
262 
263   for (p = s; p && *p; p++)
264     {
265       if (*p == '\\')
266 	p++;
267       else if (*p == '&')
268 	return 1;
269     }
270   return 0;
271 }
272 
273 /* Replace any instance of `&' in PAT with TEXT.  Backslash may be used to
274    quote a `&' and inhibit substitution.  Returns a new string.  This just
275    calls stringlib.c:strcreplace(). */
276 static char *
preproc_filterpat(pat,text)277 preproc_filterpat (pat, text)
278      char *pat;
279      const char *text;
280 {
281   char *ret;
282 
283   ret = strcreplace (pat, '&', text, 1);
284   return ret;
285 }
286 
287 /* Remove any match of FILTERPAT from SL.  A `&' in FILTERPAT is replaced by
288    TEXT.  A leading `!' in FILTERPAT negates the pattern; in this case
289    any member of SL->list that does *not* match will be removed.  This returns
290    a new STRINGLIST with the matching members of SL *copied*.  Any
291    non-matching members of SL->list are *freed*. */
292 STRINGLIST *
filter_stringlist(sl,filterpat,text)293 filter_stringlist (sl, filterpat, text)
294      STRINGLIST *sl;
295      char *filterpat;
296      const char *text;
297 {
298   int i, m, not;
299   STRINGLIST *ret;
300   char *npat, *t;
301 
302   if (sl == 0 || sl->list == 0 || sl->list_len == 0)
303     return sl;
304 
305   npat = shouldexp_filterpat (filterpat) ? preproc_filterpat (filterpat, text) : filterpat;
306 
307 #if defined (EXTENDED_GLOB)
308   not = (npat[0] == '!' && (extended_glob == 0 || npat[1] != '('));	/*)*/
309 #else
310   not = (npat[0] == '!');
311 #endif
312   t = not ? npat + 1 : npat;
313 
314   ret = strlist_create (sl->list_size);
315   for (i = 0; i < sl->list_len; i++)
316     {
317       m = strmatch (t, sl->list[i], FNMATCH_EXTFLAG | FNMATCH_IGNCASE);
318       if ((not && m == FNM_NOMATCH) || (not == 0 && m != FNM_NOMATCH))
319 	free (sl->list[i]);
320       else
321 	ret->list[ret->list_len++] = sl->list[i];
322     }
323 
324   ret->list[ret->list_len] = (char *)NULL;
325   if (npat != filterpat)
326     free (npat);
327 
328   return ret;
329 }
330 
331 /* Turn an array of strings returned by rl_completion_matches into a STRINGLIST.
332    This understands how rl_completion_matches sets matches[0] (the lcd of the
333    strings in the list, unless it's the only match). */
334 STRINGLIST *
completions_to_stringlist(matches)335 completions_to_stringlist (matches)
336      char **matches;
337 {
338   STRINGLIST *sl;
339   int mlen, i, n;
340 
341   mlen = (matches == 0) ? 0 : strvec_len (matches);
342   sl = strlist_create (mlen + 1);
343 
344   if (matches == 0 || matches[0] == 0)
345     return sl;
346 
347   if (matches[1] == 0)
348     {
349       sl->list[0] = STRDUP (matches[0]);
350       sl->list[sl->list_len = 1] = (char *)NULL;
351       return sl;
352     }
353 
354   for (i = 1, n = 0; i < mlen; i++, n++)
355     sl->list[n] = STRDUP (matches[i]);
356   sl->list_len = n;
357   sl->list[n] = (char *)NULL;
358 
359   return sl;
360 }
361 
362 /* Functions to manage the various ITEMLISTs that we populate internally.
363    The caller is responsible for setting ITP->flags correctly. */
364 
365 static int
it_init_aliases(itp)366 it_init_aliases (itp)
367      ITEMLIST *itp;
368 {
369 #ifdef ALIAS
370   alias_t **alias_list;
371   register int i, n;
372   STRINGLIST *sl;
373 
374   alias_list = all_aliases ();
375   if (alias_list == 0)
376     {
377       itp->slist = (STRINGLIST *)NULL;
378       return 0;
379     }
380   for (n = 0; alias_list[n]; n++)
381     ;
382   sl = strlist_create (n+1);
383   for (i = 0; i < n; i++)
384     sl->list[i] = STRDUP (alias_list[i]->name);
385   sl->list[n] = (char *)NULL;
386   sl->list_size = sl->list_len = n;
387   itp->slist = sl;
388 #else
389   itp->slist = (STRINGLIST *)NULL;
390 #endif
391   free (alias_list);
392   return 1;
393 }
394 
395 static void
init_itemlist_from_varlist(itp,svfunc)396 init_itemlist_from_varlist (itp, svfunc)
397      ITEMLIST *itp;
398      SVFUNC *svfunc;
399 {
400   SHELL_VAR **vlist;
401   STRINGLIST *sl;
402   register int i, n;
403 
404   vlist = (*svfunc) ();
405   if (vlist == 0)
406     {
407       itp->slist = (STRINGLIST *)NULL;
408       return;
409     }
410   for (n = 0; vlist[n]; n++)
411     ;
412   sl = strlist_create (n+1);
413   for (i = 0; i < n; i++)
414     sl->list[i] = savestring (vlist[i]->name);
415   sl->list[sl->list_len = n] = (char *)NULL;
416   itp->slist = sl;
417 }
418 
419 static int
it_init_arrayvars(itp)420 it_init_arrayvars (itp)
421      ITEMLIST *itp;
422 {
423 #if defined (ARRAY_VARS)
424   init_itemlist_from_varlist (itp, all_array_variables);
425   return 1;
426 #else
427   return 0;
428 #endif
429 }
430 
431 static int
it_init_bindings(itp)432 it_init_bindings (itp)
433      ITEMLIST *itp;
434 {
435   char **blist;
436   STRINGLIST *sl;
437 
438   /* rl_funmap_names allocates blist, but not its members */
439   blist = (char **)rl_funmap_names ();	/* XXX fix const later */
440   sl = strlist_create (0);
441   sl->list = blist;
442   sl->list_size = 0;
443   sl->list_len = strvec_len (sl->list);
444   itp->flags |= LIST_DONTFREEMEMBERS;
445   itp->slist = sl;
446 
447   return 0;
448 }
449 
450 static int
it_init_builtins(itp)451 it_init_builtins (itp)
452      ITEMLIST *itp;
453 {
454   STRINGLIST *sl;
455   register int i, n;
456 
457   sl = strlist_create (num_shell_builtins);
458   for (i = n = 0; i < num_shell_builtins; i++)
459     if (shell_builtins[i].function)
460       sl->list[n++] = shell_builtins[i].name;
461   sl->list[sl->list_len = n] = (char *)NULL;
462   itp->flags |= LIST_DONTFREEMEMBERS;
463   itp->slist = sl;
464   return 0;
465 }
466 
467 static int
it_init_enabled(itp)468 it_init_enabled (itp)
469      ITEMLIST *itp;
470 {
471   STRINGLIST *sl;
472   register int i, n;
473 
474   sl = strlist_create (num_shell_builtins);
475   for (i = n = 0; i < num_shell_builtins; i++)
476     {
477       if (shell_builtins[i].function && (shell_builtins[i].flags & BUILTIN_ENABLED))
478 	sl->list[n++] = shell_builtins[i].name;
479     }
480   sl->list[sl->list_len = n] = (char *)NULL;
481   itp->flags |= LIST_DONTFREEMEMBERS;
482   itp->slist = sl;
483   return 0;
484 }
485 
486 static int
it_init_disabled(itp)487 it_init_disabled (itp)
488      ITEMLIST *itp;
489 {
490   STRINGLIST *sl;
491   register int i, n;
492 
493   sl = strlist_create (num_shell_builtins);
494   for (i = n = 0; i < num_shell_builtins; i++)
495     {
496       if (shell_builtins[i].function && ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
497 	sl->list[n++] = shell_builtins[i].name;
498     }
499   sl->list[sl->list_len = n] = (char *)NULL;
500   itp->flags |= LIST_DONTFREEMEMBERS;
501   itp->slist = sl;
502   return 0;
503 }
504 
505 static int
it_init_exported(itp)506 it_init_exported (itp)
507      ITEMLIST *itp;
508 {
509   init_itemlist_from_varlist (itp, all_exported_variables);
510   return 0;
511 }
512 
513 static int
it_init_functions(itp)514 it_init_functions (itp)
515      ITEMLIST *itp;
516 {
517   init_itemlist_from_varlist (itp, all_visible_functions);
518   return 0;
519 }
520 
521 /* Like it_init_builtins, but includes everything the help builtin looks at,
522    not just builtins with an active implementing function. */
523 static int
it_init_helptopics(itp)524 it_init_helptopics (itp)
525      ITEMLIST *itp;
526 {
527   STRINGLIST *sl;
528   register int i, n;
529 
530   sl = strlist_create (num_shell_builtins);
531   for (i = n = 0; i < num_shell_builtins; i++)
532     sl->list[n++] = shell_builtins[i].name;
533   sl->list[sl->list_len = n] = (char *)NULL;
534   itp->flags |= LIST_DONTFREEMEMBERS;
535   itp->slist = sl;
536   return 0;
537 }
538 
539 static int
it_init_hostnames(itp)540 it_init_hostnames (itp)
541      ITEMLIST *itp;
542 {
543   STRINGLIST *sl;
544 
545   sl = strlist_create (0);
546   sl->list = get_hostname_list ();
547   sl->list_len = sl->list ? strvec_len (sl->list) : 0;
548   sl->list_size = sl->list_len;
549   itp->slist = sl;
550   itp->flags |= LIST_DONTFREEMEMBERS|LIST_DONTFREE;
551   return 0;
552 }
553 
554 static int
it_init_joblist(itp,jstate)555 it_init_joblist (itp, jstate)
556      ITEMLIST *itp;
557      int jstate;
558 {
559 #if defined (JOB_CONTROL)
560   STRINGLIST *sl;
561   register int i;
562   register PROCESS *p;
563   char *s, *t;
564   JOB *j;
565   JOB_STATE ws;		/* wanted state */
566 
567   ws = JNONE;
568   if (jstate == 0)
569     ws = JRUNNING;
570   else if (jstate == 1)
571     ws = JSTOPPED;
572 
573   sl = strlist_create (js.j_jobslots);
574   for (i = js.j_jobslots - 1; i >= 0; i--)
575     {
576       j = get_job_by_jid (i);
577       if (j == 0)
578 	continue;
579       p = j->pipe;
580       if (jstate == -1 || JOBSTATE(i) == ws)
581 	{
582 	  s = savestring (p->command);
583 	  t = strpbrk (s, " \t\n");
584 	  if (t)
585 	    *t = '\0';
586 	  sl->list[sl->list_len++] = s;
587 	}
588     }
589   itp->slist = sl;
590 #else
591   itp->slist = (STRINGLIST *)NULL;
592 #endif
593   return 0;
594 }
595 
596 static int
it_init_jobs(itp)597 it_init_jobs (itp)
598      ITEMLIST *itp;
599 {
600   return (it_init_joblist (itp, -1));
601 }
602 
603 static int
it_init_running(itp)604 it_init_running (itp)
605      ITEMLIST *itp;
606 {
607   return (it_init_joblist (itp, 0));
608 }
609 
610 static int
it_init_stopped(itp)611 it_init_stopped (itp)
612      ITEMLIST *itp;
613 {
614   return (it_init_joblist (itp, 1));
615 }
616 
617 static int
it_init_keywords(itp)618 it_init_keywords (itp)
619      ITEMLIST *itp;
620 {
621   STRINGLIST *sl;
622   register int i, n;
623 
624   for (n = 0; word_token_alist[n].word; n++)
625     ;
626   sl = strlist_create (n);
627   for (i = 0; i < n; i++)
628     sl->list[i] = word_token_alist[i].word;
629   sl->list[sl->list_len = i] = (char *)NULL;
630   itp->flags |= LIST_DONTFREEMEMBERS;
631   itp->slist = sl;
632   return 0;
633 }
634 
635 static int
it_init_signals(itp)636 it_init_signals (itp)
637      ITEMLIST *itp;
638 {
639   STRINGLIST *sl;
640 
641   sl = strlist_create (0);
642   sl->list = signal_names;
643   sl->list_len = strvec_len (sl->list);
644   itp->flags |= LIST_DONTFREE;
645   itp->slist = sl;
646   return 0;
647 }
648 
649 static int
it_init_variables(itp)650 it_init_variables (itp)
651      ITEMLIST *itp;
652 {
653   init_itemlist_from_varlist (itp, all_visible_variables);
654   return 0;
655 }
656 
657 static int
it_init_setopts(itp)658 it_init_setopts (itp)
659      ITEMLIST *itp;
660 {
661   STRINGLIST *sl;
662 
663   sl = strlist_create (0);
664   sl->list = get_minus_o_opts ();
665   sl->list_len = strvec_len (sl->list);
666   itp->slist = sl;
667   itp->flags |= LIST_DONTFREEMEMBERS;
668   return 0;
669 }
670 
671 static int
it_init_shopts(itp)672 it_init_shopts (itp)
673      ITEMLIST *itp;
674 {
675   STRINGLIST *sl;
676 
677   sl = strlist_create (0);
678   sl->list = get_shopt_options ();
679   sl->list_len = strvec_len (sl->list);
680   itp->slist = sl;
681   itp->flags |= LIST_DONTFREEMEMBERS;
682   return 0;
683 }
684 
685 /* Generate a list of all matches for TEXT using the STRINGLIST in itp->slist
686    as the list of possibilities.  If the itemlist has been marked dirty or
687    it should be regenerated every time, destroy the old STRINGLIST and make a
688    new one before trying the match.  TEXT is dequoted before attempting a
689    match. */
690 static STRINGLIST *
gen_matches_from_itemlist(itp,text)691 gen_matches_from_itemlist (itp, text)
692      ITEMLIST *itp;
693      const char *text;
694 {
695   STRINGLIST *ret, *sl;
696   int tlen, i, n;
697   char *ntxt;
698 
699   if ((itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) ||
700       (itp->flags & LIST_INITIALIZED) == 0)
701     {
702       if (itp->flags & (LIST_DIRTY|LIST_DYNAMIC))
703 	clean_itemlist (itp);
704       if ((itp->flags & LIST_INITIALIZED) == 0)
705 	initialize_itemlist (itp);
706     }
707   if (itp->slist == 0)
708     return ((STRINGLIST *)NULL);
709   ret = strlist_create (itp->slist->list_len+1);
710   sl = itp->slist;
711 
712   ntxt = bash_dequote_text (text);
713   tlen = STRLEN (ntxt);
714 
715   for (i = n = 0; i < sl->list_len; i++)
716     {
717       if (tlen == 0 || STREQN (sl->list[i], ntxt, tlen))
718 	ret->list[n++] = STRDUP (sl->list[i]);
719     }
720   ret->list[ret->list_len = n] = (char *)NULL;
721 
722   FREE (ntxt);
723   return ret;
724 }
725 
726 /* A wrapper for rl_filename_completion_function that dequotes the filename
727    before attempting completions. */
728 static char *
pcomp_filename_completion_function(text,state)729 pcomp_filename_completion_function (text, state)
730      const char *text;
731      int state;
732 {
733   static char *dfn;	/* dequoted filename */
734   int iscompgen, iscompleting;
735 
736   if (state == 0)
737     {
738       FREE (dfn);
739       /* remove backslashes quoting special characters in filenames. */
740       /* There are roughly three paths we can follow to get here:
741 		1.  complete -f
742 		2.  compgen -f "$word" from a completion function
743 		3.  compgen -f "$word" from the command line
744 	 They all need to be handled.
745 
746 	 In the first two cases, readline will run the filename dequoting
747 	 function in rl_filename_completion_function if it found a filename
748 	 quoting character in the word to be completed
749 	 (rl_completion_found_quote).  We run the dequoting function here
750 	 if we're running compgen, we're not completing, and the
751 	 rl_filename_completion_function won't dequote the filename
752 	 (rl_completion_found_quote == 0). */
753       iscompgen = this_shell_builtin == compgen_builtin;
754       iscompleting = RL_ISSTATE (RL_STATE_COMPLETING);
755       if (iscompgen && iscompleting == 0 && rl_completion_found_quote == 0
756 	  && rl_filename_dequoting_function)
757 	{
758 	  /* Use rl_completion_quote_character because any single or
759 	     double quotes have been removed by the time TEXT makes it
760 	     here, and we don't want to remove backslashes inside
761 	     quoted strings. */
762 	  dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
763 	}
764       /* Intended to solve a mismatched assumption by bash-completion.  If
765 	 the text to be completed is empty, but bash-completion turns it into
766 	 a quoted string ('') assuming that this code will dequote it before
767 	 calling readline, do the dequoting. */
768       else if (iscompgen && iscompleting &&
769 	       pcomp_curtxt && *pcomp_curtxt == 0 &&
770 	       text && (*text == '\'' || *text == '"') && text[1] == text[0] && text[2] == 0 &&
771 	       rl_filename_dequoting_function)
772 	dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
773       /* Another mismatched assumption by bash-completion.  If compgen is being
774       	 run as part of bash-completion, and the argument to compgen is not
775       	 the same as the word originally passed to the programmable completion
776       	 code, dequote the argument if it has quote characters.  It's an
777       	 attempt to detect when bash-completion is quoting its filename
778       	 argument before calling compgen. */
779       /* We could check whether gen_shell_function_matches is in the call
780 	 stack by checking whether the gen-shell-function-matches tag is in
781 	 the unwind-protect stack, but there's no function to do that yet.
782 	 We could simply check whether we're executing in a function by
783 	 checking variable_context, and may end up doing that. */
784       else if (iscompgen && iscompleting && rl_filename_dequoting_function &&
785 	       pcomp_curtxt && text &&
786 	       STREQ (pcomp_curtxt, text) == 0 &&
787 	       variable_context &&
788 	       sh_contains_quotes (text))	/* guess */
789 	dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
790       else
791 	dfn = savestring (text);
792     }
793 
794   return (rl_filename_completion_function (dfn, state));
795 }
796 
797 #define GEN_COMPS(bmap, flag, it, text, glist, tlist) \
798   do { \
799     if (bmap & flag) \
800       { \
801 	tlist = gen_matches_from_itemlist (it, text); \
802 	if (tlist) \
803 	  { \
804 	    glist = strlist_append (glist, tlist); \
805 	    strlist_dispose (tlist); \
806 	  } \
807       } \
808   } while (0)
809 
810 #define GEN_XCOMPS(bmap, flag, text, func, cmatches, glist, tlist) \
811   do { \
812     if (bmap & flag) \
813       { \
814 	cmatches = rl_completion_matches (text, func); \
815 	tlist = completions_to_stringlist (cmatches); \
816 	glist = strlist_append (glist, tlist); \
817 	strvec_dispose (cmatches); \
818 	strlist_dispose (tlist); \
819       } \
820   } while (0)
821 
822 /* Functions to generate lists of matches from the actions member of CS. */
823 
824 static STRINGLIST *
gen_action_completions(cs,text)825 gen_action_completions (cs, text)
826      COMPSPEC *cs;
827      const char *text;
828 {
829   STRINGLIST *ret, *tmatches;
830   char **cmatches;	/* from rl_completion_matches ... */
831   unsigned long flags;
832   int t;
833 
834   ret = tmatches = (STRINGLIST *)NULL;
835   flags = cs->actions;
836 
837   GEN_COMPS (flags, CA_ALIAS, &it_aliases, text, ret, tmatches);
838   GEN_COMPS (flags, CA_ARRAYVAR, &it_arrayvars, text, ret, tmatches);
839   GEN_COMPS (flags, CA_BINDING, &it_bindings, text, ret, tmatches);
840   GEN_COMPS (flags, CA_BUILTIN, &it_builtins, text, ret, tmatches);
841   GEN_COMPS (flags, CA_DISABLED, &it_disabled, text, ret, tmatches);
842   GEN_COMPS (flags, CA_ENABLED, &it_enabled, text, ret, tmatches);
843   GEN_COMPS (flags, CA_EXPORT, &it_exports, text, ret, tmatches);
844   GEN_COMPS (flags, CA_FUNCTION, &it_functions, text, ret, tmatches);
845   GEN_COMPS (flags, CA_HELPTOPIC, &it_helptopics, text, ret, tmatches);
846   GEN_COMPS (flags, CA_HOSTNAME, &it_hostnames, text, ret, tmatches);
847   GEN_COMPS (flags, CA_JOB, &it_jobs, text, ret, tmatches);
848   GEN_COMPS (flags, CA_KEYWORD, &it_keywords, text, ret, tmatches);
849   GEN_COMPS (flags, CA_RUNNING, &it_running, text, ret, tmatches);
850   GEN_COMPS (flags, CA_SETOPT, &it_setopts, text, ret, tmatches);
851   GEN_COMPS (flags, CA_SHOPT, &it_shopts, text, ret, tmatches);
852   GEN_COMPS (flags, CA_SIGNAL, &it_signals, text, ret, tmatches);
853   GEN_COMPS (flags, CA_STOPPED, &it_stopped, text, ret, tmatches);
854   GEN_COMPS (flags, CA_VARIABLE, &it_variables, text, ret, tmatches);
855 
856   GEN_XCOMPS(flags, CA_COMMAND, text, command_word_completion_function, cmatches, ret, tmatches);
857   GEN_XCOMPS(flags, CA_FILE, text, pcomp_filename_completion_function, cmatches, ret, tmatches);
858   GEN_XCOMPS(flags, CA_USER, text, rl_username_completion_function, cmatches, ret, tmatches);
859   GEN_XCOMPS(flags, CA_GROUP, text, bash_groupname_completion_function, cmatches, ret, tmatches);
860   GEN_XCOMPS(flags, CA_SERVICE, text, bash_servicename_completion_function, cmatches, ret, tmatches);
861 
862   /* And lastly, the special case for directories */
863   if (flags & CA_DIRECTORY)
864     {
865       t = rl_filename_completion_desired;
866       rl_completion_mark_symlink_dirs = 1;	/* override user preference */
867       cmatches = bash_directory_completion_matches (text);
868       /* If we did not want filename completion before this, and there are
869 	 no matches, turn off rl_filename_completion_desired so whatever
870 	 matches we get are not treated as filenames (it gets turned on by
871 	 rl_filename_completion_function unconditionally). */
872       if (t == 0 && cmatches == 0 && rl_filename_completion_desired == 1)
873         rl_filename_completion_desired = 0;
874       tmatches = completions_to_stringlist (cmatches);
875       ret = strlist_append (ret, tmatches);
876       strvec_dispose (cmatches);
877       strlist_dispose (tmatches);
878     }
879 
880   return ret;
881 }
882 
883 /* Generate a list of matches for CS->globpat.  Unresolved: should this use
884    TEXT as a match prefix, or just go without?  Currently, the code does not
885    use TEXT, just globs CS->globpat and returns the results.  If we do decide
886    to use TEXT, we should call quote_string_for_globbing before the call to
887    glob_filename. */
888 static STRINGLIST *
gen_globpat_matches(cs,text)889 gen_globpat_matches (cs, text)
890       COMPSPEC *cs;
891       const char *text;
892 {
893   STRINGLIST *sl;
894 
895   sl = strlist_create (0);
896   sl->list = glob_filename (cs->globpat, 0);
897   if (GLOB_FAILED (sl->list))
898     sl->list = (char **)NULL;
899   if (sl->list)
900     sl->list_len = sl->list_size = strvec_len (sl->list);
901   return sl;
902 }
903 
904 /* Perform the shell word expansions on CS->words and return the results.
905    Again, this ignores TEXT. */
906 static STRINGLIST *
gen_wordlist_matches(cs,text)907 gen_wordlist_matches (cs, text)
908      COMPSPEC *cs;
909      const char *text;
910 {
911   WORD_LIST *l, *l2;
912   STRINGLIST *sl;
913   int nw, tlen;
914   char *ntxt;		/* dequoted TEXT to use in comparisons */
915 
916   if (cs->words == 0 || cs->words[0] == '\0')
917     return ((STRINGLIST *)NULL);
918 
919   /* This used to be a simple expand_string(cs->words, 0), but that won't
920      do -- there's no way to split a simple list into individual words
921      that way, since the shell semantics say that word splitting is done
922      only on the results of expansion.  split_at_delims also handles embedded
923      quoted strings and preserves the quotes for the expand_words_shellexp
924      function call that follows. */
925   /* XXX - this is where this function spends most of its time */
926   l = split_at_delims (cs->words, strlen (cs->words), (char *)NULL, -1, 0, (int *)NULL, (int *)NULL);
927   if (l == 0)
928     return ((STRINGLIST *)NULL);
929   /* This will jump back to the top level if the expansion fails... */
930   l2 = expand_words_shellexp (l);
931   dispose_words (l);
932 
933   nw = list_length (l2);
934   sl = strlist_create (nw + 1);
935 
936   ntxt = bash_dequote_text (text);
937   tlen = STRLEN (ntxt);
938 
939   for (nw = 0, l = l2; l; l = l->next)
940     {
941       if (tlen == 0 || STREQN (l->word->word, ntxt, tlen))
942 	sl->list[nw++] = STRDUP (l->word->word);
943     }
944   sl->list[sl->list_len = nw] = (char *)NULL;
945 
946   dispose_words (l2);
947   FREE (ntxt);
948   return sl;
949 }
950 
951 #ifdef ARRAY_VARS
952 
953 static SHELL_VAR *
bind_comp_words(lwords)954 bind_comp_words (lwords)
955      WORD_LIST *lwords;
956 {
957   SHELL_VAR *v;
958 
959   v = find_variable_noref ("COMP_WORDS");
960   if (v == 0)
961     v = make_new_array_variable ("COMP_WORDS");
962   if (nameref_p (v))
963     VUNSETATTR (v, att_nameref);
964 #if 0
965   if (readonly_p (v))
966     VUNSETATTR (v, att_readonly);
967 #endif
968   if (array_p (v) == 0)
969     v = convert_var_to_array (v);
970   v = assign_array_var_from_word_list (v, lwords, 0);
971 
972   VUNSETATTR (v, att_invisible);
973   return v;
974 }
975 #endif /* ARRAY_VARS */
976 
977 static void
bind_compfunc_variables(line,ind,lwords,cw,exported)978 bind_compfunc_variables (line, ind, lwords, cw, exported)
979      char *line;
980      int ind;
981      WORD_LIST *lwords;
982      int cw, exported;
983 {
984   char ibuf[INT_STRLEN_BOUND(int) + 1];
985   char *value;
986   SHELL_VAR *v;
987   size_t llen;
988   int c;
989 
990   /* Set the variables that the function expects while it executes.  Maybe
991      these should be in the function environment (temporary_env). */
992   v = bind_variable ("COMP_LINE", line, 0);
993   if (v && exported)
994     VSETATTR(v, att_exported);
995 
996   /* Post bash-4.2: COMP_POINT is characters instead of bytes. */
997   c = line[ind];
998   line[ind] = '\0';
999   llen = MB_STRLEN (line);
1000   line[ind] = c;
1001   value = inttostr (llen, ibuf, sizeof(ibuf));
1002   v = bind_int_variable ("COMP_POINT", value, 0);
1003   if (v && exported)
1004     VSETATTR(v, att_exported);
1005 
1006   value = inttostr (rl_completion_type, ibuf, sizeof (ibuf));
1007   v = bind_int_variable ("COMP_TYPE", value, 0);
1008   if (v && exported)
1009     VSETATTR(v, att_exported);
1010 
1011   value = inttostr (rl_completion_invoking_key, ibuf, sizeof (ibuf));
1012   v = bind_int_variable ("COMP_KEY", value, 0);
1013   if (v && exported)
1014     VSETATTR(v, att_exported);
1015 
1016   /* Since array variables can't be exported, we don't bother making the
1017      array of words. */
1018   if (exported == 0)
1019     {
1020 #ifdef ARRAY_VARS
1021       v = bind_comp_words (lwords);
1022       value = inttostr (cw, ibuf, sizeof(ibuf));
1023       bind_int_variable ("COMP_CWORD", value, 0);
1024 #endif
1025     }
1026   else
1027     array_needs_making = 1;
1028 }
1029 
1030 static void
unbind_compfunc_variables(exported)1031 unbind_compfunc_variables (exported)
1032      int exported;
1033 {
1034   unbind_variable_noref ("COMP_LINE");
1035   unbind_variable_noref ("COMP_POINT");
1036   unbind_variable_noref ("COMP_TYPE");
1037   unbind_variable_noref ("COMP_KEY");
1038 #ifdef ARRAY_VARS
1039   unbind_variable_noref ("COMP_WORDS");
1040   unbind_variable_noref ("COMP_CWORD");
1041 #endif
1042   if (exported)
1043     array_needs_making = 1;
1044 }
1045 
1046 /* Build the list of words to pass to a function or external command
1047    as arguments.  When the function or command is invoked,
1048 
1049 	$0 == function or command being invoked
1050    	$1 == command name
1051    	$2 == word to be completed (possibly null)
1052    	$3 == previous word
1053 
1054    Functions can access all of the words in the current command line
1055    with the COMP_WORDS array.  External commands cannot; they have to
1056    make do with the COMP_LINE and COMP_POINT variables. */
1057 
1058 static WORD_LIST *
build_arg_list(cmd,cname,text,lwords,ind)1059 build_arg_list (cmd, cname, text, lwords, ind)
1060      char *cmd;
1061      const char *cname;
1062      const char *text;
1063      WORD_LIST *lwords;
1064      int ind;
1065 {
1066   WORD_LIST *ret, *cl, *l;
1067   WORD_DESC *w;
1068   int i;
1069 
1070   ret = (WORD_LIST *)NULL;
1071   w = make_word (cmd);
1072   ret = make_word_list (w, (WORD_LIST *)NULL);	/* $0 */
1073 
1074   w = make_word (cname);			/* $1 */
1075   cl = ret->next = make_word_list (w, (WORD_LIST *)NULL);
1076 
1077   w = make_word (text);
1078   cl->next = make_word_list (w, (WORD_LIST *)NULL);	/* $2 */
1079   cl = cl->next;
1080 
1081   /* Search lwords for current word */
1082   for (l = lwords, i = 1; l && i < ind-1; l = l->next, i++)
1083     ;
1084   w = (l && l->word) ? copy_word (l->word) : make_word ("");
1085   cl->next = make_word_list (w, (WORD_LIST *)NULL);
1086 
1087   return ret;
1088 }
1089 
1090 /* Build a command string with
1091 	$0 == cs->funcname	(function to execute for completion list)
1092    	$1 == command name	(command being completed)
1093    	$2 = word to be completed (possibly null)
1094    	$3 = previous word
1095    and run in the current shell.  The function should put its completion
1096    list into the array variable COMPREPLY.  We build a STRINGLIST
1097    from the results and return it.
1098 
1099    Since the shell function should return its list of matches in an array
1100    variable, this does nothing if arrays are not compiled into the shell. */
1101 
1102 static STRINGLIST *
gen_shell_function_matches(cs,cmd,text,line,ind,lwords,nw,cw,foundp)1103 gen_shell_function_matches (cs, cmd, text, line, ind, lwords, nw, cw, foundp)
1104      COMPSPEC *cs;
1105      const char *cmd;
1106      const char *text;
1107      char *line;
1108      int ind;
1109      WORD_LIST *lwords;
1110      int nw, cw;
1111      int *foundp;
1112 {
1113   char *funcname;
1114   STRINGLIST *sl;
1115   SHELL_VAR *f, *v;
1116   WORD_LIST *cmdlist;
1117   int fval, found;
1118   sh_parser_state_t ps;
1119   sh_parser_state_t * restrict pps;
1120 #if defined (ARRAY_VARS)
1121   ARRAY *a;
1122 #endif
1123 
1124   found = 0;
1125   if (foundp)
1126     *foundp = found;
1127 
1128   funcname = cs->funcname;
1129   f = find_function (funcname);
1130   if (f == 0)
1131     {
1132       internal_error (_("completion: function `%s' not found"), funcname);
1133       rl_ding ();
1134       rl_on_new_line ();
1135       return ((STRINGLIST *)NULL);
1136     }
1137 
1138 #if !defined (ARRAY_VARS)
1139   return ((STRINGLIST *)NULL);
1140 #else
1141 
1142   /* We pass cw - 1 because command_line_to_word_list returns indices that are
1143      1-based, while bash arrays are 0-based. */
1144   bind_compfunc_variables (line, ind, lwords, cw - 1, 0);
1145 
1146   cmdlist = build_arg_list (funcname, cmd, text, lwords, cw);
1147 
1148   pps = &ps;
1149   save_parser_state (pps);
1150   begin_unwind_frame ("gen-shell-function-matches");
1151   add_unwind_protect (restore_parser_state, (char *)pps);
1152   add_unwind_protect (dispose_words, (char *)cmdlist);
1153   add_unwind_protect (unbind_compfunc_variables, (char *)0);
1154 
1155   fval = execute_shell_function (f, cmdlist);
1156 
1157   discard_unwind_frame ("gen-shell-function-matches");
1158   restore_parser_state (pps);
1159 
1160   found = fval != EX_NOTFOUND;
1161   if (fval == EX_RETRYFAIL)
1162     found |= PCOMP_RETRYFAIL;
1163   if (foundp)
1164     *foundp = found;
1165 
1166   /* Now clean up and destroy everything. */
1167   dispose_words (cmdlist);
1168   unbind_compfunc_variables (0);
1169 
1170   /* The list of completions is returned in the array variable COMPREPLY. */
1171   v = find_variable ("COMPREPLY");
1172   if (v == 0)
1173     return ((STRINGLIST *)NULL);
1174   if (array_p (v) == 0 && assoc_p (v) == 0)
1175     v = convert_var_to_array (v);
1176 
1177   VUNSETATTR (v, att_invisible);
1178 
1179   a = array_cell (v);
1180   if (found == 0 || (found & PCOMP_RETRYFAIL) || a == 0 || array_p (v) == 0 || array_empty (a))
1181     sl = (STRINGLIST *)NULL;
1182   else
1183     {
1184       /* XXX - should we filter the list of completions so only those matching
1185 	 TEXT are returned?  Right now, we do not. */
1186       sl = strlist_create (0);
1187       sl->list = array_to_argv (a, 0);
1188       sl->list_len = sl->list_size = array_num_elements (a);
1189     }
1190 
1191   /* XXX - should we unbind COMPREPLY here? */
1192   unbind_variable_noref ("COMPREPLY");
1193 
1194   return (sl);
1195 #endif
1196 }
1197 
1198 /* Build a command string with
1199 	$0 == cs->command	(command to execute for completion list)
1200    	$1 == command name	(command being completed)
1201 	$2 == word to be completed (possibly null)
1202 	$3 == previous word
1203    and run it with command substitution.  Parse the results, one word
1204    per line, with backslashes allowed to escape newlines.  Build a
1205    STRINGLIST from the results and return it. */
1206 
1207 static STRINGLIST *
gen_command_matches(cs,cmd,text,line,ind,lwords,nw,cw)1208 gen_command_matches (cs, cmd, text, line, ind, lwords, nw, cw)
1209      COMPSPEC *cs;
1210      const char *cmd;
1211      const char *text;
1212      char *line;
1213      int ind;
1214      WORD_LIST *lwords;
1215      int nw, cw;
1216 {
1217   char *csbuf, *cscmd, *t;
1218   int cmdlen, cmdsize, n, ws, we;
1219   WORD_LIST *cmdlist, *cl;
1220   WORD_DESC *tw;
1221   STRINGLIST *sl;
1222 
1223   bind_compfunc_variables (line, ind, lwords, cw, 1);
1224   cmdlist = build_arg_list (cs->command, cmd, text, lwords, cw);
1225 
1226   /* Estimate the size needed for the buffer. */
1227   n = strlen (cs->command);
1228   cmdsize = n + 1;
1229   for (cl = cmdlist->next; cl; cl = cl->next)
1230     cmdsize += STRLEN (cl->word->word) + 3;
1231   cmdsize += 2;
1232 
1233   /* allocate the string for the command and fill it in. */
1234   cscmd = (char *)xmalloc (cmdsize + 1);
1235 
1236   strcpy (cscmd, cs->command);			/* $0 */
1237   cmdlen = n;
1238   cscmd[cmdlen++] = ' ';
1239   for (cl = cmdlist->next; cl; cl = cl->next)   /* $1, $2, $3, ... */
1240     {
1241       t = sh_single_quote (cl->word->word ? cl->word->word : "");
1242       n = strlen (t);
1243       RESIZE_MALLOCED_BUFFER (cscmd, cmdlen, n + 2, cmdsize, 64);
1244       strcpy (cscmd + cmdlen, t);
1245       cmdlen += n;
1246       if (cl->next)
1247 	cscmd[cmdlen++] = ' ';
1248       free (t);
1249     }
1250   cscmd[cmdlen] = '\0';
1251 
1252   tw = command_substitute (cscmd, 0, 0);
1253   csbuf = tw ? tw->word : (char *)NULL;
1254   if (tw)
1255     dispose_word_desc (tw);
1256 
1257   /* Now clean up and destroy everything. */
1258   dispose_words (cmdlist);
1259   free (cscmd);
1260   unbind_compfunc_variables (1);
1261 
1262   if (csbuf == 0 || *csbuf == '\0')
1263     {
1264       FREE (csbuf);
1265       return ((STRINGLIST *)NULL);
1266     }
1267 
1268   /* Now break CSBUF up at newlines, with backslash allowed to escape a
1269      newline, and put the individual words into a STRINGLIST. */
1270   sl = strlist_create (16);
1271   for (ws = 0; csbuf[ws]; )
1272     {
1273       we = ws;
1274       while (csbuf[we] && csbuf[we] != '\n')
1275 	{
1276 	  if (csbuf[we] == '\\' && csbuf[we+1] == '\n')
1277 	    we++;
1278 	  we++;
1279 	}
1280       t = substring (csbuf, ws, we);
1281       if (sl->list_len >= sl->list_size - 1)
1282 	strlist_resize (sl, sl->list_size + 16);
1283       sl->list[sl->list_len++] = t;
1284       while (csbuf[we] == '\n') we++;
1285       ws = we;
1286     }
1287   sl->list[sl->list_len] = (char *)NULL;
1288 
1289   free (csbuf);
1290   return (sl);
1291 }
1292 
1293 static WORD_LIST *
command_line_to_word_list(line,llen,sentinel,nwp,cwp)1294 command_line_to_word_list (line, llen, sentinel, nwp, cwp)
1295      char *line;
1296      int llen, sentinel, *nwp, *cwp;
1297 {
1298   WORD_LIST *ret;
1299   char *delims;
1300 
1301 #if 0
1302   delims = "()<>;&| \t\n";	/* shell metacharacters break words */
1303 #else
1304   delims = rl_completer_word_break_characters;
1305 #endif
1306   ret = split_at_delims (line, llen, delims, sentinel, SD_NOQUOTEDELIM|SD_COMPLETE, nwp, cwp);
1307   return (ret);
1308 }
1309 
1310 /* Evaluate COMPSPEC *cs and return all matches for WORD. */
1311 
1312 STRINGLIST *
gen_compspec_completions(cs,cmd,word,start,end,foundp)1313 gen_compspec_completions (cs, cmd, word, start, end, foundp)
1314      COMPSPEC *cs;
1315      const char *cmd;
1316      const char *word;
1317      int start, end;
1318      int *foundp;
1319 {
1320   STRINGLIST *ret, *tmatches;
1321   char *line;
1322   int llen, nw, cw, found, foundf;
1323   WORD_LIST *lwords;
1324   WORD_DESC *lw;
1325   COMPSPEC *tcs;
1326 
1327   found = 1;
1328 
1329 #ifdef DEBUG
1330   debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd, word, start, end);
1331   debug_printf ("gen_compspec_completions: %s -> %p", cmd, cs);
1332 #endif
1333   ret = gen_action_completions (cs, word);
1334 #ifdef DEBUG
1335   if (ret && progcomp_debug)
1336     {
1337       debug_printf ("gen_action_completions (%p, %s) -->", cs, word);
1338       strlist_print (ret, "\t");
1339       rl_on_new_line ();
1340     }
1341 #endif
1342 
1343   /* Now we start generating completions based on the other members of CS. */
1344   if (cs->globpat)
1345     {
1346       tmatches = gen_globpat_matches (cs, word);
1347       if (tmatches)
1348 	{
1349 #ifdef DEBUG
1350 	  if (progcomp_debug)
1351 	    {
1352 	      debug_printf ("gen_globpat_matches (%p, %s) -->", cs, word);
1353 	      strlist_print (tmatches, "\t");
1354 	      rl_on_new_line ();
1355 	    }
1356 #endif
1357 	  ret = strlist_append (ret, tmatches);
1358 	  strlist_dispose (tmatches);
1359 	  rl_filename_completion_desired = 1;
1360 	}
1361     }
1362 
1363   if (cs->words)
1364     {
1365       tmatches = gen_wordlist_matches (cs, word);
1366       if (tmatches)
1367 	{
1368 #ifdef DEBUG
1369 	  if (progcomp_debug)
1370 	    {
1371 	      debug_printf ("gen_wordlist_matches (%p, %s) -->", cs, word);
1372 	      strlist_print (tmatches, "\t");
1373 	      rl_on_new_line ();
1374 	    }
1375 #endif
1376 	  ret = strlist_append (ret, tmatches);
1377 	  strlist_dispose (tmatches);
1378 	}
1379     }
1380 
1381   lwords = (WORD_LIST *)NULL;
1382   line = (char *)NULL;
1383   if (cs->command || cs->funcname)
1384     {
1385       /* If we have a command or function to execute, we need to first break
1386 	 the command line into individual words, find the number of words,
1387 	 and find the word in the list containing the word to be completed. */
1388       line = substring (pcomp_line, start, end);
1389       llen = end - start;
1390 
1391 #ifdef DEBUG
1392       debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
1393 		line, llen, pcomp_ind - start, &nw, &cw);
1394 #endif
1395       lwords = command_line_to_word_list (line, llen, pcomp_ind - start, &nw, &cw);
1396       /* If we skipped a NULL word at the beginning of the line, add it back */
1397       if (lwords && lwords->word && cmd[0] == 0 && lwords->word->word[0] != 0)
1398 	{
1399 	  lw = make_bare_word (cmd);
1400 	  lwords = make_word_list (lw, lwords);
1401 	  nw++;
1402 	  cw++;
1403 	}
1404 #ifdef DEBUG
1405       if (lwords == 0 && llen > 0)
1406 	debug_printf ("ERROR: command_line_to_word_list returns NULL");
1407       else if (progcomp_debug)
1408 	{
1409 	  debug_printf ("command_line_to_word_list -->");
1410 	  printf ("\t");
1411 	  print_word_list (lwords, "!");
1412 	  printf ("\n");
1413 	  fflush(stdout);
1414 	  rl_on_new_line ();
1415 	}
1416 #endif
1417     }
1418 
1419   if (cs->funcname)
1420     {
1421       foundf = 0;
1422       tmatches = gen_shell_function_matches (cs, cmd, word, line, pcomp_ind - start, lwords, nw, cw, &foundf);
1423       if (foundf != 0)
1424 	found = foundf;
1425       if (tmatches)
1426 	{
1427 #ifdef DEBUG
1428 	  if (progcomp_debug)
1429 	    {
1430 	      debug_printf ("gen_shell_function_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
1431 	      strlist_print (tmatches, "\t");
1432 	      rl_on_new_line ();
1433 	    }
1434 #endif
1435 	  ret = strlist_append (ret, tmatches);
1436 	  strlist_dispose (tmatches);
1437 	}
1438     }
1439 
1440   if (cs->command)
1441     {
1442       tmatches = gen_command_matches (cs, cmd, word, line, pcomp_ind - start, lwords, nw, cw);
1443       if (tmatches)
1444 	{
1445 #ifdef DEBUG
1446 	  if (progcomp_debug)
1447 	    {
1448 	      debug_printf ("gen_command_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
1449 	      strlist_print (tmatches, "\t");
1450 	      rl_on_new_line ();
1451 	    }
1452 #endif
1453 	  ret = strlist_append (ret, tmatches);
1454 	  strlist_dispose (tmatches);
1455 	}
1456     }
1457 
1458   if (cs->command || cs->funcname)
1459     {
1460       if (lwords)
1461 	dispose_words (lwords);
1462       FREE (line);
1463     }
1464 
1465   if (foundp)
1466     *foundp = found;
1467 
1468   if (found == 0 || (found & PCOMP_RETRYFAIL))
1469     {
1470       strlist_dispose (ret);
1471       return NULL;
1472     }
1473 
1474   if (cs->filterpat)
1475     {
1476       tmatches = filter_stringlist (ret, cs->filterpat, word);
1477 #ifdef DEBUG
1478       if (progcomp_debug)
1479 	{
1480 	  debug_printf ("filter_stringlist (%p, %s, %s) -->", ret, cs->filterpat, word);
1481 	  strlist_print (tmatches, "\t");
1482 	  rl_on_new_line ();
1483 	}
1484 #endif
1485       if (ret && ret != tmatches)
1486 	{
1487 	  FREE (ret->list);
1488 	  free (ret);
1489 	}
1490       ret = tmatches;
1491     }
1492 
1493   if (cs->prefix || cs->suffix)
1494     ret = strlist_prefix_suffix (ret, cs->prefix, cs->suffix);
1495 
1496   /* If no matches have been generated and the user has specified that
1497       directory completion should be done as a default, call
1498       gen_action_completions again to generate a list of matching directory
1499       names. */
1500   if ((ret == 0 || ret->list_len == 0) && (cs->options & COPT_DIRNAMES))
1501     {
1502       tcs = compspec_create ();
1503       tcs->actions = CA_DIRECTORY;
1504       FREE (ret);
1505       ret = gen_action_completions (tcs, word);
1506       compspec_dispose (tcs);
1507     }
1508   else if (cs->options & COPT_PLUSDIRS)
1509     {
1510       tcs = compspec_create ();
1511       tcs->actions = CA_DIRECTORY;
1512       tmatches = gen_action_completions (tcs, word);
1513       ret = strlist_append (ret, tmatches);
1514       strlist_dispose (tmatches);
1515       compspec_dispose (tcs);
1516     }
1517 
1518   return (ret);
1519 }
1520 
1521 void
pcomp_set_readline_variables(flags,nval)1522 pcomp_set_readline_variables (flags, nval)
1523      int flags, nval;
1524 {
1525   /* If the user specified that the compspec returns filenames, make
1526      sure that readline knows it. */
1527   if (flags & COPT_FILENAMES)
1528     rl_filename_completion_desired = nval;
1529   /* If the user doesn't want a space appended, tell readline. */
1530   if (flags & COPT_NOSPACE)
1531     rl_completion_suppress_append = nval;
1532   /* The value here is inverted, since the default is on and the `noquote'
1533      option is supposed to turn it off */
1534   if (flags & COPT_NOQUOTE)
1535     rl_filename_quoting_desired = 1 - nval;
1536   if (flags & COPT_NOSORT)
1537     rl_sort_completion_matches = 1 - nval;
1538 }
1539 
1540 /* Set or unset FLAGS in the options word of the current compspec.
1541    SET_OR_UNSET is 1 for setting, 0 for unsetting. */
1542 void
pcomp_set_compspec_options(cs,flags,set_or_unset)1543 pcomp_set_compspec_options (cs, flags, set_or_unset)
1544      COMPSPEC *cs;
1545      int flags, set_or_unset;
1546 {
1547   if (cs == 0 && ((cs = pcomp_curcs) == 0))
1548     return;
1549   if (set_or_unset)
1550     cs->options |= flags;
1551   else
1552     cs->options &= ~flags;
1553 }
1554 
1555 static STRINGLIST *
gen_progcomp_completions(ocmd,cmd,word,start,end,foundp,retryp,lastcs)1556 gen_progcomp_completions (ocmd, cmd, word, start, end, foundp, retryp, lastcs)
1557      const char *ocmd;
1558      const char *cmd;
1559      const char *word;
1560      int start, end;
1561      int *foundp, *retryp;
1562      COMPSPEC **lastcs;
1563 {
1564   COMPSPEC *cs, *oldcs;
1565   const char *oldcmd, *oldtxt;
1566   STRINGLIST *ret;
1567 
1568   cs = progcomp_search (ocmd);
1569 
1570   if (cs == 0 || cs == *lastcs)
1571     {
1572 #if 0
1573       if (foundp)
1574 	*foundp = 0;
1575 #endif
1576       return (NULL);
1577     }
1578 
1579   if (*lastcs)
1580     compspec_dispose (*lastcs);
1581   cs->refcount++;	/* XXX */
1582   *lastcs = cs;
1583 
1584   cs = compspec_copy (cs);
1585 
1586   oldcs = pcomp_curcs;
1587   oldcmd = pcomp_curcmd;
1588   oldtxt = pcomp_curtxt;
1589 
1590   pcomp_curcs = cs;
1591   pcomp_curcmd = cmd;
1592   pcomp_curtxt = word;
1593 
1594   ret = gen_compspec_completions (cs, cmd, word, start, end, foundp);
1595 
1596   pcomp_curcs = oldcs;
1597   pcomp_curcmd = oldcmd;
1598   pcomp_curtxt = oldtxt;
1599 
1600   /* We need to conditionally handle setting *retryp here */
1601   if (retryp)
1602     *retryp = foundp && (*foundp & PCOMP_RETRYFAIL);
1603 
1604   if (foundp)
1605     {
1606       *foundp &= ~PCOMP_RETRYFAIL;
1607       *foundp |= cs->options;
1608     }
1609 
1610   compspec_dispose (cs);
1611   return ret;
1612 }
1613 
1614 /* The driver function for the programmable completion code.  Returns a list
1615    of matches for WORD, which is an argument to command CMD.  START and END
1616    bound the command currently being completed in pcomp_line (usually
1617    rl_line_buffer). */
1618 char **
programmable_completions(cmd,word,start,end,foundp)1619 programmable_completions (cmd, word, start, end, foundp)
1620      const char *cmd;
1621      const char *word;
1622      int start, end, *foundp;
1623 {
1624   COMPSPEC *lastcs;
1625   STRINGLIST *ret;
1626   char **rmatches, *t;
1627   int found, retry, count;
1628   char *ocmd;
1629   int oend;
1630 #if defined (ALIAS)
1631   alias_t *al;
1632 #endif
1633 
1634   lastcs = 0;
1635   found = count = 0;
1636 
1637   pcomp_line = rl_line_buffer;
1638   pcomp_ind = rl_point;
1639 
1640   ocmd = (char *)cmd;
1641   oend = end;
1642 
1643   do
1644     {
1645       retry = 0;
1646 
1647       /* We look at the basename of CMD if the full command does not have
1648 	 an associated COMPSPEC. */
1649       ret = gen_progcomp_completions (ocmd, ocmd, word, start, oend, &found, &retry, &lastcs);
1650       if (found == 0)
1651 	{
1652 	  t = strrchr (ocmd, '/');
1653 	  if (t && *(++t))
1654 	    ret = gen_progcomp_completions (t, ocmd, word, start, oend, &found, &retry, &lastcs);
1655 	}
1656 
1657       if (found == 0)
1658 	ret = gen_progcomp_completions (DEFAULTCMD, ocmd, word, start, oend, &found, &retry, &lastcs);
1659 
1660 #if defined (ALIAS)
1661       /* Look up any alias for CMD, try to gen completions for it */
1662       /* Look up the alias, find the value, build a new line replacing CMD
1663 	 with that value, offsetting PCOMP_IND and END appropriately, reset
1664 	 PCOMP_LINE to the new line and OCMD with the new command name, then
1665 	 call gen_progcomp_completions again. We could use alias_expand for
1666 	 this, but it does more (and less) than we need right now. */
1667       if (found == 0 && retry == 0 && progcomp_alias && (al = find_alias (ocmd)))
1668 	{
1669 	  char *ncmd, *nline, *ntxt;
1670 	  int ind, lendiff;
1671 	  size_t nlen, olen, llen;
1672 
1673 	  /* We found an alias for OCMD. Take the value and build a new line */
1674 	  ntxt = al->value;
1675 	  nlen = strlen (ntxt);
1676 	  if (nlen == 0)
1677 	    break;
1678 	  olen = strlen (ocmd);
1679 	  lendiff = nlen - olen;	/* can be negative */
1680 	  llen = strlen (pcomp_line);
1681 
1682 	  nline = (char *)xmalloc (llen + lendiff + 1);
1683 	  if (start > 0)
1684 	    strncpy (nline, pcomp_line, start);
1685 	  strncpy (nline + start, ntxt, nlen);
1686 	  strcpy (nline + start + nlen, pcomp_line + start + olen);
1687 
1688 	  /* Find the first word of the alias value and use that as OCMD. We
1689 	     don't check the alias value to see whether it begins with a valid
1690 	     command name, so this can be fooled. */
1691 	  ind = skip_to_delim (ntxt, 0, "()<>;&| \t\n", SD_NOJMP|SD_COMPLETE);
1692 	  if (ind > 0)
1693 	    ncmd = substring (ntxt, 0, ind);
1694 	  else
1695 	    {
1696 	      free (nline);
1697 	      break;		/* will free pcomp_line and ocmd later */
1698 	    }
1699 
1700 	  /* Adjust PCOMP_IND and OEND appropriately */
1701 	  pcomp_ind += lendiff;
1702 	  oend += lendiff;
1703 
1704 	  /* Set up values with new line. WORD stays the same. */
1705 	  if (ocmd != cmd)
1706 	    free (ocmd);
1707 	  if (pcomp_line != rl_line_buffer)
1708 	    free (pcomp_line);
1709 
1710 	  ocmd = ncmd;
1711 	  pcomp_line = nline;
1712 
1713 	  /* And go back and start over. */
1714 	  retry = 1;
1715 	}
1716 #endif /* ALIAS */
1717 
1718       count++;
1719 
1720       if (count > 32)
1721 	{
1722 	  internal_warning (_("programmable_completion: %s: possible retry loop"), cmd);
1723 	  break;
1724 	}
1725     }
1726   while (retry);
1727 
1728   if (pcomp_line != rl_line_buffer)
1729     free (pcomp_line);
1730   if (ocmd != cmd)
1731     free (ocmd);
1732 
1733   if (ret)
1734     {
1735       rmatches = ret->list;
1736       free (ret);
1737     }
1738   else
1739     rmatches = (char **)NULL;
1740 
1741   if (foundp)
1742     *foundp = found;
1743 
1744   if (lastcs)	/* XXX - should be while? */
1745     compspec_dispose (lastcs);
1746 
1747   /* XXX restore pcomp_line and pcomp_ind? */
1748   pcomp_line = rl_line_buffer;
1749   pcomp_ind = rl_point;
1750 
1751   return (rmatches);
1752 }
1753 
1754 #endif /* PROGRAMMABLE_COMPLETION */
1755