1 /* POSIX.2 wordexp implementation.
2 Copyright (C) 1997, 1998 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
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 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
25 #include <sys/types.h>
30 #include <sys/types.h>
37 #include <sys/param.h>
41 #include <stdio-common/_itoa.h>
43 /* Undefine the following line for the production version. */
44 /* #define NDEBUG 1 */
48 * This is a recursive-descent-style word expansion routine.
51 /* These variables are defined and initialized in the startup code. */
52 extern int __libc_argc;
53 extern char **__libc_argv;
55 /* Some forward declarations */
56 static int parse_dollars (char **word, size_t *word_length, size_t *max_length,
57 const char *words, size_t *offset, int flags,
58 wordexp_t *pwordexp, const char *ifs,
59 const char *ifs_white, int quoted)
61 static int parse_backtick (char **word, size_t *word_length,
62 size_t *max_length, const char *words,
63 size_t *offset, int flags, wordexp_t *pwordexp,
64 const char *ifs, const char *ifs_white)
66 static int parse_dquote (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)
71 static int eval_expr (char *expr, long int *result) internal_function;
73 /* The w_*() functions manipulate word lists. */
78 w_addchar (char *buffer, size_t *actlen, size_t *maxlen, char ch)
79 /* (lengths exclude trailing zero) */
81 /* Add a character to the buffer, allocating room for it if needed.
84 if (*actlen == *maxlen)
86 char *old_buffer = buffer;
87 assert (buffer == NULL || *maxlen != 0);
89 buffer = realloc (buffer, 1 + *maxlen);
98 buffer[++(*actlen)] = '\0';
106 w_addmem (char *buffer, size_t *actlen, size_t *maxlen, const char *str,
109 /* Add a string to the buffer, allocating room for it if needed.
111 if (*actlen + len > *maxlen)
113 char *old_buffer = buffer;
114 assert (buffer == NULL || *maxlen != 0);
115 *maxlen += MAX (2 * len, W_CHUNK);
116 buffer = realloc (old_buffer, 1 + *maxlen);
124 *((char *) __mempcpy (&buffer[*actlen], str, len)) = '\0';
134 w_addstr (char *buffer, size_t *actlen, size_t *maxlen, const char *str)
135 /* (lengths exclude trailing zero) */
137 /* Add a string to the buffer, allocating room for it if needed.
141 assert (str != NULL); /* w_addstr only called from this file */
144 return w_addmem (buffer, actlen, maxlen, str, len);
149 w_addword (wordexp_t *pwordexp, char *word)
151 /* Add a word to the wordlist */
155 num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs;
156 new_wordv = realloc (pwordexp->we_wordv, sizeof (char *) * num_p);
157 if (new_wordv != NULL)
159 pwordexp->we_wordv = new_wordv;
160 pwordexp->we_wordv[pwordexp->we_wordc++] = word;
161 pwordexp->we_wordv[pwordexp->we_wordc] = NULL;
168 /* The parse_*() functions should leave *offset being the offset in 'words'
169 * to the last character processed.
174 parse_backslash (char **word, size_t *word_length, size_t *max_length,
175 const char *words, size_t *offset)
177 /* We are poised _at_ a backslash, not in quotes */
179 switch (words[1 + *offset])
182 /* Backslash is last character of input words */
190 *word = w_addchar (*word, word_length, max_length, words[1 + *offset]);
203 parse_qtd_backslash (char **word, size_t *word_length, size_t *max_length,
204 const char *words, size_t *offset)
206 /* We are poised _at_ a backslash, inside quotes */
208 switch (words[1 + *offset])
211 /* Backslash is last character of input words */
222 *word = w_addchar (*word, word_length, max_length, words[1 + *offset]);
230 *word = w_addchar (*word, word_length, max_length, words[*offset]);
232 *word = w_addchar (*word, word_length, max_length, words[1 + *offset]);
246 parse_tilde (char **word, size_t *word_length, size_t *max_length,
247 const char *words, size_t *offset, size_t wordc)
249 /* We are poised _at_ a tilde */
252 if (*word_length != 0)
254 if (!((*word)[*word_length - 1] == '=' && wordc == 0))
256 if (!((*word)[*word_length - 1] == ':'
257 && strchr (*word, '=') && wordc == 0))
259 *word = w_addchar (*word, word_length, max_length, '~');
260 return *word ? 0 : WRDE_NOSPACE;
265 for (i = 1 + *offset; words[i]; i++)
267 if (words[i] == ':' || words[i] == '/' || words[i] == ' ' ||
268 words[i] == '\t' || words[i] == 0 )
271 if (words[i] == '\\')
273 *word = w_addchar (*word, word_length, max_length, '~');
274 return *word ? 0 : WRDE_NOSPACE;
278 if (i == 1 + *offset)
280 /* Tilde appears on its own */
282 struct passwd pwd, *tpwd;
284 char* buffer = __alloca (buflen);
289 while ((result = __getpwuid_r (uid, &pwd, buffer, buflen, &tpwd)) != 0
293 buffer = __alloca (buflen);
296 if (result == 0 && pwd.pw_dir != NULL)
298 *word = w_addstr (*word, word_length, max_length, pwd.pw_dir);
304 *word = w_addchar (*word, word_length, max_length, '~');
311 /* Look up user name in database to get home directory */
312 char *user = __strndup (&words[1 + *offset], i - *offset);
313 struct passwd pwd, *tpwd;
315 char* buffer = __alloca (buflen);
318 while ((result = __getpwnam_r (user, &pwd, buffer, buflen, &tpwd)) != 0
322 buffer = __alloca (buflen);
325 if (result == 0 && pwd.pw_dir)
326 *word = w_addstr (*word, word_length, max_length, pwd.pw_dir);
329 /* (invalid login name) */
330 *word = w_addchar (*word, word_length, max_length, '~');
332 *word = w_addstr (*word, word_length, max_length, user);
337 return *word ? 0 : WRDE_NOSPACE;
342 parse_glob (char **word, size_t *word_length, size_t *max_length,
343 const char *words, size_t *offset, int flags,
344 wordexp_t *pwordexp, const char *ifs, const char *ifs_white)
346 /* We are poised just after a '*', a '[' or a '?'. */
351 int quoted = 0; /* 1 if singly-quoted, 2 if doubly */
353 for (; words[*offset]; (*offset)++)
355 if ((ifs && strchr (ifs, words[*offset])) ||
356 (!ifs && strchr (" \t\n", words[*offset])))
360 /* Sort out quoting */
361 if (words[*offset] == '\'')
367 else if (quoted == 1)
372 else if (words[*offset] == '"')
378 else if (quoted == 2)
384 /* Sort out other special characters */
385 if (quoted != 1 && words[*offset] == '$')
387 error = parse_dollars (word, word_length, max_length, words, offset,
388 flags, pwordexp, ifs, ifs_white, quoted == 2);
394 else if (words[*offset] == '\\')
397 error = parse_qtd_backslash (word, word_length, max_length, words,
400 error = parse_backslash (word, word_length, max_length, words,
409 *word = w_addchar (*word, word_length, max_length, words[*offset]);
414 error = glob (*word, GLOB_NOCHECK, NULL, &globbuf);
418 /* We can only run into memory problems. */
419 assert (error == GLOB_NOSPACE);
426 /* No field splitting allowed */
427 size_t length = strlen (globbuf.gl_pathv[0]);
428 char *old_word = *word;
429 *word = realloc (*word, length + 1);
436 memcpy (*word, globbuf.gl_pathv[0], length + 1);
437 *word_length = length;
439 for (match = 1; match < globbuf.gl_pathc && *word != NULL; ++match)
441 *word = w_addchar (*word, word_length, max_length, ' ');
443 *word = w_addstr (*word, word_length, max_length,
444 globbuf.gl_pathv[match]);
447 /* Re-parse white space on return */
450 return *word ? 0 : WRDE_NOSPACE;
458 matching_word = __strdup (globbuf.gl_pathv[0]);
459 if (matching_word == NULL)
462 if (w_addword (pwordexp, matching_word) == WRDE_NOSPACE)
465 for (match = 1; match < globbuf.gl_pathc; ++match)
467 matching_word = __strdup (globbuf.gl_pathv[match]);
468 if (matching_word == NULL)
471 if (w_addword (pwordexp, matching_word) == WRDE_NOSPACE)
477 /* Re-parse white space on return */
488 parse_squote (char **word, size_t *word_length, size_t *max_length,
489 const char *words, size_t *offset)
491 /* We are poised just after a single quote */
492 for (; words[*offset]; ++(*offset))
494 if (words[*offset] != '\'')
496 *word = w_addchar (*word, word_length, max_length, words[*offset]);
503 /* Unterminated string */
507 /* Functions to evaluate an arithmetic expression */
510 eval_expr_val (char **expr, long int *result)
515 /* Skip white space */
516 for (digit = *expr; digit && *digit && isspace (*digit); ++digit);
522 /* Scan for closing paren */
523 for (++digit; **expr && **expr != ')'; ++(*expr));
531 if (eval_expr (digit, result))
536 case '+': /* Positive value */
540 case '-': /* Negative value */
546 if (!isdigit (*digit))
551 for (; *digit && isdigit (*digit); ++digit)
552 *result = (*result * 10) + (*digit - '0');
561 eval_expr_multdiv (char **expr, long int *result)
566 if (eval_expr_val (expr, result) != 0)
571 /* Skip white space */
572 for (; *expr && **expr && isspace (**expr); ++(*expr));
577 if (eval_expr_val (expr, &arg) != 0)
582 else if (**expr == '/')
585 if (eval_expr_val (expr, &arg) != 0)
598 eval_expr (char *expr, long int *result)
603 if (eval_expr_multdiv (&expr, result) != 0)
608 /* Skip white space */
609 for (; expr && *expr && isspace (*expr); ++expr);
614 if (eval_expr_multdiv (&expr, &arg) != 0)
619 else if (*expr == '-')
622 if (eval_expr_multdiv (&expr, &arg) != 0)
635 parse_arith (char **word, size_t *word_length, size_t *max_length,
636 const char *words, size_t *offset, int flags, int bracket)
638 /* We are poised just after "$((" or "$[" */
641 size_t expr_length = 0;
642 size_t expr_maxlen = 0;
645 for (; words[*offset]; ++(*offset))
647 switch (words[*offset])
650 error = parse_dollars (&expr, &expr_length, &expr_maxlen,
651 words, offset, flags, NULL, NULL, NULL, 1);
652 /* The ``1'' here is to tell parse_dollars not to
664 error = parse_backtick (&expr, &expr_length, &expr_maxlen,
665 words, offset, flags, NULL, NULL, NULL);
666 /* The first NULL here is to tell parse_backtick not to
677 error = parse_qtd_backslash (&expr, &expr_length, &expr_maxlen,
684 /* I think that a backslash within an
685 * arithmetic expansion is bound to
686 * cause an error sooner or later anyway though.
691 if (--paren_depth == 0)
693 char result[21]; /* 21 = ceil(log10(2^64)) + 1 */
694 long int numresult = 0;
695 long long int convertme;
697 if (bracket || words[1 + *offset] != ')')
703 if (*expr && eval_expr (expr, &numresult) != 0)
708 convertme = -numresult;
709 *word = w_addchar (*word, word_length, max_length, '-');
717 convertme = numresult;
720 *word = w_addstr (*word, word_length, max_length,
721 _itoa (convertme, &result[20], 10, 0));
723 return *word ? 0 : WRDE_NOSPACE;
725 expr = w_addchar (expr, &expr_length, &expr_maxlen, words[*offset]);
732 if (bracket && paren_depth == 1)
734 char result[21]; /* 21 = ceil(log10(2^64)) + 1 */
735 long int numresult = 0;
738 if (*expr && eval_expr (expr, &numresult) != 0)
742 *word = w_addstr (*word, word_length, max_length,
743 _itoa_word (numresult, &result[20], 10, 0));
745 return *word ? 0 : WRDE_NOSPACE;
761 expr = w_addchar (expr, &expr_length, &expr_maxlen, words[*offset]);
772 /* Function to execute a command and retrieve the results */
773 /* pwordexp contains NULL if field-splitting is forbidden */
776 exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
777 int flags, wordexp_t *pwordexp, const char *ifs,
778 const char *ifs_white)
787 /* Don't fork() unless necessary */
795 if ((pid = fork ()) < 0)
804 const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL };
806 /* Redirect output. */
810 /* Redirect stderr to /dev/null if we have to. */
811 if ((flags & WRDE_SHOWERR) == 0)
815 fd = open (_PATH_DEVNULL, O_WRONLY);
816 if (fd >= 0 && fd != 2)
824 __execve (_PATH_BSHELL, (char *const *) args, __environ);
833 buffer = __alloca (bufsize);
836 { /* Quoted - no field splitting */
840 if ((buflen = read (fildes[0], buffer, bufsize)) < 1)
842 if (__waitpid (pid, NULL, WNOHANG) == 0)
844 if ((buflen = read (fildes[0], buffer, bufsize)) < 1)
848 *word = w_addmem (*word, word_length, max_length, buffer, buflen);
852 __waitpid (pid, NULL, 0);
859 /* Not quoted - split fields */
863 * 0 when searching for first character in a field not IFS white space
864 * 1 when copying the text of a field
865 * 2 when searching for possible non-whitespace IFS
870 if ((buflen = read (fildes[0], buffer, bufsize)) < 1)
872 if (__waitpid (pid, NULL, WNOHANG) == 0)
874 if ((read (fildes[0], buffer, bufsize)) < 1)
878 for (i = 0; i < buflen; ++i)
880 if (strchr (ifs, buffer[i]) != NULL)
882 /* Current character is IFS */
883 if (strchr (ifs_white, buffer[i]) == NULL)
885 /* Current character is IFS but not whitespace */
891 * eg: text<space><comma><space>moretext
893 * So, strip whitespace IFS (like at the start)
900 /* fall through and delimit field.. */
904 /* Current character is IFS white space */
906 /* If not copying a field, ignore it */
910 /* End of field (search for non-IFS afterwards) */
914 /* First IFS white space, or IFS non-whitespace.
915 * Delimit the field. */
918 /* This field is null, so make it an empty string */
919 *word = w_addchar (*word, word_length, max_length, 0);
923 __waitpid (pid, NULL, 0);
929 if (w_addword (pwordexp, *word) == WRDE_NOSPACE)
932 __waitpid (pid, NULL, 0);
940 /* fall back round the loop.. */
944 /* Not IFS character */
946 *word = w_addchar (*word, word_length, max_length,
951 __waitpid (pid, NULL, 0);
960 /* Bash chops off trailing newlines, which seems sensible. */
961 while (*word_length > 0 && (*word)[*word_length - 1] == '\n')
962 (*word)[--*word_length] = '\0';
970 parse_comm (char **word, size_t *word_length, size_t *max_length,
971 const char *words, size_t *offset, int flags, wordexp_t *pwordexp,
972 const char *ifs, const char *ifs_white)
974 /* We are poised just after "$(" */
977 size_t comm_length = 0;
978 size_t comm_maxlen = 0;
980 int quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */
982 for (; words[*offset]; ++(*offset))
984 switch (words[*offset])
989 else if (quoted == 1)
997 else if (quoted == 2)
1003 if (!quoted && --paren_depth == 0)
1005 /* Go -- give script to the shell */
1008 error = exec_comm (comm, word, word_length, max_length,
1009 flags, pwordexp, ifs, ifs_white);
1016 /* This is just part of the script */
1024 comm = w_addchar (comm, &comm_length, &comm_maxlen, words[*offset]);
1026 return WRDE_NOSPACE;
1038 parse_param (char **word, size_t *word_length, size_t *max_length,
1039 const char *words, size_t *offset, int flags, wordexp_t *pwordexp,
1040 const char *ifs, const char *ifs_white, int quoted)
1042 /* We are poised just after "$" */
1046 ACT_RP_SHORT_LEFT = '#',
1047 ACT_RP_LONG_LEFT = 'L',
1048 ACT_RP_SHORT_RIGHT = '%',
1049 ACT_RP_LONG_RIGHT = 'R',
1050 ACT_NULL_ERROR = '?',
1051 ACT_NULL_SUBST = '-',
1052 ACT_NONNULL_SUBST = '+',
1053 ACT_NULL_ASSIGN = '='
1055 size_t env_length = 0;
1056 size_t env_maxlen = 0;
1057 size_t pat_length = 0;
1058 size_t pat_maxlen = 0;
1059 size_t start = *offset;
1061 char *pattern = NULL;
1063 enum action action = ACT_NONE;
1068 int pattern_is_quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */
1070 int brace = words[*offset] == '{';
1075 for (; words[*offset]; ++(*offset))
1079 if (action != ACT_NONE)
1081 switch (words[*offset])
1084 if (!pattern_is_quoted)
1089 if (!pattern_is_quoted)
1098 if (!pattern_is_quoted && words[++*offset] == '\0')
1103 if (pattern_is_quoted == 0)
1104 pattern_is_quoted = 1;
1105 else if (pattern_is_quoted == 1)
1106 pattern_is_quoted = 0;
1111 if (pattern_is_quoted == 0)
1112 pattern_is_quoted = 2;
1113 else if (pattern_is_quoted == 2)
1114 pattern_is_quoted = 0;
1119 pattern = w_addchar (pattern, &pat_length, &pat_maxlen,
1121 if (pattern == NULL)
1127 switch (words[*offset])
1140 /* '#' only has special meaning inside braces or as the very
1141 * first character after $ */
1142 if (*offset == start)
1150 /* (and re-parse this character) */
1153 /* At the start? (i.e. 'string length') */
1162 action = ACT_RP_SHORT_LEFT;
1163 if (words[1 + *offset] == '#')
1166 action = ACT_RP_LONG_LEFT;
1173 /* Re-parse this character after substitution */
1182 action = ACT_RP_SHORT_RIGHT;
1183 if (words[1 + *offset] == '%')
1186 action = ACT_RP_LONG_RIGHT;
1201 if (words[1 + *offset] != '-' && words[1 + *offset] != '='
1202 && words[1 + *offset] != '?' && words[1 + *offset] != '+')
1206 action = words[++*offset];
1219 action = words[*offset];
1223 special = (strchr ("*@$", words[*offset]) != NULL
1224 || isdigit (words[*offset]));
1226 if (!isalpha (words[*offset]) && !special)
1227 /* Stop and evaluate, remembering char we stopped at */
1230 env = w_addchar (env, &env_length, &env_maxlen,
1243 /* End of input string -- remember to reparse the character that we stopped
1249 if (words[start] == '{' && words[*offset] != '}')
1256 /* $# expands to the number of positional parameters */
1259 *word = w_addstr (*word, word_length, max_length,
1260 _itoa_word (__libc_argc - 1, &buffer[20], 10, 0));
1264 /* Just $ on its own */
1265 *offset = start - 1;
1266 *word = w_addchar (*word, word_length, max_length, '$');
1272 return *word ? 0 : WRDE_NOSPACE;
1275 /* Is it a special parameter? */
1276 if (strpbrk (env, "0123456789*@$"))
1280 /* Bad substitution if there is more than one character */
1282 fprintf (stderr, "${%s}: bad substitution\n", env);
1286 /* Is it a digit? */
1292 if (n >= __libc_argc)
1293 /* Substitute NULL */
1296 /* Replace with the appropriate positional parameter */
1297 value = __libc_argv[n];
1298 goto maybe_fieldsplit;
1301 else if (*env == '$')
1307 *word = w_addstr (*word, word_length, max_length,
1308 _itoa_word (getpid(), &pidstr[20], 10, 0));
1309 return *word ? 0 : WRDE_NOSPACE;
1311 /* Is it `$*' or `$@' (unquoted) ? */
1312 else if (*env == '*' || (*env == '@' && !quoted))
1314 size_t plist_len = 1;
1317 /* Build up value parameter by parameter (copy them) */
1319 for (p = 1; __libc_argv[p]; ++p)
1321 char *old_pointer = value;
1322 size_t argv_len = strlen (__libc_argv[p]);
1323 size_t old_plist_len = plist_len;
1326 value[plist_len - 1] = 0;
1328 plist_len += 1 + argv_len;
1330 /* First realloc will act as malloc because value is
1331 * initialised to NULL. */
1332 value = realloc (value, plist_len);
1336 return WRDE_NOSPACE;
1339 memcpy (&value[old_plist_len - 1], __libc_argv[p], argv_len + 1);
1340 if (__libc_argv[p + 1])
1342 value[plist_len - 1] = '\0';
1343 value[plist_len - 2] = ' ';
1349 goto maybe_fieldsplit;
1354 /* Must be a quoted `$@' */
1355 assert (*env == '@');
1359 /* Each parameter is a separate word ("$@") */
1360 if (__libc_argv[0] != NULL && __libc_argv[1] != NULL)
1362 /* Append first parameter to current word. */
1365 *word = w_addstr (*word, word_length, max_length, __libc_argv[1]);
1367 return WRDE_NOSPACE;
1369 for (p = 2; __libc_argv[p]; p++)
1373 if (w_addword (pwordexp, *word))
1374 return WRDE_NOSPACE;
1375 len = strlen (__libc_argv[p]) + 1;
1378 return WRDE_NOSPACE;
1379 *word = memcpy (s, __libc_argv[p], len);
1380 *max_length = *word_length = len - 1;
1387 value = getenv (env);
1389 if (action != ACT_NONE)
1393 case ACT_RP_SHORT_LEFT:
1394 case ACT_RP_LONG_LEFT:
1395 case ACT_RP_SHORT_RIGHT:
1396 case ACT_RP_LONG_RIGHT:
1402 if (!pattern || !*pattern)
1405 end = value + strlen (value);
1412 case ACT_RP_SHORT_LEFT:
1413 for (p = value; p <= end; ++p)
1417 if (fnmatch (pattern, value, 0) != FNM_NOMATCH)
1428 case ACT_RP_LONG_LEFT:
1429 for (p = end; p >= value; --p)
1433 if (fnmatch (pattern, value, 0) != FNM_NOMATCH)
1444 case ACT_RP_SHORT_RIGHT:
1445 for (p = end; p >= value; --p)
1447 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
1456 case ACT_RP_LONG_RIGHT:
1457 for (p = value; p <= end; ++p)
1459 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
1475 case ACT_NULL_ERROR:
1476 if (value && *value)
1477 /* Substitute parameter */
1480 if (!colon_seen && value)
1482 /* Substitute NULL */
1490 /* Expand 'pattern' and write it to stderr */
1493 error = wordexp (pattern, &we, flags);
1499 fprintf (stderr, "%s:", env);
1501 for (i = 0; i < we.we_wordc; ++i)
1503 fprintf (stderr, " %s", we.we_wordv[i]);
1506 fprintf (stderr, "\n");
1507 error = WRDE_BADVAL;
1516 fprintf (stderr, "%s: parameter null or not set\n", env);
1521 case ACT_NULL_SUBST:
1522 if (value && *value)
1523 /* Substitute parameter */
1526 if (!colon_seen && value)
1528 /* Substitute NULL */
1536 /* Substitute word */
1542 /* No field-splitting is allowed, so imagine
1543 quotes around the word. */
1544 char *qtd_pattern = malloc (3 + strlen (pattern));
1546 sprintf (qtd_pattern, "\"%s\"", pattern);
1548 pattern = qtd_pattern;
1551 if (pattern == NULL && (pattern = __strdup ("")) == NULL)
1554 error = wordexp (pattern, &we, flags);
1562 /* Fingers crossed that the quotes worked.. */
1563 assert (!quoted || we.we_wordc == 1);
1566 for (i = 0; i < we.we_wordc; ++i)
1567 if (w_addword (pwordexp, __strdup (we.we_wordv[i]))
1571 if (i < we.we_wordc)
1573 /* Ran out of space */
1578 if (action == ACT_NULL_ASSIGN)
1582 size_t words_size = 0;
1584 for (i = 0; i < we.we_wordc; i++)
1585 words_size += strlen (we.we_wordv[i]) + 1; /* for <space> */
1588 cp = words = __alloca (words_size);
1590 for (i = 0; i < we.we_wordc - 1; i++)
1592 cp = __stpcpy (cp, we.we_wordv[i]);
1596 __stpcpy (cp, we.we_wordv[i]);
1599 setenv (env, words, 1);
1606 case ACT_NONNULL_SUBST:
1607 if (value && *value)
1610 if (!colon_seen && value)
1613 /* Substitute NULL */
1618 case ACT_NULL_ASSIGN:
1619 if (value && *value)
1620 /* Substitute parameter */
1623 if (!colon_seen && value)
1625 /* Substitute NULL */
1631 /* This checks for '=' so it knows to assign */
1635 assert (! "Unrecognised action!");
1644 /* Variable not defined */
1645 if (flags & WRDE_UNDEF)
1653 char param_length[21];
1654 param_length[20] = '\0';
1655 *word = w_addstr (*word, word_length, max_length,
1656 _itoa_word (strlen (value), ¶m_length[20], 10, 0));
1657 return *word ? 0 : WRDE_NOSPACE;
1661 if (quoted || !pwordexp)
1663 /* Quoted - no field split */
1664 *word = w_addstr (*word, word_length, max_length, value);
1668 return *word ? 0 : WRDE_NOSPACE;
1672 /* Need to field-split */
1673 char *value_copy = __strdup (value); /* Don't modify value */
1674 char *field_begin = value_copy;
1675 int seen_nonws_ifs = 0;
1680 if (value_copy == NULL)
1681 return WRDE_NOSPACE;
1685 char *field_end = field_begin;
1688 /* If this isn't the first field, start a new word */
1689 if (field_begin != value_copy)
1691 if (w_addword (pwordexp, *word) == WRDE_NOSPACE)
1694 return WRDE_NOSPACE;
1698 *word_length = *max_length = 0;
1701 /* Skip IFS whitespace before the field */
1702 while (*field_begin && strchr (ifs_white, *field_begin) != NULL)
1705 if (!seen_nonws_ifs && *field_begin == 0)
1706 /* Nothing but whitespace */
1709 /* Search for the end of the field */
1710 field_end = field_begin;
1711 while (*field_end && strchr (ifs, *field_end) == NULL)
1714 /* Set up pointer to the character after end of field */
1715 next_field = *field_end ? field_end : NULL;
1717 /* Skip whitespace IFS after the field */
1718 while (next_field && *next_field && strchr (ifs_white, *next_field))
1721 /* Skip at most one non-whitespace IFS character after the field */
1723 if (next_field && *next_field && strchr (ifs, *next_field))
1729 /* Null-terminate it */
1732 /* Tag a copy onto the current word */
1733 *word = w_addstr (*word, word_length, max_length, field_begin);
1738 return WRDE_NOSPACE;
1741 field_begin = next_field;
1743 while (seen_nonws_ifs || (field_begin != NULL && *field_begin));
1757 return WRDE_NOSPACE;
1771 parse_dollars (char **word, size_t *word_length, size_t *max_length,
1772 const char *words, size_t *offset, int flags,
1773 wordexp_t *pwordexp, const char *ifs, const char *ifs_white,
1776 /* We are poised _at_ "$" */
1777 switch (words[1 + *offset])
1782 *word = w_addchar (*word, word_length, max_length, '$');
1783 return *word ? 0 : WRDE_NOSPACE;
1786 if (words[2 + *offset] == '(')
1788 /* Differentiate between $((1+3)) and $((echo);(ls)) */
1789 int i = 3 + *offset;
1791 while (words[i] && !(depth == 0 && words[i] == ')'))
1793 if (words[i] == '(')
1795 else if (words[i] == ')')
1801 if (words[i] == ')' && words[i + 1] == ')')
1804 /* Call parse_arith -- 0 is for "no brackets" */
1805 return parse_arith (word, word_length, max_length, words, offset,
1810 if (flags & WRDE_NOCMD)
1814 return parse_comm (word, word_length, max_length, words, offset, flags,
1815 quoted? NULL : pwordexp, ifs, ifs_white);
1819 /* Call parse_arith -- 1 is for "brackets" */
1820 return parse_arith (word, word_length, max_length, words, offset, flags,
1825 ++(*offset); /* parse_param needs to know if "{" is there */
1826 return parse_param (word, word_length, max_length, words, offset, flags,
1827 pwordexp, ifs, ifs_white, quoted);
1832 parse_backtick (char **word, size_t *word_length, size_t *max_length,
1833 const char *words, size_t *offset, int flags,
1834 wordexp_t *pwordexp, const char *ifs, const char *ifs_white)
1836 /* We are poised just after "`" */
1838 size_t comm_length = 0;
1839 size_t comm_maxlen = 0;
1843 for (; words[*offset]; ++(*offset))
1845 switch (words[*offset])
1848 /* Go -- give the script to the shell */
1849 error = exec_comm (comm, word, word_length, max_length, flags,
1850 pwordexp, ifs, ifs_white);
1857 error = parse_qtd_backslash (&comm, &comm_length, &comm_maxlen,
1870 error = parse_backslash (&comm, &comm_length, &comm_maxlen, words,
1882 squoting = 1 - squoting;
1884 comm = w_addchar (comm, &comm_length, &comm_maxlen, words[*offset]);
1886 return WRDE_NOSPACE;
1897 parse_dquote (char **word, size_t *word_length, size_t *max_length,
1898 const char *words, size_t *offset, int flags,
1899 wordexp_t *pwordexp, const char * ifs, const char * ifs_white)
1901 /* We are poised just after a double-quote */
1904 for (; words[*offset]; ++(*offset))
1906 switch (words[*offset])
1912 error = parse_dollars (word, word_length, max_length, words, offset,
1913 flags, pwordexp, ifs, ifs_white, 1);
1914 /* The ``1'' here is to tell parse_dollars not to
1915 * split the fields. It may need to, however ("$@").
1923 if (flags & WRDE_NOCMD)
1927 error = parse_backtick (word, word_length, max_length, words,
1928 offset, flags, NULL, NULL, NULL);
1929 /* The first NULL here is to tell parse_backtick not to
1938 error = parse_qtd_backslash (word, word_length, max_length, words,
1947 *word = w_addchar (*word, word_length, max_length, words[*offset]);
1949 return WRDE_NOSPACE;
1953 /* Unterminated string */
1958 * wordfree() is to be called after pwordexp is finished with.
1962 wordfree (wordexp_t *pwordexp)
1965 /* wordexp can set pwordexp to NULL */
1966 if (pwordexp && pwordexp->we_wordv)
1968 char **wordv = pwordexp->we_wordv;
1970 for (wordv += pwordexp->we_offs; *wordv; ++wordv)
1973 free (pwordexp->we_wordv);
1974 pwordexp->we_wordv = NULL;
1983 wordexp (const char *words, wordexp_t *pwordexp, int flags)
1985 size_t wordv_offset;
1986 size_t words_offset;
1987 size_t word_length = 0;
1988 size_t max_length = 0;
1993 char **old_wordv = pwordexp->we_wordv;
1994 size_t old_wordc = (flags & WRDE_REUSE) ? pwordexp->we_wordc : 0;
1996 if (flags & WRDE_REUSE)
1998 /* Minimal implementation of WRDE_REUSE for now */
1999 wordfree (pwordexp);
2003 if (flags & WRDE_DOOFFS)
2005 pwordexp->we_wordv = calloc (1 + pwordexp->we_offs, sizeof (char *));
2006 if (pwordexp->we_wordv == NULL)
2007 return WRDE_NOSPACE;
2011 pwordexp->we_wordv = calloc (1, sizeof (char *));
2012 if (pwordexp->we_wordv == NULL)
2013 return WRDE_NOSPACE;
2015 pwordexp->we_offs = 0;
2018 if ((flags & WRDE_APPEND) == 0)
2019 pwordexp->we_wordc = 0;
2021 wordv_offset = pwordexp->we_offs + pwordexp->we_wordc;
2023 /* Find out what the field separators are.
2024 * There are two types: whitespace and non-whitespace.
2026 ifs = getenv ("IFS");
2029 /* NULL IFS means no field-splitting is to be performed */
2030 ifs = strcpy (ifs_white, "");
2034 char *whch = ifs_white;
2036 /* Start off with no whitespace IFS characters */
2037 ifs_white[0] = '\0';
2039 while (*ifsch != '\0')
2041 if ((*ifsch == ' ') || (*ifsch == '\t') || (*ifsch == '\n'))
2043 /* Whitespace IFS. See first whether it is already in our
2045 char *runp = ifs_white;
2047 while (runp < whch && *runp != '\0' && *runp != *ifsch)
2059 for (words_offset = 0 ; words[words_offset] ; ++words_offset)
2060 switch (words[words_offset])
2073 wordfree (pwordexp);
2074 pwordexp->we_wordc = 0;
2075 pwordexp->we_wordv = old_wordv;
2076 return WRDE_BADCHAR;
2079 error = parse_backslash (&word, &word_length, &max_length, words,
2088 error = parse_dollars (&word, &word_length, &max_length, words,
2089 &words_offset, flags, pwordexp, ifs, ifs_white,
2098 if (flags & WRDE_NOCMD)
2102 error = parse_backtick (&word, &word_length, &max_length, words,
2103 &words_offset, flags, pwordexp, ifs,
2113 error = parse_dquote (&word, &word_length, &max_length, words,
2114 &words_offset, flags, pwordexp, ifs, ifs_white);
2123 error = parse_squote (&word, &word_length, &max_length, words,
2132 error = parse_tilde (&word, &word_length, &max_length, words,
2133 &words_offset, pwordexp->we_wordc);
2143 error = parse_glob (&word, &word_length, &max_length, words,
2144 &words_offset, flags, pwordexp, ifs, ifs_white);
2152 /* Is it a field separator? */
2153 if (strchr (ifs, words[words_offset]) == NULL)
2155 /* "Ordinary" character -- add it to word */
2157 word = w_addchar (word, &word_length, &max_length,
2158 words[words_offset]);
2161 error = WRDE_NOSPACE;
2168 /* Field separator */
2169 if (strchr (ifs_white, words[words_offset]))
2171 /* It's a whitespace IFS char. Ignore it at the beginning
2172 of a line and ignore multiple instances. */
2173 if (!word || !*word)
2176 if (w_addword (pwordexp, word) == WRDE_NOSPACE)
2178 error = WRDE_NOSPACE;
2188 /* It's a non-whitespace IFS char */
2190 /* Multiple non-whitespace IFS chars are treated as one;
2195 if (w_addword (pwordexp, word) == WRDE_NOSPACE)
2197 error = WRDE_NOSPACE;
2209 /* There was a field separator at the end */
2213 /* There was no field separator at the end */
2214 return w_addword (pwordexp, word);
2218 * free memory used (unless error is WRDE_NOSPACE), and
2219 * set we_wordc and wd_wordv back to what they were.
2222 if (error == WRDE_NOSPACE)
2223 return WRDE_NOSPACE;
2228 wordfree (pwordexp);
2229 pwordexp->we_wordv = old_wordv;
2230 pwordexp->we_wordc = old_wordc;