]>
git.ipfire.org Git - thirdparty/glibc.git/blob - posix/wordexp.c
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
;