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