Commit | Line | Data |
---|---|---|
ca2dddd6 C |
1 | /* added real/protect mode branch at runtime and real mode version |
2 | * names changed for perl | |
3 | * Kai Uwe Rommel | |
4 | */ | |
5 | ||
6 | /* | |
7 | Several people in the past have asked about having Unix-like pipe | |
8 | calls in OS/2. The following source file, adapted from 4.3 BSD Unix, | |
9 | uses a #define to give you a pipe(2) call, and contains function | |
10 | definitions for popen(3) and pclose(3). Anyone with problems should | |
11 | send mail to me; they seem to work fine. | |
12 | ||
13 | Mark Towfigh | |
14 | Racal Interlan, Inc. | |
15 | ----------------------------------cut-here------------------------------------ | |
16 | */ | |
17 | ||
18 | /* | |
19 | * The following code segment is derived from BSD 4.3 Unix. See | |
20 | * copyright below. Any bugs, questions, improvements, or problems | |
21 | * should be sent to Mark Towfigh (towfiq@interlan.interlan.com). | |
22 | * | |
23 | * Racal InterLan Inc. | |
24 | */ | |
25 | ||
26 | /* | |
27 | * Copyright (c) 1980 Regents of the University of California. | |
28 | * All rights reserved. The Berkeley software License Agreement | |
29 | * specifies the terms and conditions for redistribution. | |
30 | */ | |
31 | ||
32 | #include <stdio.h> | |
33 | #include <stdlib.h> | |
34 | #include <io.h> | |
35 | #include <string.h> | |
36 | #include <process.h> | |
37 | #include <errno.h> | |
38 | ||
39 | #define INCL_NOPM | |
40 | #define INCL_DOS | |
41 | #include <os2.h> | |
42 | ||
43 | static FILE *dos_popen(const char *cmd, const char *flags); | |
44 | static int dos_pclose(FILE *pipe); | |
45 | ||
46 | /* | |
47 | * emulate Unix pipe(2) call | |
48 | */ | |
49 | ||
50 | #define tst(a,b) (*mode == 'r'? (b) : (a)) | |
51 | #define READH 0 | |
52 | #define WRITEH 1 | |
53 | ||
54 | static int popen_pid[20]; | |
55 | ||
56 | FILE *mypopen(char *cmd, char *mode) | |
57 | { | |
58 | int p[2]; | |
59 | register myside, hisside, save_stream; | |
60 | char *shell = getenv("COMPSPEC"); | |
61 | ||
62 | if ( shell == NULL ) | |
63 | shell = "C:\\OS2\\CMD.EXE"; | |
64 | ||
65 | if ( _osmode == DOS_MODE ) | |
66 | return dos_popen(cmd, mode); | |
67 | ||
68 | if ( _pipe(p, 4096, 0) ) | |
69 | return NULL; | |
70 | ||
71 | myside = tst(p[WRITEH], p[READH]); | |
72 | hisside = tst(p[READH], p[WRITEH]); | |
73 | ||
74 | /* set up file descriptors for remote function */ | |
75 | save_stream = dup(tst(0, 1)); /* don't lose stdin/out! */ | |
76 | if (dup2(hisside, tst(0, 1)) < 0) | |
77 | { | |
78 | perror("dup2"); | |
79 | return NULL; | |
80 | } | |
81 | close(hisside); | |
82 | ||
83 | /* | |
84 | * make sure that we can close our side of the pipe, by | |
85 | * preventing it from being inherited! | |
86 | */ | |
87 | ||
88 | /* set no-inheritance flag */ | |
89 | DosSetFHandState(myside, OPEN_FLAGS_NOINHERIT); | |
90 | ||
91 | /* execute the command: it will inherit our other file descriptors */ | |
92 | popen_pid[myside] = spawnlp(P_NOWAIT, shell, shell, "/C", cmd, NULL); | |
93 | ||
94 | /* now restore our previous file descriptors */ | |
95 | if (dup2(save_stream, tst(0, 1)) < 0) /* retrieve stdin/out */ | |
96 | { | |
97 | perror("dup2"); | |
98 | return NULL; | |
99 | } | |
100 | close(save_stream); | |
101 | ||
102 | return fdopen(myside, mode); /* return a FILE pointer */ | |
103 | } | |
104 | ||
105 | int mypclose(FILE *ptr) | |
106 | { | |
107 | register f; | |
108 | int status; | |
109 | ||
110 | if ( _osmode == DOS_MODE ) | |
111 | return dos_pclose(ptr); | |
112 | ||
113 | f = fileno(ptr); | |
114 | fclose(ptr); | |
115 | ||
116 | /* wait for process to terminate */ | |
117 | cwait(&status, popen_pid[f], WAIT_GRANDCHILD); | |
118 | ||
119 | return status; | |
120 | } | |
121 | ||
122 | ||
123 | int pipe(int *filedes) | |
124 | { | |
125 | int res; | |
126 | ||
127 | if ( res = _pipe(filedes, 4096, 0) ) | |
128 | return res; | |
129 | ||
130 | DosSetFHandState(filedes[0], OPEN_FLAGS_NOINHERIT); | |
131 | DosSetFHandState(filedes[1], OPEN_FLAGS_NOINHERIT); | |
132 | return 0; | |
133 | } | |
134 | ||
135 | ||
136 | /* this is the MS-DOS version */ | |
137 | ||
138 | typedef enum { unopened = 0, reading, writing } pipemode; | |
139 | ||
140 | static struct | |
141 | { | |
142 | char *name; | |
143 | char *command; | |
144 | pipemode pmode; | |
145 | } | |
146 | pipes[_NFILE]; | |
147 | ||
148 | static FILE *dos_popen(const char *command, const char *mode) | |
149 | { | |
150 | FILE *current; | |
151 | char name[128]; | |
152 | char *tmp = getenv("TMP"); | |
153 | int cur; | |
154 | pipemode curmode; | |
155 | ||
156 | /* | |
157 | ** decide on mode. | |
158 | */ | |
159 | if(strchr(mode, 'r') != NULL) | |
160 | curmode = reading; | |
161 | else if(strchr(mode, 'w') != NULL) | |
162 | curmode = writing; | |
163 | else | |
164 | return NULL; | |
165 | ||
166 | /* | |
167 | ** get a name to use. | |
168 | */ | |
169 | strcpy(name, tmp ? tmp : "\\"); | |
170 | if ( name[strlen(name) - 1] != '\\' ) | |
171 | strcat(name, "\\"); | |
172 | strcat(name, "piXXXXXX"); | |
173 | mktemp(name); | |
174 | ||
175 | /* | |
176 | ** If we're reading, just call system to get a file filled with | |
177 | ** output. | |
178 | */ | |
179 | if(curmode == reading) | |
180 | { | |
181 | char cmd[256]; | |
182 | sprintf(cmd,"%s > %s", command, name); | |
183 | system(cmd); | |
184 | ||
185 | if((current = fopen(name, mode)) == NULL) | |
186 | return NULL; | |
187 | } | |
188 | else | |
189 | { | |
190 | if((current = fopen(name, mode)) == NULL) | |
191 | return NULL; | |
192 | } | |
193 | ||
194 | cur = fileno(current); | |
195 | pipes[cur].name = strdup(name); | |
196 | pipes[cur].command = strdup(command); | |
197 | pipes[cur].pmode = curmode; | |
198 | ||
199 | return current; | |
200 | } | |
201 | ||
202 | static int dos_pclose(FILE * current) | |
203 | { | |
204 | int cur = fileno(current), rval; | |
205 | char command[256]; | |
206 | ||
207 | /* | |
208 | ** check for an open file. | |
209 | */ | |
210 | if(pipes[cur].pmode == unopened) | |
211 | return -1; | |
212 | ||
213 | if(pipes[cur].pmode == reading) | |
214 | { | |
215 | /* | |
216 | ** input pipes are just files we're done with. | |
217 | */ | |
218 | rval = fclose(current); | |
219 | unlink(pipes[cur].name); | |
220 | } | |
221 | else | |
222 | { | |
223 | /* | |
224 | ** output pipes are temporary files we have | |
225 | ** to cram down the throats of programs. | |
226 | */ | |
227 | fclose(current); | |
228 | sprintf(command,"%s < %s", pipes[cur].command, pipes[cur].name); | |
229 | rval = system(command); | |
230 | unlink(pipes[cur].name); | |
231 | } | |
232 | ||
233 | /* | |
234 | ** clean up current pipe. | |
235 | */ | |
236 | free(pipes[cur].name); | |
237 | free(pipes[cur].command); | |
238 | pipes[cur].pmode = unopened; | |
239 | ||
240 | return rval; | |
241 | } |