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