Pristine Ack-5.5
[Ack-5.5.git] / util / ack / run.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  *
5  */
6
7 #include "ack.h"
8 #include "list.h"
9 #include "trans.h"
10 #include "grows.h"
11 #include "data.h"
12 #include <signal.h>
13
14 #ifndef NORCSID
15 static char rcs_id[] = "$Id: run.c,v 2.9 1994/06/24 10:13:06 ceriel Exp $" ;
16 #endif
17
18 #define ARG_MORE  40            /* The size of args chunks to allocate */
19
20 extern growstring scanvars();
21
22 static char      **arglist ;    /* The first argument */
23 static unsigned  argcount ;     /* The current number of arguments */
24 static unsigned  argmax;        /* The maximum number of arguments so far */
25
26 int runphase(phase) register trf *phase ; {
27         register list_elem *elem ;
28       char *prog ; int result ;
29       growstring bline ;
30
31       bline=scanvars(phase->t_prog) ;
32       prog=gr_final(&bline) ;
33         if ( v_flag || debug ) {
34                 if ( v_flag==1 && !debug ) {
35                         vprint("%s",phase->t_name) ;
36                         if ( !phase->t_combine ) {
37                                 vprint(" %s%s\n",p_basename,
38                                         strrindex(in.p_path,SUFCHAR) ) ;
39                         } else {
40                                 scanlist(l_first(phase->t_inputs), elem) {
41                                         vprint(" %s",p_cont(*elem)->p_path);
42                                 }
43                                 vprint("\n") ;
44                         }
45                 } else {
46                         /* list all args */
47                       vprint("%s",prog) ;
48                         scanlist(l_first(phase->t_flags), elem) {
49                                 vprint(" %s",l_content(*elem)) ;
50                         }
51                         scanlist(l_first(phase->t_args), elem) {
52                                 vprint(" %s",l_content(*elem)) ;
53                         }
54                         vprint("\n") ;
55                 }
56         }
57         argcount=0 ;
58         x_arg(phase->t_name) ;
59         scanlist(l_first(phase->t_flags), elem) {
60                 x_arg(l_content(*elem)) ;
61         }
62         scanlist(l_first(phase->t_args), elem) {
63                 x_arg(l_content(*elem)) ;
64         }
65         x_arg( (char *)0 ) ;
66       result=run_exec(phase,prog) ;
67       throws(prog) ;
68       return result ;
69 }
70
71 int run_exec(phase,prog) trf *phase ; char *prog ; {
72         int status, child, waitchild ;
73
74         do_flush();
75         while ( (child=fork())== -1 ) ;
76         if ( child ) {
77                 /* The parent */
78                 do {
79                         waitchild= wait(&status) ;
80                         if ( waitchild== -1 ) {
81                                 fatal("missing child") ;
82                         }
83                 } while ( waitchild!=child) ;
84                 if ( status ) {
85                         if ( status&0200 && (status&0177)!=SIGQUIT &&
86                                 t_flag<=1 ) unlink("core") ;
87                         switch ( status&0177 ) {
88                         case 0 :
89                                 break ;
90                         case SIGHUP:
91                         case SIGINT:
92                         case SIGQUIT:
93                         case SIGTERM:
94                                 quit(-5) ;
95                         default:
96                                 error("%s died with signal %d",
97                                       prog,status&0177) ;
98                         }
99                         /* The assumption is that processes voluntarely
100                            dying with a non-zero status already produced
101                            some sort of error message to the outside world.
102                         */
103                         n_error++ ;
104                         return 0 ;
105                 }
106                 return 1 ; /* From the parent */
107         }
108         /* The child */
109         if ( phase->t_stdin ) {
110                 if ( !in.p_path ) {
111                         fatal("no input file for %s",phase->t_name) ;
112                 }
113                 close(0) ;
114                 if ( open(in.p_path,0)!=0 ) {
115                         error("cannot open %s",in.p_path) ;
116                         exit(1) ;
117                 }
118         }
119         if ( phase->t_stdout ) {
120                 if ( !out.p_path ) {
121                         fatal("no output file for %s",phase->t_name) ;
122                 }
123                 close(1) ;
124                 if ( creat(out.p_path,0666)!=1 ) {
125                         close(1); dup(2);
126                         error("cannot create %s",out.p_path) ;
127                         exit(1) ;
128                 }
129         }
130       execv(prog,arglist) ;
131         if ( phase->t_stdout ) { close(1) ; dup(2) ; }
132       error("Cannot execute %s",prog) ;
133         exit(1) ;
134         /*NOTREACHED*/
135 }
136
137 x_arg(string) char *string ; {
138         /* Add one execute argument to the argument vector */
139         if ( argcount==argmax ) {
140                 if ( argmax==0 ) {
141                         argmax= 2*ARG_MORE ;
142                         arglist= (char **)getcore(argmax*sizeof (char *)) ;
143                 } else {
144                         argmax += ARG_MORE ;
145                         arglist= (char **)changecore((char *)arglist,
146                                         argmax*sizeof (char *)) ;
147                 }
148         }
149         *(arglist+argcount++) = string ;
150 }