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
;
1225 if (!isalnum (words
[*offset
]) && !special
)
1226 /* Stop and evaluate, remembering char we stopped at */
1229 env
= w_addchar (env
, &env_length
, &env_maxlen
,
1242 /* End of input string -- remember to reparse the character that we stopped
1248 if (words
[start
] == '{' && words
[*offset
] != '}')
1255 /* $# expands to the number of positional parameters */
1258 *word
= w_addstr (*word
, word_length
, max_length
,
1259 _itoa_word (__libc_argc
- 1, &buffer
[20], 10, 0));
1263 /* Just $ on its own */
1264 *offset
= start
- 1;
1265 *word
= w_addchar (*word
, word_length
, max_length
, '$');
1271 return *word
? 0 : WRDE_NOSPACE
;
1274 /* Is it a special parameter? */
1275 if (strpbrk (env
, "*@$") || isdigit (*env
))
1277 if ((isdigit(*env
) && strcspn (env
, "1234567890")) ||
1278 (!isdigit(*env
) && env
[1] != '\0'))
1280 /* Bad substitution if it isn't "*", "@", "$", or just a number. */
1283 fprintf (stderr
, "${%s}: bad substitution\n", env
);
1287 /* Is it a digit? */
1291 int n
= strtol (env
, &endp
, 10);
1297 if (n
>= __libc_argc
)
1298 /* Substitute NULL */
1301 /* Replace with the appropriate positional parameter */
1302 value
= __libc_argv
[n
];
1303 goto maybe_fieldsplit
;
1306 else if (*env
== '$')
1312 *word
= w_addstr (*word
, word_length
, max_length
,
1313 _itoa_word (getpid(), &pidstr
[20], 10, 0));
1314 return *word
? 0 : WRDE_NOSPACE
;
1316 /* Is it `$*' or `$@' (unquoted) ? */
1317 else if (*env
== '*' || (*env
== '@' && !quoted
))
1319 size_t plist_len
= 1;
1322 /* Build up value parameter by parameter (copy them) */
1324 for (p
= 1; __libc_argv
[p
]; ++p
)
1326 char *old_pointer
= value
;
1327 size_t argv_len
= strlen (__libc_argv
[p
]);
1328 size_t old_plist_len
= plist_len
;
1331 value
[plist_len
- 1] = 0;
1333 plist_len
+= 1 + argv_len
;
1335 /* First realloc will act as malloc because value is
1336 * initialised to NULL. */
1337 value
= realloc (value
, plist_len
);
1341 return WRDE_NOSPACE
;
1344 memcpy (&value
[old_plist_len
- 1], __libc_argv
[p
], argv_len
+ 1);
1345 if (__libc_argv
[p
+ 1])
1347 value
[plist_len
- 1] = '\0';
1348 value
[plist_len
- 2] = ' ';
1354 goto maybe_fieldsplit
;
1359 /* Must be a quoted `$@' */
1360 assert (*env
== '@');
1364 /* Each parameter is a separate word ("$@") */
1365 if (__libc_argv
[0] != NULL
&& __libc_argv
[1] != NULL
)
1367 /* Append first parameter to current word. */
1370 *word
= w_addstr (*word
, word_length
, max_length
, __libc_argv
[1]);
1372 return WRDE_NOSPACE
;
1374 for (p
= 2; __libc_argv
[p
]; p
++)
1378 if (w_addword (pwordexp
, *word
))
1379 return WRDE_NOSPACE
;
1380 len
= strlen (__libc_argv
[p
]) + 1;
1383 return WRDE_NOSPACE
;
1384 *word
= memcpy (s
, __libc_argv
[p
], len
);
1385 *max_length
= *word_length
= len
- 1;
1392 value
= getenv (env
);
1394 if (action
!= ACT_NONE
)
1398 case ACT_RP_SHORT_LEFT
:
1399 case ACT_RP_LONG_LEFT
:
1400 case ACT_RP_SHORT_RIGHT
:
1401 case ACT_RP_LONG_RIGHT
:
1407 if (!pattern
|| !*pattern
)
1410 end
= value
+ strlen (value
);
1417 case ACT_RP_SHORT_LEFT
:
1418 for (p
= value
; p
<= end
; ++p
)
1422 if (fnmatch (pattern
, value
, 0) != FNM_NOMATCH
)
1433 case ACT_RP_LONG_LEFT
:
1434 for (p
= end
; p
>= value
; --p
)
1438 if (fnmatch (pattern
, value
, 0) != FNM_NOMATCH
)
1449 case ACT_RP_SHORT_RIGHT
:
1450 for (p
= end
; p
>= value
; --p
)
1452 if (fnmatch (pattern
, p
, 0) != FNM_NOMATCH
)
1461 case ACT_RP_LONG_RIGHT
:
1462 for (p
= value
; p
<= end
; ++p
)
1464 if (fnmatch (pattern
, p
, 0) != FNM_NOMATCH
)
1480 case ACT_NULL_ERROR
:
1481 if (value
&& *value
)
1482 /* Substitute parameter */
1485 if (!colon_seen
&& value
)
1487 /* Substitute NULL */
1495 /* Expand 'pattern' and write it to stderr */
1498 error
= wordexp (pattern
, &we
, flags
);
1504 fprintf (stderr
, "%s:", env
);
1506 for (i
= 0; i
< we
.we_wordc
; ++i
)
1508 fprintf (stderr
, " %s", we
.we_wordv
[i
]);
1511 fprintf (stderr
, "\n");
1512 error
= WRDE_BADVAL
;
1521 fprintf (stderr
, "%s: parameter null or not set\n", env
);
1526 case ACT_NULL_SUBST
:
1527 if (value
&& *value
)
1528 /* Substitute parameter */
1531 if (!colon_seen
&& value
)
1533 /* Substitute NULL */
1541 /* Substitute word */
1547 /* No field-splitting is allowed, so imagine
1548 quotes around the word. */
1549 char *qtd_pattern
= malloc (3 + strlen (pattern
));
1551 sprintf (qtd_pattern
, "\"%s\"", pattern
);
1553 pattern
= qtd_pattern
;
1556 if (pattern
== NULL
&& (pattern
= __strdup ("")) == NULL
)
1559 error
= wordexp (pattern
, &we
, flags
);
1567 /* Fingers crossed that the quotes worked.. */
1568 assert (!quoted
|| we
.we_wordc
== 1);
1571 for (i
= 0; i
< we
.we_wordc
; ++i
)
1572 if (w_addword (pwordexp
, __strdup (we
.we_wordv
[i
]))
1576 if (i
< we
.we_wordc
)
1578 /* Ran out of space */
1583 if (action
== ACT_NULL_ASSIGN
)
1587 size_t words_size
= 0;
1589 for (i
= 0; i
< we
.we_wordc
; i
++)
1590 words_size
+= strlen (we
.we_wordv
[i
]) + 1; /* for <space> */
1593 cp
= words
= __alloca (words_size
);
1595 for (i
= 0; i
< we
.we_wordc
- 1; i
++)
1597 cp
= __stpcpy (cp
, we
.we_wordv
[i
]);
1601 __stpcpy (cp
, we
.we_wordv
[i
]);
1604 setenv (env
, words
, 1);
1611 case ACT_NONNULL_SUBST
:
1612 if (value
&& *value
)
1615 if (!colon_seen
&& value
)
1618 /* Substitute NULL */
1623 case ACT_NULL_ASSIGN
:
1624 if (value
&& *value
)
1625 /* Substitute parameter */
1628 if (!colon_seen
&& value
)
1630 /* Substitute NULL */
1636 /* This checks for '=' so it knows to assign */
1640 assert (! "Unrecognised action!");
1649 /* Variable not defined */
1650 if (flags
& WRDE_UNDEF
)
1658 char param_length
[21];
1659 param_length
[20] = '\0';
1660 *word
= w_addstr (*word
, word_length
, max_length
,
1661 _itoa_word (strlen (value
), ¶m_length
[20], 10, 0));
1662 return *word
? 0 : WRDE_NOSPACE
;
1666 if (quoted
|| !pwordexp
)
1668 /* Quoted - no field split */
1669 *word
= w_addstr (*word
, word_length
, max_length
, value
);
1673 return *word
? 0 : WRDE_NOSPACE
;
1677 /* Need to field-split */
1678 char *value_copy
= __strdup (value
); /* Don't modify value */
1679 char *field_begin
= value_copy
;
1680 int seen_nonws_ifs
= 0;
1685 if (value_copy
== NULL
)
1686 return WRDE_NOSPACE
;
1690 char *field_end
= field_begin
;
1693 /* If this isn't the first field, start a new word */
1694 if (field_begin
!= value_copy
)
1696 if (w_addword (pwordexp
, *word
) == WRDE_NOSPACE
)
1699 return WRDE_NOSPACE
;
1703 *word_length
= *max_length
= 0;
1706 /* Skip IFS whitespace before the field */
1707 while (*field_begin
&& strchr (ifs_white
, *field_begin
) != NULL
)
1710 if (!seen_nonws_ifs
&& *field_begin
== 0)
1711 /* Nothing but whitespace */
1714 /* Search for the end of the field */
1715 field_end
= field_begin
;
1716 while (*field_end
&& strchr (ifs
, *field_end
) == NULL
)
1719 /* Set up pointer to the character after end of field */
1720 next_field
= *field_end
? field_end
: NULL
;
1722 /* Skip whitespace IFS after the field */
1723 while (next_field
&& *next_field
&& strchr (ifs_white
, *next_field
))
1726 /* Skip at most one non-whitespace IFS character after the field */
1728 if (next_field
&& *next_field
&& strchr (ifs
, *next_field
))
1734 /* Null-terminate it */
1737 /* Tag a copy onto the current word */
1738 *word
= w_addstr (*word
, word_length
, max_length
, field_begin
);
1743 return WRDE_NOSPACE
;
1746 field_begin
= next_field
;
1748 while (seen_nonws_ifs
|| (field_begin
!= NULL
&& *field_begin
));
1762 return WRDE_NOSPACE
;
1776 parse_dollars (char **word
, size_t *word_length
, size_t *max_length
,
1777 const char *words
, size_t *offset
, int flags
,
1778 wordexp_t
*pwordexp
, const char *ifs
, const char *ifs_white
,
1781 /* We are poised _at_ "$" */
1782 switch (words
[1 + *offset
])
1787 *word
= w_addchar (*word
, word_length
, max_length
, '$');
1788 return *word
? 0 : WRDE_NOSPACE
;
1791 if (words
[2 + *offset
] == '(')
1793 /* Differentiate between $((1+3)) and $((echo);(ls)) */
1794 int i
= 3 + *offset
;
1796 while (words
[i
] && !(depth
== 0 && words
[i
] == ')'))
1798 if (words
[i
] == '(')
1800 else if (words
[i
] == ')')
1806 if (words
[i
] == ')' && words
[i
+ 1] == ')')
1809 /* Call parse_arith -- 0 is for "no brackets" */
1810 return parse_arith (word
, word_length
, max_length
, words
, offset
,
1815 if (flags
& WRDE_NOCMD
)
1819 return parse_comm (word
, word_length
, max_length
, words
, offset
, flags
,
1820 quoted
? NULL
: pwordexp
, ifs
, ifs_white
);
1824 /* Call parse_arith -- 1 is for "brackets" */
1825 return parse_arith (word
, word_length
, max_length
, words
, offset
, flags
,
1830 ++(*offset
); /* parse_param needs to know if "{" is there */
1831 return parse_param (word
, word_length
, max_length
, words
, offset
, flags
,
1832 pwordexp
, ifs
, ifs_white
, quoted
);
1837 parse_backtick (char **word
, size_t *word_length
, size_t *max_length
,
1838 const char *words
, size_t *offset
, int flags
,
1839 wordexp_t
*pwordexp
, const char *ifs
, const char *ifs_white
)
1841 /* We are poised just after "`" */
1843 size_t comm_length
= 0;
1844 size_t comm_maxlen
= 0;
1848 for (; words
[*offset
]; ++(*offset
))
1850 switch (words
[*offset
])
1853 /* Go -- give the script to the shell */
1854 error
= exec_comm (comm
, word
, word_length
, max_length
, flags
,
1855 pwordexp
, ifs
, ifs_white
);
1862 error
= parse_qtd_backslash (&comm
, &comm_length
, &comm_maxlen
,
1875 error
= parse_backslash (&comm
, &comm_length
, &comm_maxlen
, words
,
1887 squoting
= 1 - squoting
;
1889 comm
= w_addchar (comm
, &comm_length
, &comm_maxlen
, words
[*offset
]);
1891 return WRDE_NOSPACE
;
1902 parse_dquote (char **word
, size_t *word_length
, size_t *max_length
,
1903 const char *words
, size_t *offset
, int flags
,
1904 wordexp_t
*pwordexp
, const char * ifs
, const char * ifs_white
)
1906 /* We are poised just after a double-quote */
1909 for (; words
[*offset
]; ++(*offset
))
1911 switch (words
[*offset
])
1917 error
= parse_dollars (word
, word_length
, max_length
, words
, offset
,
1918 flags
, pwordexp
, ifs
, ifs_white
, 1);
1919 /* The ``1'' here is to tell parse_dollars not to
1920 * split the fields. It may need to, however ("$@").
1928 if (flags
& WRDE_NOCMD
)
1932 error
= parse_backtick (word
, word_length
, max_length
, words
,
1933 offset
, flags
, NULL
, NULL
, NULL
);
1934 /* The first NULL here is to tell parse_backtick not to
1943 error
= parse_qtd_backslash (word
, word_length
, max_length
, words
,
1952 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
1954 return WRDE_NOSPACE
;
1958 /* Unterminated string */
1963 * wordfree() is to be called after pwordexp is finished with.
1967 wordfree (wordexp_t
*pwordexp
)
1970 /* wordexp can set pwordexp to NULL */
1971 if (pwordexp
&& pwordexp
->we_wordv
)
1973 char **wordv
= pwordexp
->we_wordv
;
1975 for (wordv
+= pwordexp
->we_offs
; *wordv
; ++wordv
)
1978 free (pwordexp
->we_wordv
);
1979 pwordexp
->we_wordv
= NULL
;
1988 wordexp (const char *words
, wordexp_t
*pwordexp
, int flags
)
1990 size_t wordv_offset
;
1991 size_t words_offset
;
1992 size_t word_length
= 0;
1993 size_t max_length
= 0;
1998 char **old_wordv
= pwordexp
->we_wordv
;
1999 size_t old_wordc
= (flags
& WRDE_REUSE
) ? pwordexp
->we_wordc
: 0;
2001 if (flags
& WRDE_REUSE
)
2003 /* Minimal implementation of WRDE_REUSE for now */
2004 wordfree (pwordexp
);
2008 if (flags
& WRDE_DOOFFS
)
2010 pwordexp
->we_wordv
= calloc (1 + pwordexp
->we_offs
, sizeof (char *));
2011 if (pwordexp
->we_wordv
== NULL
)
2012 return WRDE_NOSPACE
;
2016 pwordexp
->we_wordv
= calloc (1, sizeof (char *));
2017 if (pwordexp
->we_wordv
== NULL
)
2018 return WRDE_NOSPACE
;
2020 pwordexp
->we_offs
= 0;
2023 if ((flags
& WRDE_APPEND
) == 0)
2024 pwordexp
->we_wordc
= 0;
2026 wordv_offset
= pwordexp
->we_offs
+ pwordexp
->we_wordc
;
2028 /* Find out what the field separators are.
2029 * There are two types: whitespace and non-whitespace.
2031 ifs
= getenv ("IFS");
2034 /* NULL IFS means no field-splitting is to be performed */
2035 ifs
= strcpy (ifs_white
, "");
2039 char *whch
= ifs_white
;
2041 /* Start off with no whitespace IFS characters */
2042 ifs_white
[0] = '\0';
2044 while (*ifsch
!= '\0')
2046 if ((*ifsch
== ' ') || (*ifsch
== '\t') || (*ifsch
== '\n'))
2048 /* Whitespace IFS. See first whether it is already in our
2050 char *runp
= ifs_white
;
2052 while (runp
< whch
&& *runp
!= '\0' && *runp
!= *ifsch
)
2064 for (words_offset
= 0 ; words
[words_offset
] ; ++words_offset
)
2065 switch (words
[words_offset
])
2078 wordfree (pwordexp
);
2079 pwordexp
->we_wordc
= 0;
2080 pwordexp
->we_wordv
= old_wordv
;
2081 return WRDE_BADCHAR
;
2084 error
= parse_backslash (&word
, &word_length
, &max_length
, words
,
2093 error
= parse_dollars (&word
, &word_length
, &max_length
, words
,
2094 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
,
2103 if (flags
& WRDE_NOCMD
)
2107 error
= parse_backtick (&word
, &word_length
, &max_length
, words
,
2108 &words_offset
, flags
, pwordexp
, ifs
,
2118 error
= parse_dquote (&word
, &word_length
, &max_length
, words
,
2119 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
);
2128 error
= parse_squote (&word
, &word_length
, &max_length
, words
,
2137 error
= parse_tilde (&word
, &word_length
, &max_length
, words
,
2138 &words_offset
, pwordexp
->we_wordc
);
2148 error
= parse_glob (&word
, &word_length
, &max_length
, words
,
2149 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
);
2157 /* Is it a field separator? */
2158 if (strchr (ifs
, words
[words_offset
]) == NULL
)
2160 /* "Ordinary" character -- add it to word */
2162 word
= w_addchar (word
, &word_length
, &max_length
,
2163 words
[words_offset
]);
2166 error
= WRDE_NOSPACE
;
2173 /* Field separator */
2174 if (strchr (ifs_white
, words
[words_offset
]))
2176 /* It's a whitespace IFS char. Ignore it at the beginning
2177 of a line and ignore multiple instances. */
2178 if (!word
|| !*word
)
2181 if (w_addword (pwordexp
, word
) == WRDE_NOSPACE
)
2183 error
= WRDE_NOSPACE
;
2193 /* It's a non-whitespace IFS char */
2195 /* Multiple non-whitespace IFS chars are treated as one;
2200 if (w_addword (pwordexp
, word
) == WRDE_NOSPACE
)
2202 error
= WRDE_NOSPACE
;
2214 /* There was a field separator at the end */
2218 /* There was no field separator at the end */
2219 return w_addword (pwordexp
, word
);
2223 * free memory used (unless error is WRDE_NOSPACE), and
2224 * set we_wordc and wd_wordv back to what they were.
2227 if (error
== WRDE_NOSPACE
)
2228 return WRDE_NOSPACE
;
2233 wordfree (pwordexp
);
2234 pwordexp
->we_wordv
= old_wordv
;
2235 pwordexp
->we_wordc
= old_wordc
;