Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / librols / spawn.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)spawn.c  1.17 04/09/25 Copyright 1985, 1989, 1995-2003 J. Schilling */
14 /*
15  *      Spawn another process/ wait for child process
16  *
17  *      Copyright (c) 1985, 1989, 1995-2003 J. Schilling
18  */
19 /*
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License version 2
22  * as published by the Free Software Foundation.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License along with
30  * this program; see the file COPYING.  If not, write to the Free Software
31  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32  */
33
34 #include <mconfig.h>
35 #include <stdio.h>
36 #include <standard.h>
37 #define fspawnl __nothing__     /* prototype in schily.h is wrong */
38 #define spawnl  __nothing__     /* prototype in schily.h is wrong */
39 #include <schily.h>
40 #undef  fspawnl
41 #undef  spawnl
42 #include <unixstd.h>
43 #include <stdxlib.h>
44 #include <vadefs.h>
45 #include <waitdefs.h>
46 #include <errno.h>
47
48 #define MAX_F_ARGS      16
49
50 EXPORT  int     fspawnl __PR((FILE *, FILE *, FILE *, ...));
51
52 EXPORT int
53 fspawnv(in, out, err, argc, argv)
54         FILE    *in;
55         FILE    *out;
56         FILE    *err;
57         int     argc;
58         char    * const argv[];
59 {
60         int     pid;
61
62         if ((pid = fspawnv_nowait(in, out, err, argv[0], argc, argv)) < 0)
63                 return (pid);
64
65         return (wait_chld(pid));
66 }
67
68 /* VARARGS3 */
69 #ifdef  PROTOTYPES
70 EXPORT int
71 fspawnl(FILE *in, FILE *out, FILE *err, ...)
72 #else
73 EXPORT int
74 fspawnl(in, out, err, va_alist)
75         FILE    *in;
76         FILE    *out;
77         FILE    *err;
78         va_dcl
79 #endif
80 {
81         va_list args;
82         int     ac = 0;
83         char    *xav[MAX_F_ARGS];
84         char    **av;
85         char    **pav;
86         char    *p;
87         int     ret;
88
89 #ifdef  PROTOTYPES
90         va_start(args, err);
91 #else
92         va_start(args);
93 #endif
94         while (va_arg(args, char *) != NULL)
95                 ac++;
96         va_end(args);
97
98         if (ac < MAX_F_ARGS) {
99                 pav = av = xav;
100         } else {
101                 pav = av = (char **)malloc((ac+1)*sizeof (char *));
102                 if (av == 0)
103                         return (-1);
104         }
105
106 #ifdef  PROTOTYPES
107         va_start(args, err);
108 #else
109         va_start(args);
110 #endif
111         do {
112                 p = va_arg(args, char *);
113                 *pav++ = p;
114         } while (p != NULL);
115         va_end(args);
116
117         ret =  fspawnv(in, out, err, ac, av);
118         if (av != xav)
119                 free(av);
120         return (ret);
121 }
122
123 EXPORT int
124 fspawnv_nowait(in, out, err, name, argc, argv)
125         FILE            *in;
126         FILE            *out;
127         FILE            *err;
128         const char      *name;
129         int             argc;
130         char            * const argv[];
131 {
132         int     pid = -1;       /* Initialization needed to make GCC happy */
133         int     i;
134
135         for (i = 1; i < 64; i *= 2) {
136                 if ((pid = fork()) >= 0)
137                         break;
138                 sleep(i);
139         }
140         if (pid != 0)
141                 return (pid);
142                                 /*
143                                  * silly: fexecv must set av[ac] = NULL
144                                  * so we have to cast argv tp (char **)
145                                  */
146         rols_fexecv(name, in, out, err, argc, (char **)argv);
147         exit(geterrno());
148         /* NOTREACHED */
149 }
150
151 EXPORT int
152 wait_chld(pid)
153         int     pid;
154 {
155         int     died;
156         WAIT_T  status;
157
158         do {
159                 do {
160                         died = wait(&status);
161                 } while (died < 0 && geterrno() == EINTR);
162                 if (died < 0)
163                         return (died);
164         } while (died != pid);
165
166         if (WCOREDUMP(status))
167                 unlink("core");
168
169         return (WEXITSTATUS(status));
170 }