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