No specific user configuration
[platform/upstream/bash.git] / pathexp.c
1 /* pathexp.c -- The shell interface to the globbing library. */
2
3 /* Copyright (C) 1995-2014 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 #include "bashtypes.h"
24 #include <stdio.h>
25
26 #if defined (HAVE_UNISTD_H)
27 #  include <unistd.h>
28 #endif
29
30 #include "bashansi.h"
31
32 #include "shell.h"
33 #include "pathexp.h"
34 #include "flags.h"
35
36 #include "shmbutil.h"
37 #include "bashintl.h"
38
39 #include <glob/strmatch.h>
40
41 static int glob_name_is_acceptable __P((const char *));
42 static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
43 static char *split_ignorespec __P((char *, int *));
44                
45 #if defined (USE_POSIX_GLOB_LIBRARY)
46 #  include <glob.h>
47 typedef int posix_glob_errfunc_t __P((const char *, int));
48 #else
49 #  include <glob/glob.h>
50 #endif
51
52 /* Control whether * matches .files in globbing. */
53 int glob_dot_filenames;
54
55 /* Control whether the extended globbing features are enabled. */
56 int extended_glob = EXTGLOB_DEFAULT;
57
58 /* Control enabling special handling of `**' */
59 int glob_star = 0;
60
61 /* Return nonzero if STRING has any unquoted special globbing chars in it.  */
62 int
63 unquoted_glob_pattern_p (string)
64      register char *string;
65 {
66   register int c;
67   char *send;
68   int open;
69
70   DECLARE_MBSTATE;
71
72   open = 0;
73   send = string + strlen (string);
74
75   while (c = *string++)
76     {
77       switch (c)
78         {
79         case '?':
80         case '*':
81           return (1);
82
83         case '[':
84           open++;
85           continue;
86
87         case ']':
88           if (open)
89             return (1);
90           continue;
91
92         case '+':
93         case '@':
94         case '!':
95           if (*string == '(')   /*)*/
96             return (1);
97           continue;
98
99         case CTLESC:
100         case '\\':
101           if (*string++ == '\0')
102             return (0);
103         }
104
105       /* Advance one fewer byte than an entire multibyte character to
106          account for the auto-increment in the loop above. */
107 #ifdef HANDLE_MULTIBYTE
108       string--;
109       ADVANCE_CHAR_P (string, send - string);
110       string++;
111 #else
112       ADVANCE_CHAR_P (string, send - string);
113 #endif
114     }
115   return (0);
116 }
117
118 /* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
119    be quoted to match itself. */
120 static inline int
121 ere_char (c)
122      int c;
123 {
124   switch (c)
125     {
126     case '.':
127     case '[':
128     case '\\':
129     case '(':
130     case ')':
131     case '*':
132     case '+':
133     case '?':
134     case '{':
135     case '|':
136     case '^':
137     case '$':
138       return 1;
139     default: 
140       return 0;
141     }
142   return (0);
143 }
144
145 int
146 glob_char_p (s)
147      const char *s;
148 {
149   switch (*s)
150     {
151     case '*':
152     case '[':
153     case ']':
154     case '?':
155     case '\\':
156       return 1;
157     case '+':
158     case '@':
159     case '!':
160       if (s[1] == '(')  /*(*/
161         return 1;
162       break;
163     }
164   return 0;
165 }
166
167 /* PATHNAME can contain characters prefixed by CTLESC; this indicates
168    that the character is to be quoted.  We quote it here in the style
169    that the glob library recognizes.  If flags includes QGLOB_CVTNULL,
170    we change quoted null strings (pathname[0] == CTLNUL) into empty
171    strings (pathname[0] == 0).  If this is called after quote removal
172    is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
173    removal has not been done (for example, before attempting to match a
174    pattern while executing a case statement), flags should include
175    QGLOB_CVTNULL.  If flags includes QGLOB_FILENAME, appropriate quoting
176    to match a filename should be performed.  QGLOB_REGEXP means we're
177    quoting for a Posix ERE (for [[ string =~ pat ]]) and that requires
178    some special handling. */
179 char *
180 quote_string_for_globbing (pathname, qflags)
181      const char *pathname;
182      int qflags;
183 {
184   char *temp;
185   register int i, j;
186   int brack, cclass, collsym, equiv, c, last_was_backslash;
187
188   temp = (char *)xmalloc (2 * strlen (pathname) + 1);
189
190   if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
191     {
192       temp[0] = '\0';
193       return temp;
194     }
195
196   brack = cclass = collsym = equiv = last_was_backslash = 0;
197   for (i = j = 0; pathname[i]; i++)
198     {
199       /* Fix for CTLESC at the end of the string? */
200       if (pathname[i] == CTLESC && pathname[i+1] == '\0')
201         {
202           temp[j++] = pathname[i++];
203           break;
204         }
205       /* If we are parsing regexp, turn CTLESC CTLESC into CTLESC. It's not an
206          ERE special character, so we should just be able to pass it through. */
207       else if ((qflags & QGLOB_REGEXP) && pathname[i] == CTLESC && pathname[i+1] == CTLESC)
208         {
209           i++;
210           temp[j++] = pathname[i];
211           continue;
212         }
213       else if (pathname[i] == CTLESC)
214         {
215           if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
216             continue;
217           /* What to do if preceding char is backslash? */
218           if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
219             continue;
220           temp[j++] = '\\';
221           i++;
222           if (pathname[i] == '\0')
223             break;
224         }
225       else if ((qflags & QGLOB_REGEXP) && (i == 0 || pathname[i-1] != CTLESC) && pathname[i] == '[')    /*]*/
226         {
227           brack = 1;
228           temp[j++] = pathname[i++];    /* open bracket */
229           c = pathname[i++];    /* c == char after open bracket */
230           do
231             {
232               if (c == 0)
233                 goto endpat;
234               else if (c == CTLESC)
235                 {
236                   /* skip c, check for EOS, let assignment at end of loop */
237                   /* pathname[i] == backslash-escaped character */
238                   if (pathname[i] == 0)
239                     goto endpat;
240                   temp[j++] = pathname[i++];
241                 }
242               else if (c == '[' && pathname[i] == ':')
243                 {
244                   temp[j++] = c;
245                   temp[j++] = pathname[i++];
246                   cclass = 1;
247                 }
248               else if (cclass && c == ':' && pathname[i] == ']')
249                 {
250                   temp[j++] = c;
251                   temp[j++] = pathname[i++];
252                   cclass = 0;
253                 }
254               else if (c == '[' && pathname[i] == '=')
255                 {
256                   temp[j++] = c;
257                   temp[j++] = pathname[i++];
258                   if (pathname[i] == ']')
259                     temp[j++] = pathname[i++];          /* right brack can be in equiv */
260                   equiv = 1;
261                 }
262               else if (equiv && c == '=' && pathname[i] == ']')
263                 {
264                   temp[j++] = c;
265                   temp[j++] = pathname[i++];
266                   equiv = 0;
267                 }
268               else if (c == '[' && pathname[i] == '.')
269                 {
270                   temp[j++] = c;
271                   temp[j++] = pathname[i++];
272                   if (pathname[i] == ']')
273                     temp[j++] = pathname[i++];          /* right brack can be in collsym */
274                   collsym = 1;
275                 }
276               else if (collsym && c == '.' && pathname[i] == ']')
277                 {
278                   temp[j++] = c;
279                   temp[j++] = pathname[i++];
280                   collsym = 0;
281                 }
282               else
283                 temp[j++] = c;
284             }
285           while ((c = pathname[i++]) != ']');
286           temp[j++] = c;        /* closing right bracket */
287           i--;                  /* increment will happen above in loop */
288           continue;             /* skip double assignment below */
289         }
290       else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP) == 0)
291         {
292           /* XXX - if not quoting regexp, use backslash as quote char. Should
293              we just pass it through without treating it as special? That is
294              what ksh93 seems to do. */
295
296           /* If we want to pass through backslash unaltered, comment out these
297              lines. */
298           temp[j++] = '\\';
299
300           i++;
301           if (pathname[i] == '\0')
302             break;
303         }
304       else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP))
305         last_was_backslash = 1;
306       temp[j++] = pathname[i];
307     }
308 endpat:
309   temp[j] = '\0';
310
311   return (temp);
312 }
313
314 char *
315 quote_globbing_chars (string)
316      char *string;
317 {
318   size_t slen;
319   char *temp, *s, *t, *send;
320   DECLARE_MBSTATE;
321
322   slen = strlen (string);
323   send = string + slen;
324
325   temp = (char *)xmalloc (slen * 2 + 1);
326   for (t = temp, s = string; *s; )
327     {
328       if (glob_char_p (s))
329         *t++ = '\\';
330
331       /* Copy a single (possibly multibyte) character from s to t,
332          incrementing both. */
333       COPY_CHAR_P (t, s, send);
334     }
335   *t = '\0';
336   return temp;
337 }
338
339 /* Call the glob library to do globbing on PATHNAME. */
340 char **
341 shell_glob_filename (pathname)
342      const char *pathname;
343 {
344 #if defined (USE_POSIX_GLOB_LIBRARY)
345   register int i;
346   char *temp, **results;
347   glob_t filenames;
348   int glob_flags;
349
350   temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
351
352   filenames.gl_offs = 0;
353
354 #  if defined (GLOB_PERIOD)
355   glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
356 #  else
357   glob_flags = 0;
358 #  endif /* !GLOB_PERIOD */
359
360   glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
361
362   i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
363
364   free (temp);
365
366   if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
367     return ((char **)NULL);
368   else if (i == GLOB_NOMATCH)
369     filenames.gl_pathv = (char **)NULL;
370   else if (i != 0)              /* other error codes not in POSIX.2 */
371     filenames.gl_pathv = (char **)NULL;
372
373   results = filenames.gl_pathv;
374
375   if (results && ((GLOB_FAILED (results)) == 0))
376     {
377       if (should_ignore_glob_matches ())
378         ignore_glob_matches (results);
379       if (results && results[0])
380         strvec_sort (results);
381       else
382         {
383           FREE (results);
384           results = (char **)NULL;
385         }
386     }
387
388   return (results);
389
390 #else /* !USE_POSIX_GLOB_LIBRARY */
391
392   char *temp, **results;
393
394   noglob_dot_filenames = glob_dot_filenames == 0;
395
396   temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
397   results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
398   free (temp);
399
400   if (results && ((GLOB_FAILED (results)) == 0))
401     {
402       if (should_ignore_glob_matches ())
403         ignore_glob_matches (results);
404       if (results && results[0])
405         strvec_sort (results);
406       else
407         {
408           FREE (results);
409           results = (char **)&glob_error_return;
410         }
411     }
412
413   return (results);
414 #endif /* !USE_POSIX_GLOB_LIBRARY */
415 }
416
417 /* Stuff for GLOBIGNORE. */
418
419 static struct ignorevar globignore =
420 {
421   "GLOBIGNORE",
422   (struct ign *)0,
423   0,
424   (char *)0,
425   (sh_iv_item_func_t *)0,
426 };
427
428 /* Set up to ignore some glob matches because the value of GLOBIGNORE
429    has changed.  If GLOBIGNORE is being unset, we also need to disable
430    the globbing of filenames beginning with a `.'. */
431 void
432 setup_glob_ignore (name)
433      char *name;
434 {
435   char *v;
436
437   v = get_string_value (name);
438   setup_ignore_patterns (&globignore);
439
440   if (globignore.num_ignores)
441     glob_dot_filenames = 1;
442   else if (v == 0)
443     glob_dot_filenames = 0;
444 }
445
446 int
447 should_ignore_glob_matches ()
448 {
449   return globignore.num_ignores;
450 }
451
452 /* Return 0 if NAME matches a pattern in the globignore.ignores list. */
453 static int
454 glob_name_is_acceptable (name)
455      const char *name;
456 {
457   struct ign *p;
458   int flags;
459
460   /* . and .. are never matched */
461   if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
462     return (0);
463
464   flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
465   for (p = globignore.ignores; p->val; p++)
466     {
467       if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
468         return (0);
469     }
470   return (1);
471 }
472
473 /* Internal function to test whether filenames in NAMES should be
474    ignored.  NAME_FUNC is a pointer to a function to call with each
475    name.  It returns non-zero if the name is acceptable to the particular
476    ignore function which called _ignore_names; zero if the name should
477    be removed from NAMES. */
478
479 static void
480 ignore_globbed_names (names, name_func)
481      char **names;
482      sh_ignore_func_t *name_func;
483 {
484   char **newnames;
485   int n, i;
486
487   for (i = 0; names[i]; i++)
488     ;
489   newnames = strvec_create (i + 1);
490
491   for (n = i = 0; names[i]; i++)
492     {
493       if ((*name_func) (names[i]))
494         newnames[n++] = names[i];
495       else
496         free (names[i]);
497     }
498
499   newnames[n] = (char *)NULL;
500
501   if (n == 0)
502     {
503       names[0] = (char *)NULL;
504       free (newnames);
505       return;
506     }
507
508   /* Copy the acceptable names from NEWNAMES back to NAMES and set the
509      new array end. */
510   for (n = 0; newnames[n]; n++)
511     names[n] = newnames[n];
512   names[n] = (char *)NULL;
513   free (newnames);
514 }
515
516 void
517 ignore_glob_matches (names)
518      char **names;
519 {
520   if (globignore.num_ignores == 0)
521     return;
522
523   ignore_globbed_names (names, glob_name_is_acceptable);
524 }
525
526 static char *
527 split_ignorespec (s, ip)
528      char *s;
529      int *ip;
530 {
531   char *t;
532   int n, i;
533
534   if (s == 0)
535     return 0;
536
537   i = *ip;
538   if (s[i] == 0)
539     return 0;
540
541   n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB);
542   t = substring (s, i, n);
543
544   if (s[n] == ':')
545     n++;  
546   *ip = n;  
547   return t;
548 }
549   
550 void
551 setup_ignore_patterns (ivp)
552      struct ignorevar *ivp;
553 {
554   int numitems, maxitems, ptr;
555   char *colon_bit, *this_ignoreval;
556   struct ign *p;
557
558   this_ignoreval = get_string_value (ivp->varname);
559
560   /* If nothing has changed then just exit now. */
561   if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
562       (!this_ignoreval && !ivp->last_ignoreval))
563     return;
564
565   /* Oops.  The ignore variable has changed.  Re-parse it. */
566   ivp->num_ignores = 0;
567
568   if (ivp->ignores)
569     {
570       for (p = ivp->ignores; p->val; p++)
571         free(p->val);
572       free (ivp->ignores);
573       ivp->ignores = (struct ign *)NULL;
574     }
575
576   if (ivp->last_ignoreval)
577     {
578       free (ivp->last_ignoreval);
579       ivp->last_ignoreval = (char *)NULL;
580     }
581
582   if (this_ignoreval == 0 || *this_ignoreval == '\0')
583     return;
584
585   ivp->last_ignoreval = savestring (this_ignoreval);
586
587   numitems = maxitems = ptr = 0;
588
589 #if 0
590   while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
591 #else
592   while (colon_bit = split_ignorespec (this_ignoreval, &ptr))
593 #endif
594     {
595       if (numitems + 1 >= maxitems)
596         {
597           maxitems += 10;
598           ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
599         }
600       ivp->ignores[numitems].val = colon_bit;
601       ivp->ignores[numitems].len = strlen (colon_bit);
602       ivp->ignores[numitems].flags = 0;
603       if (ivp->item_func)
604         (*ivp->item_func) (&ivp->ignores[numitems]);
605       numitems++;
606     }
607   ivp->ignores[numitems].val = (char *)NULL;
608   ivp->num_ignores = numitems;
609 }