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