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