update dev300-m58
[ooovba.git] / dmake / qssl / runargv.c
blob1b30907a660747b2725c33559bfaef36d2bd627f
1 /* RCS $Id: runargv.c,v 1.3 2007-10-15 15:46:20 ihi Exp $
2 --
3 -- SYNOPSIS
4 -- Invoke a sub process.
5 --
6 -- DESCRIPTION
7 -- Use the standard methods of executing a sub process.
8 --
9 -- AUTHOR
10 -- Dennis Vadura, dvadura@dmake.wticorp.com
12 -- WWW
13 -- http://dmake.wticorp.com/
15 -- COPYRIGHT
16 -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
17 --
18 -- This program is NOT free software; you can redistribute it and/or
19 -- modify it under the terms of the Software License Agreement Provided
20 -- in the file <distribution-root>/readme/license.txt.
22 -- LOG
23 -- Use cvs log to obtain detailed change logs.
26 #include <signal.h>
27 #include "extern.h"
28 #include "sysintf.h"
30 typedef struct prp {
31 char *prp_cmd;
32 int prp_group;
33 int prp_ignore;
34 int prp_last;
35 int prp_shell;
36 struct prp *prp_next;
37 } RCP, *RCPPTR;
39 typedef struct pr {
40 int pr_valid;
41 int pr_pid;
42 CELLPTR pr_target;
43 int pr_ignore;
44 int pr_last;
45 RCPPTR pr_recipe;
46 RCPPTR pr_recipe_end;
47 char *pr_dir;
48 } PR;
50 static PR *_procs = NIL(PR);
51 static int _proc_cnt = 0;
52 static int _abort_flg= FALSE;
53 static int _use_i = -1;
54 static int _do_upd = 0;
56 static void _add_child ANSI((int, CELLPTR, int, int));
57 static void _attach_cmd ANSI((char *, int, int, CELLPTR, int, int));
58 static void _finished_child ANSI((int, int));
59 static int _running ANSI((CELLPTR));
61 /* iz71422 changed the parameters for runargv but it (and the rest of
62 * qssl) got *NOT* fixed. */
63 iz81252 changed the parameters for Pack_argv() and runargv() but this file
64 did not get fixed!
65 PUBLIC int
66 runargv(target, ignore, group, last, shell, cmd)
67 CELLPTR target;
68 int ignore;
69 int group;
70 int last;
71 int shell;
72 char *cmd;
74 extern int errno;
75 int pid;
76 char **argv;
78 if( _running(target) /*&& Max_proc != 1*/ ) {
79 /* The command will be executed when the previous recipe
80 * line completes. */
81 _attach_cmd( cmd, group, ignore, target, last, shell );
82 return(1);
85 while( _proc_cnt == Max_proc )
86 if( Wait_for_child(FALSE, -1) == -1 ) Fatal( "Lost a child %d", errno );
88 argv = Pack_argv( group, shell, cmd );
90 switch( pid=fork() ){
91 int wid;
92 int status;
94 case -1: /* fork failed */
95 Error("%s: %s", argv[0], strerror(errno));
96 Handle_result(-1, ignore, _abort_flg, target);
97 return(-1);
99 case 0: /* child */
100 execvp(argv[0], argv);
101 Continue = TRUE; /* survive error message */
102 Error("%s: %s", argv[0], strerror(errno));
103 kill(getpid(), SIGTERM);
104 /*NOTREACHED*/
106 default: /* parent */
107 _add_child(pid, target, ignore, last);
110 return(1);
114 PUBLIC int
115 Wait_for_child( abort_flg, pid )
116 int abort_flg;
117 int pid;
119 int wid;
120 int status;
121 int waitchild;
123 waitchild = (pid == -1)? FALSE : Wait_for_completion;
125 do {
126 if( (wid = wait(&status)) == -1 ) return(-1);
128 _abort_flg = abort_flg;
129 _finished_child(wid, status);
130 _abort_flg = FALSE;
132 while( waitchild && pid != wid );
134 return(0);
138 PUBLIC void
139 Clean_up_processes()
141 register int i;
143 if( _procs != NIL(PR) ) {
144 for( i=0; i<Max_proc; i++ )
145 if( _procs[i].pr_valid )
146 kill(_procs[i].pr_pid, SIGTERM);
148 while( Wait_for_child(TRUE, -1) != -1 );
153 static void
154 _add_child( pid, target, ignore, last )
155 int pid;
156 CELLPTR target;
157 int ignore;
158 int last;
160 register int i;
161 register PR *pp;
163 if( _procs == NIL(PR) ) {
164 TALLOC( _procs, Max_proc, PR );
167 if( (i = _use_i) == -1 )
168 for( i=0; i<Max_proc; i++ )
169 if( !_procs[i].pr_valid )
170 break;
172 pp = _procs+i;
174 pp->pr_valid = 1;
175 pp->pr_pid = pid;
176 pp->pr_target = target;
177 pp->pr_ignore = ignore;
178 pp->pr_last = last;
179 pp->pr_dir = DmStrDup(Get_current_dir());
181 Current_target = NIL(CELL);
183 _proc_cnt++;
185 if( Wait_for_completion ) Wait_for_child( FALSE, pid );
189 static void
190 _finished_child(pid, status)
191 int pid;
192 int status;
194 register int i;
195 register PR *pp;
196 char *dir;
198 for( i=0; i<Max_proc; i++ )
199 if( _procs[i].pr_valid && _procs[i].pr_pid == pid )
200 break;
202 /* Some children we didn't make esp true if using /bin/sh to execute a
203 * a pipe and feed the output as a makefile into dmake. */
204 if( i == Max_proc ) return;
205 _procs[i].pr_valid = 0;
206 _proc_cnt--;
207 dir = DmStrDup(Get_current_dir());
208 Set_dir( _procs[i].pr_dir );
210 if( _procs[i].pr_recipe != NIL(RCP) && !_abort_flg ) {
211 RCPPTR rp = _procs[i].pr_recipe;
214 Current_target = _procs[i].pr_target;
215 Handle_result( status, _procs[i].pr_ignore, FALSE, _procs[i].pr_target );
216 Current_target = NIL(CELL);
218 if ( _procs[i].pr_target->ce_attr & A_ERROR ) {
219 _procs[i].pr_last = TRUE;
220 goto ABORT_REMAINDER_OF_RECIPE;
223 _procs[i].pr_recipe = rp->prp_next;
225 _use_i = i;
226 runargv( _procs[i].pr_target, rp->prp_ignore, rp->prp_group,
227 rp->prp_last, rp->prp_shell, rp->prp_cmd );
228 _use_i = -1;
230 FREE( rp->prp_cmd );
231 FREE( rp );
233 if( _proc_cnt == Max_proc ) Wait_for_child( FALSE, -1 );
235 else {
236 Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target);
238 ABORT_REMAINDER_OF_RECIPE:
239 if( _procs[i].pr_last ) {
240 FREE(_procs[i].pr_dir );
242 if( !Doing_bang ) Update_time_stamp( _procs[i].pr_target );
246 Set_dir(dir);
247 FREE(dir);
251 static int
252 _running( cp )
253 CELLPTR cp;
255 register int i;
257 if( !_procs ) return(FALSE);
259 for( i=0; i<Max_proc; i++ )
260 if( _procs[i].pr_valid &&
261 _procs[i].pr_target == cp )
262 break;
264 return( i != Max_proc );
268 static void
269 _attach_cmd( cmd, group, ignore, cp, last, shell )
270 char *cmd;
271 int group;
272 int ignore;
273 CELLPTR cp;
274 int last;
275 int shell;
277 register int i;
278 RCPPTR rp;
280 for( i=0; i<Max_proc; i++ )
281 if( _procs[i].pr_valid &&
282 _procs[i].pr_target == cp )
283 break;
285 TALLOC( rp, 1, RCP );
286 rp->prp_cmd = DmStrDup(cmd);
287 rp->prp_group = group;
288 rp->prp_ignore= ignore;
289 rp->prp_last = last;
290 rp->prp_shell = shell;
292 if( _procs[i].pr_recipe == NIL(RCP) )
293 _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp;
294 else {
295 _procs[i].pr_recipe_end->prp_next = rp;
296 _procs[i].pr_recipe_end = rp;