1169695Skan/* Utilities to execute a program in a subprocess (possibly linked by pipes
2169695Skan   with other subprocesses), and wait for it.  DJGPP specialization.
3169695Skan   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005
4169695Skan   Free Software Foundation, Inc.
5169695Skan
6169695SkanThis file is part of the libiberty library.
7169695SkanLibiberty is free software; you can redistribute it and/or
8169695Skanmodify it under the terms of the GNU Library General Public
9169695SkanLicense as published by the Free Software Foundation; either
10169695Skanversion 2 of the License, or (at your option) any later version.
11169695Skan
12169695SkanLibiberty is distributed in the hope that it will be useful,
13169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
14169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15169695SkanLibrary General Public License for more details.
16169695Skan
17169695SkanYou should have received a copy of the GNU Library General Public
18169695SkanLicense along with libiberty; see the file COPYING.LIB.  If not,
19169695Skanwrite to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20169695SkanBoston, MA 02110-1301, USA.  */
21169695Skan
22169695Skan#include "pex-common.h"
23169695Skan
24169695Skan#include <stdio.h>
25169695Skan#include <errno.h>
26169695Skan#ifdef NEED_DECLARATION_ERRNO
27169695Skanextern int errno;
28169695Skan#endif
29169695Skan#ifdef HAVE_STDLIB_H
30169695Skan#include <stdlib.h>
31169695Skan#endif
32169695Skan#include <string.h>
33169695Skan#include <fcntl.h>
34169695Skan#include <unistd.h>
35169695Skan#include <sys/stat.h>
36169695Skan#include <process.h>
37169695Skan
38169695Skan/* Use ECHILD if available, otherwise use EINVAL.  */
39169695Skan#ifdef ECHILD
40169695Skan#define PWAIT_ERROR ECHILD
41169695Skan#else
42169695Skan#define PWAIT_ERROR EINVAL
43169695Skan#endif
44169695Skan
45169695Skanstatic int pex_djgpp_open_read (struct pex_obj *, const char *, int);
46169695Skanstatic int pex_djgpp_open_write (struct pex_obj *, const char *, int);
47169695Skanstatic long pex_djgpp_exec_child (struct pex_obj *, int, const char *,
48169695Skan				  char * const *, char * const *,
49169695Skan				  int, int, int, int,
50169695Skan				  const char **, int *);
51169695Skanstatic int pex_djgpp_close (struct pex_obj *, int);
52169695Skanstatic int pex_djgpp_wait (struct pex_obj *, long, int *, struct pex_time *,
53169695Skan			   int, const char **, int *);
54169695Skan
55169695Skan/* The list of functions we pass to the common routines.  */
56169695Skan
57169695Skanconst struct pex_funcs funcs =
58169695Skan{
59169695Skan  pex_djgpp_open_read,
60169695Skan  pex_djgpp_open_write,
61169695Skan  pex_djgpp_exec_child,
62169695Skan  pex_djgpp_close,
63169695Skan  pex_djgpp_wait,
64169695Skan  NULL, /* pipe */
65169695Skan  NULL, /* fdopenr */
66169695Skan  NULL, /* fdopenw */
67169695Skan  NULL  /* cleanup */
68169695Skan};
69169695Skan
70169695Skan/* Return a newly initialized pex_obj structure.  */
71169695Skan
72169695Skanstruct pex_obj *
73169695Skanpex_init (int flags, const char *pname, const char *tempbase)
74169695Skan{
75169695Skan  /* DJGPP does not support pipes.  */
76169695Skan  flags &= ~ PEX_USE_PIPES;
77169695Skan  return pex_init_common (flags, pname, tempbase, &funcs);
78169695Skan}
79169695Skan
80169695Skan/* Open a file for reading.  */
81169695Skan
82169695Skanstatic int
83169695Skanpex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED,
84169695Skan		     const char *name, int binary)
85169695Skan{
86169695Skan  return open (name, O_RDONLY | (binary ? O_BINARY : O_TEXT));
87169695Skan}
88169695Skan
89169695Skan/* Open a file for writing.  */
90169695Skan
91169695Skanstatic int
92169695Skanpex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED,
93169695Skan		      const char *name, int binary)
94169695Skan{
95169695Skan  /* Note that we can't use O_EXCL here because gcc may have already
96169695Skan     created the temporary file via make_temp_file.  */
97169695Skan  return open (name,
98169695Skan	       (O_WRONLY | O_CREAT | O_TRUNC
99169695Skan		| (binary ? O_BINARY : O_TEXT)),
100169695Skan	       S_IRUSR | S_IWUSR);
101169695Skan}
102169695Skan
103169695Skan/* Close a file.  */
104169695Skan
105169695Skanstatic int
106169695Skanpex_djgpp_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
107169695Skan{
108169695Skan  return close (fd);
109169695Skan}
110169695Skan
111169695Skan/* Execute a child.  */
112169695Skan
113169695Skanstatic long
114169695Skanpex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable,
115169695Skan		      char * const * argv, char * const * env,
116169695Skan                      int in, int out, int errdes,
117169695Skan		      int toclose ATTRIBUTE_UNUSED, const char **errmsg,
118169695Skan		      int *err)
119169695Skan{
120169695Skan  int org_in, org_out, org_errdes;
121169695Skan  int status;
122169695Skan  int *statuses;
123169695Skan
124169695Skan  org_in = -1;
125169695Skan  org_out = -1;
126169695Skan  org_errdes = -1;
127169695Skan
128169695Skan  if (in != STDIN_FILE_NO)
129169695Skan    {
130169695Skan      org_in = dup (STDIN_FILE_NO);
131169695Skan      if (org_in < 0)
132169695Skan	{
133169695Skan	  *err = errno;
134169695Skan	  *errmsg = "dup";
135169695Skan	  return -1;
136169695Skan	}
137169695Skan      if (dup2 (in, STDIN_FILE_NO) < 0)
138169695Skan	{
139169695Skan	  *err = errno;
140169695Skan	  *errmsg = "dup2";
141169695Skan	  return -1;
142169695Skan	}
143169695Skan      if (close (in) < 0)
144169695Skan	{
145169695Skan	  *err = errno;
146169695Skan	  *errmsg = "close";
147169695Skan	  return -1;
148169695Skan	}
149169695Skan    }
150169695Skan
151169695Skan  if (out != STDOUT_FILE_NO)
152169695Skan    {
153169695Skan      org_out = dup (STDOUT_FILE_NO);
154169695Skan      if (org_out < 0)
155169695Skan	{
156169695Skan	  *err = errno;
157169695Skan	  *errmsg = "dup";
158169695Skan	  return -1;
159169695Skan	}
160169695Skan      if (dup2 (out, STDOUT_FILE_NO) < 0)
161169695Skan	{
162169695Skan	  *err = errno;
163169695Skan	  *errmsg = "dup2";
164169695Skan	  return -1;
165169695Skan	}
166169695Skan      if (close (out) < 0)
167169695Skan	{
168169695Skan	  *err = errno;
169169695Skan	  *errmsg = "close";
170169695Skan	  return -1;
171169695Skan	}
172169695Skan    }
173169695Skan
174169695Skan  if (errdes != STDERR_FILE_NO
175169695Skan      || (flags & PEX_STDERR_TO_STDOUT) != 0)
176169695Skan    {
177169695Skan      org_errdes = dup (STDERR_FILE_NO);
178169695Skan      if (org_errdes < 0)
179169695Skan	{
180169695Skan	  *err = errno;
181169695Skan	  *errmsg = "dup";
182169695Skan	  return -1;
183169695Skan	}
184169695Skan      if (dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes,
185169695Skan		 STDERR_FILE_NO) < 0)
186169695Skan	{
187169695Skan	  *err = errno;
188169695Skan	  *errmsg = "dup2";
189169695Skan	  return -1;
190169695Skan	}
191169695Skan      if (errdes != STDERR_FILE_NO)
192169695Skan	{
193169695Skan	  if (close (errdes) < 0)
194169695Skan	    {
195169695Skan	      *err = errno;
196169695Skan	      *errmsg = "close";
197169695Skan	      return -1;
198169695Skan	    }
199169695Skan	}
200169695Skan    }
201169695Skan
202169695Skan  if (env)
203169695Skan    status = (((flags & PEX_SEARCH) != 0 ? spawnvpe : spawnve)
204169695Skan	      (P_WAIT, executable, argv, env));
205169695Skan  else
206169695Skan    status = (((flags & PEX_SEARCH) != 0 ? spawnvp : spawnv)
207169695Skan  	      (P_WAIT, executable, argv));
208169695Skan
209169695Skan  if (status == -1)
210169695Skan    {
211169695Skan      *err = errno;
212169695Skan      *errmsg = ((flags & PEX_SEARCH) != 0) ? "spawnvp" : "spawnv";
213169695Skan    }
214169695Skan
215169695Skan  if (in != STDIN_FILE_NO)
216169695Skan    {
217169695Skan      if (dup2 (org_in, STDIN_FILE_NO) < 0)
218169695Skan	{
219169695Skan	  *err = errno;
220169695Skan	  *errmsg = "dup2";
221169695Skan	  return -1;
222169695Skan	}
223169695Skan      if (close (org_in) < 0)
224169695Skan	{
225169695Skan	  *err = errno;
226169695Skan	  *errmsg = "close";
227169695Skan	  return -1;
228169695Skan	}
229169695Skan    }
230169695Skan
231169695Skan  if (out != STDOUT_FILE_NO)
232169695Skan    {
233169695Skan      if (dup2 (org_out, STDOUT_FILE_NO) < 0)
234169695Skan	{
235169695Skan	  *err = errno;
236169695Skan	  *errmsg = "dup2";
237169695Skan	  return -1;
238169695Skan	}
239169695Skan      if (close (org_out) < 0)
240169695Skan	{
241169695Skan	  *err = errno;
242169695Skan	  *errmsg = "close";
243169695Skan	  return -1;
244169695Skan	}
245169695Skan    }
246169695Skan
247169695Skan  if (errdes != STDERR_FILE_NO
248169695Skan      || (flags & PEX_STDERR_TO_STDOUT) != 0)
249169695Skan    {
250169695Skan      if (dup2 (org_errdes, STDERR_FILE_NO) < 0)
251169695Skan	{
252169695Skan	  *err = errno;
253169695Skan	  *errmsg = "dup2";
254169695Skan	  return -1;
255169695Skan	}
256169695Skan      if (close (org_errdes) < 0)
257169695Skan	{
258169695Skan	  *err = errno;
259169695Skan	  *errmsg = "close";
260169695Skan	  return -1;
261169695Skan	}
262169695Skan    }
263169695Skan
264169695Skan  /* Save the exit status for later.  When we are called, obj->count
265169695Skan     is the number of children which have executed before this
266169695Skan     one.  */
267169695Skan  statuses = (int *) obj->sysdep;
268169695Skan  statuses = XRESIZEVEC (int, statuses, obj->count + 1);
269169695Skan  statuses[obj->count] = status;
270169695Skan  obj->sysdep = (void *) statuses;
271169695Skan
272169695Skan  return obj->count;
273169695Skan}
274169695Skan
275169695Skan/* Wait for a child process to complete.  Actually the child process
276169695Skan   has already completed, and we just need to return the exit
277169695Skan   status.  */
278169695Skan
279169695Skanstatic int
280169695Skanpex_djgpp_wait (struct pex_obj *obj, long pid, int *status,
281169695Skan		struct pex_time *time, int done ATTRIBUTE_UNUSED,
282169695Skan		const char **errmsg ATTRIBUTE_UNUSED,
283169695Skan		int *err ATTRIBUTE_UNUSED)
284169695Skan{
285169695Skan  int *statuses;
286169695Skan
287169695Skan  if (time != NULL)
288169695Skan    memset (time, 0, sizeof *time);
289169695Skan
290169695Skan  statuses = (int *) obj->sysdep;
291169695Skan  *status = statuses[pid];
292169695Skan
293169695Skan  return 0;
294169695Skan}
295