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
= 1; __libc_argv
[p
]; p
++)
1371 if (w_addword (pwordexp
, *word
))
1372 return WRDE_NOSPACE
;
1373 *word
= __strdup (__libc_argv
[p
]);
1374 *max_length
= *word_length
= strlen (*word
);
1376 return WRDE_NOSPACE
;
1383 value
= getenv (env
);
1385 if (action
!= ACT_NONE
)
1389 case ACT_RP_SHORT_LEFT
:
1390 case ACT_RP_LONG_LEFT
:
1391 case ACT_RP_SHORT_RIGHT
:
1392 case ACT_RP_LONG_RIGHT
:
1398 if (!pattern
|| !*pattern
)
1401 end
= value
+ strlen (value
);
1408 case ACT_RP_SHORT_LEFT
:
1409 for (p
= value
; p
<= end
; ++p
)
1413 if (fnmatch (pattern
, value
, 0) != FNM_NOMATCH
)
1424 case ACT_RP_LONG_LEFT
:
1425 for (p
= end
; p
>= value
; --p
)
1429 if (fnmatch (pattern
, value
, 0) != FNM_NOMATCH
)
1440 case ACT_RP_SHORT_RIGHT
:
1441 for (p
= end
; p
>= value
; --p
)
1443 if (fnmatch (pattern
, p
, 0) != FNM_NOMATCH
)
1452 case ACT_RP_LONG_RIGHT
:
1453 for (p
= value
; p
<= end
; ++p
)
1455 if (fnmatch (pattern
, p
, 0) != FNM_NOMATCH
)
1471 case ACT_NULL_ERROR
:
1472 if (value
&& *value
)
1473 /* Substitute parameter */
1476 if (!colon_seen
&& value
)
1478 /* Substitute NULL */
1486 /* Expand 'pattern' and write it to stderr */
1489 error
= wordexp (pattern
, &we
, flags
);
1495 fprintf (stderr
, "%s:", env
);
1497 for (i
= 0; i
< we
.we_wordc
; ++i
)
1499 fprintf (stderr
, " %s", we
.we_wordv
[i
]);
1502 fprintf (stderr
, "\n");
1503 error
= WRDE_BADVAL
;
1512 fprintf (stderr
, "%s: parameter null or not set\n", env
);
1517 case ACT_NULL_SUBST
:
1518 if (value
&& *value
)
1519 /* Substitute parameter */
1522 if (!colon_seen
&& value
)
1524 /* Substitute NULL */
1532 /* Substitute word */
1538 /* No field-splitting is allowed, so imagine
1539 quotes around the word. */
1540 char *qtd_pattern
= malloc (3 + strlen (pattern
));
1542 sprintf (qtd_pattern
, "\"%s\"", pattern
);
1544 pattern
= qtd_pattern
;
1547 if (pattern
== NULL
&& (pattern
= __strdup("")) == NULL
)
1550 error
= wordexp (pattern
, &we
, flags
);
1558 /* Fingers crossed that the quotes worked.. */
1559 assert (!quoted
|| we
.we_wordc
== 1);
1562 for (i
= 0; i
< we
.we_wordc
; i
++)
1563 if (w_addword (pwordexp
, __strdup(we
.we_wordv
[i
]))
1567 if (i
< we
.we_wordc
)
1569 /* Ran out of space */
1574 if (action
== ACT_NULL_ASSIGN
)
1578 size_t words_size
= 0;
1580 for (i
= 0; i
< we
.we_wordc
; i
++)
1581 words_size
+= strlen (we
.we_wordv
[i
]) + 1; /* for <space> */
1584 cp
= words
= __alloca (words_size
);
1586 for (i
= 0; i
< we
.we_wordc
- 1; i
++)
1588 cp
= __stpcpy (cp
, we
.we_wordv
[i
]);
1592 __stpcpy (cp
, we
.we_wordv
[i
]);
1595 setenv (env
, words
, 1);
1602 case ACT_NONNULL_SUBST
:
1603 if (value
&& *value
)
1606 if (!colon_seen
&& value
)
1609 /* Substitute NULL */
1614 case ACT_NULL_ASSIGN
:
1615 if (value
&& *value
)
1616 /* Substitute parameter */
1619 if (!colon_seen
&& value
)
1621 /* Substitute NULL */
1627 /* This checks for '=' so it knows to assign */
1631 assert (! "Unrecognised action!");
1640 /* Variable not defined */
1641 if (flags
& WRDE_UNDEF
)
1649 char param_length
[21];
1650 param_length
[20] = '\0';
1651 *word
= w_addstr (*word
, word_length
, max_length
,
1652 _itoa_word (strlen (value
), ¶m_length
[20], 10, 0));
1653 return *word
? 0 : WRDE_NOSPACE
;
1657 if (quoted
|| !pwordexp
)
1659 /* Quoted - no field split */
1660 *word
= w_addstr (*word
, word_length
, max_length
, value
);
1664 return *word
? 0 : WRDE_NOSPACE
;
1668 /* Need to field-split */
1669 char *value_copy
= __strdup (value
); /* Don't modify value */
1670 char *field_begin
= value_copy
;
1671 int seen_nonws_ifs
= 0;
1676 if (value_copy
== NULL
)
1677 return WRDE_NOSPACE
;
1681 char *field_end
= field_begin
;
1684 /* If this isn't the first field, start a new word */
1685 if (field_begin
!= value_copy
)
1687 if (w_addword (pwordexp
, *word
) == WRDE_NOSPACE
)
1690 return WRDE_NOSPACE
;
1694 *word_length
= *max_length
= 0;
1697 /* Skip IFS whitespace before the field */
1698 while (*field_begin
&& strchr (ifs_white
, *field_begin
) != NULL
)
1701 if (!seen_nonws_ifs
&& *field_begin
== 0)
1702 /* Nothing but whitespace */
1705 /* Search for the end of the field */
1706 field_end
= field_begin
;
1707 while (*field_end
&& strchr (ifs
, *field_end
) == NULL
)
1710 /* Set up pointer to the character after end of field */
1711 next_field
= *field_end
? field_end
: NULL
;
1713 /* Skip whitespace IFS after the field */
1714 while (next_field
&& *next_field
&& strchr (ifs_white
, *next_field
))
1717 /* Skip at most one non-whitespace IFS character after the field */
1719 if (next_field
&& *next_field
&& strchr (ifs
, *next_field
))
1725 /* Null-terminate it */
1728 /* Tag a copy onto the current word */
1729 *word
= w_addstr (*word
, word_length
, max_length
, field_begin
);
1734 return WRDE_NOSPACE
;
1737 field_begin
= next_field
;
1739 while (seen_nonws_ifs
|| (field_begin
!= NULL
&& *field_begin
));
1753 return WRDE_NOSPACE
;
1767 parse_dollars (char **word
, size_t *word_length
, size_t *max_length
,
1768 const char *words
, size_t *offset
, int flags
,
1769 wordexp_t
*pwordexp
, const char *ifs
, const char *ifs_white
,
1772 /* We are poised _at_ "$" */
1773 switch (words
[1 + *offset
])
1778 *word
= w_addchar (*word
, word_length
, max_length
, '$');
1779 return *word
? 0 : WRDE_NOSPACE
;
1782 if (words
[2 + *offset
] == '(')
1784 /* Differentiate between $((1+3)) and $((echo);(ls)) */
1785 int i
= 3 + *offset
;
1787 while (words
[i
] && !(depth
== 0 && words
[i
] == ')'))
1789 if (words
[i
] == '(')
1791 else if (words
[i
] == ')')
1797 if (words
[i
] == ')' && words
[i
+ 1] == ')')
1800 /* Call parse_arith -- 0 is for "no brackets" */
1801 return parse_arith (word
, word_length
, max_length
, words
, offset
,
1806 if (flags
& WRDE_NOCMD
)
1810 return parse_comm (word
, word_length
, max_length
, words
, offset
, flags
,
1811 quoted
? NULL
: pwordexp
, ifs
, ifs_white
);
1815 /* Call parse_arith -- 1 is for "brackets" */
1816 return parse_arith (word
, word_length
, max_length
, words
, offset
, flags
,
1821 ++(*offset
); /* parse_param needs to know if "{" is there */
1822 return parse_param (word
, word_length
, max_length
, words
, offset
, flags
,
1823 pwordexp
, ifs
, ifs_white
, quoted
);
1828 parse_backtick (char **word
, size_t *word_length
, size_t *max_length
,
1829 const char *words
, size_t *offset
, int flags
,
1830 wordexp_t
*pwordexp
, const char *ifs
, const char *ifs_white
)
1832 /* We are poised just after "`" */
1834 size_t comm_length
= 0;
1835 size_t comm_maxlen
= 0;
1839 for (; words
[*offset
]; ++(*offset
))
1841 switch (words
[*offset
])
1844 /* Go -- give the script to the shell */
1845 error
= exec_comm (comm
, word
, word_length
, max_length
, flags
,
1846 pwordexp
, ifs
, ifs_white
);
1853 error
= parse_qtd_backslash (&comm
, &comm_length
, &comm_maxlen
,
1866 error
= parse_backslash (&comm
, &comm_length
, &comm_maxlen
, words
,
1878 squoting
= 1 - squoting
;
1880 comm
= w_addchar (comm
, &comm_length
, &comm_maxlen
, words
[*offset
]);
1882 return WRDE_NOSPACE
;
1893 parse_dquote (char **word
, size_t *word_length
, size_t *max_length
,
1894 const char *words
, size_t *offset
, int flags
,
1895 wordexp_t
*pwordexp
, const char * ifs
, const char * ifs_white
)
1897 /* We are poised just after a double-quote */
1900 for (; words
[*offset
]; ++(*offset
))
1902 switch (words
[*offset
])
1908 error
= parse_dollars (word
, word_length
, max_length
, words
, offset
,
1909 flags
, pwordexp
, ifs
, ifs_white
, 1);
1910 /* The ``1'' here is to tell parse_dollars not to
1911 * split the fields. It may need to, however ("$@").
1919 if (flags
& WRDE_NOCMD
)
1923 error
= parse_backtick (word
, word_length
, max_length
, words
,
1924 offset
, flags
, NULL
, NULL
, NULL
);
1925 /* The first NULL here is to tell parse_backtick not to
1934 error
= parse_qtd_backslash (word
, word_length
, max_length
, words
,
1943 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
1945 return WRDE_NOSPACE
;
1949 /* Unterminated string */
1954 * wordfree() is to be called after pwordexp is finished with.
1958 wordfree (wordexp_t
*pwordexp
)
1961 /* wordexp can set pwordexp to NULL */
1962 if (pwordexp
&& pwordexp
->we_wordv
)
1964 char **wordv
= pwordexp
->we_wordv
;
1966 for (wordv
+= pwordexp
->we_offs
; *wordv
; ++wordv
)
1969 free (pwordexp
->we_wordv
);
1970 pwordexp
->we_wordv
= NULL
;
1979 wordexp (const char *words
, wordexp_t
*pwordexp
, int flags
)
1981 size_t wordv_offset
;
1982 size_t words_offset
;
1983 size_t word_length
= 0;
1984 size_t max_length
= 0;
1989 char **old_wordv
= pwordexp
->we_wordv
;
1990 size_t old_wordc
= (flags
& WRDE_REUSE
) ? pwordexp
->we_wordc
: 0;
1992 if (flags
& WRDE_REUSE
)
1994 /* Minimal implementation of WRDE_REUSE for now */
1995 wordfree (pwordexp
);
1999 if (flags
& WRDE_DOOFFS
)
2001 pwordexp
->we_wordv
= calloc (1 + pwordexp
->we_offs
, sizeof (char *));
2002 if (pwordexp
->we_wordv
== NULL
)
2003 return WRDE_NOSPACE
;
2007 pwordexp
->we_wordv
= calloc (1, sizeof (char *));
2008 if (pwordexp
->we_wordv
== NULL
)
2009 return WRDE_NOSPACE
;
2011 pwordexp
->we_offs
= 0;
2014 if ((flags
& WRDE_APPEND
) == 0)
2015 pwordexp
->we_wordc
= 0;
2017 wordv_offset
= pwordexp
->we_offs
+ pwordexp
->we_wordc
;
2019 /* Find out what the field separators are.
2020 * There are two types: whitespace and non-whitespace.
2022 ifs
= getenv ("IFS");
2025 /* NULL IFS means no field-splitting is to be performed */
2026 ifs
= strcpy (ifs_white
, "");
2030 char *whch
= ifs_white
;
2032 /* Start off with no whitespace IFS characters */
2033 ifs_white
[0] = '\0';
2035 while (*ifsch
!= '\0')
2037 if ((*ifsch
== ' ') || (*ifsch
== '\t') || (*ifsch
== '\n'))
2039 /* Whitespace IFS. See first whether it is already in our
2041 char *runp
= ifs_white
;
2043 while (runp
< whch
&& *runp
!= '\0' && *runp
!= *ifsch
)
2055 for (words_offset
= 0 ; words
[words_offset
] ; ++words_offset
)
2056 switch (words
[words_offset
])
2069 wordfree (pwordexp
);
2070 pwordexp
->we_wordc
= 0;
2071 pwordexp
->we_wordv
= old_wordv
;
2072 return WRDE_BADCHAR
;
2075 error
= parse_backslash (&word
, &word_length
, &max_length
, words
,
2084 error
= parse_dollars (&word
, &word_length
, &max_length
, words
,
2085 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
,
2094 if (flags
& WRDE_NOCMD
)
2098 error
= parse_backtick (&word
, &word_length
, &max_length
, words
,
2099 &words_offset
, flags
, pwordexp
, ifs
,
2109 error
= parse_dquote (&word
, &word_length
, &max_length
, words
,
2110 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
);
2119 error
= parse_squote (&word
, &word_length
, &max_length
, words
,
2128 error
= parse_tilde (&word
, &word_length
, &max_length
, words
,
2129 &words_offset
, pwordexp
->we_wordc
);
2139 error
= parse_glob (&word
, &word_length
, &max_length
, words
,
2140 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
);
2148 /* Is it a field separator? */
2149 if (strchr (ifs
, words
[words_offset
]) == NULL
)
2151 /* "Ordinary" character -- add it to word */
2153 word
= w_addchar (word
, &word_length
, &max_length
,
2154 words
[words_offset
]);
2157 error
= WRDE_NOSPACE
;
2164 /* Field separator */
2165 if (strchr (ifs_white
, words
[words_offset
]))
2167 /* It's a whitespace IFS char. Ignore it at the beginning
2168 of a line and ignore multiple instances. */
2169 if (!word
|| !*word
)
2172 if (w_addword (pwordexp
, word
) == WRDE_NOSPACE
)
2174 error
= WRDE_NOSPACE
;
2184 /* It's a non-whitespace IFS char */
2186 /* Multiple non-whitespace IFS chars are treated as one;
2191 if (w_addword (pwordexp
, word
) == WRDE_NOSPACE
)
2193 error
= WRDE_NOSPACE
;
2205 /* There was a field separator at the end */
2209 /* There was no field separator at the end */
2210 return w_addword (pwordexp
, word
);
2214 * free memory used (unless error is WRDE_NOSPACE), and
2215 * set we_wordc and wd_wordv back to what they were.
2218 if (error
== WRDE_NOSPACE
)
2219 return WRDE_NOSPACE
;
2224 wordfree (pwordexp
);
2225 pwordexp
->we_wordv
= old_wordv
;
2226 pwordexp
->we_wordc
= old_wordc
;