Sun Jun 16 00:40:20 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
[glibc.git] / posix / wordexp.c
blob1922e446423efabea8bb3b1ffb161abb2534ee37
1 /* Copyright (C) 1992 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
19 #include <ansidecl.h>
20 #include <sys/types.h>
21 #include <wordexp.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <sys/wait.h>
25 #include <signal.h>
28 /* We do word expansion with a pipe to the shell.
29 The shell command `sh [-P] [-u] -w "words ..."' expands words.
30 If -P, command substitution is an error.
31 If -u, reference to an undefined variable is an error.
32 The shell writes on its stdout:
33 %u\0 Number of words.
34 %u\0 Number of bytes in all words together (not counting \0s).
35 word1\0
36 word2\0
37 ...
38 wordN\0
41 #define SHELL_PATH "/bin/sh"
42 #define SHELL_NAME "sh"
45 int
46 DEFUN(wordexp, (string, pwordexp, flags),
47 CONST char *string AND wordexp_t *pwordexp AND int flags)
49 int error;
50 pid_t pid;
51 int d[2];
52 int status;
54 FILE *f;
55 size_t wordc, start, buflen;
56 char *buf;
58 /* Create the pipe through which we will communicate to the shell. */
59 if (pipe (d) < 0)
60 return -1;
62 pid = fork ();
63 if (pid < 0)
64 return -1;
66 if (pid == 0)
68 /* Child. Run the shell. */
70 CONST char *argv[5];
72 close (d[STDIN_FILENO]);
73 dup2 (d[STDOUT_FILENO], STDOUT_FILENO);
74 if (!(flags & WRDE_SHOWERR))
75 close (STDERR_FILENO);
77 i = 0;
78 argv[i++] = SHELL_NAME;
79 if (flags & WRDE_NOCMD)
80 argv[i++] = "-P";
81 if (flags & WRDE_UNDEF)
82 argv[i++] = "-u";
83 argv[i++] = "-w";
84 argv[i++] = string;
85 argv[i++] = NULL;
87 execv (SHELL_PATH, argv);
88 _exit (WRDE_NOSPACE);
91 /* Parent. */
93 buf = NULL;
94 error = WRDE_NOSPACE;
96 close (d[STDOUT_FILENO]);
97 f = fdopen (d[STDIN_FILENO]);
98 if (f == NULL)
99 goto lose;
101 /* Read the number of words and number of bytes from the shell. */
102 if (fscanf (f, "%u", &wordc) != 1 || getc (f) != '\0' ||
103 fscanf (f, "%u", &buflen) != 1 || getc (f) != '\0')
104 goto lose;
106 /* Read the words from the shell, and wait for it to return. */
107 buflen += wordc;
108 buf = malloc (buflen);
109 if (buf == NULL ||
110 fread (buf, buflen, 1, f) != 1 ||
111 waitpid (pid, &status, 0) != pid)
112 goto lose;
114 if (WIFEXITED (status))
116 if (WEXITSTATUS (status) != 0)
118 error = WEXITSTATUS (status);
119 goto lose;
122 else
123 goto lose;
125 /* Pack the structure. */
127 start = 0;
128 if (flags & WRDE_DOOFFS)
129 start += pwordexp->we_offs;
130 if (flags & WRDE_APPEND)
131 start += pwordexp->we_wordc;
132 wordc = start + wordc + 1;
134 if (flags & WRDE_APPEND)
135 wordv = (char **) realloc ((PTR) pwordexp->we_wordv,
136 wordc * sizeof (char *));
137 else
138 wordv = (char **) malloc (wordc * sizeof (char *));
139 if (wordv == NULL)
140 goto lose;
142 if (flags & WRDE_DOOFFS)
143 for (i = 0; i < pwordexp->we_offs; ++i)
144 wordv[i] = NULL;
146 for (i = start; i < wordc; ++i)
148 pwordexp->we_wordv[i] = buf;
149 buf = strchr (buf, '\0') + 1;
151 wordv[i] = NULL;
153 if (flags & WRDE_REUSE)
155 free (pwordexp->we_wordv[0]);
156 if (!(flags & WRDE_APPEND))
157 free (pwordexp->we_wordv);
160 pwordexp->we_wordc = wordc;
161 pwordexp->we_wordv = wordv;
163 return 0;
165 lose:
167 int save;
168 save = errno;
169 (void) kill (pid, SIGKILL);
170 free (buf);
171 (void) waitpid (pid, (int *) NULL, 0);
172 errno = save;
173 return error;
178 void
179 DEFUN(wordexp, (pwordexp), wordexp_t *pwordexp)
181 /* All the other elts point into the first. */
182 free (pwordexp->we_wordv[0]);
183 free (pwordexp->we_wordv);