Line data Source code
1 : #include "burp.h"
2 : #include "alloc.h"
3 : #include "asfd.h"
4 : #include "conf.h"
5 : #include "fzp.h"
6 : #include "forkchild.h"
7 : #include "handy.h"
8 : #include "log.h"
9 : #include "strlist.h"
10 : #include "run_script.h"
11 :
12 : #ifndef HAVE_WIN32
13 :
14 0 : static int log_script_output(struct asfd *asfd, struct fzp **fzp,
15 : struct conf **confs,
16 : int do_logp, int log_remote, int is_stderr, char **logbuf)
17 : {
18 0 : char buf[256]="";
19 0 : if(!fzp || !*fzp) return 0;
20 0 : if(fzp_gets(*fzp, buf, sizeof(buf)))
21 : {
22 0 : if(logbuf && astrcat(logbuf, buf, __func__)) return -1;
23 0 : if(log_remote)
24 : {
25 : // logm and low will also log to stdout.
26 0 : if(is_stderr) logw(asfd, confs?get_cntr(confs):NULL,
27 : "%s", buf);
28 0 : else logm(asfd, confs, "%s", buf);
29 : }
30 : else
31 : {
32 : // logc does not print a prefix
33 0 : if(do_logp) logp("%s", buf);
34 0 : else logc("%s", buf);
35 : }
36 : }
37 0 : if(fzp_eof(*fzp)) fzp_close(fzp);
38 : return 0;
39 : }
40 :
41 : static int got_sigchld=0;
42 : static int run_script_status=-1;
43 :
44 0 : static void run_script_sigchld_handler(__attribute__ ((unused)) int sig)
45 : {
46 : //printf("in run_script_sigchld_handler\n");
47 0 : got_sigchld=1;
48 0 : run_script_status=-1;
49 0 : waitpid(-1, &run_script_status, 0);
50 0 : }
51 :
52 0 : static int run_script_select(struct asfd *asfd,
53 : struct fzp **sout, struct fzp **serr,
54 : struct conf **confs, int do_logp, int log_remote, char **logbuf)
55 : {
56 0 : int mfd=-1;
57 : fd_set fsr;
58 : struct timeval tval;
59 0 : int soutfd=fzp_fileno(*sout);
60 0 : int serrfd=fzp_fileno(*serr);
61 : // FIX THIS: convert to asfd?
62 0 : fzp_setlinebuf(*sout);
63 0 : fzp_setlinebuf(*serr);
64 0 : set_non_blocking(soutfd);
65 0 : set_non_blocking(serrfd);
66 :
67 : while(1)
68 : {
69 0 : mfd=-1;
70 0 : FD_ZERO(&fsr);
71 0 : if(*sout) add_fd_to_sets(soutfd, &fsr, NULL, NULL, &mfd);
72 0 : if(*serr) add_fd_to_sets(serrfd, &fsr, NULL, NULL, &mfd);
73 0 : tval.tv_sec=1;
74 0 : tval.tv_usec=0;
75 0 : if(select(mfd+1, &fsr, NULL, NULL, &tval)<0)
76 : {
77 0 : if(errno!=EAGAIN && errno!=EINTR)
78 : {
79 0 : logp("%s error: %s\n", __func__,
80 : strerror(errno));
81 0 : return -1;
82 : }
83 : }
84 0 : if(FD_ISSET(soutfd, &fsr))
85 : {
86 0 : if(log_script_output(asfd, sout, confs,
87 : do_logp, log_remote, 0, logbuf)) return -1;
88 : }
89 0 : if(FD_ISSET(serrfd, &fsr))
90 : {
91 0 : if(log_script_output(asfd, serr, confs,
92 : do_logp, log_remote, 1, logbuf)) return -1;
93 : }
94 :
95 0 : if(!*sout && !*serr && got_sigchld)
96 : {
97 : //fclose(*sout); *sout=NULL;
98 : //fclose(*serr); *serr=NULL;
99 0 : got_sigchld=0;
100 0 : return 0;
101 : }
102 : }
103 :
104 : // Never get here.
105 : return -1;
106 : }
107 :
108 : #endif
109 :
110 1 : int run_script_to_buf(struct asfd *asfd,
111 : const char **args, struct strlist *userargs, struct conf **confs,
112 : int do_wait, int do_logp, int log_remote, char **logbuf)
113 : {
114 1 : int a=0;
115 1 : int l=0;
116 : pid_t p;
117 1 : struct fzp *serr=NULL;
118 1 : struct fzp *sout=NULL;
119 1 : char *cmd[64]={ NULL };
120 : struct strlist *sl;
121 : #ifndef HAVE_WIN32
122 1 : struct cntr *cntr=NULL;
123 1 : int s=0;
124 : #endif
125 1 : if(!args || !args[0]) return 0;
126 :
127 0 : for(a=0; args[a]; a++) cmd[l++]=(char *)args[a];
128 0 : for(sl=userargs; sl; sl=sl->next) cmd[l++]=sl->path;
129 0 : cmd[l++]=NULL;
130 :
131 : #ifndef HAVE_WIN32
132 0 : setup_signal(SIGCHLD, run_script_sigchld_handler);
133 : #endif
134 :
135 0 : fflush(stdout); fflush(stderr);
136 0 : if(do_wait)
137 : {
138 0 : if((p=forkchild(NULL,
139 0 : &sout, &serr, cmd[0], cmd))==-1) return -1;
140 : }
141 : else
142 : {
143 0 : if((p=forkchild_no_wait(NULL,
144 0 : &sout, &serr, cmd[0], cmd))==-1) return -1;
145 0 : return 0;
146 : }
147 : #ifdef HAVE_WIN32
148 : // My windows forkchild currently just executes, then returns.
149 : return 0;
150 : #else
151 0 : s=run_script_select(asfd, &sout, &serr,
152 : confs, do_logp, log_remote, logbuf);
153 :
154 : // Set SIGCHLD back to default.
155 0 : setup_signal(SIGCHLD, SIG_DFL);
156 :
157 0 : if(s) return -1;
158 :
159 0 : if(confs) cntr=get_cntr(confs);
160 :
161 0 : if(WIFEXITED(run_script_status))
162 : {
163 0 : int ret=WEXITSTATUS(run_script_status);
164 0 : logp("%s returned: %d\n", cmd[0], ret);
165 0 : if(log_remote && confs && ret)
166 0 : logw(asfd, cntr, "%s returned: %d\n", cmd[0], ret);
167 0 : return ret;
168 : }
169 0 : else if(WIFSIGNALED(run_script_status))
170 : {
171 0 : logp("%s terminated on signal %d\n",
172 0 : cmd[0], WTERMSIG(run_script_status));
173 0 : if(log_remote && confs)
174 0 : logw(asfd, cntr, "%s terminated on signal %d\n",
175 0 : cmd[0], WTERMSIG(run_script_status));
176 : }
177 : else
178 : {
179 0 : logp("Strange return when trying to run %s\n", cmd[0]);
180 0 : if(log_remote && confs) logw(asfd, cntr,
181 : "Strange return when trying to run %s\n", cmd[0]);
182 : }
183 : return -1;
184 : #endif
185 : }
186 :
187 1 : int run_script(struct asfd *asfd, const char **args, struct strlist *userargs,
188 : struct conf **confs, int do_wait, int do_logp, int log_remote)
189 : {
190 1 : return run_script_to_buf(asfd, args, userargs, confs, do_wait,
191 : do_logp, log_remote, NULL /* do not save output to buffer */);
192 : }
|