IA64: Move NPTL public headers to sysdeps/ia64/nptl/.
[platform/upstream/glibc.git] / posix / wordexp.c
1 /* POSIX.2 wordexp implementation.
2    Copyright (C) 1997-2014 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <alloca.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <fnmatch.h>
25 #include <glob.h>
26 #include <libintl.h>
27 #include <paths.h>
28 #include <pwd.h>
29 #include <signal.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <unistd.h>
41 #include <wchar.h>
42 #include <wordexp.h>
43 #include <kernel-features.h>
44
45 #include <bits/libc-lock.h>
46 #include <_itoa.h>
47
48 /* Undefine the following line for the production version.  */
49 /* #define NDEBUG 1 */
50 #include <assert.h>
51
52 /* Get some device information.  */
53 #include <device-nrs.h>
54
55 /*
56  * This is a recursive-descent-style word expansion routine.
57  */
58
59 /* These variables are defined and initialized in the startup code.  */
60 extern int __libc_argc attribute_hidden;
61 extern char **__libc_argv attribute_hidden;
62
63 /* Some forward declarations */
64 static int parse_dollars (char **word, size_t *word_length, size_t *max_length,
65                           const char *words, size_t *offset, int flags,
66                           wordexp_t *pwordexp, const char *ifs,
67                           const char *ifs_white, int quoted)
68      internal_function;
69 static int parse_backtick (char **word, size_t *word_length,
70                            size_t *max_length, const char *words,
71                            size_t *offset, int flags, wordexp_t *pwordexp,
72                            const char *ifs, const char *ifs_white)
73      internal_function;
74 static int parse_dquote (char **word, size_t *word_length, size_t *max_length,
75                          const char *words, size_t *offset, int flags,
76                          wordexp_t *pwordexp, const char *ifs,
77                          const char *ifs_white)
78      internal_function;
79 static int eval_expr (char *expr, long int *result) internal_function;
80
81 /* The w_*() functions manipulate word lists. */
82
83 #define W_CHUNK (100)
84
85 /* Result of w_newword will be ignored if it's the last word. */
86 static inline char *
87 w_newword (size_t *actlen, size_t *maxlen)
88 {
89   *actlen = *maxlen = 0;
90   return NULL;
91 }
92
93 static char *
94 w_addchar (char *buffer, size_t *actlen, size_t *maxlen, char ch)
95      /* (lengths exclude trailing zero) */
96 {
97   /* Add a character to the buffer, allocating room for it if needed.  */
98
99   if (*actlen == *maxlen)
100     {
101       char *old_buffer = buffer;
102       assert (buffer == NULL || *maxlen != 0);
103       *maxlen += W_CHUNK;
104       buffer = (char *) realloc (buffer, 1 + *maxlen);
105
106       if (buffer == NULL)
107         free (old_buffer);
108     }
109
110   if (buffer != NULL)
111     {
112       buffer[*actlen] = ch;
113       buffer[++(*actlen)] = '\0';
114     }
115
116   return buffer;
117 }
118
119 static char *
120 internal_function
121 w_addmem (char *buffer, size_t *actlen, size_t *maxlen, const char *str,
122           size_t len)
123 {
124   /* Add a string to the buffer, allocating room for it if needed.
125    */
126   if (*actlen + len > *maxlen)
127     {
128       char *old_buffer = buffer;
129       assert (buffer == NULL || *maxlen != 0);
130       *maxlen += MAX (2 * len, W_CHUNK);
131       buffer = realloc (old_buffer, 1 + *maxlen);
132
133       if (buffer == NULL)
134         free (old_buffer);
135     }
136
137   if (buffer != NULL)
138     {
139       *((char *) __mempcpy (&buffer[*actlen], str, len)) = '\0';
140       *actlen += len;
141     }
142
143   return buffer;
144 }
145
146 static char *
147 internal_function
148 w_addstr (char *buffer, size_t *actlen, size_t *maxlen, const char *str)
149      /* (lengths exclude trailing zero) */
150 {
151   /* Add a string to the buffer, allocating room for it if needed.
152    */
153   size_t len;
154
155   assert (str != NULL); /* w_addstr only called from this file */
156   len = strlen (str);
157
158   return w_addmem (buffer, actlen, maxlen, str, len);
159 }
160
161 static int
162 internal_function
163 w_addword (wordexp_t *pwordexp, char *word)
164 {
165   /* Add a word to the wordlist */
166   size_t num_p;
167   char **new_wordv;
168   bool allocated = false;
169
170   /* Internally, NULL acts like "".  Convert NULLs to "" before
171    * the caller sees them.
172    */
173   if (word == NULL)
174     {
175       word = __strdup ("");
176       if (word == NULL)
177         goto no_space;
178       allocated = true;
179     }
180
181   num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs;
182   new_wordv = realloc (pwordexp->we_wordv, sizeof (char *) * num_p);
183   if (new_wordv != NULL)
184     {
185       pwordexp->we_wordv = new_wordv;
186       pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc++] = word;
187       pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc] = NULL;
188       return 0;
189     }
190
191   if (allocated)
192     free (word);
193
194 no_space:
195   return WRDE_NOSPACE;
196 }
197
198 /* The parse_*() functions should leave *offset being the offset in 'words'
199  * to the last character processed.
200  */
201
202 static int
203 internal_function
204 parse_backslash (char **word, size_t *word_length, size_t *max_length,
205                  const char *words, size_t *offset)
206 {
207   /* We are poised _at_ a backslash, not in quotes */
208
209   switch (words[1 + *offset])
210     {
211     case 0:
212       /* Backslash is last character of input words */
213       return WRDE_SYNTAX;
214
215     case '\n':
216       ++(*offset);
217       break;
218
219     default:
220       *word = w_addchar (*word, word_length, max_length, words[1 + *offset]);
221       if (*word == NULL)
222         return WRDE_NOSPACE;
223
224       ++(*offset);
225       break;
226     }
227
228   return 0;
229 }
230
231 static int
232 internal_function
233 parse_qtd_backslash (char **word, size_t *word_length, size_t *max_length,
234                      const char *words, size_t *offset)
235 {
236   /* We are poised _at_ a backslash, inside quotes */
237
238   switch (words[1 + *offset])
239     {
240     case 0:
241       /* Backslash is last character of input words */
242       return WRDE_SYNTAX;
243
244     case '\n':
245       ++(*offset);
246       break;
247
248     case '$':
249     case '`':
250     case '"':
251     case '\\':
252       *word = w_addchar (*word, word_length, max_length, words[1 + *offset]);
253       if (*word == NULL)
254         return WRDE_NOSPACE;
255
256       ++(*offset);
257       break;
258
259     default:
260       *word = w_addchar (*word, word_length, max_length, words[*offset]);
261       if (*word != NULL)
262         *word = w_addchar (*word, word_length, max_length, words[1 + *offset]);
263
264       if (*word == NULL)
265         return WRDE_NOSPACE;
266
267       ++(*offset);
268       break;
269     }
270
271   return 0;
272 }
273
274 static int
275 internal_function
276 parse_tilde (char **word, size_t *word_length, size_t *max_length,
277              const char *words, size_t *offset, size_t wordc)
278 {
279   /* We are poised _at_ a tilde */
280   size_t i;
281
282   if (*word_length != 0)
283     {
284       if (!((*word)[*word_length - 1] == '=' && wordc == 0))
285         {
286           if (!((*word)[*word_length - 1] == ':'
287                 && strchr (*word, '=') && wordc == 0))
288             {
289               *word = w_addchar (*word, word_length, max_length, '~');
290               return *word ? 0 : WRDE_NOSPACE;
291             }
292         }
293     }
294
295   for (i = 1 + *offset; words[i]; i++)
296     {
297       if (words[i] == ':' || words[i] == '/' || words[i] == ' ' ||
298           words[i] == '\t' || words[i] == 0 )
299         break;
300
301       if (words[i] == '\\')
302         {
303           *word = w_addchar (*word, word_length, max_length, '~');
304           return *word ? 0 : WRDE_NOSPACE;
305         }
306     }
307
308   if (i == 1 + *offset)
309     {
310       /* Tilde appears on its own */
311       uid_t uid;
312       struct passwd pwd, *tpwd;
313       int buflen = 1000;
314       char* home;
315       char* buffer;
316       int result;
317
318       /* POSIX.2 says ~ expands to $HOME and if HOME is unset the
319          results are unspecified.  We do a lookup on the uid if
320          HOME is unset. */
321
322       home = getenv ("HOME");
323       if (home != NULL)
324         {
325           *word = w_addstr (*word, word_length, max_length, home);
326           if (*word == NULL)
327             return WRDE_NOSPACE;
328         }
329       else
330         {
331           uid = __getuid ();
332           buffer = __alloca (buflen);
333
334           while ((result = __getpwuid_r (uid, &pwd, buffer, buflen, &tpwd)) != 0
335                  && errno == ERANGE)
336             buffer = extend_alloca (buffer, buflen, buflen + 1000);
337
338           if (result == 0 && tpwd != NULL && pwd.pw_dir != NULL)
339             {
340               *word = w_addstr (*word, word_length, max_length, pwd.pw_dir);
341               if (*word == NULL)
342                 return WRDE_NOSPACE;
343             }
344           else
345             {
346               *word = w_addchar (*word, word_length, max_length, '~');
347               if (*word == NULL)
348                 return WRDE_NOSPACE;
349             }
350         }
351     }
352   else
353     {
354       /* Look up user name in database to get home directory */
355       char *user = strndupa (&words[1 + *offset], i - (1 + *offset));
356       struct passwd pwd, *tpwd;
357       int buflen = 1000;
358       char* buffer = __alloca (buflen);
359       int result;
360
361       while ((result = __getpwnam_r (user, &pwd, buffer, buflen, &tpwd)) != 0
362              && errno == ERANGE)
363         buffer = extend_alloca (buffer, buflen, buflen + 1000);
364
365       if (result == 0 && tpwd != NULL && pwd.pw_dir)
366         *word = w_addstr (*word, word_length, max_length, pwd.pw_dir);
367       else
368         {
369           /* (invalid login name) */
370           *word = w_addchar (*word, word_length, max_length, '~');
371           if (*word != NULL)
372             *word = w_addstr (*word, word_length, max_length, user);
373         }
374
375       *offset = i - 1;
376     }
377   return *word ? 0 : WRDE_NOSPACE;
378 }
379
380
381 static int
382 internal_function
383 do_parse_glob (const char *glob_word, char **word, size_t *word_length,
384                size_t *max_length, wordexp_t *pwordexp, const char *ifs,
385                const char *ifs_white)
386 {
387   int error;
388   unsigned int match;
389   glob_t globbuf;
390
391   error = glob (glob_word, GLOB_NOCHECK, NULL, &globbuf);
392
393   if (error != 0)
394     {
395       /* We can only run into memory problems.  */
396       assert (error == GLOB_NOSPACE);
397       return WRDE_NOSPACE;
398     }
399
400   if (ifs && !*ifs)
401     {
402       /* No field splitting allowed. */
403       assert (globbuf.gl_pathv[0] != NULL);
404       *word = w_addstr (*word, word_length, max_length, globbuf.gl_pathv[0]);
405       for (match = 1; match < globbuf.gl_pathc && *word != NULL; ++match)
406         {
407           *word = w_addchar (*word, word_length, max_length, ' ');
408           if (*word != NULL)
409             *word = w_addstr (*word, word_length, max_length,
410                               globbuf.gl_pathv[match]);
411         }
412
413       globfree (&globbuf);
414       return *word ? 0 : WRDE_NOSPACE;
415     }
416
417   assert (ifs == NULL || *ifs != '\0');
418   if (*word != NULL)
419     {
420       free (*word);
421       *word = w_newword (word_length, max_length);
422     }
423
424   for (match = 0; match < globbuf.gl_pathc; ++match)
425     {
426       char *matching_word = __strdup (globbuf.gl_pathv[match]);
427       if (matching_word == NULL || w_addword (pwordexp, matching_word))
428         {
429           globfree (&globbuf);
430           return WRDE_NOSPACE;
431         }
432     }
433
434   globfree (&globbuf);
435   return 0;
436 }
437
438 static int
439 internal_function
440 parse_glob (char **word, size_t *word_length, size_t *max_length,
441             const char *words, size_t *offset, int flags,
442             wordexp_t *pwordexp, const char *ifs, const char *ifs_white)
443 {
444   /* We are poised just after a '*', a '[' or a '?'. */
445   int error = WRDE_NOSPACE;
446   int quoted = 0; /* 1 if singly-quoted, 2 if doubly */
447   size_t i;
448   wordexp_t glob_list; /* List of words to glob */
449
450   glob_list.we_wordc = 0;
451   glob_list.we_wordv = NULL;
452   glob_list.we_offs = 0;
453   for (; words[*offset] != '\0'; ++*offset)
454     {
455       if (strchr (ifs, words[*offset]) != NULL)
456         /* Reached IFS */
457         break;
458
459       /* Sort out quoting */
460       if (words[*offset] == '\'')
461         {
462           if (quoted == 0)
463             {
464               quoted = 1;
465               continue;
466             }
467           else if (quoted == 1)
468             {
469               quoted = 0;
470               continue;
471             }
472         }
473       else if (words[*offset] == '"')
474         {
475           if (quoted == 0)
476             {
477               quoted = 2;
478               continue;
479             }
480           else if (quoted == 2)
481             {
482               quoted = 0;
483               continue;
484             }
485         }
486
487       /* Sort out other special characters */
488       if (quoted != 1 && words[*offset] == '$')
489         {
490           error = parse_dollars (word, word_length, max_length, words,
491                                  offset, flags, &glob_list, ifs, ifs_white,
492                                  quoted == 2);
493           if (error)
494             goto tidy_up;
495
496           continue;
497         }
498       else if (words[*offset] == '\\')
499         {
500           if (quoted)
501             error = parse_qtd_backslash (word, word_length, max_length,
502                                          words, offset);
503           else
504             error = parse_backslash (word, word_length, max_length,
505                                      words, offset);
506
507           if (error)
508             goto tidy_up;
509
510           continue;
511         }
512
513       *word = w_addchar (*word, word_length, max_length, words[*offset]);
514       if (*word == NULL)
515         goto tidy_up;
516     }
517
518   /* Don't forget to re-parse the character we stopped at. */
519   --*offset;
520
521   /* Glob the words */
522   error = w_addword (&glob_list, *word);
523   *word = w_newword (word_length, max_length);
524   for (i = 0; error == 0 && i < glob_list.we_wordc; i++)
525     error = do_parse_glob (glob_list.we_wordv[i], word, word_length,
526                            max_length, pwordexp, ifs, ifs_white);
527
528   /* Now tidy up */
529 tidy_up:
530   wordfree (&glob_list);
531   return error;
532 }
533
534 static int
535 internal_function
536 parse_squote (char **word, size_t *word_length, size_t *max_length,
537               const char *words, size_t *offset)
538 {
539   /* We are poised just after a single quote */
540   for (; words[*offset]; ++(*offset))
541     {
542       if (words[*offset] != '\'')
543         {
544           *word = w_addchar (*word, word_length, max_length, words[*offset]);
545           if (*word == NULL)
546             return WRDE_NOSPACE;
547         }
548       else return 0;
549     }
550
551   /* Unterminated string */
552   return WRDE_SYNTAX;
553 }
554
555 /* Functions to evaluate an arithmetic expression */
556 static int
557 internal_function
558 eval_expr_val (char **expr, long int *result)
559 {
560   char *digit;
561
562   /* Skip white space */
563   for (digit = *expr; digit && *digit && isspace (*digit); ++digit);
564
565   if (*digit == '(')
566     {
567       /* Scan for closing paren */
568       for (++digit; **expr && **expr != ')'; ++(*expr));
569
570       /* Is there one? */
571       if (!**expr)
572         return WRDE_SYNTAX;
573
574       *(*expr)++ = 0;
575
576       if (eval_expr (digit, result))
577         return WRDE_SYNTAX;
578
579       return 0;
580     }
581
582   /* POSIX requires that decimal, octal, and hexadecimal constants are
583      recognized.  Therefore we pass 0 as the third parameter to strtol.  */
584   *result = strtol (digit, expr, 0);
585   if (digit == *expr)
586     return WRDE_SYNTAX;
587
588   return 0;
589 }
590
591 static int
592 internal_function
593 eval_expr_multdiv (char **expr, long int *result)
594 {
595   long int arg;
596
597   /* Read a Value */
598   if (eval_expr_val (expr, result) != 0)
599     return WRDE_SYNTAX;
600
601   while (**expr)
602     {
603       /* Skip white space */
604       for (; *expr && **expr && isspace (**expr); ++(*expr));
605
606       if (**expr == '*')
607         {
608           ++(*expr);
609           if (eval_expr_val (expr, &arg) != 0)
610             return WRDE_SYNTAX;
611
612           *result *= arg;
613         }
614       else if (**expr == '/')
615         {
616           ++(*expr);
617           if (eval_expr_val (expr, &arg) != 0)
618             return WRDE_SYNTAX;
619
620           *result /= arg;
621         }
622       else break;
623     }
624
625   return 0;
626 }
627
628 static int
629 internal_function
630 eval_expr (char *expr, long int *result)
631 {
632   long int arg;
633
634   /* Read a Multdiv */
635   if (eval_expr_multdiv (&expr, result) != 0)
636     return WRDE_SYNTAX;
637
638   while (*expr)
639     {
640       /* Skip white space */
641       for (; expr && *expr && isspace (*expr); ++expr);
642
643       if (*expr == '+')
644         {
645           ++expr;
646           if (eval_expr_multdiv (&expr, &arg) != 0)
647             return WRDE_SYNTAX;
648
649           *result += arg;
650         }
651       else if (*expr == '-')
652         {
653           ++expr;
654           if (eval_expr_multdiv (&expr, &arg) != 0)
655             return WRDE_SYNTAX;
656
657           *result -= arg;
658         }
659       else break;
660     }
661
662   return 0;
663 }
664
665 static int
666 internal_function
667 parse_arith (char **word, size_t *word_length, size_t *max_length,
668              const char *words, size_t *offset, int flags, int bracket)
669 {
670   /* We are poised just after "$((" or "$[" */
671   int error;
672   int paren_depth = 1;
673   size_t expr_length;
674   size_t expr_maxlen;
675   char *expr;
676
677   expr = w_newword (&expr_length, &expr_maxlen);
678   for (; words[*offset]; ++(*offset))
679     {
680       switch (words[*offset])
681         {
682         case '$':
683           error = parse_dollars (&expr, &expr_length, &expr_maxlen,
684                                  words, offset, flags, NULL, NULL, NULL, 1);
685           /* The ``1'' here is to tell parse_dollars not to
686            * split the fields.
687            */
688           if (error)
689             {
690               free (expr);
691               return error;
692             }
693           break;
694
695         case '`':
696           (*offset)++;
697           error = parse_backtick (&expr, &expr_length, &expr_maxlen,
698                                   words, offset, flags, NULL, NULL, NULL);
699           /* The first NULL here is to tell parse_backtick not to
700            * split the fields.
701            */
702           if (error)
703             {
704               free (expr);
705               return error;
706             }
707           break;
708
709         case '\\':
710           error = parse_qtd_backslash (&expr, &expr_length, &expr_maxlen,
711                                        words, offset);
712           if (error)
713             {
714               free (expr);
715               return error;
716             }
717           /* I think that a backslash within an
718            * arithmetic expansion is bound to
719            * cause an error sooner or later anyway though.
720            */
721           break;
722
723         case ')':
724           if (--paren_depth == 0)
725             {
726               char result[21];  /* 21 = ceil(log10(2^64)) + 1 */
727               long int numresult = 0;
728               long long int convertme;
729
730               if (bracket || words[1 + *offset] != ')')
731                 {
732                   free (expr);
733                   return WRDE_SYNTAX;
734                 }
735
736               ++(*offset);
737
738               /* Go - evaluate. */
739               if (*expr && eval_expr (expr, &numresult) != 0)
740                 {
741                   free (expr);
742                   return WRDE_SYNTAX;
743                 }
744
745               if (numresult < 0)
746                 {
747                   convertme = -numresult;
748                   *word = w_addchar (*word, word_length, max_length, '-');
749                   if (!*word)
750                     {
751                       free (expr);
752                       return WRDE_NOSPACE;
753                     }
754                 }
755               else
756                 convertme = numresult;
757
758               result[20] = '\0';
759               *word = w_addstr (*word, word_length, max_length,
760                                 _itoa (convertme, &result[20], 10, 0));
761               free (expr);
762               return *word ? 0 : WRDE_NOSPACE;
763             }
764           expr = w_addchar (expr, &expr_length, &expr_maxlen, words[*offset]);
765           if (expr == NULL)
766             return WRDE_NOSPACE;
767
768           break;
769
770         case ']':
771           if (bracket && paren_depth == 1)
772             {
773               char result[21];  /* 21 = ceil(log10(2^64)) + 1 */
774               long int numresult = 0;
775
776               /* Go - evaluate. */
777               if (*expr && eval_expr (expr, &numresult) != 0)
778                 {
779                   free (expr);
780                   return WRDE_SYNTAX;
781                 }
782
783               result[20] = '\0';
784               *word = w_addstr (*word, word_length, max_length,
785                                 _itoa_word (numresult, &result[20], 10, 0));
786               free (expr);
787               return *word ? 0 : WRDE_NOSPACE;
788             }
789
790           free (expr);
791           return WRDE_SYNTAX;
792
793         case '\n':
794         case ';':
795         case '{':
796         case '}':
797           free (expr);
798           return WRDE_BADCHAR;
799
800         case '(':
801           ++paren_depth;
802         default:
803           expr = w_addchar (expr, &expr_length, &expr_maxlen, words[*offset]);
804           if (expr == NULL)
805             return WRDE_NOSPACE;
806         }
807     }
808
809   /* Premature end */
810   free (expr);
811   return WRDE_SYNTAX;
812 }
813
814 /* Function called by child process in exec_comm() */
815 static inline void
816 internal_function __attribute__ ((always_inline))
817 exec_comm_child (char *comm, int *fildes, int showerr, int noexec)
818 {
819   const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL };
820
821   /* Execute the command, or just check syntax? */
822   if (noexec)
823     args[1] = "-nc";
824
825   /* Redirect output.  */
826   if (__glibc_likely (fildes[1] != STDOUT_FILENO))
827     {
828       __dup2 (fildes[1], STDOUT_FILENO);
829       __close (fildes[1]);
830     }
831   else
832     {
833 #ifdef O_CLOEXEC
834       /* Reset the close-on-exec flag (if necessary).  */
835 # ifndef __ASSUME_PIPE2
836       if (__have_pipe2 > 0)
837 # endif
838         __fcntl (fildes[1], F_SETFD, 0);
839 #endif
840     }
841
842   /* Redirect stderr to /dev/null if we have to.  */
843   if (showerr == 0)
844     {
845       struct stat64 st;
846       int fd;
847       __close (STDERR_FILENO);
848       fd = __open (_PATH_DEVNULL, O_WRONLY);
849       if (fd >= 0 && fd != STDERR_FILENO)
850         {
851           __dup2 (fd, STDERR_FILENO);
852           __close (fd);
853         }
854       /* Be paranoid.  Check that we actually opened the /dev/null
855          device.  */
856       if (__builtin_expect (__fxstat64 (_STAT_VER, STDERR_FILENO, &st), 0) != 0
857           || __builtin_expect (S_ISCHR (st.st_mode), 1) == 0
858 #if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
859           || st.st_rdev != makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR)
860 #endif
861           )
862         /* It's not the /dev/null device.  Stop right here.  The
863            problem is: how do we stop?  We use _exit() with an
864            hopefully unusual exit code.  */
865         _exit (90);
866     }
867
868   /* Make sure the subshell doesn't field-split on our behalf. */
869   __unsetenv ("IFS");
870
871   __close (fildes[0]);
872   __execve (_PATH_BSHELL, (char *const *) args, __environ);
873
874   /* Bad.  What now?  */
875   abort ();
876 }
877
878 /* Function to execute a command and retrieve the results */
879 /* pwordexp contains NULL if field-splitting is forbidden */
880 static int
881 internal_function
882 exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
883            int flags, wordexp_t *pwordexp, const char *ifs,
884            const char *ifs_white)
885 {
886   int fildes[2];
887 #define bufsize 128
888   int buflen;
889   int i;
890   int status = 0;
891   size_t maxnewlines = 0;
892   char buffer[bufsize];
893   pid_t pid;
894   int noexec = 0;
895
896   /* Don't fork() unless necessary */
897   if (!comm || !*comm)
898     return 0;
899
900 #ifdef O_CLOEXEC
901 # ifndef __ASSUME_PIPE2
902   if (__have_pipe2 >= 0)
903 # endif
904     {
905       int r = __pipe2 (fildes, O_CLOEXEC);
906 # ifndef __ASSUME_PIPE2
907       if (__have_pipe2 == 0)
908         __have_pipe2 = r != -1 || errno != ENOSYS ? 1 : -1;
909
910       if (__have_pipe2 > 0)
911 # endif
912         if (r < 0)
913           /* Bad */
914           return WRDE_NOSPACE;
915     }
916 #endif
917 #ifndef __ASSUME_PIPE2
918 # ifdef O_CLOEXEC
919   if (__have_pipe2 < 0)
920 # endif
921     if (__pipe (fildes) < 0)
922       /* Bad */
923       return WRDE_NOSPACE;
924 #endif
925
926  again:
927   if ((pid = __fork ()) < 0)
928     {
929       /* Bad */
930       __close (fildes[0]);
931       __close (fildes[1]);
932       return WRDE_NOSPACE;
933     }
934
935   if (pid == 0)
936     exec_comm_child (comm, fildes, noexec ? 0 : flags & WRDE_SHOWERR, noexec);
937
938   /* Parent */
939
940   /* If we are just testing the syntax, only wait.  */
941   if (noexec)
942     return (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) == pid
943             && status != 0) ? WRDE_SYNTAX : 0;
944
945   __close (fildes[1]);
946   fildes[1] = -1;
947
948   if (!pwordexp)
949     /* Quoted - no field splitting */
950     {
951       while (1)
952         {
953           if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
954                                                     bufsize))) < 1)
955             {
956               /* If read returned 0 then the process has closed its
957                  stdout.  Don't use WNOHANG in that case to avoid busy
958                  looping until the process eventually exits.  */
959               if (TEMP_FAILURE_RETRY (__waitpid (pid, &status,
960                                                  buflen == 0 ? 0 : WNOHANG))
961                   == 0)
962                 continue;
963               if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
964                                                         bufsize))) < 1)
965                 break;
966             }
967
968           maxnewlines += buflen;
969
970           *word = w_addmem (*word, word_length, max_length, buffer, buflen);
971           if (*word == NULL)
972             goto no_space;
973         }
974     }
975   else
976     /* Not quoted - split fields */
977     {
978       int copying = 0;
979       /* 'copying' is:
980        *  0 when searching for first character in a field not IFS white space
981        *  1 when copying the text of a field
982        *  2 when searching for possible non-whitespace IFS
983        *  3 when searching for non-newline after copying field
984        */
985
986       while (1)
987         {
988           if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
989                                                     bufsize))) < 1)
990             {
991               /* If read returned 0 then the process has closed its
992                  stdout.  Don't use WNOHANG in that case to avoid busy
993                  looping until the process eventually exits.  */
994               if (TEMP_FAILURE_RETRY (__waitpid (pid, &status,
995                                                  buflen == 0 ? 0 : WNOHANG))
996                   == 0)
997                 continue;
998               if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
999                                                         bufsize))) < 1)
1000                 break;
1001             }
1002
1003           for (i = 0; i < buflen; ++i)
1004             {
1005               if (strchr (ifs, buffer[i]) != NULL)
1006                 {
1007                   /* Current character is IFS */
1008                   if (strchr (ifs_white, buffer[i]) == NULL)
1009                     {
1010                       /* Current character is IFS but not whitespace */
1011                       if (copying == 2)
1012                         {
1013                           /*            current character
1014                            *                   |
1015                            *                   V
1016                            * eg: text<space><comma><space>moretext
1017                            *
1018                            * So, strip whitespace IFS (like at the start)
1019                            */
1020                           copying = 0;
1021                           continue;
1022                         }
1023
1024                       copying = 0;
1025                       /* fall through and delimit field.. */
1026                     }
1027                   else
1028                     {
1029                       if (buffer[i] == '\n')
1030                         {
1031                           /* Current character is (IFS) newline */
1032
1033                           /* If copying a field, this is the end of it,
1034                              but maybe all that's left is trailing newlines.
1035                              So start searching for a non-newline. */
1036                           if (copying == 1)
1037                             copying = 3;
1038
1039                           continue;
1040                         }
1041                       else
1042                         {
1043                           /* Current character is IFS white space, but
1044                              not a newline */
1045
1046                           /* If not either copying a field or searching
1047                              for non-newline after a field, ignore it */
1048                           if (copying != 1 && copying != 3)
1049                             continue;
1050
1051                           /* End of field (search for non-ws IFS afterwards) */
1052                           copying = 2;
1053                         }
1054                     }
1055
1056                   /* First IFS white space (non-newline), or IFS non-whitespace.
1057                    * Delimit the field.  Nulls are converted by w_addword. */
1058                   if (w_addword (pwordexp, *word) == WRDE_NOSPACE)
1059                     goto no_space;
1060
1061                   *word = w_newword (word_length, max_length);
1062
1063                   maxnewlines = 0;
1064                   /* fall back round the loop.. */
1065                 }
1066               else
1067                 {
1068                   /* Not IFS character */
1069
1070                   if (copying == 3)
1071                     {
1072                       /* Nothing but (IFS) newlines since the last field,
1073                          so delimit it here before starting new word */
1074                       if (w_addword (pwordexp, *word) == WRDE_NOSPACE)
1075                         goto no_space;
1076
1077                       *word = w_newword (word_length, max_length);
1078                     }
1079
1080                   copying = 1;
1081
1082                   if (buffer[i] == '\n') /* happens if newline not in IFS */
1083                     maxnewlines++;
1084                   else
1085                     maxnewlines = 0;
1086
1087                   *word = w_addchar (*word, word_length, max_length,
1088                                      buffer[i]);
1089                   if (*word == NULL)
1090                     goto no_space;
1091                 }
1092             }
1093         }
1094     }
1095
1096   /* Chop off trailing newlines (required by POSIX.2)  */
1097   /* Ensure we don't go back further than the beginning of the
1098      substitution (i.e. remove maxnewlines bytes at most) */
1099   while (maxnewlines-- != 0 &&
1100          *word_length > 0 && (*word)[*word_length - 1] == '\n')
1101     {
1102       (*word)[--*word_length] = '\0';
1103
1104       /* If the last word was entirely newlines, turn it into a new word
1105        * which can be ignored if there's nothing following it. */
1106       if (*word_length == 0)
1107         {
1108           free (*word);
1109           *word = w_newword (word_length, max_length);
1110           break;
1111         }
1112     }
1113
1114   __close (fildes[0]);
1115   fildes[0] = -1;
1116
1117   /* Check for syntax error (re-execute but with "-n" flag) */
1118   if (buflen < 1 && status != 0)
1119     {
1120       noexec = 1;
1121       goto again;
1122     }
1123
1124   return 0;
1125
1126 no_space:
1127   __kill (pid, SIGKILL);
1128   TEMP_FAILURE_RETRY (__waitpid (pid, NULL, 0));
1129   __close (fildes[0]);
1130   return WRDE_NOSPACE;
1131 }
1132
1133 static int
1134 internal_function
1135 parse_comm (char **word, size_t *word_length, size_t *max_length,
1136             const char *words, size_t *offset, int flags, wordexp_t *pwordexp,
1137             const char *ifs, const char *ifs_white)
1138 {
1139   /* We are poised just after "$(" */
1140   int paren_depth = 1;
1141   int error = 0;
1142   int quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */
1143   size_t comm_length;
1144   size_t comm_maxlen;
1145   char *comm = w_newword (&comm_length, &comm_maxlen);
1146
1147   for (; words[*offset]; ++(*offset))
1148     {
1149       switch (words[*offset])
1150         {
1151         case '\'':
1152           if (quoted == 0)
1153             quoted = 1;
1154           else if (quoted == 1)
1155             quoted = 0;
1156
1157           break;
1158
1159         case '"':
1160           if (quoted == 0)
1161             quoted = 2;
1162           else if (quoted == 2)
1163             quoted = 0;
1164
1165           break;
1166
1167         case ')':
1168           if (!quoted && --paren_depth == 0)
1169             {
1170               /* Go -- give script to the shell */
1171               if (comm)
1172                 {
1173 #ifdef __libc_ptf_call
1174                   /* We do not want the exec_comm call to be cut short
1175                      by a thread cancellation since cleanup is very
1176                      ugly.  Therefore disable cancellation for
1177                      now.  */
1178                   // XXX Ideally we do want the thread being cancelable.
1179                   // XXX If demand is there we'll change it.
1180                   int state = PTHREAD_CANCEL_ENABLE;
1181                   __libc_ptf_call (pthread_setcancelstate,
1182                                    (PTHREAD_CANCEL_DISABLE, &state), 0);
1183 #endif
1184
1185                   error = exec_comm (comm, word, word_length, max_length,
1186                                      flags, pwordexp, ifs, ifs_white);
1187
1188 #ifdef __libc_ptf_call
1189                   __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
1190 #endif
1191
1192                   free (comm);
1193                 }
1194
1195               return error;
1196             }
1197
1198           /* This is just part of the script */
1199           break;
1200
1201         case '(':
1202           if (!quoted)
1203             ++paren_depth;
1204         }
1205
1206       comm = w_addchar (comm, &comm_length, &comm_maxlen, words[*offset]);
1207       if (comm == NULL)
1208         return WRDE_NOSPACE;
1209     }
1210
1211   /* Premature end.  */
1212   free (comm);
1213
1214   return WRDE_SYNTAX;
1215 }
1216
1217 static int
1218 internal_function
1219 parse_param (char **word, size_t *word_length, size_t *max_length,
1220              const char *words, size_t *offset, int flags, wordexp_t *pwordexp,
1221              const char *ifs, const char *ifs_white, int quoted)
1222 {
1223   /* We are poised just after "$" */
1224   enum action
1225   {
1226     ACT_NONE,
1227     ACT_RP_SHORT_LEFT = '#',
1228     ACT_RP_LONG_LEFT = 'L',
1229     ACT_RP_SHORT_RIGHT = '%',
1230     ACT_RP_LONG_RIGHT = 'R',
1231     ACT_NULL_ERROR = '?',
1232     ACT_NULL_SUBST = '-',
1233     ACT_NONNULL_SUBST = '+',
1234     ACT_NULL_ASSIGN = '='
1235   };
1236   size_t env_length;
1237   size_t env_maxlen;
1238   size_t pat_length;
1239   size_t pat_maxlen;
1240   size_t start = *offset;
1241   char *env;
1242   char *pattern;
1243   char *value = NULL;
1244   enum action action = ACT_NONE;
1245   int depth = 0;
1246   int colon_seen = 0;
1247   int seen_hash = 0;
1248   int free_value = 0;
1249   int pattern_is_quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */
1250   int error;
1251   int special = 0;
1252   char buffer[21];
1253   int brace = words[*offset] == '{';
1254
1255   env = w_newword (&env_length, &env_maxlen);
1256   pattern = w_newword (&pat_length, &pat_maxlen);
1257
1258   if (brace)
1259     ++*offset;
1260
1261   /* First collect the parameter name. */
1262
1263   if (words[*offset] == '#')
1264     {
1265       seen_hash = 1;
1266       if (!brace)
1267         goto envsubst;
1268       ++*offset;
1269     }
1270
1271   if (isalpha (words[*offset]) || words[*offset] == '_')
1272     {
1273       /* Normal parameter name. */
1274       do
1275         {
1276           env = w_addchar (env, &env_length, &env_maxlen,
1277                            words[*offset]);
1278           if (env == NULL)
1279             goto no_space;
1280         }
1281       while (isalnum (words[++*offset]) || words[*offset] == '_');
1282     }
1283   else if (isdigit (words[*offset]))
1284     {
1285       /* Numeric parameter name. */
1286       special = 1;
1287       do
1288         {
1289           env = w_addchar (env, &env_length, &env_maxlen,
1290                            words[*offset]);
1291           if (env == NULL)
1292             goto no_space;
1293           if (!brace)
1294             goto envsubst;
1295         }
1296       while (isdigit(words[++*offset]));
1297     }
1298   else if (strchr ("*@$", words[*offset]) != NULL)
1299     {
1300       /* Special parameter. */
1301       special = 1;
1302       env = w_addchar (env, &env_length, &env_maxlen,
1303                        words[*offset]);
1304       if (env == NULL)
1305         goto no_space;
1306       ++*offset;
1307     }
1308   else
1309     {
1310       if (brace)
1311         goto syntax;
1312     }
1313
1314   if (brace)
1315     {
1316       /* Check for special action to be applied to the value. */
1317       switch (words[*offset])
1318         {
1319         case '}':
1320           /* Evaluate. */
1321           goto envsubst;
1322
1323         case '#':
1324           action = ACT_RP_SHORT_LEFT;
1325           if (words[1 + *offset] == '#')
1326             {
1327               ++*offset;
1328               action = ACT_RP_LONG_LEFT;
1329             }
1330           break;
1331
1332         case '%':
1333           action = ACT_RP_SHORT_RIGHT;
1334           if (words[1 + *offset] == '%')
1335             {
1336               ++*offset;
1337               action = ACT_RP_LONG_RIGHT;
1338             }
1339           break;
1340
1341         case ':':
1342           if (strchr ("-=?+", words[1 + *offset]) == NULL)
1343             goto syntax;
1344
1345           colon_seen = 1;
1346           action = words[++*offset];
1347           break;
1348
1349         case '-':
1350         case '=':
1351         case '?':
1352         case '+':
1353           action = words[*offset];
1354           break;
1355
1356         default:
1357           goto syntax;
1358         }
1359
1360       /* Now collect the pattern, but don't expand it yet. */
1361       ++*offset;
1362       for (; words[*offset]; ++(*offset))
1363         {
1364           switch (words[*offset])
1365             {
1366             case '{':
1367               if (!pattern_is_quoted)
1368                 ++depth;
1369               break;
1370
1371             case '}':
1372               if (!pattern_is_quoted)
1373                 {
1374                   if (depth == 0)
1375                     goto envsubst;
1376                   --depth;
1377                 }
1378               break;
1379
1380             case '\\':
1381               if (pattern_is_quoted)
1382                 /* Quoted; treat as normal character. */
1383                 break;
1384
1385               /* Otherwise, it's an escape: next character is literal. */
1386               if (words[++*offset] == '\0')
1387                 goto syntax;
1388
1389               pattern = w_addchar (pattern, &pat_length, &pat_maxlen, '\\');
1390               if (pattern == NULL)
1391                 goto no_space;
1392
1393               break;
1394
1395             case '\'':
1396               if (pattern_is_quoted == 0)
1397                 pattern_is_quoted = 1;
1398               else if (pattern_is_quoted == 1)
1399                 pattern_is_quoted = 0;
1400
1401               break;
1402
1403             case '"':
1404               if (pattern_is_quoted == 0)
1405                 pattern_is_quoted = 2;
1406               else if (pattern_is_quoted == 2)
1407                 pattern_is_quoted = 0;
1408
1409               break;
1410             }
1411
1412           pattern = w_addchar (pattern, &pat_length, &pat_maxlen,
1413                                words[*offset]);
1414           if (pattern == NULL)
1415             goto no_space;
1416         }
1417     }
1418
1419   /* End of input string -- remember to reparse the character that we
1420    * stopped at.  */
1421   --(*offset);
1422
1423 envsubst:
1424   if (words[start] == '{' && words[*offset] != '}')
1425     goto syntax;
1426
1427   if (env == NULL)
1428     {
1429       if (seen_hash)
1430         {
1431           /* $# expands to the number of positional parameters */
1432           buffer[20] = '\0';
1433           value = _itoa_word (__libc_argc - 1, &buffer[20], 10, 0);
1434           seen_hash = 0;
1435         }
1436       else
1437         {
1438           /* Just $ on its own */
1439           *offset = start - 1;
1440           *word = w_addchar (*word, word_length, max_length, '$');
1441           return *word ? 0 : WRDE_NOSPACE;
1442         }
1443     }
1444   /* Is it a numeric parameter? */
1445   else if (isdigit (env[0]))
1446     {
1447       int n = atoi (env);
1448
1449       if (n >= __libc_argc)
1450         /* Substitute NULL. */
1451         value = NULL;
1452       else
1453         /* Replace with appropriate positional parameter. */
1454         value = __libc_argv[n];
1455     }
1456   /* Is it a special parameter? */
1457   else if (special)
1458     {
1459       /* Is it `$$'? */
1460       if (*env == '$')
1461         {
1462           buffer[20] = '\0';
1463           value = _itoa_word (__getpid (), &buffer[20], 10, 0);
1464         }
1465       /* Is it `${#*}' or `${#@}'? */
1466       else if ((*env == '*' || *env == '@') && seen_hash)
1467         {
1468           buffer[20] = '\0';
1469           value = _itoa_word (__libc_argc > 0 ? __libc_argc - 1 : 0,
1470                               &buffer[20], 10, 0);
1471           *word = w_addstr (*word, word_length, max_length, value);
1472           free (env);
1473           free (pattern);
1474           return *word ? 0 : WRDE_NOSPACE;
1475         }
1476       /* Is it `$*' or `$@' (unquoted) ? */
1477       else if (*env == '*' || (*env == '@' && !quoted))
1478         {
1479           size_t plist_len = 0;
1480           int p;
1481           char *end;
1482
1483           /* Build up value parameter by parameter (copy them) */
1484           for (p = 1; __libc_argv[p]; ++p)
1485             plist_len += strlen (__libc_argv[p]) + 1; /* for space */
1486           value = malloc (plist_len);
1487           if (value == NULL)
1488             goto no_space;
1489           end = value;
1490           *end = 0;
1491           for (p = 1; __libc_argv[p]; ++p)
1492             {
1493               if (p > 1)
1494                 *end++ = ' ';
1495               end = __stpcpy (end, __libc_argv[p]);
1496             }
1497
1498           free_value = 1;
1499         }
1500       else
1501         {
1502           /* Must be a quoted `$@' */
1503           assert (*env == '@' && quoted);
1504
1505           /* Each parameter is a separate word ("$@") */
1506           if (__libc_argc == 2)
1507             value = __libc_argv[1];
1508           else if (__libc_argc > 2)
1509             {
1510               int p;
1511
1512               /* Append first parameter to current word. */
1513               value = w_addstr (*word, word_length, max_length,
1514                                 __libc_argv[1]);
1515               if (value == NULL || w_addword (pwordexp, value))
1516                 goto no_space;
1517
1518               for (p = 2; __libc_argv[p + 1]; p++)
1519                 {
1520                   char *newword = __strdup (__libc_argv[p]);
1521                   if (newword == NULL || w_addword (pwordexp, newword))
1522                     goto no_space;
1523                 }
1524
1525               /* Start a new word with the last parameter. */
1526               *word = w_newword (word_length, max_length);
1527               value = __libc_argv[p];
1528             }
1529           else
1530             {
1531               free (env);
1532               free (pattern);
1533               return 0;
1534             }
1535         }
1536     }
1537   else
1538     value = getenv (env);
1539
1540   if (value == NULL && (flags & WRDE_UNDEF))
1541     {
1542       /* Variable not defined. */
1543       error = WRDE_BADVAL;
1544       goto do_error;
1545     }
1546
1547   if (action != ACT_NONE)
1548     {
1549       int expand_pattern = 0;
1550
1551       /* First, find out if we need to expand pattern (i.e. if we will
1552        * use it). */
1553       switch (action)
1554         {
1555         case ACT_RP_SHORT_LEFT:
1556         case ACT_RP_LONG_LEFT:
1557         case ACT_RP_SHORT_RIGHT:
1558         case ACT_RP_LONG_RIGHT:
1559           /* Always expand for these. */
1560           expand_pattern = 1;
1561           break;
1562
1563         case ACT_NULL_ERROR:
1564         case ACT_NULL_SUBST:
1565         case ACT_NULL_ASSIGN:
1566           if (!value || (!*value && colon_seen))
1567             /* If param is unset, or set but null and a colon has been seen,
1568                the expansion of the pattern will be needed. */
1569             expand_pattern = 1;
1570
1571           break;
1572
1573         case ACT_NONNULL_SUBST:
1574           /* Expansion of word will be needed if parameter is set and not null,
1575              or set null but no colon has been seen. */
1576           if (value && (*value || !colon_seen))
1577             expand_pattern = 1;
1578
1579           break;
1580
1581         default:
1582           assert (! "Unrecognised action!");
1583         }
1584
1585       if (expand_pattern)
1586         {
1587           /* We need to perform tilde expansion, parameter expansion,
1588              command substitution, and arithmetic expansion.  We also
1589              have to be a bit careful with wildcard characters, as
1590              pattern might be given to fnmatch soon.  To do this, we
1591              convert quotes to escapes. */
1592
1593           char *expanded;
1594           size_t exp_len;
1595           size_t exp_maxl;
1596           char *p;
1597           int quoted = 0; /* 1: single quotes; 2: double */
1598
1599           expanded = w_newword (&exp_len, &exp_maxl);
1600           for (p = pattern; p && *p; p++)
1601             {
1602               size_t offset;
1603
1604               switch (*p)
1605                 {
1606                 case '"':
1607                   if (quoted == 2)
1608                     quoted = 0;
1609                   else if (quoted == 0)
1610                     quoted = 2;
1611                   else break;
1612
1613                   continue;
1614
1615                 case '\'':
1616                   if (quoted == 1)
1617                     quoted = 0;
1618                   else if (quoted == 0)
1619                     quoted = 1;
1620                   else break;
1621
1622                   continue;
1623
1624                 case '*':
1625                 case '?':
1626                   if (quoted)
1627                     {
1628                       /* Convert quoted wildchar to escaped wildchar. */
1629                       expanded = w_addchar (expanded, &exp_len,
1630                                             &exp_maxl, '\\');
1631
1632                       if (expanded == NULL)
1633                         goto no_space;
1634                     }
1635                   break;
1636
1637                 case '$':
1638                   offset = 0;
1639                   error = parse_dollars (&expanded, &exp_len, &exp_maxl, p,
1640                                          &offset, flags, NULL, NULL, NULL, 1);
1641                   if (error)
1642                     {
1643                       if (free_value)
1644                         free (value);
1645
1646                       free (expanded);
1647
1648                       goto do_error;
1649                     }
1650
1651                   p += offset;
1652                   continue;
1653
1654                 case '~':
1655                   if (quoted || exp_len)
1656                     break;
1657
1658                   offset = 0;
1659                   error = parse_tilde (&expanded, &exp_len, &exp_maxl, p,
1660                                        &offset, 0);
1661                   if (error)
1662                     {
1663                       if (free_value)
1664                         free (value);
1665
1666                       free (expanded);
1667
1668                       goto do_error;
1669                     }
1670
1671                   p += offset;
1672                   continue;
1673
1674                 case '\\':
1675                   expanded = w_addchar (expanded, &exp_len, &exp_maxl, '\\');
1676                   ++p;
1677                   assert (*p); /* checked when extracted initially */
1678                   if (expanded == NULL)
1679                     goto no_space;
1680                 }
1681
1682               expanded = w_addchar (expanded, &exp_len, &exp_maxl, *p);
1683
1684               if (expanded == NULL)
1685                 goto no_space;
1686             }
1687
1688           free (pattern);
1689
1690           pattern = expanded;
1691         }
1692
1693       switch (action)
1694         {
1695         case ACT_RP_SHORT_LEFT:
1696         case ACT_RP_LONG_LEFT:
1697         case ACT_RP_SHORT_RIGHT:
1698         case ACT_RP_LONG_RIGHT:
1699           {
1700             char *p;
1701             char c;
1702             char *end;
1703
1704             if (value == NULL || pattern == NULL || *pattern == '\0')
1705               break;
1706
1707             end = value + strlen (value);
1708
1709             switch (action)
1710               {
1711               case ACT_RP_SHORT_LEFT:
1712                 for (p = value; p <= end; ++p)
1713                   {
1714                     c = *p;
1715                     *p = '\0';
1716                     if (fnmatch (pattern, value, 0) != FNM_NOMATCH)
1717                       {
1718                         *p = c;
1719                         if (free_value)
1720                           {
1721                             char *newval = __strdup (p);
1722                             if (newval == NULL)
1723                               {
1724                                 free (value);
1725                                 goto no_space;
1726                               }
1727                             free (value);
1728                             value = newval;
1729                           }
1730                         else
1731                           value = p;
1732                         break;
1733                       }
1734                     *p = c;
1735                   }
1736
1737                 break;
1738
1739               case ACT_RP_LONG_LEFT:
1740                 for (p = end; p >= value; --p)
1741                   {
1742                     c = *p;
1743                     *p = '\0';
1744                     if (fnmatch (pattern, value, 0) != FNM_NOMATCH)
1745                       {
1746                         *p = c;
1747                         if (free_value)
1748                           {
1749                             char *newval = __strdup (p);
1750                             if (newval == NULL)
1751                               {
1752                                 free (value);
1753                                 goto no_space;
1754                               }
1755                             free (value);
1756                             value = newval;
1757                           }
1758                         else
1759                           value = p;
1760                         break;
1761                       }
1762                     *p = c;
1763                   }
1764
1765                 break;
1766
1767               case ACT_RP_SHORT_RIGHT:
1768                 for (p = end; p >= value; --p)
1769                   {
1770                     if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
1771                       {
1772                         char *newval;
1773                         newval = malloc (p - value + 1);
1774
1775                         if (newval == NULL)
1776                           {
1777                             if (free_value)
1778                               free (value);
1779                             goto no_space;
1780                           }
1781
1782                         *(char *) __mempcpy (newval, value, p - value) = '\0';
1783                         if (free_value)
1784                           free (value);
1785                         value = newval;
1786                         free_value = 1;
1787                         break;
1788                       }
1789                   }
1790
1791                 break;
1792
1793               case ACT_RP_LONG_RIGHT:
1794                 for (p = value; p <= end; ++p)
1795                   {
1796                     if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
1797                       {
1798                         char *newval;
1799                         newval = malloc (p - value + 1);
1800
1801                         if (newval == NULL)
1802                           {
1803                             if (free_value)
1804                               free (value);
1805                             goto no_space;
1806                           }
1807
1808                         *(char *) __mempcpy (newval, value, p - value) = '\0';
1809                         if (free_value)
1810                           free (value);
1811                         value = newval;
1812                         free_value = 1;
1813                         break;
1814                       }
1815                   }
1816
1817                 break;
1818
1819               default:
1820                 break;
1821               }
1822
1823             break;
1824           }
1825
1826         case ACT_NULL_ERROR:
1827           if (value && *value)
1828             /* Substitute parameter */
1829             break;
1830
1831           error = 0;
1832           if (!colon_seen && value)
1833             /* Substitute NULL */
1834             ;
1835           else
1836             {
1837               const char *str = pattern;
1838
1839               if (str[0] == '\0')
1840                 str = _("parameter null or not set");
1841
1842               __fxprintf (NULL, "%s: %s\n", env, str);
1843             }
1844
1845           if (free_value)
1846             free (value);
1847           goto do_error;
1848
1849         case ACT_NULL_SUBST:
1850           if (value && *value)
1851             /* Substitute parameter */
1852             break;
1853
1854           if (free_value)
1855             free (value);
1856
1857           if (!colon_seen && value)
1858             /* Substitute NULL */
1859             goto success;
1860
1861           value = pattern ? __strdup (pattern) : pattern;
1862           free_value = 1;
1863
1864           if (pattern && !value)
1865             goto no_space;
1866
1867           break;
1868
1869         case ACT_NONNULL_SUBST:
1870           if (value && (*value || !colon_seen))
1871             {
1872               if (free_value)
1873                 free (value);
1874
1875               value = pattern ? __strdup (pattern) : pattern;
1876               free_value = 1;
1877
1878               if (pattern && !value)
1879                 goto no_space;
1880
1881               break;
1882             }
1883
1884           /* Substitute NULL */
1885           if (free_value)
1886             free (value);
1887           goto success;
1888
1889         case ACT_NULL_ASSIGN:
1890           if (value && *value)
1891             /* Substitute parameter */
1892             break;
1893
1894           if (!colon_seen && value)
1895             {
1896               /* Substitute NULL */
1897               if (free_value)
1898                 free (value);
1899               goto success;
1900             }
1901
1902           if (free_value)
1903             free (value);
1904
1905           value = pattern ? __strdup (pattern) : pattern;
1906           free_value = 1;
1907
1908           if (pattern && !value)
1909             goto no_space;
1910
1911           __setenv (env, value, 1);
1912           break;
1913
1914         default:
1915           assert (! "Unrecognised action!");
1916         }
1917     }
1918
1919   free (env);
1920   env = NULL;
1921   free (pattern);
1922   pattern = NULL;
1923
1924   if (seen_hash)
1925     {
1926       char param_length[21];
1927       param_length[20] = '\0';
1928       *word = w_addstr (*word, word_length, max_length,
1929                         _itoa_word (value ? strlen (value) : 0,
1930                                     &param_length[20], 10, 0));
1931       if (free_value)
1932         {
1933           assert (value != NULL);
1934           free (value);
1935         }
1936
1937       return *word ? 0 : WRDE_NOSPACE;
1938     }
1939
1940   if (value == NULL)
1941     return 0;
1942
1943   if (quoted || !pwordexp)
1944     {
1945       /* Quoted - no field split */
1946       *word = w_addstr (*word, word_length, max_length, value);
1947       if (free_value)
1948         free (value);
1949
1950       return *word ? 0 : WRDE_NOSPACE;
1951     }
1952   else
1953     {
1954       /* Need to field-split */
1955       char *value_copy = __strdup (value); /* Don't modify value */
1956       char *field_begin = value_copy;
1957       int seen_nonws_ifs = 0;
1958
1959       if (free_value)
1960         free (value);
1961
1962       if (value_copy == NULL)
1963         goto no_space;
1964
1965       do
1966         {
1967           char *field_end = field_begin;
1968           char *next_field;
1969
1970           /* If this isn't the first field, start a new word */
1971           if (field_begin != value_copy)
1972             {
1973               if (w_addword (pwordexp, *word) == WRDE_NOSPACE)
1974                 {
1975                   free (value_copy);
1976                   goto no_space;
1977                 }
1978
1979               *word = w_newword (word_length, max_length);
1980             }
1981
1982           /* Skip IFS whitespace before the field */
1983           field_begin += strspn (field_begin, ifs_white);
1984
1985           if (!seen_nonws_ifs && *field_begin == 0)
1986             /* Nothing but whitespace */
1987             break;
1988
1989           /* Search for the end of the field */
1990           field_end = field_begin + strcspn (field_begin, ifs);
1991
1992           /* Set up pointer to the character after end of field and
1993              skip whitespace IFS after it. */
1994           next_field = field_end + strspn (field_end, ifs_white);
1995
1996           /* Skip at most one non-whitespace IFS character after the field */
1997           seen_nonws_ifs = 0;
1998           if (*next_field && strchr (ifs, *next_field))
1999             {
2000               seen_nonws_ifs = 1;
2001               next_field++;
2002             }
2003
2004           /* Null-terminate it */
2005           *field_end = 0;
2006
2007           /* Tag a copy onto the current word */
2008           *word = w_addstr (*word, word_length, max_length, field_begin);
2009
2010           if (*word == NULL && *field_begin != '\0')
2011             {
2012               free (value_copy);
2013               goto no_space;
2014             }
2015
2016           field_begin = next_field;
2017         }
2018       while (seen_nonws_ifs || *field_begin);
2019
2020       free (value_copy);
2021     }
2022
2023   return 0;
2024
2025 success:
2026   error = 0;
2027   goto do_error;
2028
2029 no_space:
2030   error = WRDE_NOSPACE;
2031   goto do_error;
2032
2033 syntax:
2034   error = WRDE_SYNTAX;
2035
2036 do_error:
2037   free (env);
2038
2039   free (pattern);
2040
2041   return error;
2042 }
2043
2044 static int
2045 internal_function
2046 parse_dollars (char **word, size_t *word_length, size_t *max_length,
2047                const char *words, size_t *offset, int flags,
2048                wordexp_t *pwordexp, const char *ifs, const char *ifs_white,
2049                int quoted)
2050 {
2051   /* We are poised _at_ "$" */
2052   switch (words[1 + *offset])
2053     {
2054     case '"':
2055     case '\'':
2056     case 0:
2057       *word = w_addchar (*word, word_length, max_length, '$');
2058       return *word ? 0 : WRDE_NOSPACE;
2059
2060     case '(':
2061       if (words[2 + *offset] == '(')
2062         {
2063           /* Differentiate between $((1+3)) and $((echo);(ls)) */
2064           int i = 3 + *offset;
2065           int depth = 0;
2066           while (words[i] && !(depth == 0 && words[i] == ')'))
2067             {
2068               if (words[i] == '(')
2069                 ++depth;
2070               else if (words[i] == ')')
2071                 --depth;
2072
2073               ++i;
2074             }
2075
2076           if (words[i] == ')' && words[i + 1] == ')')
2077             {
2078               (*offset) += 3;
2079               /* Call parse_arith -- 0 is for "no brackets" */
2080               return parse_arith (word, word_length, max_length, words, offset,
2081                                   flags, 0);
2082             }
2083         }
2084
2085       if (flags & WRDE_NOCMD)
2086         return WRDE_CMDSUB;
2087
2088       (*offset) += 2;
2089       return parse_comm (word, word_length, max_length, words, offset, flags,
2090                          quoted? NULL : pwordexp, ifs, ifs_white);
2091
2092     case '[':
2093       (*offset) += 2;
2094       /* Call parse_arith -- 1 is for "brackets" */
2095       return parse_arith (word, word_length, max_length, words, offset, flags,
2096                           1);
2097
2098     case '{':
2099     default:
2100       ++(*offset);      /* parse_param needs to know if "{" is there */
2101       return parse_param (word, word_length, max_length, words, offset, flags,
2102                            pwordexp, ifs, ifs_white, quoted);
2103     }
2104 }
2105
2106 static int
2107 internal_function
2108 parse_backtick (char **word, size_t *word_length, size_t *max_length,
2109                 const char *words, size_t *offset, int flags,
2110                 wordexp_t *pwordexp, const char *ifs, const char *ifs_white)
2111 {
2112   /* We are poised just after "`" */
2113   int error;
2114   int squoting = 0;
2115   size_t comm_length;
2116   size_t comm_maxlen;
2117   char *comm = w_newword (&comm_length, &comm_maxlen);
2118
2119   for (; words[*offset]; ++(*offset))
2120     {
2121       switch (words[*offset])
2122         {
2123         case '`':
2124           /* Go -- give the script to the shell */
2125           error = exec_comm (comm, word, word_length, max_length, flags,
2126                              pwordexp, ifs, ifs_white);
2127           free (comm);
2128           return error;
2129
2130         case '\\':
2131           if (squoting)
2132             {
2133               error = parse_qtd_backslash (&comm, &comm_length, &comm_maxlen,
2134                                            words, offset);
2135
2136               if (error)
2137                 {
2138                   free (comm);
2139                   return error;
2140                 }
2141
2142               break;
2143             }
2144
2145           ++(*offset);
2146           error = parse_backslash (&comm, &comm_length, &comm_maxlen, words,
2147                                    offset);
2148
2149           if (error)
2150             {
2151               free (comm);
2152               return error;
2153             }
2154
2155           break;
2156
2157         case '\'':
2158           squoting = 1 - squoting;
2159         default:
2160           comm = w_addchar (comm, &comm_length, &comm_maxlen, words[*offset]);
2161           if (comm == NULL)
2162             return WRDE_NOSPACE;
2163         }
2164     }
2165
2166   /* Premature end */
2167   free (comm);
2168   return WRDE_SYNTAX;
2169 }
2170
2171 static int
2172 internal_function
2173 parse_dquote (char **word, size_t *word_length, size_t *max_length,
2174               const char *words, size_t *offset, int flags,
2175               wordexp_t *pwordexp, const char * ifs, const char * ifs_white)
2176 {
2177   /* We are poised just after a double-quote */
2178   int error;
2179
2180   for (; words[*offset]; ++(*offset))
2181     {
2182       switch (words[*offset])
2183         {
2184         case '"':
2185           return 0;
2186
2187         case '$':
2188           error = parse_dollars (word, word_length, max_length, words, offset,
2189                                  flags, pwordexp, ifs, ifs_white, 1);
2190           /* The ``1'' here is to tell parse_dollars not to
2191            * split the fields.  It may need to, however ("$@").
2192            */
2193           if (error)
2194             return error;
2195
2196           break;
2197
2198         case '`':
2199           if (flags & WRDE_NOCMD)
2200             return WRDE_CMDSUB;
2201
2202           ++(*offset);
2203           error = parse_backtick (word, word_length, max_length, words,
2204                                   offset, flags, NULL, NULL, NULL);
2205           /* The first NULL here is to tell parse_backtick not to
2206            * split the fields.
2207            */
2208           if (error)
2209             return error;
2210
2211           break;
2212
2213         case '\\':
2214           error = parse_qtd_backslash (word, word_length, max_length, words,
2215                                        offset);
2216
2217           if (error)
2218             return error;
2219
2220           break;
2221
2222         default:
2223           *word = w_addchar (*word, word_length, max_length, words[*offset]);
2224           if (*word == NULL)
2225             return WRDE_NOSPACE;
2226         }
2227     }
2228
2229   /* Unterminated string */
2230   return WRDE_SYNTAX;
2231 }
2232
2233 /*
2234  * wordfree() is to be called after pwordexp is finished with.
2235  */
2236
2237 void
2238 wordfree (wordexp_t *pwordexp)
2239 {
2240
2241   /* wordexp can set pwordexp to NULL */
2242   if (pwordexp && pwordexp->we_wordv)
2243     {
2244       char **wordv = pwordexp->we_wordv;
2245
2246       for (wordv += pwordexp->we_offs; *wordv; ++wordv)
2247         free (*wordv);
2248
2249       free (pwordexp->we_wordv);
2250       pwordexp->we_wordv = NULL;
2251     }
2252 }
2253 libc_hidden_def (wordfree)
2254
2255 /*
2256  * wordexp()
2257  */
2258
2259 int
2260 wordexp (const char *words, wordexp_t *pwordexp, int flags)
2261 {
2262   size_t words_offset;
2263   size_t word_length;
2264   size_t max_length;
2265   char *word = w_newword (&word_length, &max_length);
2266   int error;
2267   char *ifs;
2268   char ifs_white[4];
2269   wordexp_t old_word = *pwordexp;
2270
2271   if (flags & WRDE_REUSE)
2272     {
2273       /* Minimal implementation of WRDE_REUSE for now */
2274       wordfree (pwordexp);
2275       old_word.we_wordv = NULL;
2276     }
2277
2278   if ((flags & WRDE_APPEND) == 0)
2279     {
2280       pwordexp->we_wordc = 0;
2281
2282       if (flags & WRDE_DOOFFS)
2283         {
2284           pwordexp->we_wordv = calloc (1 + pwordexp->we_offs, sizeof (char *));
2285           if (pwordexp->we_wordv == NULL)
2286             {
2287               error = WRDE_NOSPACE;
2288               goto do_error;
2289             }
2290         }
2291       else
2292         {
2293           pwordexp->we_wordv = calloc (1, sizeof (char *));
2294           if (pwordexp->we_wordv == NULL)
2295             {
2296               error = WRDE_NOSPACE;
2297               goto do_error;
2298             }
2299
2300           pwordexp->we_offs = 0;
2301         }
2302     }
2303
2304   /* Find out what the field separators are.
2305    * There are two types: whitespace and non-whitespace.
2306    */
2307   ifs = getenv ("IFS");
2308
2309   if (ifs == NULL)
2310     /* IFS unset - use <space><tab><newline>. */
2311     ifs = strcpy (ifs_white, " \t\n");
2312   else
2313     {
2314       char *ifsch = ifs;
2315       char *whch = ifs_white;
2316
2317       while (*ifsch != '\0')
2318         {
2319           if (*ifsch == ' ' || *ifsch == '\t' || *ifsch == '\n')
2320             {
2321               /* Whitespace IFS.  See first whether it is already in our
2322                  collection.  */
2323               char *runp = ifs_white;
2324
2325               while (runp < whch && *runp != *ifsch)
2326                 ++runp;
2327
2328               if (runp == whch)
2329                 *whch++ = *ifsch;
2330             }
2331
2332           ++ifsch;
2333         }
2334       *whch = '\0';
2335     }
2336
2337   for (words_offset = 0 ; words[words_offset] ; ++words_offset)
2338     switch (words[words_offset])
2339       {
2340       case '\\':
2341         error = parse_backslash (&word, &word_length, &max_length, words,
2342                                  &words_offset);
2343
2344         if (error)
2345           goto do_error;
2346
2347         break;
2348
2349       case '$':
2350         error = parse_dollars (&word, &word_length, &max_length, words,
2351                                &words_offset, flags, pwordexp, ifs, ifs_white,
2352                                0);
2353
2354         if (error)
2355           goto do_error;
2356
2357         break;
2358
2359       case '`':
2360         if (flags & WRDE_NOCMD)
2361           {
2362             error = WRDE_CMDSUB;
2363             goto do_error;
2364           }
2365
2366         ++words_offset;
2367         error = parse_backtick (&word, &word_length, &max_length, words,
2368                                 &words_offset, flags, pwordexp, ifs,
2369                                 ifs_white);
2370
2371         if (error)
2372           goto do_error;
2373
2374         break;
2375
2376       case '"':
2377         ++words_offset;
2378         error = parse_dquote (&word, &word_length, &max_length, words,
2379                               &words_offset, flags, pwordexp, ifs, ifs_white);
2380
2381         if (error)
2382           goto do_error;
2383
2384         if (!word_length)
2385           {
2386             error = w_addword (pwordexp, NULL);
2387
2388             if (error)
2389               return error;
2390           }
2391
2392         break;
2393
2394       case '\'':
2395         ++words_offset;
2396         error = parse_squote (&word, &word_length, &max_length, words,
2397                               &words_offset);
2398
2399         if (error)
2400           goto do_error;
2401
2402         if (!word_length)
2403           {
2404             error = w_addword (pwordexp, NULL);
2405
2406             if (error)
2407               return error;
2408           }
2409
2410         break;
2411
2412       case '~':
2413         error = parse_tilde (&word, &word_length, &max_length, words,
2414                              &words_offset, pwordexp->we_wordc);
2415
2416         if (error)
2417           goto do_error;
2418
2419         break;
2420
2421       case '*':
2422       case '[':
2423       case '?':
2424         error = parse_glob (&word, &word_length, &max_length, words,
2425                             &words_offset, flags, pwordexp, ifs, ifs_white);
2426
2427         if (error)
2428           goto do_error;
2429
2430         break;
2431
2432       default:
2433         /* Is it a word separator? */
2434         if (strchr (" \t", words[words_offset]) == NULL)
2435           {
2436             char ch = words[words_offset];
2437
2438             /* Not a word separator -- but is it a valid word char? */
2439             if (strchr ("\n|&;<>(){}", ch))
2440               {
2441                 /* Fail */
2442                 error = WRDE_BADCHAR;
2443                 goto do_error;
2444               }
2445
2446             /* "Ordinary" character -- add it to word */
2447             word = w_addchar (word, &word_length, &max_length,
2448                               ch);
2449             if (word == NULL)
2450               {
2451                 error = WRDE_NOSPACE;
2452                 goto do_error;
2453               }
2454
2455             break;
2456           }
2457
2458         /* If a word has been delimited, add it to the list. */
2459         if (word != NULL)
2460           {
2461             error = w_addword (pwordexp, word);
2462             if (error)
2463               goto do_error;
2464           }
2465
2466         word = w_newword (&word_length, &max_length);
2467       }
2468
2469   /* End of string */
2470
2471   /* There was a word separator at the end */
2472   if (word == NULL) /* i.e. w_newword */
2473     return 0;
2474
2475   /* There was no field separator at the end */
2476   return w_addword (pwordexp, word);
2477
2478 do_error:
2479   /* Error:
2480    *    free memory used (unless error is WRDE_NOSPACE), and
2481    *    set pwordexp members back to what they were.
2482    */
2483
2484   free (word);
2485
2486   if (error == WRDE_NOSPACE)
2487     return WRDE_NOSPACE;
2488
2489   if ((flags & WRDE_APPEND) == 0)
2490     wordfree (pwordexp);
2491
2492   *pwordexp = old_word;
2493   return error;
2494 }