update dev300-m58
[ooovba.git] / dmake / winnt / microsft / vpp40 / runargv.c
blob3d64653048ea0b7b5a7f2e2a55a2890c5e991f38
1 Blake sent me the wrong one.
3 /* RCS $Id: runargv.c,v 1.2 2007-10-15 16:00:01 ihi Exp $
4 --
5 -- SYNOPSIS
6 -- Invoke a sub process.
7 --
8 -- DESCRIPTION
9 -- Use the standard methods of executing a sub process.
11 -- AUTHOR
12 -- Dennis Vadura, dvadura@dmake.wticorp.com
14 -- WWW
15 -- http://dmake.wticorp.com/
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>/readme/license.txt.
24 -- LOG
25 -- Use cvs log to obtain detailed change logs.
28 #include <process.h>
29 #include <errno.h>
30 #include <signal.h>
31 #include "extern.h"
32 #include "sysintf.h"
34 extern char **environ;
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;
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;
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;
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));
67 PUBLIC int
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;
76 extern int errno;
77 extern char *sys_errlist[];
78 int pid;
79 char **argv;
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);
88 while( _proc_cnt == Max_proc )
89 if( Wait_for_child(FALSE, -1) == -1 ) Fatal( "Lost a child %d", errno );
91 argv = Pack_argv( group, shell, cmd );
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);
101 return(1);
105 PUBLIC int
106 Wait_for_child( abort_flg, pid )
107 int abort_flg;
108 int pid;
110 int wid;
111 int status;
112 int waitchild;
114 waitchild = (pid == -1)? FALSE : Wait_for_completion;
116 do {
117 if( (wid = wait(&status)) == -1 ) return(-1);
119 _abort_flg = abort_flg;
120 _finished_child(wid, status);
121 _abort_flg = FALSE;
122 } while( waitchild && pid != wid );
124 return(0);
128 PUBLIC void
129 Clean_up_processes()
131 register int i;
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);
138 while( Wait_for_child(TRUE, -1) != -1 );
143 static void
144 _add_child( pid, target, ignore, last )
145 int pid;
146 CELLPTR target;
147 int ignore;
148 int last;
150 register int i;
151 register PR *pp;
153 if( _procs == NIL(PR) ) {
154 TALLOC( _procs, Max_proc, PR );
157 if( (i = _use_i) == -1 )
158 for( i=0; i<Max_proc; i++ )
159 if( !_procs[i].pr_valid )
160 break;
162 pp = _procs+i;
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());
171 Current_target = NIL(CELL);
173 _proc_cnt++;
175 if( Wait_for_completion ) Wait_for_child( FALSE, pid );
179 static void
180 _finished_child(pid, status)
181 int pid;
182 int status;
184 register int i;
185 register PR *pp;
186 char *dir;
188 for( i=0; i<Max_proc; i++ )
189 if( _procs[i].pr_valid && _procs[i].pr_pid == pid )
190 break;
192 /* Some children we didn't make esp true if using /bin/sh to execute a
193 * a pipe and feed the output as a makefile into dmake. */
194 if( i == Max_proc ) return;
195 _procs[i].pr_valid = 0;
196 _proc_cnt--;
197 dir = DmStrDup(Get_current_dir());
198 Set_dir( _procs[i].pr_dir );
200 if( _procs[i].pr_recipe != NIL(RCP) && !_abort_flg ) {
201 RCPPTR rp = _procs[i].pr_recipe;
204 Current_target = _procs[i].pr_target;
205 Handle_result( status, _procs[i].pr_ignore, FALSE, _procs[i].pr_target );
206 Current_target = NIL(CELL);
208 if ( _procs[i].pr_target->ce_attr & A_ERROR ) {
209 _procs[i].pr_last = TRUE;
210 goto ABORT_REMAINDER_OF_RECIPE;
213 _procs[i].pr_recipe = rp->prp_next;
215 _use_i = i;
216 runargv( _procs[i].pr_target, rp->prp_ignore, rp->prp_group,
217 rp->prp_last, rp->prp_shell, rp->prp_cmd );
218 _use_i = -1;
220 FREE( rp->prp_cmd );
221 FREE( rp );
223 if( _proc_cnt == Max_proc ) Wait_for_child( FALSE, -1 );
225 else {
226 Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target);
228 ABORT_REMAINDER_OF_RECIPE:
229 if( _procs[i].pr_last ) {
230 FREE(_procs[i].pr_dir );
232 if( !Doing_bang ) Update_time_stamp( _procs[i].pr_target );
236 Set_dir(dir);
237 FREE(dir);
241 static int
242 _running( cp )
243 CELLPTR cp;
245 register int i;
247 if( !_procs ) return(FALSE);
249 for( i=0; i<Max_proc; i++ )
250 if( _procs[i].pr_valid &&
251 _procs[i].pr_target == cp )
252 break;
254 return( i != Max_proc );
258 static void
259 _attach_cmd( cmd, group, ignore, cp, last, shell )
260 char *cmd;
261 int group;
262 int ignore;
263 CELLPTR cp;
264 int last;
265 int shell;
267 register int i;
268 RCPPTR rp;
270 for( i=0; i<Max_proc; i++ )
271 if( _procs[i].pr_valid &&
272 _procs[i].pr_target == cp )
273 break;
275 TALLOC( rp, 1, RCP );
276 rp->prp_cmd = DmStrDup(cmd);
277 rp->prp_group = group;
278 rp->prp_ignore= ignore;
279 rp->prp_last = last;
280 rp->prp_shell = shell;
282 if( _procs[i].pr_recipe == NIL(RCP) )
283 _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp;
284 else {
285 _procs[i].pr_recipe_end->prp_next = rp;
286 _procs[i].pr_recipe_end = rp;