1 Blake sent me the wrong one.
2
3 /* RCS $Id: runargv.c,v 1.2 2007-10-15 15:58:54 ihi Exp $
4 --
5 -- SYNOPSIS
6 -- Invoke a sub process.
7 --
8 -- DESCRIPTION
9 -- Use the standard methods of executing a sub process.
10 --
11 -- AUTHOR
12 -- Dennis Vadura, dvadura@dmake.wticorp.com
13 --
14 -- WWW
15 -- http://dmake.wticorp.com/
16 --
17 -- COPYRIGHT
18 -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
19 --
20 -- This program is NOT free software; you can redistribute it and/or
21 -- modify it under the terms of the Software License Agreement Provided
22 -- in the file <distribution-root>/COPYING.
23 --
24 -- LOG
25 -- Use cvs log to obtain detailed change logs.
26 */
27
28 #include <process.h>
29 #include <errno.h>
30 #include <signal.h>
31 #include "extern.h"
32 #include "sysintf.h"
33
34 extern char **environ;
35
36 typedef struct prp {
37 char *prp_cmd;
38 int prp_group;
39 int prp_ignore;
40 int prp_last;
41 int prp_shell;
42 struct prp *prp_next;
43 } RCP, *RCPPTR;
44
45 typedef struct pr {
46 int pr_valid;
47 int pr_pid;
48 CELLPTR pr_target;
49 int pr_ignore;
50 int pr_last;
51 RCPPTR pr_recipe;
52 RCPPTR pr_recipe_end;
53 char *pr_dir;
54 } PR;
55
56 static PR *_procs = NIL(PR);
57 static int _proc_cnt = 0;
58 static int _abort_flg= FALSE;
59 static int _use_i = -1;
60 static int _do_upd = 0;
61
62 static void _add_child ANSI((int, CELLPTR, int, int));
63 static void _attach_cmd ANSI((char *, int, int, CELLPTR, int, int));
64 static void _finished_child ANSI((int, int));
65 static int _running ANSI((CELLPTR));
66
67 PUBLIC int
runargv(target,ignore,group,last,shell,cmd)68 runargv(target, ignore, group, last, shell, cmd)
69 CELLPTR target;
70 int ignore;
71 int group;
72 int last;
73 int shell;
74 char *cmd;
75 {
76 extern int errno;
77 extern char *sys_errlist[];
78 int pid;
79 char **argv;
80
81 if( _running(target) /*&& Max_proc != 1*/ ) {
82 /* The command will be executed when the previous recipe
83 * line completes. */
84 _attach_cmd( cmd, group, ignore, target, last, shell );
85 return(1);
86 }
87
88 while( _proc_cnt == Max_proc )
89 if( Wait_for_child(FALSE, -1) == -1 ) Fatal( "Lost a child %d", errno );
90
91 argv = Pack_argv( group, shell, cmd );
92
93 pid = _spawnvpe(_P_NOWAIT, argv[0], argv, environ);
94 if (pid == -1) { /* failed */
95 Error("%s: %s", argv[0], sys_errlist[errno]);
96 Handle_result(-1, ignore, _abort_flg, target);
97 return(-1);
98 } else
99 _add_child(pid, target, ignore, last);
100
101 return(1);
102 }
103
104
105 PUBLIC int
Wait_for_child(abort_flg,pid)106 Wait_for_child( abort_flg, pid )
107 int abort_flg;
108 int pid;
109 {
110 int wid;
111 int status;
112 int waitchild;
113
114 waitchild = (pid == -1)? FALSE : Wait_for_completion;
115
116 do {
117 if( (wid = wait(&status)) == -1 ) return(-1);
118
119 _abort_flg = abort_flg;
120 _finished_child(wid, status);
121 _abort_flg = FALSE;
122 } while( waitchild && pid != wid );
123
124 return(0);
125 }
126
127
128 PUBLIC void
Clean_up_processes()129 Clean_up_processes()
130 {
131 int i;
132
133 if( _procs != NIL(PR) ) {
134 for( i=0; i<Max_proc; i++ )
135 if( _procs[i].pr_valid )
136 kill(_procs[i].pr_pid, SIGTERM);
137
138 while( Wait_for_child(TRUE, -1) != -1 );
139 }
140 }
141
142
143 static void
_add_child(pid,target,ignore,last)144 _add_child( pid, target, ignore, last )
145 int pid;
146 CELLPTR target;
147 int ignore;
148 int last;
149 {
150 register int i;
151 register PR *pp;
152
153 if( _procs == NIL(PR) ) {
154 TALLOC( _procs, Max_proc, PR );
155 }
156
157 if( (i = _use_i) == -1 )
158 for( i=0; i<Max_proc; i++ )
159 if( !_procs[i].pr_valid )
160 break;
161
162 pp = _procs+i;
163
164 pp->pr_valid = 1;
165 pp->pr_pid = pid;
166 pp->pr_target = target;
167 pp->pr_ignore = ignore;
168 pp->pr_last = last;
169 pp->pr_dir = DmStrDup(Get_current_dir());
170
171 Current_target = NIL(CELL);
172
173 _proc_cnt++;
174
175 if( Wait_for_completion ) Wait_for_child( FALSE, pid );
176 }
177
178
179 static void
_finished_child(pid,status)180 _finished_child(pid, status)
181 int pid;
182 int status;
183 {
184 register int i;
185 char *dir;
186
187 for( i=0; i<Max_proc; i++ )
188 if( _procs[i].pr_valid && _procs[i].pr_pid == pid )
189 break;
190
191 /* Some children we didn't make esp true if using /bin/sh to execute a
192 * a pipe and feed the output as a makefile into dmake. */
193 if( i == Max_proc ) return;
194 _procs[i].pr_valid = 0;
195 _proc_cnt--;
196 dir = DmStrDup(Get_current_dir());
197 Set_dir( _procs[i].pr_dir );
198
199 if( _procs[i].pr_recipe != NIL(RCP) && !_abort_flg ) {
200 RCPPTR rp = _procs[i].pr_recipe;
201
202
203 Current_target = _procs[i].pr_target;
204 Handle_result( status, _procs[i].pr_ignore, FALSE, _procs[i].pr_target );
205 Current_target = NIL(CELL);
206
207 if ( _procs[i].pr_target->ce_attr & A_ERROR ) {
208 _procs[i].pr_last = TRUE;
209 goto ABORT_REMAINDER_OF_RECIPE;
210 }
211
212 _procs[i].pr_recipe = rp->prp_next;
213
214 _use_i = i;
215 runargv( _procs[i].pr_target, rp->prp_ignore, rp->prp_group,
216 rp->prp_last, rp->prp_shell, rp->prp_cmd );
217 _use_i = -1;
218
219 FREE( rp->prp_cmd );
220 FREE( rp );
221
222 if( _proc_cnt == Max_proc ) Wait_for_child( FALSE, -1 );
223 }
224 else {
225 Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target);
226
227 ABORT_REMAINDER_OF_RECIPE:
228 if( _procs[i].pr_last ) {
229 FREE(_procs[i].pr_dir );
230
231 if( !Doing_bang ) Update_time_stamp( _procs[i].pr_target );
232 }
233 }
234
235 Set_dir(dir);
236 FREE(dir);
237 }
238
239
240 static int
_running(cp)241 _running( cp )
242 CELLPTR cp;
243 {
244 register int i;
245
246 if( !_procs ) return(FALSE);
247
248 for( i=0; i<Max_proc; i++ )
249 if( _procs[i].pr_valid &&
250 _procs[i].pr_target == cp )
251 break;
252
253 return( i != Max_proc );
254 }
255
256
257 static void
_attach_cmd(cmd,group,ignore,cp,last,shell)258 _attach_cmd( cmd, group, ignore, cp, last, shell )
259 char *cmd;
260 int group;
261 int ignore;
262 CELLPTR cp;
263 int last;
264 int shell;
265 {
266 register int i;
267 RCPPTR rp;
268
269 for( i=0; i<Max_proc; i++ )
270 if( _procs[i].pr_valid &&
271 _procs[i].pr_target == cp )
272 break;
273
274 TALLOC( rp, 1, RCP );
275 rp->prp_cmd = DmStrDup(cmd);
276 rp->prp_group = group;
277 rp->prp_ignore= ignore;
278 rp->prp_last = last;
279 rp->prp_shell = shell;
280
281 if( _procs[i].pr_recipe == NIL(RCP) )
282 _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp;
283 else {
284 _procs[i].pr_recipe_end->prp_next = rp;
285 _procs[i].pr_recipe_end = rp;
286 }
287 }
288