1 /* @(#)spawn.c 1.30 15/07/06 Copyright 1985, 1989, 1995-2015 J. Schilling */
2 /*
3 * Spawn another process/ wait for child process
4 *
5 * Copyright (c) 1985, 1989, 1995-2015 J. Schilling
6 *
7 * This is an interface that exists in the public since 1982.
8 * The POSIX.1-2008 standard did ignore POSIX rules not to
9 * redefine existing public interfaces and redefined the interfaces
10 * forcing us to add a js_*() prefix to the original functions.
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #ifndef __DO__FSPAWNL__
27 #define fspawnv __no__fspawnv__
28 #define fspawnl __no__fspawnl__
29 #define fspawnv_nowait __no__fspawnv_nowait__
30
31 #include <schily/mconfig.h>
32 #include <schily/stdio.h>
33 #include <schily/standard.h>
34 #include <schily/unistd.h>
35 #include <schily/stdlib.h>
36 #include <schily/varargs.h>
37 #include <schily/wait.h>
38 #include <schily/errno.h>
39 #include <schily/schily.h>
40 #define VMS_VFORK_OK
41 #include <schily/vfork.h>
42 #endif /* __DO__FSPAWNL__ */
43
44 #define MAX_F_ARGS 16
45
46 #ifndef __DO__FSPAWNL__
47 #ifndef NO_FSPAWN_COMPAT /* Define to disable backward compatibility */
48 #undef fspawnv
49 #undef fspawnl
50 #undef fspawnv_nowait
51
52 /*
53 * The Cygwin compile environment incorrectly implements #pragma weak.
54 * The weak symbols are only defined as local symbols making it impossible
55 * to use them from outside the scope of this source file.
56 * A platform that allows linking with global symbols has HAVE_LINK_WEAK
57 * defined.
58 */
59 #if defined(HAVE_PRAGMA_WEAK) && defined(HAVE_LINK_WEAK)
60 #pragma weak fspawnv = js_fspawnv
61 #pragma weak fspawnl = js_fspawnl
62 #pragma weak fspawnv_nowait = js_fspawnv_nowait
63 #else
64
65 EXPORT int fspawnv __PR((FILE *, FILE *, FILE *, int, char * const *));
66 EXPORT int fspawnl __PR((FILE *, FILE *, FILE *, const char *, ...));
67 EXPORT int fspawnv_nowait __PR((FILE *, FILE *, FILE *,
68 const char *, int, char *const*));
69 EXPORT int
fspawnv(in,out,err,argc,argv)70 fspawnv(in, out, err, argc, argv)
71 FILE *in;
72 FILE *out;
73 FILE *err;
74 int argc;
75 char * const argv[];
76 {
77 return (js_fspawnv(in, out, err, argc, argv));
78 }
79
80 EXPORT int
fspawnv_nowait(in,out,err,name,argc,argv)81 fspawnv_nowait(in, out, err, name, argc, argv)
82 FILE *in;
83 FILE *out;
84 FILE *err;
85 const char *name;
86 int argc;
87 char * const argv[];
88 {
89 return (js_fspawnv_nowait(in, out, err, name, argc, argv));
90 }
91
92 #define __DO__FSPAWNL__
93 #define js_fspawnl fspawnl
94 #include "spawn.c"
95 #undef js_fspawnl
96 #undef __DO__FSPAWNL__
97
98 #endif /* HAVE_PRAGMA_WEAK && HAVE_LINK_WEAK */
99 #endif /* NO_FSPAWN_COMPAT */
100
101 EXPORT int
js_fspawnv(in,out,err,argc,argv)102 js_fspawnv(in, out, err, argc, argv)
103 FILE *in;
104 FILE *out;
105 FILE *err;
106 int argc;
107 char * const argv[];
108 {
109 int pid;
110
111 if ((pid = js_fspawnv_nowait(in, out, err, argv[0], argc, argv)) < 0)
112 return (pid);
113
114 return (wait_chld(pid));
115 }
116 #endif /* __DO__FSPAWNL__ */
117
118 /* VARARGS3 */
119 #ifdef PROTOTYPES
120 EXPORT int
js_fspawnl(FILE * in,FILE * out,FILE * err,const char * arg0,...)121 js_fspawnl(FILE *in, FILE *out, FILE *err, const char *arg0, ...)
122 #else
123 EXPORT int
124 js_fspawnl(in, out, err, arg0, va_alist)
125 FILE *in;
126 FILE *out;
127 FILE *err;
128 const char *arg0;
129 va_dcl
130 #endif
131 {
132 va_list args;
133 int ac = 0;
134 char *xav[MAX_F_ARGS+1];
135 char **av;
136 const char **pav;
137 char *p;
138 int ret;
139
140 #ifdef PROTOTYPES
141 va_start(args, arg0);
142 #else
143 va_start(args);
144 #endif
145 if (arg0) {
146 ac++;
147 while (va_arg(args, char *) != NULL)
148 ac++;
149 }
150 va_end(args);
151
152 if (ac <= MAX_F_ARGS) {
153 av = xav;
154 } else {
155 av = (char **)malloc((ac+1)*sizeof (char *));
156 if (av == 0)
157 return (-1);
158 }
159 pav = (const char **)av;
160
161 #ifdef PROTOTYPES
162 va_start(args, arg0);
163 #else
164 va_start(args);
165 #endif
166 *pav++ = arg0;
167 if (arg0) do {
168 p = va_arg(args, char *);
169 *pav++ = p;
170 } while (p != NULL);
171 va_end(args);
172
173 ret = js_fspawnv(in, out, err, ac, av);
174 if (av != xav)
175 free(av);
176 return (ret);
177 }
178
179 #ifndef __DO__FSPAWNL__
180 EXPORT int
js_fspawnv_nowait(in,out,err,name,argc,argv)181 js_fspawnv_nowait(in, out, err, name, argc, argv)
182 FILE *in;
183 FILE *out;
184 FILE *err;
185 const char *name;
186 int argc;
187 char * const argv[];
188 {
189 int pid = -1; /* Initialization needed to make GCC happy */
190 volatile int i;
191
192 for (i = 1; i < 64; i *= 2) {
193 if ((pid = vfork()) >= 0)
194 break;
195 sleep(i);
196 }
197 if (pid != 0)
198 return (pid);
199 /*
200 * silly: fexecv must set av[ac] = NULL
201 * so we have to cast argv tp (char **)
202 */
203 fexecv(name, in, out, err, argc, (char **)argv);
204 _exit(geterrno());
205 /* NOTREACHED */
206 #ifndef lint
207 return (0); /* keep gnu compiler happy */
208 #endif
209 }
210
211 EXPORT int
wait_chld(pid)212 wait_chld(pid)
213 int pid;
214 {
215 int died;
216 WAIT_T status;
217
218 do {
219 do {
220 died = wait(&status);
221 } while (died < 0 && geterrno() == EINTR);
222 if (died < 0)
223 return (died);
224 } while (died != pid);
225
226 if (WCOREDUMP(status))
227 unlink("core");
228
229 if (WIFEXITED(status))
230 return (WEXITSTATUS(status));
231 return (-WTERMSIG(status));
232 }
233 #endif /* __DO__FSPAWNL__ */
234