]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/newlib-tumbl.git/blob - newlib/libc/posix/wordexp.c
b2f63cfad164a2865bc00d931940ac1e8eed2860
[fpga/lx-cpu1/newlib-tumbl.git] / newlib / libc / posix / wordexp.c
1 /* Copyright (C) 2002 by  Red Hat, Incorporated. All rights reserved.
2  *
3  * Permission to use, copy, modify, and distribute this software
4  * is freely granted, provided that this notice is preserved.
5  */
6 #ifndef _NO_WORDEXP
7
8 #include <sys/param.h>
9 #include <sys/stat.h>
10
11 #include <ctype.h>
12 #include <dirent.h>
13 #include <errno.h>
14 #include <glob.h>
15 #include <pwd.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <sys/wait.h>
21
22 #include <wordexp.h>
23
24 #define MAXLINELEN 500
25
26 /* Note: This implementation of wordexp requires a version of bash
27    that supports the --wordexp and --protected arguments to be present
28    on the system.  It does not support the WRDE_UNDEF flag. */
29 int
30 wordexp(const char *words, wordexp_t *pwordexp, int flags)
31 {
32   FILE *f = NULL;
33   FILE *f_err = NULL;
34   char tmp[MAXLINELEN];
35   int i = 0;
36   int offs = 0;
37   char *iter;
38   pid_t pid;
39   int num_words = 0;
40   int num_bytes = 0;
41   int fd[2];
42   int fd_err[2];
43   int err = WRDE_NOSPACE;
44   char **wordv;
45   char *ewords = NULL;
46   char *eword;
47
48   if (pwordexp == NULL)
49     {
50       return WRDE_NOSPACE;
51     }
52
53   if (flags & WRDE_REUSE)
54     wordfree(pwordexp);
55
56   if ((flags & WRDE_APPEND) == 0)
57     {
58       pwordexp->we_wordc = 0;
59       pwordexp->we_wordv = NULL;
60     }
61
62   if (flags & WRDE_DOOFFS)
63     {
64       offs = pwordexp->we_offs;
65
66       wordv = (char **)realloc(pwordexp->we_wordv, (pwordexp->we_wordc + offs + 1) * sizeof(char *));
67       if (!wordv)
68         return err;
69       pwordexp->we_wordv = wordv;
70
71       for (i = 0; i < offs; i++)
72         pwordexp->we_wordv[i] = NULL;
73     }
74
75   if (pipe(fd))
76     return err;
77   if (pipe(fd_err))
78     {
79       close(fd[0]);
80       close(fd[1]);
81       return err;
82     }
83   pid = fork();
84
85   if (pid == -1)
86     {
87       /* In "parent" process, but fork failed */
88       close(fd_err[0]);
89       close(fd_err[1]);
90       close(fd[0]);
91       close(fd[1]);
92       return err;
93     }
94   else if (pid > 0)
95     {
96       /* In parent process. */
97
98       /* Close write end of parent's pipe. */
99       close(fd[1]);
100       close(fd_err[1]);
101
102       /* f_err is the standard error from the shell command. */
103       if (!(f_err = fdopen(fd_err[0], "r")))
104         goto cleanup;
105
106       /* Check for errors. */
107       if (fgets(tmp, MAXLINELEN, f_err))
108         {
109           if (strstr(tmp, "EOF"))
110             err = WRDE_SYNTAX;
111           else if (strstr(tmp, "`\n'") || strstr(tmp, "`|'")
112                    || strstr(tmp, "`&'") || strstr(tmp, "`;'")
113                    || strstr(tmp, "`<'") || strstr(tmp, "`>'")
114                    || strstr(tmp, "`('") || strstr(tmp, "`)'")
115                    || strstr(tmp, "`{'") || strstr(tmp, "`}'"))
116             err = WRDE_BADCHAR;
117           else if (strstr(tmp, "command substitution"))
118             err = WRDE_CMDSUB;
119           else
120             err = WRDE_SYNTAX;
121
122           if (flags & WRDE_SHOWERR)
123             {
124               fprintf(stderr, tmp);
125               while(fgets(tmp, MAXLINELEN, f_err))
126                 fprintf(stderr, tmp);
127             }
128
129           goto cleanup;
130         }
131
132       /* f is the standard output from the shell command. */
133       if (!(f = fdopen(fd[0], "r")))
134         goto cleanup;
135
136       /* Get number of words expanded by shell. */
137       if (!fgets(tmp, MAXLINELEN, f))
138         goto cleanup;
139
140       if((iter = strchr(tmp, '\n')))
141           *iter = '\0';
142
143       num_words = atoi(tmp);
144
145       wordv = (char **)realloc(pwordexp->we_wordv,
146                                (pwordexp->we_wordc + num_words + offs + 1) * sizeof(char *));
147       if (!wordv)
148         goto cleanup;
149       pwordexp->we_wordv = wordv;
150
151       /* Get number of bytes required for storage of all num_words words. */
152       if (!fgets(tmp, MAXLINELEN, f))
153         goto cleanup;
154
155       if((iter = strchr(tmp, '\n')))
156           *iter = '\0';
157
158       num_bytes = atoi(tmp);
159
160       /* Get expansion from the shell output. */
161       if (!(ewords = (char *)malloc(num_bytes + num_words + 1)))
162         goto cleanup;
163       if (!fread(ewords, 1, num_bytes + num_words, f))
164         goto cleanup;
165       ewords[num_bytes + num_words] = 0;
166
167       /* Store each entry in pwordexp's we_wordv vector. */
168       eword = ewords;
169       for(i = 0; i < num_words; i++)
170         {
171           if (eword && (iter = strchr(eword, '\n')))
172             *iter = '\0';
173
174           if (!eword ||
175               !(pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = strdup(eword)))
176             {
177               pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = NULL;
178               pwordexp->we_wordc += i;
179               goto cleanup;
180             }
181           eword = iter ? iter + 1 : iter;
182         }
183
184       pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = NULL;
185       pwordexp->we_wordc += num_words;
186       err = WRDE_SUCCESS;
187
188 cleanup:
189       free(ewords);
190       if (f)
191         fclose(f);
192       else
193         close(fd[0]);
194       if (f_err)
195         fclose(f_err);
196       else
197         close(fd_err[0]);
198
199       /* Wait for child to finish. */
200       waitpid (pid, NULL, 0);
201
202       return err;
203     }
204   else
205     {
206       /* In child process. */
207
208       /* Close read end of child's pipe. */
209       close(fd[0]);
210       close(fd_err[0]);
211
212       /* Pipe standard output to parent process via fd. */
213       if (fd[1] != STDOUT_FILENO)
214         {
215           if (dup2(fd[1], STDOUT_FILENO) == -1)
216             _exit(EXIT_FAILURE);
217           /* fd[1] no longer required. */
218           close(fd[1]);
219         }
220
221       /* Pipe standard error to parent process via fd_err. */
222       if (fd_err[1] != STDERR_FILENO)
223         {
224           if (dup2(fd_err[1], STDERR_FILENO) == -1)
225             _exit(EXIT_FAILURE);
226           /* fd_err[1] no longer required. */
227           close(fd_err[1]);
228         }
229
230       if (flags & WRDE_NOCMD)
231         execl("/bin/bash", "bash", "--protected", "--wordexp", words, (char *)0);
232       else
233         execl("/bin/bash", "bash", "--wordexp", words, (char *)0);
234       _exit(EXIT_FAILURE);
235     }
236   return WRDE_SUCCESS;
237 }
238 #endif /* !_NO_WORDEXP  */