1 /* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved.
3 * Permission to use, copy, modify, and distribute this software
4 * is freely granted, provided that this notice is preserved.
21 #include <sys/queue.h>
26 #define MAXLINELEN 500
28 /* Note: This implementation of wordexp requires a version of bash
29 that supports the --wordexp and --protected arguments to be present
30 on the system. It does not support the WRDE_UNDEF flag. */
32 wordexp(const char *__restrict words
, wordexp_t
*__restrict pwordexp
, int flags
)
45 int err
= WRDE_NOSPACE
;
46 ext_wordv_t
*wordv
= NULL
;
48 struct ewords_entry
*entry
;
55 if (flags
& WRDE_REUSE
)
58 if ((flags
& WRDE_APPEND
) == 0)
60 pwordexp
->we_wordc
= 0;
61 pwordexp
->we_wordv
= NULL
;
64 if (flags
& WRDE_DOOFFS
)
66 offs
= pwordexp
->we_offs
;
68 if (pwordexp
->we_wordv
)
69 wordv
= WE_WORDV_TO_EXT_WORDV(pwordexp
->we_wordv
);
70 wordv
= (ext_wordv_t
*)realloc(wordv
, sizeof(ext_wordv_t
) + (offs
+ pwordexp
->we_wordc
) * sizeof(char *));
73 if (!pwordexp
->we_wordv
)
74 SLIST_INIT(&wordv
->list
);
75 pwordexp
->we_wordv
= wordv
->we_wordv
;
77 for (i
= 0; i
< offs
; i
++)
78 pwordexp
->we_wordv
[i
] = NULL
;
93 /* In "parent" process, but fork failed */
102 /* In parent process. */
104 /* Close write end of parent's pipe. */
108 /* f_err is the standard error from the shell command. */
109 if (!(f_err
= fdopen(fd_err
[0], "r")))
112 /* Check for errors. */
113 if (fgets(tmp
, MAXLINELEN
, f_err
))
115 if (strstr(tmp
, "EOF"))
117 else if (strstr(tmp
, "`\n'") || strstr(tmp
, "`|'")
118 || strstr(tmp
, "`&'") || strstr(tmp
, "`;'")
119 || strstr(tmp
, "`<'") || strstr(tmp
, "`>'")
120 || strstr(tmp
, "`('") || strstr(tmp
, "`)'")
121 || strstr(tmp
, "`{'") || strstr(tmp
, "`}'"))
123 else if (strstr(tmp
, "command substitution"))
128 if (flags
& WRDE_SHOWERR
)
131 while(fgets(tmp
, MAXLINELEN
, f_err
))
138 /* f is the standard output from the shell command. */
139 if (!(f
= fdopen(fd
[0], "r")))
142 /* Get number of words expanded by shell. */
143 if (!fgets(tmp
, MAXLINELEN
, f
))
146 if((iter
= strchr(tmp
, '\n')))
149 num_words
= atoi(tmp
);
151 if (pwordexp
->we_wordv
)
152 wordv
= WE_WORDV_TO_EXT_WORDV(pwordexp
->we_wordv
);
153 wordv
= (ext_wordv_t
*)realloc(wordv
, sizeof(ext_wordv_t
) + (offs
+ pwordexp
->we_wordc
+ num_words
) * sizeof(char *));
156 if (!pwordexp
->we_wordv
)
157 SLIST_INIT(&wordv
->list
);
158 pwordexp
->we_wordv
= wordv
->we_wordv
;
160 /* Get number of bytes required for storage of all num_words words. */
161 if (!fgets(tmp
, MAXLINELEN
, f
))
164 if((iter
= strchr(tmp
, '\n')))
167 num_bytes
= atoi(tmp
);
169 if (!(entry
= (struct ewords_entry
*)malloc(sizeof(struct ewords_entry
) + num_bytes
+ num_words
)))
171 SLIST_INSERT_HEAD(&wordv
->list
, entry
, next
);
173 /* Get expansion from the shell output. */
174 if (!fread(entry
->ewords
, 1, num_bytes
+ num_words
, f
))
176 entry
->ewords
[num_bytes
+ num_words
] = 0;
178 /* Store each entry in pwordexp's we_wordv vector. */
179 eword
= entry
->ewords
;
180 for(i
= 0; i
< num_words
; i
++, eword
= iter
)
184 pwordexp
->we_wordv
[offs
+ pwordexp
->we_wordc
+ i
] = eword
;
185 if ((iter
= strchr(eword
, '\n')))
189 pwordexp
->we_wordv
[offs
+ pwordexp
->we_wordc
+ i
] = NULL
;
190 pwordexp
->we_wordc
+= num_words
;
204 /* Wait for child to finish. */
205 waitpid (pid
, NULL
, 0);
211 /* In child process. */
213 /* Close read end of child's pipe. */
217 /* Pipe standard output to parent process via fd. */
218 if (fd
[1] != STDOUT_FILENO
)
220 if (dup2(fd
[1], STDOUT_FILENO
) == -1)
222 /* fd[1] no longer required. */
226 /* Pipe standard error to parent process via fd_err. */
227 if (fd_err
[1] != STDERR_FILENO
)
229 if (dup2(fd_err
[1], STDERR_FILENO
) == -1)
231 /* fd_err[1] no longer required. */
235 if (flags
& WRDE_NOCMD
)
236 execl("/bin/bash", "bash", "--protected", "--wordexp", words
, (char *)0);
238 execl("/bin/bash", "bash", "--wordexp", words
, (char *)0);
243 #endif /* !_NO_WORDEXP */