Fix typo.
[glibc/history.git] / posix / wordexp.c
blob52869fe1d39a156f69c9737751a69222db695d1a
1 /* Copyright (C) 1992, 1997 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 not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #include <sys/types.h>
20 #include <wordexp.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <sys/wait.h>
24 #include <signal.h>
27 /* We do word expansion with a pipe to the shell.
28 The shell command `sh [-P] [-u] -w "words ..."' expands words.
29 If -P, command substitution is an error.
30 If -u, reference to an undefined variable is an error.
31 The shell writes on its stdout:
32 %u\0 Number of words.
33 %u\0 Number of bytes in all words together (not counting \0s).
34 word1\0
35 word2\0
36 ...
37 wordN\0
40 #define SHELL_PATH "/bin/sh"
41 #define SHELL_NAME "sh"
44 int
45 wordexp (string, pwordexp, flags)
46 const char *string;
47 wordexp_t *pwordexp;
48 int flags;
50 int error;
51 pid_t pid;
52 int d[2];
53 int status;
55 FILE *f;
56 size_t wordc, start, buflen;
57 char *buf;
59 /* Create the pipe through which we will communicate to the shell. */
60 if (pipe (d) < 0)
61 return -1;
63 pid = fork ();
64 if (pid < 0)
65 return -1;
67 if (pid == 0)
69 /* Child. Run the shell. */
71 const char *argv[5];
73 close (d[STDIN_FILENO]);
74 dup2 (d[STDOUT_FILENO], STDOUT_FILENO);
75 if (!(flags & WRDE_SHOWERR))
76 close (STDERR_FILENO);
78 i = 0;
79 argv[i++] = SHELL_NAME;
80 if (flags & WRDE_NOCMD)
81 argv[i++] = "-P";
82 if (flags & WRDE_UNDEF)
83 argv[i++] = "-u";
84 argv[i++] = "-w";
85 argv[i++] = string;
86 argv[i++] = NULL;
88 execv (SHELL_PATH, argv);
89 _exit (WRDE_NOSPACE);
92 /* Parent. */
94 buf = NULL;
95 error = WRDE_NOSPACE;
97 close (d[STDOUT_FILENO]);
98 f = fdopen (d[STDIN_FILENO]);
99 if (f == NULL)
100 goto lose;
102 /* Read the number of words and number of bytes from the shell. */
103 if (fscanf (f, "%u", &wordc) != 1 || getc (f) != '\0' ||
104 fscanf (f, "%u", &buflen) != 1 || getc (f) != '\0')
105 goto lose;
107 /* Read the words from the shell, and wait for it to return. */
108 buflen += wordc;
109 buf = malloc (buflen);
110 if (buf == NULL ||
111 fread (buf, buflen, 1, f) != 1 ||
112 waitpid (pid, &status, 0) != pid)
113 goto lose;
115 if (WIFEXITED (status))
117 if (WEXITSTATUS (status) != 0)
119 error = WEXITSTATUS (status);
120 goto lose;
123 else
124 goto lose;
126 /* Pack the structure. */
128 start = 0;
129 if (flags & WRDE_DOOFFS)
130 start += pwordexp->we_offs;
131 if (flags & WRDE_APPEND)
132 start += pwordexp->we_wordc;
133 wordc = start + wordc + 1;
135 if (flags & WRDE_APPEND)
136 wordv = (char **) realloc ((void *) pwordexp->we_wordv,
137 wordc * sizeof (char *));
138 else
139 wordv = (char **) malloc (wordc * sizeof (char *));
140 if (wordv == NULL)
141 goto lose;
143 if (flags & WRDE_DOOFFS)
144 for (i = 0; i < pwordexp->we_offs; ++i)
145 wordv[i] = NULL;
147 for (i = start; i < wordc; ++i)
149 pwordexp->we_wordv[i] = buf;
150 buf = strchr (buf, '\0') + 1;
152 wordv[i] = NULL;
154 if (flags & WRDE_REUSE)
156 free (pwordexp->we_wordv[0]);
157 if (!(flags & WRDE_APPEND))
158 free (pwordexp->we_wordv);
161 pwordexp->we_wordc = wordc;
162 pwordexp->we_wordv = wordv;
164 return 0;
166 lose:
168 int save;
169 save = errno;
170 (void) kill (pid, SIGKILL);
171 free (buf);
172 (void) waitpid (pid, (int *) NULL, 0);
173 errno = save;
174 return error;
179 void
180 DEFUN(wordexp, (pwordexp), wordexp_t *pwordexp)
182 /* All the other elts point into the first. */
183 free (pwordexp->we_wordv[0]);
184 free (pwordexp->we_wordv);