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 /* This variable is defined and initialized in the startup code. */
52 extern char **__libc_argv
;
54 /* Some forward declarations */
55 static int parse_dollars (char **word
, size_t *word_length
, size_t *max_length
,
56 const char *words
, size_t *offset
, int flags
,
57 wordexp_t
*pwordexp
, const char *ifs
,
58 const char *ifs_white
, int quoted
)
60 static int parse_backtick (char **word
, size_t *word_length
,
61 size_t *max_length
, const char *words
,
62 size_t *offset
, int flags
, wordexp_t
*pwordexp
,
63 const char *ifs
, const char *ifs_white
)
65 static int eval_expr (char *expr
, long int *result
) internal_function
;
67 /* The w_*() functions manipulate word lists. */
72 w_addchar (char *buffer
, size_t *actlen
, size_t *maxlen
, char ch
)
73 /* (lengths exclude trailing zero) */
75 /* Add a character to the buffer, allocating room for it if needed.
78 if (*actlen
== *maxlen
)
80 char *old_buffer
= buffer
;
81 assert (buffer
== NULL
|| *maxlen
!= 0);
83 buffer
= realloc (buffer
, 1 + *maxlen
);
92 buffer
[++(*actlen
)] = '\0';
100 w_addmem (char *buffer
, size_t *actlen
, size_t *maxlen
, const char *str
,
103 /* Add a string to the buffer, allocating room for it if needed.
105 if (*actlen
+ len
> *maxlen
)
107 char *old_buffer
= buffer
;
108 assert (buffer
== NULL
|| *maxlen
!= 0);
109 *maxlen
+= MAX (2 * len
, W_CHUNK
);
110 buffer
= realloc (old_buffer
, 1 + *maxlen
);
118 *((char *) __mempcpy (&buffer
[*actlen
], str
, len
)) = '\0';
128 w_addstr (char *buffer
, size_t *actlen
, size_t *maxlen
, const char *str
)
129 /* (lengths exclude trailing zero) */
131 /* Add a string to the buffer, allocating room for it if needed.
135 assert (str
!= NULL
); /* w_addstr only called from this file */
138 return w_addmem (buffer
, actlen
, maxlen
, str
, len
);
143 w_addword (wordexp_t
*pwordexp
, char *word
)
145 /* Add a word to the wordlist */
148 num_p
= 2 + pwordexp
->we_wordc
+ pwordexp
->we_offs
;
149 pwordexp
->we_wordv
= realloc (pwordexp
->we_wordv
, sizeof (char *) * num_p
);
150 if (pwordexp
->we_wordv
!= NULL
)
152 pwordexp
->we_wordv
[pwordexp
->we_wordc
++] = word
;
153 pwordexp
->we_wordv
[pwordexp
->we_wordc
] = NULL
;
160 /* The parse_*() functions should leave *offset being the offset in 'words'
161 * to the last character processed.
166 parse_backslash (char **word
, size_t *word_length
, size_t *max_length
,
167 const char *words
, size_t *offset
)
169 /* We are poised _at_ a backslash, not in quotes */
171 switch (words
[1 + *offset
])
174 /* Backslash is last character of input words */
182 *word
= w_addchar (*word
, word_length
, max_length
, words
[1 + *offset
]);
195 parse_qtd_backslash (char **word
, size_t *word_length
, size_t *max_length
,
196 const char *words
, size_t *offset
)
198 /* We are poised _at_ a backslash, inside quotes */
200 switch (words
[1 + *offset
])
203 /* Backslash is last character of input words */
214 *word
= w_addchar (*word
, word_length
, max_length
, words
[1 + *offset
]);
222 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
224 *word
= w_addchar (*word
, word_length
, max_length
, words
[1 + *offset
]);
238 parse_tilde (char **word
, size_t *word_length
, size_t *max_length
,
239 const char *words
, size_t *offset
, size_t wordc
)
241 /* We are poised _at_ a tilde */
244 if (*word_length
!= 0)
246 if (!((*word
)[*word_length
- 1] == '=' && wordc
== 0))
248 if (!((*word
)[*word_length
- 1] == ':'
249 && strchr (*word
, '=') && wordc
== 0))
251 *word
= w_addchar (*word
, word_length
, max_length
, '~');
252 return *word
? 0 : WRDE_NOSPACE
;
257 for (i
= 1 + *offset
; words
[i
]; i
++)
259 if (words
[i
] == ':' || words
[i
] == '/' || words
[i
] == ' ' ||
260 words
[i
] == '\t' || words
[i
] == 0 )
263 if (words
[i
] == '\\')
265 *word
= w_addchar (*word
, word_length
, max_length
, '~');
266 return *word
? 0 : WRDE_NOSPACE
;
270 if (i
== 1 + *offset
)
272 /* Tilde appears on its own */
274 struct passwd pwd
, *tpwd
;
276 char* buffer
= __alloca (buflen
);
281 while ((result
= __getpwuid_r (uid
, &pwd
, buffer
, buflen
, &tpwd
)) != 0
285 buffer
= __alloca (buflen
);
288 if (result
== 0 && pwd
.pw_dir
!= NULL
)
290 *word
= w_addstr (*word
, word_length
, max_length
, pwd
.pw_dir
);
296 *word
= w_addchar (*word
, word_length
, max_length
, '~');
303 /* Look up user name in database to get home directory */
304 char *user
= __strndup (&words
[1 + *offset
], i
- *offset
);
305 struct passwd pwd
, *tpwd
;
307 char* buffer
= __alloca (buflen
);
310 while ((result
= __getpwnam_r (user
, &pwd
, buffer
, buflen
, &tpwd
)) != 0
314 buffer
= __alloca (buflen
);
317 if (result
== 0 && pwd
.pw_dir
)
318 *word
= w_addstr (*word
, word_length
, max_length
, pwd
.pw_dir
);
321 /* (invalid login name) */
322 *word
= w_addchar (*word
, word_length
, max_length
, '~');
324 *word
= w_addstr (*word
, word_length
, max_length
, user
);
329 return *word
? 0 : WRDE_NOSPACE
;
334 parse_glob (char **word
, size_t *word_length
, size_t *max_length
,
335 const char *words
, size_t *offset
, int flags
,
336 wordexp_t
*pwordexp
, const char *ifs
, const char *ifs_white
)
338 /* We are poised just after a '*', a '[' or a '?'. */
343 int quoted
= 0; /* 1 if singly-quoted, 2 if doubly */
345 for (; words
[*offset
]; (*offset
)++)
347 if ((ifs
&& strchr (ifs
, words
[*offset
])) ||
348 (!ifs
&& strchr (" \t\n", words
[*offset
])))
352 /* Sort out quoting */
353 if (words
[*offset
] == '\'')
359 else if (quoted
== 1)
364 else if (words
[*offset
] == '"')
370 else if (quoted
== 2)
376 /* Sort out other special characters */
377 if (quoted
!= 1 && words
[*offset
] == '$')
379 error
= parse_dollars (word
, word_length
, max_length
, words
, offset
,
380 flags
, pwordexp
, ifs
, ifs_white
, quoted
== 2);
386 else if (words
[*offset
] == '\\')
389 error
= parse_qtd_backslash (word
, word_length
, max_length
, words
,
392 error
= parse_backslash (word
, word_length
, max_length
, words
,
401 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
406 error
= glob (*word
, GLOB_NOCHECK
, NULL
, &globbuf
);
410 /* We can only run into memory problems. */
411 assert (error
== GLOB_NOSPACE
);
418 /* No field splitting allowed */
419 size_t length
= strlen (globbuf
.gl_pathv
[0]);
420 *word
= realloc (*word
, length
+ 1);
424 memcpy (*word
, globbuf
.gl_pathv
[0], length
+ 1);
425 *word_length
= length
;
427 for (match
= 1; match
< globbuf
.gl_pathc
&& *word
!= NULL
; ++match
)
429 *word
= w_addchar (*word
, word_length
, max_length
, ' ');
431 *word
= w_addstr (*word
, word_length
, max_length
,
432 globbuf
.gl_pathv
[match
]);
435 /* Re-parse white space on return */
438 return *word
? 0 : WRDE_NOSPACE
;
446 matching_word
= __strdup (globbuf
.gl_pathv
[0]);
447 if (matching_word
== NULL
)
450 if (w_addword (pwordexp
, matching_word
) == WRDE_NOSPACE
)
453 for (match
= 1; match
< globbuf
.gl_pathc
; ++match
)
455 matching_word
= __strdup (globbuf
.gl_pathv
[match
]);
456 if (matching_word
== NULL
)
459 if (w_addword (pwordexp
, matching_word
) == WRDE_NOSPACE
)
465 /* Re-parse white space on return */
476 parse_squote (char **word
, size_t *word_length
, size_t *max_length
,
477 const char *words
, size_t *offset
)
479 /* We are poised just after a single quote */
480 for (; words
[*offset
]; ++(*offset
))
482 if (words
[*offset
] != '\'')
484 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
491 /* Unterminated string */
495 /* Functions to evaluate an arithmetic expression */
498 eval_expr_val (char **expr
, long int *result
)
503 /* Skip white space */
504 for (digit
= *expr
; digit
&& *digit
&& isspace (*digit
); ++digit
);
510 /* Scan for closing paren */
511 for (++digit
; **expr
&& **expr
!= ')'; ++(*expr
));
519 if (eval_expr (digit
, result
))
524 case '+': /* Positive value */
528 case '-': /* Negative value */
534 if (!isdigit (*digit
))
539 for (; *digit
&& isdigit (*digit
); ++digit
)
540 *result
= (*result
* 10) + (*digit
- '0');
549 eval_expr_multdiv (char **expr
, long int *result
)
554 if (eval_expr_val (expr
, result
) != 0)
559 /* Skip white space */
560 for (; *expr
&& **expr
&& isspace (**expr
); ++(*expr
));
565 if (eval_expr_val (expr
, &arg
) != 0)
570 else if (**expr
== '/')
573 if (eval_expr_val (expr
, &arg
) != 0)
586 eval_expr (char *expr
, long int *result
)
591 if (eval_expr_multdiv (&expr
, result
) != 0)
596 /* Skip white space */
597 for (; expr
&& *expr
&& isspace (*expr
); ++expr
);
602 if (eval_expr_multdiv (&expr
, &arg
) != 0)
607 else if (*expr
== '-')
610 if (eval_expr_multdiv (&expr
, &arg
) != 0)
623 parse_arith (char **word
, size_t *word_length
, size_t *max_length
,
624 const char *words
, size_t *offset
, int flags
, int bracket
)
626 /* We are poised just after "$((" or "$[" */
629 size_t expr_length
= 0;
630 size_t expr_maxlen
= 0;
633 for (; words
[*offset
]; ++(*offset
))
635 switch (words
[*offset
])
638 error
= parse_dollars (&expr
, &expr_length
, &expr_maxlen
,
639 words
, offset
, flags
, NULL
, NULL
, NULL
, 1);
640 /* The ``1'' here is to tell parse_dollars not to
652 error
= parse_backtick (&expr
, &expr_length
, &expr_maxlen
,
653 words
, offset
, flags
, NULL
, NULL
, NULL
);
654 /* The first NULL here is to tell parse_backtick not to
665 error
= parse_qtd_backslash (&expr
, &expr_length
, &expr_maxlen
,
672 /* I think that a backslash within an
673 * arithmetic expansion is bound to
674 * cause an error sooner or later anyway though.
679 if (--paren_depth
== 0)
681 char result
[21]; /* 21 = ceil(log10(2^64)) + 1 */
682 long int numresult
= 0;
683 long long int convertme
;
685 if (bracket
|| words
[1 + *offset
] != ')')
691 if (*expr
&& eval_expr (expr
, &numresult
) != 0)
696 convertme
= -numresult
;
697 *word
= w_addchar (*word
, word_length
, max_length
, '-');
705 convertme
= numresult
;
708 *word
= w_addstr (*word
, word_length
, max_length
,
709 _itoa (convertme
, &result
[20], 10, 0));
711 return *word
? 0 : WRDE_NOSPACE
;
713 expr
= w_addchar (expr
, &expr_length
, &expr_maxlen
, words
[*offset
]);
720 if (bracket
&& paren_depth
== 1)
722 char result
[21]; /* 21 = ceil(log10(2^64)) + 1 */
723 long int numresult
= 0;
726 if (*expr
&& eval_expr (expr
, &numresult
) != 0)
730 *word
= w_addstr (*word
, word_length
, max_length
,
731 _itoa_word (numresult
, &result
[20], 10, 0));
733 return *word
? 0 : WRDE_NOSPACE
;
749 expr
= w_addchar (expr
, &expr_length
, &expr_maxlen
, words
[*offset
]);
760 /* Function to execute a command and retrieve the results */
761 /* pwordexp contains NULL if field-splitting is forbidden */
764 exec_comm (char *comm
, char **word
, size_t *word_length
, size_t *max_length
,
765 int flags
, wordexp_t
*pwordexp
, const char *ifs
,
766 const char *ifs_white
)
775 /* Don't fork() unless necessary */
783 if ((pid
= fork ()) < 0)
792 const char *args
[4] = { _PATH_BSHELL
, "-c", comm
, NULL
};
794 /* Redirect input and output */
797 /* Close stderr if we have to */
798 if ((flags
& WRDE_SHOWERR
) == 0)
801 __execve (_PATH_BSHELL
, (char *const *) args
, __environ
);
810 buffer
= __alloca (bufsize
);
813 { /* Quoted - no field splitting */
817 if ((buflen
= read (fildes
[0], buffer
, bufsize
)) < 1)
819 if (__waitpid (pid
, NULL
, WNOHANG
) == 0)
821 if ((buflen
= read (fildes
[0], buffer
, bufsize
)) < 1)
825 *word
= w_addmem (*word
, word_length
, max_length
, buffer
, buflen
);
837 /* Not quoted - split fields */
841 * 0 when searching for first character in a field not IFS white space
842 * 1 when copying the text of a field
843 * 2 when searching for possible non-whitespace IFS
848 if ((buflen
= read (fildes
[0], buffer
, bufsize
)) < 1)
850 if (__waitpid (pid
, NULL
, WNOHANG
) == 0)
852 if ((read (fildes
[0], buffer
, bufsize
)) < 1)
856 for (i
= 0; i
< buflen
; ++i
)
858 if (strchr (ifs
, buffer
[i
]) != NULL
)
860 /* Current character is IFS */
861 if (strchr (ifs_white
, buffer
[i
]) == NULL
)
863 /* Current character is IFS but not whitespace */
869 * eg: text<space><comma><space>moretext
871 * So, strip whitespace IFS (like at the start)
878 /* fall through and delimit field.. */
882 /* Current character is IFS white space */
884 /* If not copying a field, ignore it */
888 /* End of field (search for non-IFS afterwards) */
892 /* First IFS white space, or IFS non-whitespace.
893 * Delimit the field. */
896 /* This field is null, so make it an empty string */
897 *word
= w_addchar (*word
, word_length
, max_length
, 0);
905 if (w_addword (pwordexp
, *word
) == WRDE_NOSPACE
)
907 /* Should do __waitpid? */
915 /* fall back round the loop.. */
919 /* Not IFS character */
921 *word
= w_addchar (*word
, word_length
, max_length
,
939 parse_comm (char **word
, size_t *word_length
, size_t *max_length
,
940 const char *words
, size_t *offset
, int flags
, wordexp_t
*pwordexp
,
941 const char *ifs
, const char *ifs_white
)
943 /* We are poised just after "$(" */
946 size_t comm_length
= 0;
947 size_t comm_maxlen
= 0;
950 for (; words
[*offset
]; ++(*offset
))
952 switch (words
[*offset
])
955 if (--paren_depth
== 0)
957 /* Go -- give script to the shell */
958 error
= exec_comm (comm
, word
, word_length
, max_length
, flags
,
959 pwordexp
, ifs
, ifs_white
);
964 /* This is just part of the script */
965 comm
= w_addchar (comm
, &comm_length
, &comm_maxlen
, words
[*offset
]);
974 comm
= w_addchar (comm
, &comm_length
, &comm_maxlen
, words
[*offset
]);
989 parse_param (char **word
, size_t *word_length
, size_t *max_length
,
990 const char *words
, size_t *offset
, int flags
, wordexp_t
*pwordexp
,
991 const char *ifs
, const char *ifs_white
, int quoted
)
993 /* We are poised just after "$" */
994 enum remove_pattern_enum
1002 size_t start
= *offset
;
1003 size_t env_length
= 0;
1004 size_t env_maxlen
= 0;
1005 size_t pat_length
= 0;
1006 size_t pat_maxlen
= 0;
1008 char *pattern
= NULL
;
1011 enum remove_pattern_enum remove
= RP_NONE
;
1014 int substitute_length
= 0;
1018 for (; words
[*offset
]; ++(*offset
))
1020 switch (words
[*offset
])
1025 if (action
!= '\0' || remove
!= RP_NONE
)
1027 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1029 if (pattern
== NULL
)
1035 if (*offset
== start
)
1038 /* Otherwise evaluate */
1039 /* (and re-parse this character) */
1044 if (words
[start
] != '{')
1047 if (action
!= '\0' || remove
!= RP_NONE
)
1051 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1053 if (pattern
== NULL
)
1064 /* '#' only has special meaning inside braces */
1065 if (words
[start
] != '{')
1068 /* (and re-parse this character) */
1073 /* At the start? (i.e. 'string length') */
1074 if (*offset
== start
+ 1)
1076 substitute_length
= 1;
1079 else if (substitute_length
)
1082 /* Separating variable name from prefix pattern? */
1083 if (remove
== RP_NONE
)
1085 remove
= RP_SHORT_LEFT
;
1088 else if (remove
== RP_SHORT_LEFT
)
1090 remove
= RP_LONG_LEFT
;
1094 /* Must be part of prefix/suffix pattern. */
1095 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1097 if (pattern
== NULL
)
1106 /* Separating variable name from suffix pattern? */
1107 if (remove
== RP_NONE
)
1109 remove
= RP_SHORT_RIGHT
;
1112 else if (remove
== RP_SHORT_RIGHT
)
1114 remove
= RP_LONG_RIGHT
;
1118 /* Must be part of prefix/suffix pattern. */
1119 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1121 if (pattern
== NULL
)
1130 if (action
!= '\0' || remove
!= RP_NONE
)
1132 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1134 if (pattern
== NULL
)
1140 if ((words
[1 + *offset
] == '-') || (words
[1 + *offset
] == '=')
1141 || (words
[1 + *offset
] == '?') || (words
[1 + *offset
] == '+'))
1156 if (substitute_length
)
1159 if (action
!= '\0' || remove
!= RP_NONE
)
1161 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1163 if (pattern
== NULL
)
1169 action
= words
[*offset
];
1173 if (action
!= '\0' || remove
!= RP_NONE
)
1175 /* Um. Is this right? */
1176 error
= parse_qtd_backslash (word
, word_length
, max_length
,
1183 error
= WRDE_SYNTAX
;
1189 if (pattern
!= NULL
)
1195 if (action
!= '\0' || remove
!= RP_NONE
)
1197 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1199 if (pattern
== NULL
)
1205 star
= strchr ("*@", words
[*offset
]) != NULL
;
1206 if (isalnum (words
[*offset
]) || star
)
1208 env
= w_addchar (env
, &env_length
, &env_maxlen
, words
[*offset
]);
1223 /* End of input string -- remember to reparse the character that we stopped
1228 if (words
[start
] == '{' && words
[*offset
] != '}')
1233 *offset
= start
- 1;
1234 *word
= w_addchar (*word
, word_length
, max_length
, '$');
1236 return *word
? 0 : WRDE_NOSPACE
;
1239 /* Is it `$*' or `$@' ? */
1240 if (strpbrk (env
, "*@") != NULL
)
1242 size_t plist_len
= 1;
1247 /* Bad substitution if there is more than one character */
1248 fprintf (stderr
, "${%s}: bad substitution\n", env
);
1252 if (!quoted
|| *env
== '*')
1254 /* Build up value parameter by parameter (copy them) */
1255 for (p
= 1; __libc_argv
[p
]; p
++)
1257 char * old_pointer
= value
;
1260 value
[plist_len
- 1] = 0;
1262 plist_len
+= 1 + strlen (__libc_argv
[p
]);
1264 /* First realloc will act as malloc because value is
1265 * initialised to NULL. */
1266 value
= realloc (value
, plist_len
);
1270 return WRDE_NOSPACE
;
1273 strcat (value
, __libc_argv
[p
]);
1274 if (__libc_argv
[p
+ 1])
1276 value
[plist_len
- 1] = '\0';
1277 value
[plist_len
- 2] = ' ';
1282 goto maybe_fieldsplit
;
1285 /* Each parameter is a separate word ("$@") */
1286 if (__libc_argv
[0] == NULL
)
1288 /* This can happen if the application is started without any
1289 parameter, not even a name. This is legal according to
1290 POSIX since the giving parameters is only a "should" rule. */
1291 *word
= __strdup ("");
1292 *max_length
= *word_length
= 0;
1296 for (p
= 1; __libc_argv
[p
+ 1]; p
++)
1298 char *copy
= __strdup (__libc_argv
[p
]);
1300 return WRDE_NOSPACE
;
1302 strcpy (copy
, __libc_argv
[p
]);
1303 error
= w_addword (pwordexp
, copy
);
1311 /* Last parameter becomes current word */
1314 *word
= __strdup (__libc_argv
[p
]);
1315 *max_length
= *word_length
= strlen (*word
);
1322 value
= getenv (env
);
1324 if (action
!= '\0' || remove
!= RP_NONE
)
1334 if (!pattern
|| !*pattern
)
1337 end
= value
+ strlen (value
);
1345 for (p
= value
; p
<= end
; ++p
)
1349 if (fnmatch (pattern
, value
, 0) != FNM_NOMATCH
)
1361 for (p
= end
; p
>= value
; --p
)
1365 if (fnmatch (pattern
, value
, 0) != FNM_NOMATCH
)
1376 case RP_SHORT_RIGHT
:
1377 for (p
= end
; p
>= value
; --p
)
1379 if (fnmatch (pattern
, p
, 0) != FNM_NOMATCH
)
1389 for (p
= value
; p
<= end
; ++p
)
1391 if (fnmatch (pattern
, p
, 0) != FNM_NOMATCH
)
1401 assert (! "Unexpected `remove' value\n");
1408 if (value
&& *value
)
1409 /* Substitute parameter */
1412 if (!colon_seen
&& value
)
1414 /* Substitute NULL */
1421 fprintf (stderr
, "%s: ", env
);
1425 /* Expand 'pattern' and write it to stderr */
1428 error
= wordexp (pattern
, &we
, flags
);
1434 for (i
= 0; i
< we
.we_wordc
; ++i
)
1436 fprintf (stderr
, "%s%s", i
? " " : "", we
.we_wordv
[i
]);
1439 fprintf (stderr
, "\n");
1440 error
= WRDE_BADVAL
;
1449 fprintf (stderr
, "parameter null or not set\n");
1455 if (value
&& *value
)
1456 /* Substitute parameter */
1459 if (!colon_seen
&& value
)
1461 /* Substitute NULL */
1469 /* Substitute word */
1475 /* No field-splitting is allowed, so imagine
1476 quotes around the word. */
1477 char *qtd_pattern
= malloc (3 + strlen (pattern
));
1478 sprintf (qtd_pattern
, "\"%s\"", pattern
);
1480 pattern
= qtd_pattern
;
1483 error
= wordexp (pattern
, &we
, flags
);
1491 /* Fingers crossed that the quotes worked.. */
1492 assert (!quoted
|| we
.we_wordc
== 1);
1495 for (i
= 0; i
< we
.we_wordc
; i
++)
1496 if (w_addword (pwordexp
, __strdup(we
.we_wordv
[i
]))
1502 setenv (env
, we
.we_wordv
[0], 1); /* need to strdup? */
1506 if (i
< we
.we_wordc
)
1507 /* Ran out of space */
1514 if (value
&& *value
)
1517 if (!colon_seen
&& value
)
1520 /* Substitute NULL */
1526 if (value
&& *value
)
1527 /* Substitute parameter */
1530 if (!colon_seen
&& value
)
1532 /* Substitute NULL */
1538 /* This checks for '=' so it knows to assign */
1542 assert (! "Unrecognised action!");
1551 /* Variable not defined */
1552 if (flags
& WRDE_UNDEF
)
1558 if (substitute_length
)
1560 char param_length
[21];
1561 param_length
[20] = '\0';
1562 *word
= w_addstr (*word
, word_length
, max_length
,
1563 _itoa_word (strlen (value
), ¶m_length
[20], 10, 0));
1564 return *word
? 0 : WRDE_NOSPACE
;
1569 if (quoted
|| !pwordexp
)
1571 /* Quoted - no field split */
1572 *word
= w_addstr (*word
, word_length
, max_length
, value
);
1573 return *word
? 0 : WRDE_NOSPACE
;
1577 /* Need to field-split */
1578 char *field_begin
= value
;
1579 int seen_nonws_ifs
= 0;
1583 char *field_end
= field_begin
;
1587 /* If this isn't the first field, start a new word */
1588 if (field_begin
!= value
)
1590 if (w_addword (pwordexp
, *word
) == WRDE_NOSPACE
)
1591 return WRDE_NOSPACE
;
1594 *word_length
= *max_length
= 0;
1597 /* Skip IFS whitespace before the field */
1598 while (*field_begin
&& strchr (ifs_white
, *field_begin
) != NULL
)
1601 if (!seen_nonws_ifs
&& *field_begin
== 0)
1602 /* Nothing but whitespace */
1605 /* Search for the end of the field */
1606 field_end
= field_begin
;
1607 while (*field_end
&& strchr (ifs
, *field_end
) == NULL
)
1610 /* Set up pointer to the character after end of field */
1612 next_field
= ch
? field_end
: NULL
;
1614 /* Skip whitespace IFS after the field */
1615 while (next_field
&& *next_field
&& strchr (ifs_white
, *next_field
))
1618 /* Skip at most one non-whitespace IFS character after the field */
1620 if (next_field
&& *next_field
&& strchr (ifs
, *next_field
))
1626 /* Null-terminate it */
1629 /* Tag a copy onto the current word */
1630 *word
= w_addstr (*word
, word_length
, max_length
,
1631 __strdup (field_begin
));
1633 return WRDE_NOSPACE
;
1635 field_begin
= next_field
;
1636 } while (seen_nonws_ifs
|| (field_begin
&& *field_begin
));
1648 return WRDE_NOSPACE
;
1662 parse_dollars (char **word
, size_t *word_length
, size_t *max_length
,
1663 const char *words
, size_t *offset
, int flags
,
1664 wordexp_t
*pwordexp
, const char *ifs
, const char *ifs_white
,
1667 /* We are poised _at_ "$" */
1668 switch (words
[1 + *offset
])
1673 *word
= w_addchar (*word
, word_length
, max_length
, '$');
1674 return *word
? 0 : WRDE_NOSPACE
;
1677 if (words
[2 + *offset
] == '(')
1679 /* Differentiate between $((1+3)) and $((echo);(ls)) */
1680 int i
= 3 + *offset
;
1681 while (words
[i
] && words
[i
] != ')')
1683 if (words
[i
] == ')' && words
[i
+ 1] == ')')
1686 /* Call parse_arith -- 0 is for "no brackets" */
1687 return parse_arith (word
, word_length
, max_length
, words
, offset
,
1692 if (flags
& WRDE_NOCMD
)
1696 return parse_comm (word
, word_length
, max_length
, words
, offset
, flags
,
1697 pwordexp
, ifs
, ifs_white
);
1701 /* Call parse_arith -- 1 is for "brackets" */
1702 return parse_arith (word
, word_length
, max_length
, words
, offset
, flags
,
1707 ++(*offset
); /* parse_param needs to know if "{" is there */
1708 return parse_param (word
, word_length
, max_length
, words
, offset
, flags
,
1709 pwordexp
, ifs
, ifs_white
, quoted
);
1714 parse_backtick (char **word
, size_t *word_length
, size_t *max_length
,
1715 const char *words
, size_t *offset
, int flags
,
1716 wordexp_t
*pwordexp
, const char *ifs
, const char *ifs_white
)
1718 /* We are poised just after "`" */
1720 size_t comm_length
= 0;
1721 size_t comm_maxlen
= 0;
1725 for (; words
[*offset
]; ++(*offset
))
1727 switch (words
[*offset
])
1730 /* Go -- give the script to the shell */
1731 error
= exec_comm (comm
, word
, word_length
, max_length
, flags
,
1732 pwordexp
, ifs
, ifs_white
);
1739 error
= parse_qtd_backslash (&comm
, &comm_length
, &comm_maxlen
,
1752 error
= parse_backslash (&comm
, &comm_length
, &comm_maxlen
, words
,
1764 squoting
= 1 - squoting
;
1766 comm
= w_addchar (comm
, &comm_length
, &comm_maxlen
, words
[*offset
]);
1768 return WRDE_NOSPACE
;
1779 parse_dquote (char **word
, size_t *word_length
, size_t *max_length
,
1780 const char *words
, size_t *offset
, int flags
,
1781 wordexp_t
*pwordexp
, const char * ifs
, const char * ifs_white
)
1783 /* We are poised just after a double-quote */
1786 for (; words
[*offset
]; ++(*offset
))
1788 switch (words
[*offset
])
1794 error
= parse_dollars (word
, word_length
, max_length
, words
, offset
,
1795 flags
, pwordexp
, ifs
, ifs_white
, 1);
1796 /* The ``1'' here is to tell parse_dollars not to
1797 * split the fields. It may need to, however ("$@").
1805 if (flags
& WRDE_NOCMD
)
1809 error
= parse_backtick (word
, word_length
, max_length
, words
,
1810 offset
, flags
, NULL
, NULL
, NULL
);
1811 /* The first NULL here is to tell parse_backtick not to
1820 error
= parse_qtd_backslash (word
, word_length
, max_length
, words
,
1829 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
1831 return WRDE_NOSPACE
;
1835 /* Unterminated string */
1840 * wordfree() is to be called after pwordexp is finished with.
1844 wordfree (wordexp_t
*pwordexp
)
1847 /* wordexp can set pwordexp to NULL */
1848 if (pwordexp
&& pwordexp
->we_wordv
)
1850 char **wordv
= pwordexp
->we_wordv
;
1852 for (wordv
+= pwordexp
->we_offs
; *wordv
; ++wordv
)
1855 free (pwordexp
->we_wordv
);
1856 pwordexp
->we_wordv
= NULL
;
1865 wordexp (const char *words
, wordexp_t
*pwordexp
, int flags
)
1867 size_t wordv_offset
;
1868 size_t words_offset
;
1869 size_t word_length
= 0;
1870 size_t max_length
= 0;
1875 char **old_wordv
= pwordexp
->we_wordv
;
1876 size_t old_wordc
= (flags
& WRDE_REUSE
) ? pwordexp
->we_wordc
: 0;
1878 if (flags
& WRDE_REUSE
)
1879 /* Minimal implementation of WRDE_REUSE for now */
1880 wordfree (pwordexp
);
1882 if (flags
& WRDE_DOOFFS
)
1884 pwordexp
->we_wordv
= calloc (1 + pwordexp
->we_offs
, sizeof (char *));
1885 if (pwordexp
->we_wordv
== NULL
)
1886 return WRDE_NOSPACE
;
1890 pwordexp
->we_wordv
= calloc (1, sizeof (char *));
1891 if (pwordexp
->we_wordv
== NULL
)
1892 return WRDE_NOSPACE
;
1894 pwordexp
->we_offs
= 0;
1897 if ((flags
& WRDE_APPEND
) == 0)
1898 pwordexp
->we_wordc
= 0;
1900 wordv_offset
= pwordexp
->we_offs
+ pwordexp
->we_wordc
;
1902 /* Find out what the field separators are.
1903 * There are two types: whitespace and non-whitespace.
1905 ifs
= getenv ("IFS");
1908 /* NULL IFS means no field-splitting is to be performed */
1909 ifs
= strcpy (ifs_white
, "");
1913 char *whch
= ifs_white
;
1915 /* Start off with no whitespace IFS characters */
1916 ifs_white
[0] = '\0';
1918 while (*ifsch
!= '\0')
1920 if ((*ifsch
== ' ') || (*ifsch
== '\t') || (*ifsch
== '\n'))
1922 /* Whitespace IFS. See first whether it is already in our
1924 char *runp
= ifs_white
;
1926 while (runp
< whch
&& *runp
!= '\0' && *runp
!= *ifsch
)
1938 for (words_offset
= 0 ; words
[words_offset
] ; ++words_offset
)
1939 switch (words
[words_offset
])
1951 wordfree (pwordexp
);
1952 pwordexp
->we_wordc
= 0;
1953 pwordexp
->we_wordv
= old_wordv
;
1954 return WRDE_BADCHAR
;
1957 error
= parse_backslash (&word
, &word_length
, &max_length
, words
,
1966 error
= parse_dollars (&word
, &word_length
, &max_length
, words
,
1967 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
,
1976 if (flags
& WRDE_NOCMD
)
1980 error
= parse_backtick (&word
, &word_length
, &max_length
, words
,
1981 &words_offset
, flags
, pwordexp
, ifs
,
1991 error
= parse_dquote (&word
, &word_length
, &max_length
, words
,
1992 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
);
2001 error
= parse_squote (&word
, &word_length
, &max_length
, words
,
2010 error
= parse_tilde (&word
, &word_length
, &max_length
, words
,
2011 &words_offset
, pwordexp
->we_wordc
);
2021 error
= parse_glob (&word
, &word_length
, &max_length
, words
,
2022 &words_offset
, flags
, pwordexp
, ifs
, ifs_white
);
2030 /* Is it a field separator? */
2031 if (strchr (ifs
, words
[words_offset
]) == NULL
)
2033 /* "Ordinary" character -- add it to word */
2035 word
= w_addchar (word
, &word_length
, &max_length
,
2036 words
[words_offset
]);
2039 error
= WRDE_NOSPACE
;
2046 /* Field separator */
2047 if (strchr (ifs_white
, words
[words_offset
]))
2049 /* It's a whitespace IFS char. Ignore it at the beginning
2050 of a line and ignore multiple instances. */
2051 if (!word
|| !*word
)
2054 if (w_addword (pwordexp
, word
) == WRDE_NOSPACE
)
2056 error
= WRDE_NOSPACE
;
2066 /* It's a non-whitespace IFS char */
2068 /* Multiple non-whitespace IFS chars are treated as one;
2073 if (w_addword (pwordexp
, word
) == WRDE_NOSPACE
)
2075 error
= WRDE_NOSPACE
;
2087 /* There was a field separator at the end */
2091 /* There was no field separator at the end */
2092 return w_addword (pwordexp
, word
);
2096 * free memory used (unless error is WRDE_NOSPACE), and
2097 * set we_wordc and wd_wordv back to what they were.
2100 if (error
== WRDE_NOSPACE
)
2101 return WRDE_NOSPACE
;
2106 wordfree (pwordexp
);
2107 pwordexp
->we_wordv
= old_wordv
;
2108 pwordexp
->we_wordc
= old_wordc
;