source: trunk/libs/newlib/src/newlib/libc/posix/wordexp.c @ 577

Last change on this file since 577 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 6.1 KB
Line 
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#include <sys/queue.h>
22
23#include <wordexp.h>
24#include "wordexp2.h"
25
26#define MAXLINELEN 500
27
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. */
31int
32wordexp(const char *__restrict words, wordexp_t *__restrict pwordexp, int flags)
33{
34  FILE *f = NULL;
35  FILE *f_err = NULL;
36  char tmp[MAXLINELEN];
37  int i = 0;
38  int offs = 0;
39  char *iter;
40  pid_t pid;
41  int num_words = 0;
42  int num_bytes = 0;
43  int fd[2];
44  int fd_err[2];
45  int err = WRDE_NOSPACE;
46  ext_wordv_t *wordv = NULL;
47  char *eword;
48  struct ewords_entry *entry;
49
50  if (pwordexp == NULL)
51    {
52      return WRDE_NOSPACE;
53    }
54
55  if (flags & WRDE_REUSE)
56    wordfree(pwordexp);
57
58  if ((flags & WRDE_APPEND) == 0)
59    {
60      pwordexp->we_wordc = 0;
61      pwordexp->we_wordv = NULL;
62    }
63
64  if (flags & WRDE_DOOFFS)
65    {
66      offs = pwordexp->we_offs;
67
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 *));
71      if (!wordv)
72        return err;
73      if (!pwordexp->we_wordv)
74        SLIST_INIT(&wordv->list);
75      pwordexp->we_wordv = wordv->we_wordv;
76
77      for (i = 0; i < offs; i++)
78        pwordexp->we_wordv[i] = NULL;
79    }
80
81  if (pipe(fd))
82    return err;
83  if (pipe(fd_err))
84    {
85      close(fd[0]);
86      close(fd[1]);
87      return err;
88    }
89  pid = fork();
90
91  if (pid == -1)
92    {
93      /* In "parent" process, but fork failed */
94      close(fd_err[0]);
95      close(fd_err[1]);
96      close(fd[0]);
97      close(fd[1]);
98      return err;
99    }
100  else if (pid > 0)
101    {
102      /* In parent process. */
103
104      /* Close write end of parent's pipe. */
105      close(fd[1]);
106      close(fd_err[1]);
107
108      /* f_err is the standard error from the shell command. */
109      if (!(f_err = fdopen(fd_err[0], "r")))
110        goto cleanup;
111
112      /* Check for errors. */
113      if (fgets(tmp, MAXLINELEN, f_err))
114        {
115          if (strstr(tmp, "EOF"))
116            err = WRDE_SYNTAX;
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, "`}'"))
122            err = WRDE_BADCHAR;
123          else if (strstr(tmp, "command substitution"))
124            err = WRDE_CMDSUB;
125          else
126            err = WRDE_SYNTAX;
127
128          if (flags & WRDE_SHOWERR)
129            {
130              fprintf(stderr, tmp);
131              while(fgets(tmp, MAXLINELEN, f_err))
132                fprintf(stderr, tmp);
133            }
134
135          goto cleanup;
136        }
137
138      /* f is the standard output from the shell command. */
139      if (!(f = fdopen(fd[0], "r")))
140        goto cleanup;
141
142      /* Get number of words expanded by shell. */
143      if (!fgets(tmp, MAXLINELEN, f))
144        goto cleanup;
145
146      if((iter = strchr(tmp, '\n')))
147          *iter = '\0';
148
149      num_words = atoi(tmp);
150
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 *));
154      if (!wordv)
155        return err;
156      if (!pwordexp->we_wordv)
157        SLIST_INIT(&wordv->list);
158      pwordexp->we_wordv = wordv->we_wordv;
159
160      /* Get number of bytes required for storage of all num_words words. */
161      if (!fgets(tmp, MAXLINELEN, f))
162        goto cleanup;
163
164      if((iter = strchr(tmp, '\n')))
165          *iter = '\0';
166
167      num_bytes = atoi(tmp);
168
169      if (!(entry = (struct ewords_entry *)malloc(sizeof(struct ewords_entry) + num_bytes + num_words)))
170        goto cleanup;
171      SLIST_INSERT_HEAD(&wordv->list, entry, next);
172
173      /* Get expansion from the shell output. */
174      if (!fread(entry->ewords, 1, num_bytes + num_words, f))
175        goto cleanup;
176      entry->ewords[num_bytes + num_words] = 0;
177
178      /* Store each entry in pwordexp's we_wordv vector. */
179      eword = entry->ewords;
180      for(i = 0; i < num_words; i++, eword = iter)
181        {
182          if (!eword)
183            break;
184          pwordexp->we_wordv[offs + pwordexp->we_wordc + i] = eword;
185          if ((iter = strchr(eword, '\n')))
186            *iter++ = '\0';
187        }
188
189      pwordexp->we_wordv[offs + pwordexp->we_wordc + i] = NULL;
190      pwordexp->we_wordc += num_words;
191      if (i == num_words)
192        err = WRDE_SUCCESS;
193
194cleanup:
195      if (f)
196        fclose(f);
197      else
198        close(fd[0]);
199      if (f_err)
200        fclose(f_err);
201      else
202        close(fd_err[0]);
203
204      /* Wait for child to finish. */
205      waitpid (pid, NULL, 0);
206
207      return err;
208    }
209  else
210    {
211      /* In child process. */
212
213      /* Close read end of child's pipe. */
214      close(fd[0]);
215      close(fd_err[0]);
216
217      /* Pipe standard output to parent process via fd. */
218      if (fd[1] != STDOUT_FILENO)
219        {
220          if (dup2(fd[1], STDOUT_FILENO) == -1)
221            _exit(EXIT_FAILURE);
222          /* fd[1] no longer required. */
223          close(fd[1]);
224        }
225
226      /* Pipe standard error to parent process via fd_err. */
227      if (fd_err[1] != STDERR_FILENO)
228        {
229          if (dup2(fd_err[1], STDERR_FILENO) == -1)
230            _exit(EXIT_FAILURE);
231          /* fd_err[1] no longer required. */
232          close(fd_err[1]);
233        }
234
235      if (flags & WRDE_NOCMD)
236        execl("/bin/bash", "bash", "--protected", "--wordexp", words, (char *)0);
237      else
238        execl("/bin/bash", "bash", "--wordexp", words, (char *)0);
239      _exit(EXIT_FAILURE);
240    }
241  return WRDE_SUCCESS;
242}
243#endif /* !_NO_WORDEXP  */
Note: See TracBrowser for help on using the repository browser.