BSD 4_4_Lite2 development
[unix-history] / usr / src / contrib / perl-4.036 / os2 / popen.c
CommitLineData
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/*
7Several people in the past have asked about having Unix-like pipe
8calls in OS/2. The following source file, adapted from 4.3 BSD Unix,
9uses a #define to give you a pipe(2) call, and contains function
10definitions for popen(3) and pclose(3). Anyone with problems should
11send mail to me; they seem to work fine.
12
13Mark Towfigh
14Racal 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
43static FILE *dos_popen(const char *cmd, const char *flags);
44static 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
54static int popen_pid[20];
55
56FILE *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
105int 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
123int 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
138typedef enum { unopened = 0, reading, writing } pipemode;
139
140static struct
141{
142 char *name;
143 char *command;
144 pipemode pmode;
145}
146pipes[_NFILE];
147
148static 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
202static 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}