source: trunk/essentials/sys-apps/gawk/pc/popen.c

Last change on this file was 3076, checked in by bird, 18 years ago

gawk 3.1.5

File size: 5.5 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <io.h>
4#include <string.h>
5#include <process.h>
6
7#ifdef OS2
8#ifdef _MSC_VER
9#define popen(c,m) _popen(c,m)
10#define pclose(f) _pclose(f)
11#endif
12#endif
13
14#if defined(WIN32) && defined(_MSC_VER)
15#define popen _popen
16#define pclose _pclose
17#endif
18
19#ifndef _NFILE
20#define _NFILE 40
21#endif
22
23static char template[] = "piXXXXXX";
24static struct {
25 char *command;
26 char *name;
27 char pmode[4];
28} pipes[_NFILE];
29
30
31/*
32 * For systems where system() and popen() do not follow SHELL:
33 * 1. Write command to temp file. Temp filename must have slashes
34 * compatible with SHELL (if set) or COMSPEC.
35 * 2. Convert slashes in SHELL (if present) to be compatible with COMSPEC.
36 * Currently, only MSC (running under DOS) and MINGW versions are managed.
37 */
38
39#if defined(_MSC_VER) || defined(__MINGW32__)
40
41static int
42unixshell(char *p)
43{
44 static char *shell[] = {"sh", "bash", "csh", "tcsh", "sh32", "sh16", "ksh", NULL};
45 char **shellp = shell, *s, *q;
46
47 if (p == NULL) return (0);
48 s = p = strdup(p);
49 if ((q = strrchr(p, '\\')) != NULL)
50 p = q + 1;
51 if ((q = strrchr(p, '/')) != NULL)
52 p = q + 1;
53 if ((q = strchr(p, '.')) != NULL)
54 *q = '\0';
55 strlwr(p);
56 do {
57 if (strcmp(*shellp, p) == 0) break;
58 } while (*++shellp);
59 free(s);
60 return(*shellp ? 1 : 0);
61}
62
63static char *
64slashify(char *p, char *s)
65{
66 if (unixshell(s))
67 while (s = strchr(p, '\\')) *s = '/';
68 else
69 while (s = strchr(p, '/')) *s = '\\';
70 return(p);
71}
72
73static char *
74scriptify(char *command)
75{
76 FILE *fp;
77 char *cmd, *name, *s, *p;
78 int i;
79
80 if((name = tempnam(".", "pip")) == NULL) return(NULL);
81 p = getenv("COMSPEC"); s = getenv("SHELL");
82 cmd = malloc(strlen(name) + (s ? strlen(s) : 0) + 9); *cmd = '\0';
83 if (s) {
84 slashify(strcpy(cmd, s), p);
85 p = s;
86 }
87 slashify(name, p);
88 if (! (i = unixshell(p))) {
89 char *p = (char *) realloc(name, strlen(name) + 5);
90 if (p == NULL)
91 return NULL;
92 name = p;
93 strcat(name, ".bat");
94 }
95 if (s) sprintf(cmd + strlen(cmd), " %cc ", unixshell(s) ? '-' : '/');
96 strcpy(p = cmd + strlen(cmd), name); free(name);
97
98 if ((fp = fopen(p, i ? "wb" : "w")) != NULL) {
99 if (! i) fputs("@echo off\n", fp);
100 i = strlen(command);
101 if ((fwrite(command, 1, i, fp) < i) || (fputc('\n', fp) == EOF))
102 cmd = NULL;
103 } else
104 cmd = NULL;
105 if (fp) fclose(fp);
106 return(cmd);
107}
108
109static void
110unlink_and_free(char *cmd)
111{
112 char *s;
113
114 if (s = strrchr(cmd, ' '))
115 s++;
116 else
117 s = cmd;
118 unlink(s); free(cmd);
119}
120
121int
122os_system(char *cmd)
123{
124 char *s;
125 int i;
126
127#if defined(OS2)
128 if (_osmode == OS2_MODE)
129 return(system(cmd));
130#endif
131
132 if ((cmd = scriptify(cmd)) == NULL) return(1);
133 if (s = getenv("SHELL"))
134 i = spawnlp(P_WAIT, s, s, cmd + strlen(s), NULL);
135 else
136 i = system(cmd);
137 unlink_and_free(cmd);
138 return(i);
139}
140#else
141#define os_system(cmd) system(cmd)
142#endif
143
144
145FILE *
146os_popen( char *command, char *mode )
147{
148 FILE *current;
149 char *name;
150 int cur;
151 char curmode[4];
152
153#if defined(OS2) && (_MSC_VER != 510)
154 if (_osmode == OS2_MODE)
155 return(popen(command, mode));
156#endif
157
158 if (*mode != 'r' && *mode != 'w')
159 return NULL;
160 strncpy(curmode, mode, 3); curmode[3] = '\0';
161
162#if defined(__MINGW32__) || (defined(_MSC_VER) && defined(WIN32))
163 current = popen(command = scriptify(command), mode);
164 cur = fileno(current);
165 strcpy(pipes[cur].pmode, curmode);
166 pipes[cur].command = command;
167 return(current);
168#endif
169
170 /*
171 ** get a name to use.
172 */
173 if((name = tempnam(".","pip"))==NULL)
174 return NULL;
175 /*
176 ** If we're reading, just call system to get a file filled with
177 ** output.
178 */
179 if (*curmode == 'r') {
180 FILE *fp;
181 if ((cur = dup(fileno(stdout))) == -1)
182 return NULL;
183 *curmode = 'w';
184 if ((current = freopen(name, curmode, stdout)) == NULL)
185 return NULL;
186 os_system(command);
187 if (dup2(cur, fileno(stdout)) == -1)
188 return NULL;
189 close(cur);
190 *curmode = 'r';
191 if ((current = fopen(name, curmode)) == NULL)
192 return NULL;
193 } else {
194 if ((current = fopen(name, curmode)) == NULL)
195 return NULL;
196 }
197 cur = fileno(current);
198 pipes[cur].name = name;
199 strcpy(pipes[cur].pmode, curmode);
200 pipes[cur].command = strdup(command);
201 return current;
202}
203
204int
205os_pclose( FILE * current)
206{
207 int cur = fileno(current);
208 int fd, rval;
209
210#if defined(OS2) && (_MSC_VER != 510)
211 if (_osmode == OS2_MODE)
212 return(pclose(current));
213#endif
214
215#if defined(__MINGW32__) || (defined(_MSC_VER) && defined(WIN32))
216 rval = pclose(current);
217 *pipes[cur].pmode = '\0';
218 unlink_and_free(pipes[cur].command);
219 return rval;
220#endif
221
222 /*
223 ** check for an open file.
224 */
225 switch (*pipes[cur].pmode) {
226 case 'r':
227 /*
228 ** input pipes are just files we're done with.
229 */
230 rval = fclose(current);
231 unlink(pipes[cur].name);
232 break;
233 case 'w':
234 /*
235 ** output pipes are temporary files we have
236 ** to cram down the throats of programs.
237 */
238 fclose(current);
239 rval = -1;
240 if ((fd = dup(fileno(stdin))) != -1) {
241 char *mode = pipes[cur].pmode; *mode = 'r';
242 if (current = freopen(pipes[cur].name, mode, stdin)) {
243 rval = os_system(pipes[cur].command);
244 fclose(current);
245 if (dup2(fd, fileno(stdin)) == -1) rval = -1;
246 close(fd);
247 }
248 }
249 unlink(pipes[cur].name);
250 break;
251 default:
252 return -1;
253 }
254 /*
255 ** clean up current pipe.
256 */
257 *pipes[cur].pmode = '\0';
258 free(pipes[cur].name);
259 free(pipes[cur].command);
260 return rval;
261}
Note: See TracBrowser for help on using the repository browser.