Blame


1 00f0146a 2010-11-09 rsc /*
2 00f0146a 2010-11-09 rsc * mirror manager.
3 00f0146a 2010-11-09 rsc * a work in progress.
4 00f0146a 2010-11-09 rsc * use at your own risk.
5 00f0146a 2010-11-09 rsc */
6 00f0146a 2010-11-09 rsc
7 00f0146a 2010-11-09 rsc #include "stdinc.h"
8 00f0146a 2010-11-09 rsc #include <regexp.h>
9 00f0146a 2010-11-09 rsc #include <bio.h>
10 00f0146a 2010-11-09 rsc #include "dat.h"
11 00f0146a 2010-11-09 rsc #include "fns.h"
12 00f0146a 2010-11-09 rsc
13 bd51695c 2011-11-21 rsc #ifdef PLAN9PORT
14 bd51695c 2011-11-21 rsc #define sp s.sp
15 bd51695c 2011-11-21 rsc #define ep e.ep
16 bd51695c 2011-11-21 rsc #endif
17 bd51695c 2011-11-21 rsc
18 00f0146a 2010-11-09 rsc void sendmail(char *content, char *subject, char *msg);
19 00f0146a 2010-11-09 rsc #define TIME "[0-9]+/[0-9]+ [0-9]+:[0-9]+:[0-9]+"
20 00f0146a 2010-11-09 rsc
21 00f0146a 2010-11-09 rsc char *mirrorregexp =
22 00f0146a 2010-11-09 rsc "^" TIME " ("
23 00f0146a 2010-11-09 rsc "([^ ]+ \\([0-9,]+-[0-9,]+\\))"
24 00f0146a 2010-11-09 rsc "|( copy [0-9,]+-[0-9,]+ (data|hole|directory|tail))"
25 00f0146a 2010-11-09 rsc "|( sha1 [0-9,]+-[0-9,]+)"
26 bd51695c 2011-11-21 rsc "|([^ ]+: [0-9,]+ used mirrored)"
27 00f0146a 2010-11-09 rsc "|([^ \\-]+-[^ \\-]+( mirrored| sealed| empty)+)"
28 00f0146a 2010-11-09 rsc ")$";
29 00f0146a 2010-11-09 rsc Reprog *mirrorprog;
30 00f0146a 2010-11-09 rsc
31 bd51695c 2011-11-21 rsc char *verifyregexp =
32 bd51695c 2011-11-21 rsc "^" TIME " ("
33 bd51695c 2011-11-21 rsc "([^ ]+: unsealed [0-9,]+ bytes)"
34 bd51695c 2011-11-21 rsc ")$";
35 bd51695c 2011-11-21 rsc Reprog *verifyprog;
36 bd51695c 2011-11-21 rsc
37 00f0146a 2010-11-09 rsc #undef pipe
38 00f0146a 2010-11-09 rsc enum
39 00f0146a 2010-11-09 rsc {
40 00f0146a 2010-11-09 rsc LogSize = 4*1024*1024 // TODO: make smaller
41 00f0146a 2010-11-09 rsc };
42 00f0146a 2010-11-09 rsc
43 00f0146a 2010-11-09 rsc VtLog *errlog;
44 00f0146a 2010-11-09 rsc
45 00f0146a 2010-11-09 rsc typedef struct Mirror Mirror;
46 00f0146a 2010-11-09 rsc struct Mirror
47 00f0146a 2010-11-09 rsc {
48 00f0146a 2010-11-09 rsc char *src;
49 00f0146a 2010-11-09 rsc char *dst;
50 00f0146a 2010-11-09 rsc };
51 00f0146a 2010-11-09 rsc
52 00f0146a 2010-11-09 rsc typedef struct Conf Conf;
53 00f0146a 2010-11-09 rsc struct Conf
54 00f0146a 2010-11-09 rsc {
55 00f0146a 2010-11-09 rsc Mirror *mirror;
56 00f0146a 2010-11-09 rsc int nmirror;
57 00f0146a 2010-11-09 rsc char **verify;
58 00f0146a 2010-11-09 rsc int nverify;
59 00f0146a 2010-11-09 rsc char *httpaddr;
60 00f0146a 2010-11-09 rsc char *webroot;
61 00f0146a 2010-11-09 rsc char *smtp;
62 00f0146a 2010-11-09 rsc char *mailfrom;
63 00f0146a 2010-11-09 rsc char *mailto;
64 00f0146a 2010-11-09 rsc int mirrorfreq;
65 00f0146a 2010-11-09 rsc int verifyfreq;
66 00f0146a 2010-11-09 rsc };
67 00f0146a 2010-11-09 rsc
68 00f0146a 2010-11-09 rsc typedef struct Job Job;
69 00f0146a 2010-11-09 rsc struct Job
70 00f0146a 2010-11-09 rsc {
71 00f0146a 2010-11-09 rsc char *name;
72 00f0146a 2010-11-09 rsc QLock lk;
73 00f0146a 2010-11-09 rsc char *argv[10];
74 00f0146a 2010-11-09 rsc int oldok;
75 00f0146a 2010-11-09 rsc int newok;
76 00f0146a 2010-11-09 rsc VtLog *oldlog;
77 00f0146a 2010-11-09 rsc VtLog *newlog;
78 00f0146a 2010-11-09 rsc int pid;
79 00f0146a 2010-11-09 rsc int pipe;
80 00f0146a 2010-11-09 rsc int nrun;
81 00f0146a 2010-11-09 rsc vlong freq;
82 00f0146a 2010-11-09 rsc vlong runstart;
83 00f0146a 2010-11-09 rsc vlong runend;
84 00f0146a 2010-11-09 rsc double offset;
85 00f0146a 2010-11-09 rsc int (*ok)(char*);
86 00f0146a 2010-11-09 rsc };
87 00f0146a 2010-11-09 rsc
88 00f0146a 2010-11-09 rsc Job *job;
89 00f0146a 2010-11-09 rsc int njob;
90 00f0146a 2010-11-09 rsc char *bin;
91 00f0146a 2010-11-09 rsc
92 00f0146a 2010-11-09 rsc vlong time0;
93 00f0146a 2010-11-09 rsc Conf conf;
94 00f0146a 2010-11-09 rsc
95 00f0146a 2010-11-09 rsc void
96 00f0146a 2010-11-09 rsc usage(void)
97 00f0146a 2010-11-09 rsc {
98 00f0146a 2010-11-09 rsc fprint(2, "usage: mgr [-s] [-b bin/venti/] venti.conf\n");
99 00f0146a 2010-11-09 rsc threadexitsall(0);
100 00f0146a 2010-11-09 rsc }
101 00f0146a 2010-11-09 rsc
102 00f0146a 2010-11-09 rsc int
103 00f0146a 2010-11-09 rsc rdconf(char *file, Conf *conf)
104 00f0146a 2010-11-09 rsc {
105 00f0146a 2010-11-09 rsc char *s, *line, *flds[10];
106 00f0146a 2010-11-09 rsc int i, ok;
107 00f0146a 2010-11-09 rsc IFile f;
108 fa325e9b 2020-01-10 cross
109 00f0146a 2010-11-09 rsc if(readifile(&f, file) < 0)
110 00f0146a 2010-11-09 rsc return -1;
111 00f0146a 2010-11-09 rsc memset(conf, 0, sizeof *conf);
112 00f0146a 2010-11-09 rsc ok = -1;
113 00f0146a 2010-11-09 rsc line = nil;
114 00f0146a 2010-11-09 rsc for(;;){
115 00f0146a 2010-11-09 rsc s = ifileline(&f);
116 00f0146a 2010-11-09 rsc if(s == nil){
117 00f0146a 2010-11-09 rsc ok = 0;
118 00f0146a 2010-11-09 rsc break;
119 00f0146a 2010-11-09 rsc }
120 00f0146a 2010-11-09 rsc line = estrdup(s);
121 00f0146a 2010-11-09 rsc i = getfields(s, flds, nelem(flds), 1, " \t\r");
122 00f0146a 2010-11-09 rsc if(i <= 0 || strcmp(flds[0], "mgr") != 0) {
123 00f0146a 2010-11-09 rsc /* do nothing */
124 00f0146a 2010-11-09 rsc }else if(i == 4 && strcmp(flds[1], "mirror") == 0) {
125 00f0146a 2010-11-09 rsc if(conf->nmirror%64 == 0)
126 00f0146a 2010-11-09 rsc conf->mirror = vtrealloc(conf->mirror, (conf->nmirror+64)*sizeof(conf->mirror[0]));
127 00f0146a 2010-11-09 rsc conf->mirror[conf->nmirror].src = vtstrdup(flds[2]);
128 00f0146a 2010-11-09 rsc conf->mirror[conf->nmirror].dst = vtstrdup(flds[3]);
129 00f0146a 2010-11-09 rsc conf->nmirror++;
130 00f0146a 2010-11-09 rsc }else if(i == 3 && strcmp(flds[1], "mirrorfreq") == 0) {
131 00f0146a 2010-11-09 rsc conf->mirrorfreq = atoi(flds[2]);
132 00f0146a 2010-11-09 rsc }else if(i == 3 && strcmp(flds[1], "verify") == 0) {
133 00f0146a 2010-11-09 rsc if(conf->nverify%64 == 0)
134 00f0146a 2010-11-09 rsc conf->verify = vtrealloc(conf->verify, (conf->nverify+64)*sizeof(conf->verify[0]));
135 fa325e9b 2020-01-10 cross conf->verify[conf->nverify++] = vtstrdup(flds[2]);
136 00f0146a 2010-11-09 rsc }else if(i == 3 && strcmp(flds[1], "verifyfreq") == 0) {
137 00f0146a 2010-11-09 rsc conf->verifyfreq = atoi(flds[2]);
138 00f0146a 2010-11-09 rsc }else if(i == 3 && strcmp(flds[1], "httpaddr") == 0){
139 00f0146a 2010-11-09 rsc if(conf->httpaddr){
140 00f0146a 2010-11-09 rsc seterr(EAdmin, "duplicate httpaddr lines in configuration file %s", file);
141 00f0146a 2010-11-09 rsc break;
142 00f0146a 2010-11-09 rsc }
143 00f0146a 2010-11-09 rsc conf->httpaddr = estrdup(flds[2]);
144 00f0146a 2010-11-09 rsc }else if(i == 3 && strcmp(flds[1], "webroot") == 0){
145 00f0146a 2010-11-09 rsc if(conf->webroot){
146 00f0146a 2010-11-09 rsc seterr(EAdmin, "duplicate webroot lines in configuration file %s", file);
147 00f0146a 2010-11-09 rsc break;
148 00f0146a 2010-11-09 rsc }
149 00f0146a 2010-11-09 rsc conf->webroot = estrdup(flds[2]);
150 00f0146a 2010-11-09 rsc }else if(i == 3 && strcmp(flds[1], "smtp") == 0) {
151 00f0146a 2010-11-09 rsc if(conf->smtp){
152 00f0146a 2010-11-09 rsc seterr(EAdmin, "duplicate smtp lines in configuration file %s", file);
153 00f0146a 2010-11-09 rsc break;
154 00f0146a 2010-11-09 rsc }
155 00f0146a 2010-11-09 rsc conf->smtp = estrdup(flds[2]);
156 00f0146a 2010-11-09 rsc }else if(i == 3 && strcmp(flds[1], "mailfrom") == 0) {
157 00f0146a 2010-11-09 rsc if(conf->mailfrom){
158 00f0146a 2010-11-09 rsc seterr(EAdmin, "duplicate mailfrom lines in configuration file %s", file);
159 00f0146a 2010-11-09 rsc break;
160 00f0146a 2010-11-09 rsc }
161 00f0146a 2010-11-09 rsc conf->mailfrom = estrdup(flds[2]);
162 00f0146a 2010-11-09 rsc }else if(i == 3 && strcmp(flds[1], "mailto") == 0) {
163 00f0146a 2010-11-09 rsc if(conf->mailto){
164 00f0146a 2010-11-09 rsc seterr(EAdmin, "duplicate mailto lines in configuration file %s", file);
165 00f0146a 2010-11-09 rsc break;
166 00f0146a 2010-11-09 rsc }
167 00f0146a 2010-11-09 rsc conf->mailto = estrdup(flds[2]);
168 00f0146a 2010-11-09 rsc }else{
169 00f0146a 2010-11-09 rsc seterr(EAdmin, "illegal line '%s' in configuration file %s", line, file);
170 00f0146a 2010-11-09 rsc break;
171 00f0146a 2010-11-09 rsc }
172 00f0146a 2010-11-09 rsc free(line);
173 00f0146a 2010-11-09 rsc line = nil;
174 00f0146a 2010-11-09 rsc }
175 00f0146a 2010-11-09 rsc free(line);
176 00f0146a 2010-11-09 rsc freeifile(&f);
177 00f0146a 2010-11-09 rsc return ok;
178 00f0146a 2010-11-09 rsc }
179 00f0146a 2010-11-09 rsc
180 00f0146a 2010-11-09 rsc static QLock loglk;
181 00f0146a 2010-11-09 rsc static char *logbuf;
182 00f0146a 2010-11-09 rsc
183 00f0146a 2010-11-09 rsc char*
184 00f0146a 2010-11-09 rsc logtext(VtLog *l)
185 00f0146a 2010-11-09 rsc {
186 00f0146a 2010-11-09 rsc int i;
187 00f0146a 2010-11-09 rsc char *p;
188 00f0146a 2010-11-09 rsc VtLogChunk *c;
189 fa325e9b 2020-01-10 cross
190 00f0146a 2010-11-09 rsc p = logbuf;
191 00f0146a 2010-11-09 rsc c = l->w;
192 00f0146a 2010-11-09 rsc for(i=0; i<l->nchunk; i++) {
193 00f0146a 2010-11-09 rsc if(++c == l->chunk+l->nchunk)
194 00f0146a 2010-11-09 rsc c = l->chunk;
195 00f0146a 2010-11-09 rsc memmove(p, c->p, c->wp - c->p);
196 00f0146a 2010-11-09 rsc p += c->wp - c->p;
197 00f0146a 2010-11-09 rsc }
198 00f0146a 2010-11-09 rsc *p = 0;
199 00f0146a 2010-11-09 rsc return logbuf;
200 00f0146a 2010-11-09 rsc }
201 00f0146a 2010-11-09 rsc
202 00f0146a 2010-11-09 rsc
203 00f0146a 2010-11-09 rsc typedef struct HttpObj HttpObj;
204 00f0146a 2010-11-09 rsc
205 00f0146a 2010-11-09 rsc static int fromwebdir(HConnect*);
206 00f0146a 2010-11-09 rsc
207 00f0146a 2010-11-09 rsc enum
208 00f0146a 2010-11-09 rsc {
209 00f0146a 2010-11-09 rsc ObjNameSize = 64,
210 00f0146a 2010-11-09 rsc MaxObjs = 64
211 00f0146a 2010-11-09 rsc };
212 00f0146a 2010-11-09 rsc
213 00f0146a 2010-11-09 rsc struct HttpObj
214 00f0146a 2010-11-09 rsc {
215 00f0146a 2010-11-09 rsc char name[ObjNameSize];
216 00f0146a 2010-11-09 rsc int (*f)(HConnect*);
217 00f0146a 2010-11-09 rsc };
218 00f0146a 2010-11-09 rsc
219 00f0146a 2010-11-09 rsc static HttpObj objs[MaxObjs];
220 00f0146a 2010-11-09 rsc static void httpproc(void*);
221 00f0146a 2010-11-09 rsc
222 00f0146a 2010-11-09 rsc static HConnect*
223 00f0146a 2010-11-09 rsc mkconnect(void)
224 00f0146a 2010-11-09 rsc {
225 00f0146a 2010-11-09 rsc HConnect *c;
226 00f0146a 2010-11-09 rsc
227 00f0146a 2010-11-09 rsc c = mallocz(sizeof(HConnect), 1);
228 00f0146a 2010-11-09 rsc if(c == nil)
229 00f0146a 2010-11-09 rsc sysfatal("out of memory");
230 00f0146a 2010-11-09 rsc c->replog = nil;
231 00f0146a 2010-11-09 rsc c->hpos = c->header;
232 00f0146a 2010-11-09 rsc c->hstop = c->header;
233 00f0146a 2010-11-09 rsc return c;
234 00f0146a 2010-11-09 rsc }
235 00f0146a 2010-11-09 rsc
236 00f0146a 2010-11-09 rsc static int
237 00f0146a 2010-11-09 rsc preq(HConnect *c)
238 00f0146a 2010-11-09 rsc {
239 00f0146a 2010-11-09 rsc if(hparseheaders(c, 0) < 0)
240 00f0146a 2010-11-09 rsc return -1;
241 00f0146a 2010-11-09 rsc if(strcmp(c->req.meth, "GET") != 0
242 00f0146a 2010-11-09 rsc && strcmp(c->req.meth, "HEAD") != 0)
243 00f0146a 2010-11-09 rsc return hunallowed(c, "GET, HEAD");
244 00f0146a 2010-11-09 rsc if(c->head.expectother || c->head.expectcont)
245 00f0146a 2010-11-09 rsc return hfail(c, HExpectFail, nil);
246 00f0146a 2010-11-09 rsc return 0;
247 00f0146a 2010-11-09 rsc }
248 00f0146a 2010-11-09 rsc
249 00f0146a 2010-11-09 rsc int
250 00f0146a 2010-11-09 rsc hsettype(HConnect *c, char *type)
251 00f0146a 2010-11-09 rsc {
252 00f0146a 2010-11-09 rsc Hio *hout;
253 00f0146a 2010-11-09 rsc int r;
254 00f0146a 2010-11-09 rsc
255 00f0146a 2010-11-09 rsc r = preq(c);
256 00f0146a 2010-11-09 rsc if(r < 0)
257 00f0146a 2010-11-09 rsc return r;
258 00f0146a 2010-11-09 rsc
259 00f0146a 2010-11-09 rsc hout = &c->hout;
260 00f0146a 2010-11-09 rsc if(c->req.vermaj){
261 00f0146a 2010-11-09 rsc hokheaders(c);
262 00f0146a 2010-11-09 rsc hprint(hout, "Content-type: %s\r\n", type);
263 00f0146a 2010-11-09 rsc if(http11(c))
264 00f0146a 2010-11-09 rsc hprint(hout, "Transfer-Encoding: chunked\r\n");
265 00f0146a 2010-11-09 rsc hprint(hout, "\r\n");
266 00f0146a 2010-11-09 rsc }
267 00f0146a 2010-11-09 rsc
268 00f0146a 2010-11-09 rsc if(http11(c))
269 00f0146a 2010-11-09 rsc hxferenc(hout, 1);
270 00f0146a 2010-11-09 rsc else
271 00f0146a 2010-11-09 rsc c->head.closeit = 1;
272 00f0146a 2010-11-09 rsc return 0;
273 00f0146a 2010-11-09 rsc }
274 00f0146a 2010-11-09 rsc
275 00f0146a 2010-11-09 rsc int
276 00f0146a 2010-11-09 rsc hsethtml(HConnect *c)
277 00f0146a 2010-11-09 rsc {
278 00f0146a 2010-11-09 rsc return hsettype(c, "text/html; charset=utf-8");
279 00f0146a 2010-11-09 rsc }
280 00f0146a 2010-11-09 rsc
281 00f0146a 2010-11-09 rsc int
282 00f0146a 2010-11-09 rsc hsettext(HConnect *c)
283 00f0146a 2010-11-09 rsc {
284 00f0146a 2010-11-09 rsc return hsettype(c, "text/plain; charset=utf-8");
285 00f0146a 2010-11-09 rsc }
286 fa325e9b 2020-01-10 cross
287 00f0146a 2010-11-09 rsc int
288 00f0146a 2010-11-09 rsc hnotfound(HConnect *c)
289 00f0146a 2010-11-09 rsc {
290 00f0146a 2010-11-09 rsc int r;
291 00f0146a 2010-11-09 rsc
292 00f0146a 2010-11-09 rsc r = preq(c);
293 00f0146a 2010-11-09 rsc if(r < 0)
294 00f0146a 2010-11-09 rsc return r;
295 00f0146a 2010-11-09 rsc return hfail(c, HNotFound, c->req.uri);
296 00f0146a 2010-11-09 rsc }
297 00f0146a 2010-11-09 rsc
298 00f0146a 2010-11-09 rsc static int
299 00f0146a 2010-11-09 rsc xloglist(HConnect *c)
300 00f0146a 2010-11-09 rsc {
301 00f0146a 2010-11-09 rsc if(hsettype(c, "text/html") < 0)
302 00f0146a 2010-11-09 rsc return -1;
303 00f0146a 2010-11-09 rsc vtloghlist(&c->hout);
304 00f0146a 2010-11-09 rsc hflush(&c->hout);
305 00f0146a 2010-11-09 rsc return 0;
306 00f0146a 2010-11-09 rsc }
307 00f0146a 2010-11-09 rsc
308 00f0146a 2010-11-09 rsc static int
309 00f0146a 2010-11-09 rsc strpcmp(const void *va, const void *vb)
310 00f0146a 2010-11-09 rsc {
311 00f0146a 2010-11-09 rsc return strcmp(*(char**)va, *(char**)vb);
312 00f0146a 2010-11-09 rsc }
313 00f0146a 2010-11-09 rsc
314 00f0146a 2010-11-09 rsc void
315 00f0146a 2010-11-09 rsc vtloghlist(Hio *h)
316 00f0146a 2010-11-09 rsc {
317 00f0146a 2010-11-09 rsc char **p;
318 00f0146a 2010-11-09 rsc int i, n;
319 fa325e9b 2020-01-10 cross
320 00f0146a 2010-11-09 rsc hprint(h, "<html><head>\n");
321 00f0146a 2010-11-09 rsc hprint(h, "<title>Venti Server Logs</title>\n");
322 00f0146a 2010-11-09 rsc hprint(h, "</head><body>\n");
323 00f0146a 2010-11-09 rsc hprint(h, "<b>Venti Server Logs</b>\n<p>\n");
324 fa325e9b 2020-01-10 cross
325 00f0146a 2010-11-09 rsc p = vtlognames(&n);
326 00f0146a 2010-11-09 rsc qsort(p, n, sizeof(p[0]), strpcmp);
327 00f0146a 2010-11-09 rsc for(i=0; i<n; i++)
328 00f0146a 2010-11-09 rsc hprint(h, "<a href=\"/log?log=%s\">%s</a><br>\n", p[i], p[i]);
329 00f0146a 2010-11-09 rsc vtfree(p);
330 00f0146a 2010-11-09 rsc hprint(h, "</body></html>\n");
331 00f0146a 2010-11-09 rsc }
332 00f0146a 2010-11-09 rsc
333 00f0146a 2010-11-09 rsc void
334 00f0146a 2010-11-09 rsc vtloghdump(Hio *h, VtLog *l)
335 00f0146a 2010-11-09 rsc {
336 00f0146a 2010-11-09 rsc int i;
337 00f0146a 2010-11-09 rsc VtLogChunk *c;
338 00f0146a 2010-11-09 rsc char *name;
339 fa325e9b 2020-01-10 cross
340 00f0146a 2010-11-09 rsc name = l ? l->name : "&lt;nil&gt;";
341 00f0146a 2010-11-09 rsc
342 00f0146a 2010-11-09 rsc hprint(h, "<html><head>\n");
343 00f0146a 2010-11-09 rsc hprint(h, "<title>Venti Server Log: %s</title>\n", name);
344 00f0146a 2010-11-09 rsc hprint(h, "</head><body>\n");
345 00f0146a 2010-11-09 rsc hprint(h, "<b>Venti Server Log: %s</b>\n<p>\n", name);
346 fa325e9b 2020-01-10 cross
347 00f0146a 2010-11-09 rsc if(l){
348 00f0146a 2010-11-09 rsc c = l->w;
349 00f0146a 2010-11-09 rsc for(i=0; i<l->nchunk; i++){
350 00f0146a 2010-11-09 rsc if(++c == l->chunk+l->nchunk)
351 00f0146a 2010-11-09 rsc c = l->chunk;
352 00f0146a 2010-11-09 rsc hwrite(h, c->p, c->wp-c->p);
353 00f0146a 2010-11-09 rsc }
354 00f0146a 2010-11-09 rsc }
355 00f0146a 2010-11-09 rsc hprint(h, "</body></html>\n");
356 00f0146a 2010-11-09 rsc }
357 00f0146a 2010-11-09 rsc
358 00f0146a 2010-11-09 rsc
359 00f0146a 2010-11-09 rsc char*
360 00f0146a 2010-11-09 rsc hargstr(HConnect *c, char *name, char *def)
361 00f0146a 2010-11-09 rsc {
362 00f0146a 2010-11-09 rsc HSPairs *p;
363 fa325e9b 2020-01-10 cross
364 00f0146a 2010-11-09 rsc for(p=c->req.searchpairs; p; p=p->next)
365 00f0146a 2010-11-09 rsc if(strcmp(p->s, name) == 0)
366 00f0146a 2010-11-09 rsc return p->t;
367 00f0146a 2010-11-09 rsc return def;
368 00f0146a 2010-11-09 rsc }
369 00f0146a 2010-11-09 rsc
370 00f0146a 2010-11-09 rsc static int
371 00f0146a 2010-11-09 rsc xlog(HConnect *c)
372 00f0146a 2010-11-09 rsc {
373 00f0146a 2010-11-09 rsc char *name;
374 00f0146a 2010-11-09 rsc VtLog *l;
375 00f0146a 2010-11-09 rsc
376 00f0146a 2010-11-09 rsc name = hargstr(c, "log", "");
377 00f0146a 2010-11-09 rsc if(!name[0])
378 00f0146a 2010-11-09 rsc return xloglist(c);
379 00f0146a 2010-11-09 rsc l = vtlogopen(name, 0);
380 00f0146a 2010-11-09 rsc if(l == nil)
381 00f0146a 2010-11-09 rsc return hnotfound(c);
382 00f0146a 2010-11-09 rsc if(hsettype(c, "text/html") < 0){
383 00f0146a 2010-11-09 rsc vtlogclose(l);
384 00f0146a 2010-11-09 rsc return -1;
385 00f0146a 2010-11-09 rsc }
386 00f0146a 2010-11-09 rsc vtloghdump(&c->hout, l);
387 00f0146a 2010-11-09 rsc vtlogclose(l);
388 00f0146a 2010-11-09 rsc hflush(&c->hout);
389 00f0146a 2010-11-09 rsc return 0;
390 00f0146a 2010-11-09 rsc }
391 00f0146a 2010-11-09 rsc
392 00f0146a 2010-11-09 rsc static void
393 00f0146a 2010-11-09 rsc httpdproc(void *vaddress)
394 00f0146a 2010-11-09 rsc {
395 00f0146a 2010-11-09 rsc HConnect *c;
396 00f0146a 2010-11-09 rsc char *address, ndir[NETPATHLEN], dir[NETPATHLEN];
397 00f0146a 2010-11-09 rsc int ctl, nctl, data;
398 00f0146a 2010-11-09 rsc
399 00f0146a 2010-11-09 rsc address = vaddress;
400 00f0146a 2010-11-09 rsc ctl = announce(address, dir);
401 00f0146a 2010-11-09 rsc if(ctl < 0){
402 00f0146a 2010-11-09 rsc sysfatal("announce %s: %r", address);
403 00f0146a 2010-11-09 rsc return;
404 00f0146a 2010-11-09 rsc }
405 00f0146a 2010-11-09 rsc
406 00f0146a 2010-11-09 rsc if(0) print("announce ctl %d dir %s\n", ctl, dir);
407 00f0146a 2010-11-09 rsc for(;;){
408 00f0146a 2010-11-09 rsc /*
409 00f0146a 2010-11-09 rsc * wait for a call (or an error)
410 00f0146a 2010-11-09 rsc */
411 00f0146a 2010-11-09 rsc nctl = listen(dir, ndir);
412 00f0146a 2010-11-09 rsc if(0) print("httpd listen %d %s...\n", nctl, ndir);
413 00f0146a 2010-11-09 rsc if(nctl < 0){
414 00f0146a 2010-11-09 rsc fprint(2, "mgr: httpd can't listen on %s: %r\n", address);
415 00f0146a 2010-11-09 rsc return;
416 00f0146a 2010-11-09 rsc }
417 00f0146a 2010-11-09 rsc
418 00f0146a 2010-11-09 rsc data = accept(ctl, ndir);
419 00f0146a 2010-11-09 rsc if(0) print("httpd accept %d...\n", data);
420 00f0146a 2010-11-09 rsc if(data < 0){
421 00f0146a 2010-11-09 rsc fprint(2, "mgr: httpd accept: %r\n");
422 00f0146a 2010-11-09 rsc close(nctl);
423 00f0146a 2010-11-09 rsc continue;
424 00f0146a 2010-11-09 rsc }
425 00f0146a 2010-11-09 rsc if(0) print("httpd close nctl %d\n", nctl);
426 00f0146a 2010-11-09 rsc close(nctl);
427 00f0146a 2010-11-09 rsc c = mkconnect();
428 00f0146a 2010-11-09 rsc hinit(&c->hin, data, Hread);
429 00f0146a 2010-11-09 rsc hinit(&c->hout, data, Hwrite);
430 00f0146a 2010-11-09 rsc vtproc(httpproc, c);
431 00f0146a 2010-11-09 rsc }
432 00f0146a 2010-11-09 rsc }
433 00f0146a 2010-11-09 rsc
434 bd51695c 2011-11-21 rsc static void
435 00f0146a 2010-11-09 rsc httpproc(void *v)
436 00f0146a 2010-11-09 rsc {
437 00f0146a 2010-11-09 rsc HConnect *c;
438 00f0146a 2010-11-09 rsc int ok, i, n;
439 00f0146a 2010-11-09 rsc
440 00f0146a 2010-11-09 rsc c = v;
441 00f0146a 2010-11-09 rsc
442 00f0146a 2010-11-09 rsc for(;;){
443 00f0146a 2010-11-09 rsc /*
444 00f0146a 2010-11-09 rsc * No timeout because the signal appears to hit every
445 00f0146a 2010-11-09 rsc * proc, not just us.
446 00f0146a 2010-11-09 rsc */
447 00f0146a 2010-11-09 rsc if(hparsereq(c, 0) < 0)
448 00f0146a 2010-11-09 rsc break;
449 fa325e9b 2020-01-10 cross
450 00f0146a 2010-11-09 rsc for(i = 0; i < MaxObjs && objs[i].name[0]; i++){
451 00f0146a 2010-11-09 rsc n = strlen(objs[i].name);
452 00f0146a 2010-11-09 rsc if((objs[i].name[n-1] == '/' && strncmp(c->req.uri, objs[i].name, n) == 0)
453 00f0146a 2010-11-09 rsc || (objs[i].name[n-1] != '/' && strcmp(c->req.uri, objs[i].name) == 0)){
454 00f0146a 2010-11-09 rsc ok = (*objs[i].f)(c);
455 00f0146a 2010-11-09 rsc goto found;
456 00f0146a 2010-11-09 rsc }
457 00f0146a 2010-11-09 rsc }
458 00f0146a 2010-11-09 rsc ok = fromwebdir(c);
459 00f0146a 2010-11-09 rsc found:
460 00f0146a 2010-11-09 rsc hflush(&c->hout);
461 00f0146a 2010-11-09 rsc if(c->head.closeit)
462 00f0146a 2010-11-09 rsc ok = -1;
463 00f0146a 2010-11-09 rsc hreqcleanup(c);
464 00f0146a 2010-11-09 rsc
465 00f0146a 2010-11-09 rsc if(ok < 0)
466 00f0146a 2010-11-09 rsc break;
467 00f0146a 2010-11-09 rsc }
468 00f0146a 2010-11-09 rsc hreqcleanup(c);
469 00f0146a 2010-11-09 rsc close(c->hin.fd);
470 00f0146a 2010-11-09 rsc free(c);
471 00f0146a 2010-11-09 rsc }
472 00f0146a 2010-11-09 rsc
473 00f0146a 2010-11-09 rsc static int
474 00f0146a 2010-11-09 rsc httpdobj(char *name, int (*f)(HConnect*))
475 00f0146a 2010-11-09 rsc {
476 00f0146a 2010-11-09 rsc int i;
477 00f0146a 2010-11-09 rsc
478 00f0146a 2010-11-09 rsc if(name == nil || strlen(name) >= ObjNameSize)
479 00f0146a 2010-11-09 rsc return -1;
480 00f0146a 2010-11-09 rsc for(i = 0; i < MaxObjs; i++){
481 00f0146a 2010-11-09 rsc if(objs[i].name[0] == '\0'){
482 00f0146a 2010-11-09 rsc strcpy(objs[i].name, name);
483 00f0146a 2010-11-09 rsc objs[i].f = f;
484 00f0146a 2010-11-09 rsc return 0;
485 00f0146a 2010-11-09 rsc }
486 00f0146a 2010-11-09 rsc if(strcmp(objs[i].name, name) == 0)
487 00f0146a 2010-11-09 rsc return -1;
488 00f0146a 2010-11-09 rsc }
489 00f0146a 2010-11-09 rsc return -1;
490 00f0146a 2010-11-09 rsc }
491 00f0146a 2010-11-09 rsc
492 00f0146a 2010-11-09 rsc
493 00f0146a 2010-11-09 rsc struct {
494 00f0146a 2010-11-09 rsc char *ext;
495 00f0146a 2010-11-09 rsc char *type;
496 00f0146a 2010-11-09 rsc } exttab[] = {
497 00f0146a 2010-11-09 rsc ".html", "text/html",
498 00f0146a 2010-11-09 rsc ".txt", "text/plain",
499 00f0146a 2010-11-09 rsc ".xml", "text/xml",
500 00f0146a 2010-11-09 rsc ".png", "image/png",
501 00f0146a 2010-11-09 rsc ".gif", "image/gif",
502 00f0146a 2010-11-09 rsc 0
503 00f0146a 2010-11-09 rsc };
504 00f0146a 2010-11-09 rsc
505 00f0146a 2010-11-09 rsc static int
506 00f0146a 2010-11-09 rsc fromwebdir(HConnect *c)
507 00f0146a 2010-11-09 rsc {
508 00f0146a 2010-11-09 rsc char buf[4096], *p, *ext, *type;
509 00f0146a 2010-11-09 rsc int i, fd, n, defaulted;
510 00f0146a 2010-11-09 rsc Dir *d;
511 fa325e9b 2020-01-10 cross
512 00f0146a 2010-11-09 rsc if(conf.webroot == nil || strstr(c->req.uri, ".."))
513 00f0146a 2010-11-09 rsc return hnotfound(c);
514 00f0146a 2010-11-09 rsc snprint(buf, sizeof buf-20, "%s/%s", conf.webroot, c->req.uri+1);
515 00f0146a 2010-11-09 rsc defaulted = 0;
516 00f0146a 2010-11-09 rsc reopen:
517 00f0146a 2010-11-09 rsc if((fd = open(buf, OREAD)) < 0)
518 00f0146a 2010-11-09 rsc return hnotfound(c);
519 00f0146a 2010-11-09 rsc d = dirfstat(fd);
520 00f0146a 2010-11-09 rsc if(d == nil){
521 00f0146a 2010-11-09 rsc close(fd);
522 00f0146a 2010-11-09 rsc return hnotfound(c);
523 00f0146a 2010-11-09 rsc }
524 00f0146a 2010-11-09 rsc if(d->mode&DMDIR){
525 00f0146a 2010-11-09 rsc if(!defaulted){
526 00f0146a 2010-11-09 rsc defaulted = 1;
527 00f0146a 2010-11-09 rsc strcat(buf, "/index.html");
528 00f0146a 2010-11-09 rsc free(d);
529 00f0146a 2010-11-09 rsc close(fd);
530 00f0146a 2010-11-09 rsc goto reopen;
531 00f0146a 2010-11-09 rsc }
532 00f0146a 2010-11-09 rsc free(d);
533 00f0146a 2010-11-09 rsc return hnotfound(c);
534 00f0146a 2010-11-09 rsc }
535 00f0146a 2010-11-09 rsc free(d);
536 00f0146a 2010-11-09 rsc p = buf+strlen(buf);
537 00f0146a 2010-11-09 rsc type = "application/octet-stream";
538 00f0146a 2010-11-09 rsc for(i=0; exttab[i].ext; i++){
539 00f0146a 2010-11-09 rsc ext = exttab[i].ext;
540 00f0146a 2010-11-09 rsc if(p-strlen(ext) >= buf && strcmp(p-strlen(ext), ext) == 0){
541 00f0146a 2010-11-09 rsc type = exttab[i].type;
542 00f0146a 2010-11-09 rsc break;
543 00f0146a 2010-11-09 rsc }
544 00f0146a 2010-11-09 rsc }
545 00f0146a 2010-11-09 rsc if(hsettype(c, type) < 0){
546 00f0146a 2010-11-09 rsc close(fd);
547 00f0146a 2010-11-09 rsc return 0;
548 00f0146a 2010-11-09 rsc }
549 00f0146a 2010-11-09 rsc while((n = read(fd, buf, sizeof buf)) > 0)
550 00f0146a 2010-11-09 rsc if(hwrite(&c->hout, buf, n) < 0)
551 00f0146a 2010-11-09 rsc break;
552 00f0146a 2010-11-09 rsc close(fd);
553 00f0146a 2010-11-09 rsc hflush(&c->hout);
554 00f0146a 2010-11-09 rsc return 0;
555 00f0146a 2010-11-09 rsc }
556 00f0146a 2010-11-09 rsc
557 00f0146a 2010-11-09 rsc static int
558 00f0146a 2010-11-09 rsc hmanager(HConnect *c)
559 00f0146a 2010-11-09 rsc {
560 00f0146a 2010-11-09 rsc Hio *hout;
561 00f0146a 2010-11-09 rsc int r;
562 00f0146a 2010-11-09 rsc int i, k;
563 00f0146a 2010-11-09 rsc Job *j;
564 00f0146a 2010-11-09 rsc VtLog *l;
565 00f0146a 2010-11-09 rsc VtLogChunk *ch;
566 00f0146a 2010-11-09 rsc
567 00f0146a 2010-11-09 rsc r = hsethtml(c);
568 00f0146a 2010-11-09 rsc if(r < 0)
569 00f0146a 2010-11-09 rsc return r;
570 00f0146a 2010-11-09 rsc
571 00f0146a 2010-11-09 rsc hout = &c->hout;
572 00f0146a 2010-11-09 rsc hprint(hout, "<html><head><title>venti mgr status</title></head>\n");
573 00f0146a 2010-11-09 rsc hprint(hout, "<body><h2>venti mgr status</h2>\n");
574 00f0146a 2010-11-09 rsc
575 00f0146a 2010-11-09 rsc for(i=0; i<njob; i++) {
576 00f0146a 2010-11-09 rsc j = &job[i];
577 00f0146a 2010-11-09 rsc hprint(hout, "<b>");
578 00f0146a 2010-11-09 rsc if(j->nrun == 0)
579 00f0146a 2010-11-09 rsc hprint(hout, "----/--/-- --:--:--");
580 00f0146a 2010-11-09 rsc else
581 00f0146a 2010-11-09 rsc hprint(hout, "%+T", (long)(j->runstart + time0));
582 00f0146a 2010-11-09 rsc hprint(hout, " %s", j->name);
583 00f0146a 2010-11-09 rsc if(j->nrun > 0) {
584 00f0146a 2010-11-09 rsc if(j->newok == -1) {
585 00f0146a 2010-11-09 rsc hprint(hout, " (running)");
586 00f0146a 2010-11-09 rsc } else if(!j->newok) {
587 00f0146a 2010-11-09 rsc hprint(hout, " <font color=\"#cc0000\">(FAILED)</font>");
588 00f0146a 2010-11-09 rsc }
589 00f0146a 2010-11-09 rsc }
590 00f0146a 2010-11-09 rsc hprint(hout, "</b>\n");
591 00f0146a 2010-11-09 rsc hprint(hout, "<font size=-1><pre>\n");
592 00f0146a 2010-11-09 rsc l = j->newlog;
593 00f0146a 2010-11-09 rsc ch = l->w;
594 00f0146a 2010-11-09 rsc for(k=0; k<l->nchunk; k++){
595 00f0146a 2010-11-09 rsc if(++ch == l->chunk+l->nchunk)
596 00f0146a 2010-11-09 rsc ch = l->chunk;
597 00f0146a 2010-11-09 rsc hwrite(hout, ch->p, ch->wp-ch->p);
598 00f0146a 2010-11-09 rsc }
599 00f0146a 2010-11-09 rsc hprint(hout, "</pre></font>\n");
600 00f0146a 2010-11-09 rsc hprint(hout, "\n");
601 00f0146a 2010-11-09 rsc }
602 00f0146a 2010-11-09 rsc hprint(hout, "</body></html>\n");
603 00f0146a 2010-11-09 rsc hflush(hout);
604 00f0146a 2010-11-09 rsc return 0;
605 00f0146a 2010-11-09 rsc }
606 00f0146a 2010-11-09 rsc
607 00f0146a 2010-11-09 rsc void
608 00f0146a 2010-11-09 rsc piper(void *v)
609 00f0146a 2010-11-09 rsc {
610 00f0146a 2010-11-09 rsc Job *j;
611 00f0146a 2010-11-09 rsc char buf[512];
612 00f0146a 2010-11-09 rsc VtLog *l;
613 00f0146a 2010-11-09 rsc int n;
614 00f0146a 2010-11-09 rsc int fd;
615 00f0146a 2010-11-09 rsc char *p;
616 00f0146a 2010-11-09 rsc int ok;
617 fa325e9b 2020-01-10 cross
618 00f0146a 2010-11-09 rsc j = v;
619 00f0146a 2010-11-09 rsc fd = j->pipe;
620 00f0146a 2010-11-09 rsc l = j->newlog;
621 00f0146a 2010-11-09 rsc while((n = read(fd, buf, 512-1)) > 0) {
622 00f0146a 2010-11-09 rsc buf[n] = 0;
623 00f0146a 2010-11-09 rsc if(l != nil)
624 00f0146a 2010-11-09 rsc vtlogprint(l, "%s", buf);
625 00f0146a 2010-11-09 rsc }
626 00f0146a 2010-11-09 rsc qlock(&loglk);
627 00f0146a 2010-11-09 rsc p = logtext(l);
628 fa325e9b 2020-01-10 cross ok = j->ok(p);
629 00f0146a 2010-11-09 rsc qunlock(&loglk);
630 00f0146a 2010-11-09 rsc j->newok = ok;
631 00f0146a 2010-11-09 rsc close(fd);
632 00f0146a 2010-11-09 rsc }
633 00f0146a 2010-11-09 rsc
634 00f0146a 2010-11-09 rsc void
635 00f0146a 2010-11-09 rsc kickjob(Job *j)
636 00f0146a 2010-11-09 rsc {
637 00f0146a 2010-11-09 rsc int i;
638 00f0146a 2010-11-09 rsc int fd[3];
639 00f0146a 2010-11-09 rsc int p[2];
640 00f0146a 2010-11-09 rsc VtLog *l;
641 00f0146a 2010-11-09 rsc
642 00f0146a 2010-11-09 rsc if((fd[0] = open("/dev/null", ORDWR)) < 0) {
643 00f0146a 2010-11-09 rsc vtlogprint(errlog, "%T open /dev/null: %r\n");
644 00f0146a 2010-11-09 rsc return;
645 00f0146a 2010-11-09 rsc }
646 00f0146a 2010-11-09 rsc if(pipe(p) < 0) {
647 00f0146a 2010-11-09 rsc vtlogprint(errlog, "%T pipe: %r\n");
648 00f0146a 2010-11-09 rsc close(fd[0]);
649 00f0146a 2010-11-09 rsc return;
650 00f0146a 2010-11-09 rsc }
651 00f0146a 2010-11-09 rsc qlock(&j->lk);
652 00f0146a 2010-11-09 rsc l = j->oldlog;
653 00f0146a 2010-11-09 rsc j->oldlog = j->newlog;
654 00f0146a 2010-11-09 rsc j->newlog = l;
655 00f0146a 2010-11-09 rsc qlock(&l->lk);
656 00f0146a 2010-11-09 rsc for(i=0; i<l->nchunk; i++)
657 00f0146a 2010-11-09 rsc l->chunk[i].wp = l->chunk[i].p;
658 00f0146a 2010-11-09 rsc qunlock(&l->lk);
659 00f0146a 2010-11-09 rsc j->oldok = j->newok;
660 00f0146a 2010-11-09 rsc j->newok = -1;
661 00f0146a 2010-11-09 rsc qunlock(&j->lk);
662 00f0146a 2010-11-09 rsc
663 00f0146a 2010-11-09 rsc fd[1] = p[1];
664 00f0146a 2010-11-09 rsc fd[2] = p[1];
665 00f0146a 2010-11-09 rsc j->pid = threadspawn(fd, j->argv[0], j->argv);
666 00f0146a 2010-11-09 rsc if(j->pid < 0) {
667 00f0146a 2010-11-09 rsc vtlogprint(errlog, "%T exec %s: %r\n", j->argv[0]);
668 00f0146a 2010-11-09 rsc close(fd[0]);
669 00f0146a 2010-11-09 rsc close(fd[1]);
670 00f0146a 2010-11-09 rsc close(p[0]);
671 00f0146a 2010-11-09 rsc }
672 00f0146a 2010-11-09 rsc // fd[0], fd[1], fd[2] are closed now
673 00f0146a 2010-11-09 rsc j->pipe = p[0];
674 00f0146a 2010-11-09 rsc j->nrun++;
675 00f0146a 2010-11-09 rsc vtproc(piper, j);
676 00f0146a 2010-11-09 rsc }
677 00f0146a 2010-11-09 rsc
678 00f0146a 2010-11-09 rsc int
679 00f0146a 2010-11-09 rsc getline(Resub *text, Resub *line)
680 00f0146a 2010-11-09 rsc {
681 00f0146a 2010-11-09 rsc char *p;
682 00f0146a 2010-11-09 rsc
683 bd51695c 2011-11-21 rsc if(text->sp >= text->ep)
684 00f0146a 2010-11-09 rsc return -1;
685 bd51695c 2011-11-21 rsc line->sp = text->sp;
686 bd51695c 2011-11-21 rsc p = memchr(text->sp, '\n', text->ep - text->sp);
687 00f0146a 2010-11-09 rsc if(p == nil) {
688 bd51695c 2011-11-21 rsc line->ep = text->ep;
689 bd51695c 2011-11-21 rsc text->sp = text->ep;
690 bd51695c 2011-11-21 rsc } else {
691 bd51695c 2011-11-21 rsc line->ep = p;
692 bd51695c 2011-11-21 rsc text->sp = p+1;
693 00f0146a 2010-11-09 rsc }
694 bd51695c 2011-11-21 rsc return 0;
695 00f0146a 2010-11-09 rsc }
696 00f0146a 2010-11-09 rsc
697 00f0146a 2010-11-09 rsc int
698 bd51695c 2011-11-21 rsc verifyok(char *output)
699 00f0146a 2010-11-09 rsc {
700 00f0146a 2010-11-09 rsc Resub text, line, m;
701 00f0146a 2010-11-09 rsc
702 bd51695c 2011-11-21 rsc text.sp = output;
703 bd51695c 2011-11-21 rsc text.ep = output+strlen(output);
704 00f0146a 2010-11-09 rsc while(getline(&text, &line) >= 0) {
705 bd51695c 2011-11-21 rsc *line.ep = 0;
706 00f0146a 2010-11-09 rsc memset(&m, 0, sizeof m);
707 bd51695c 2011-11-21 rsc if(!regexec(verifyprog, line.sp, nil, 0))
708 00f0146a 2010-11-09 rsc return 0;
709 bd51695c 2011-11-21 rsc *line.ep = '\n';
710 00f0146a 2010-11-09 rsc }
711 00f0146a 2010-11-09 rsc return 1;
712 00f0146a 2010-11-09 rsc }
713 00f0146a 2010-11-09 rsc
714 bd51695c 2011-11-21 rsc int
715 bd51695c 2011-11-21 rsc mirrorok(char *output)
716 bd51695c 2011-11-21 rsc {
717 bd51695c 2011-11-21 rsc Resub text, line, m;
718 bd51695c 2011-11-21 rsc
719 bd51695c 2011-11-21 rsc text.sp = output;
720 bd51695c 2011-11-21 rsc text.ep = output+strlen(output);
721 bd51695c 2011-11-21 rsc while(getline(&text, &line) >= 0) {
722 bd51695c 2011-11-21 rsc *line.ep = 0;
723 bd51695c 2011-11-21 rsc memset(&m, 0, sizeof m);
724 bd51695c 2011-11-21 rsc if(!regexec(mirrorprog, line.sp, nil, 0))
725 bd51695c 2011-11-21 rsc return 0;
726 bd51695c 2011-11-21 rsc *line.ep = '\n';
727 bd51695c 2011-11-21 rsc }
728 bd51695c 2011-11-21 rsc return 1;
729 bd51695c 2011-11-21 rsc }
730 bd51695c 2011-11-21 rsc
731 00f0146a 2010-11-09 rsc void
732 00f0146a 2010-11-09 rsc mkjob(Job *j, ...)
733 00f0146a 2010-11-09 rsc {
734 00f0146a 2010-11-09 rsc int i;
735 00f0146a 2010-11-09 rsc char *p;
736 00f0146a 2010-11-09 rsc va_list arg;
737 00f0146a 2010-11-09 rsc
738 00f0146a 2010-11-09 rsc memset(j, 0, sizeof *j);
739 00f0146a 2010-11-09 rsc i = 0;
740 00f0146a 2010-11-09 rsc va_start(arg, j);
741 00f0146a 2010-11-09 rsc while((p = va_arg(arg, char*)) != nil) {
742 00f0146a 2010-11-09 rsc j->argv[i++] = p;
743 00f0146a 2010-11-09 rsc if(i >= nelem(j->argv))
744 00f0146a 2010-11-09 rsc sysfatal("job argv size too small");
745 00f0146a 2010-11-09 rsc }
746 00f0146a 2010-11-09 rsc j->argv[i] = nil;
747 bd51695c 2011-11-21 rsc j->oldlog = vtlogopen(smprint("log%ld.0", j-job), LogSize);
748 bd51695c 2011-11-21 rsc j->newlog = vtlogopen(smprint("log%ld.1", j-job), LogSize);
749 00f0146a 2010-11-09 rsc va_end(arg);
750 00f0146a 2010-11-09 rsc }
751 00f0146a 2010-11-09 rsc
752 00f0146a 2010-11-09 rsc void
753 00f0146a 2010-11-09 rsc manager(void *v)
754 00f0146a 2010-11-09 rsc {
755 00f0146a 2010-11-09 rsc int i;
756 00f0146a 2010-11-09 rsc Job *j;
757 00f0146a 2010-11-09 rsc vlong now;
758 00f0146a 2010-11-09 rsc
759 bd51695c 2011-11-21 rsc USED(v);
760 00f0146a 2010-11-09 rsc for(;; sleep(1000)) {
761 00f0146a 2010-11-09 rsc for(i=0; i<njob; i++) {
762 00f0146a 2010-11-09 rsc now = time(0) - time0;
763 00f0146a 2010-11-09 rsc j = &job[i];
764 00f0146a 2010-11-09 rsc if(j->pid > 0 || j->newok == -1) {
765 00f0146a 2010-11-09 rsc // still running
766 00f0146a 2010-11-09 rsc if(now - j->runstart > 2*j->freq) {
767 00f0146a 2010-11-09 rsc //TODO: log slow running j
768 00f0146a 2010-11-09 rsc }
769 00f0146a 2010-11-09 rsc continue;
770 00f0146a 2010-11-09 rsc }
771 00f0146a 2010-11-09 rsc if((j->nrun > 0 && now - j->runend > j->freq)
772 00f0146a 2010-11-09 rsc || (j->nrun == 0 && now > (vlong)(j->offset*j->freq))) {
773 00f0146a 2010-11-09 rsc j->runstart = now;
774 00f0146a 2010-11-09 rsc j->runend = 0;
775 00f0146a 2010-11-09 rsc kickjob(j);
776 00f0146a 2010-11-09 rsc }
777 00f0146a 2010-11-09 rsc }
778 00f0146a 2010-11-09 rsc }
779 00f0146a 2010-11-09 rsc }
780 00f0146a 2010-11-09 rsc
781 00f0146a 2010-11-09 rsc void
782 00f0146a 2010-11-09 rsc waitproc(void *v)
783 00f0146a 2010-11-09 rsc {
784 00f0146a 2010-11-09 rsc Channel *c;
785 00f0146a 2010-11-09 rsc Waitmsg *w;
786 00f0146a 2010-11-09 rsc int i;
787 00f0146a 2010-11-09 rsc Job *j;
788 00f0146a 2010-11-09 rsc
789 00f0146a 2010-11-09 rsc c = v;
790 00f0146a 2010-11-09 rsc for(;;) {
791 00f0146a 2010-11-09 rsc w = recvp(c);
792 00f0146a 2010-11-09 rsc for(i=0; i<njob; i++) {
793 00f0146a 2010-11-09 rsc j = &job[i];
794 00f0146a 2010-11-09 rsc if(j->pid == w->pid) {
795 00f0146a 2010-11-09 rsc j->pid = 0;
796 00f0146a 2010-11-09 rsc j->runend = time(0) - time0;
797 00f0146a 2010-11-09 rsc break;
798 00f0146a 2010-11-09 rsc }
799 00f0146a 2010-11-09 rsc }
800 00f0146a 2010-11-09 rsc free(w);
801 00f0146a 2010-11-09 rsc }
802 00f0146a 2010-11-09 rsc }
803 00f0146a 2010-11-09 rsc
804 00f0146a 2010-11-09 rsc void
805 00f0146a 2010-11-09 rsc threadmain(int argc, char **argv)
806 00f0146a 2010-11-09 rsc {
807 00f0146a 2010-11-09 rsc int i;
808 00f0146a 2010-11-09 rsc int nofork;
809 00f0146a 2010-11-09 rsc char *prog;
810 00f0146a 2010-11-09 rsc Job *j;
811 fa325e9b 2020-01-10 cross
812 00f0146a 2010-11-09 rsc ventilogging = 1;
813 00f0146a 2010-11-09 rsc ventifmtinstall();
814 bd51695c 2011-11-21 rsc #ifdef PLAN9PORT
815 00f0146a 2010-11-09 rsc bin = unsharp("#9/bin/venti");
816 bd51695c 2011-11-21 rsc #else
817 bd51695c 2011-11-21 rsc bin = "/bin/venti";
818 bd51695c 2011-11-21 rsc #endif
819 00f0146a 2010-11-09 rsc nofork = 0;
820 00f0146a 2010-11-09 rsc ARGBEGIN{
821 00f0146a 2010-11-09 rsc case 'b':
822 00f0146a 2010-11-09 rsc bin = EARGF(usage());
823 00f0146a 2010-11-09 rsc break;
824 00f0146a 2010-11-09 rsc case 's':
825 00f0146a 2010-11-09 rsc nofork = 1;
826 00f0146a 2010-11-09 rsc break;
827 00f0146a 2010-11-09 rsc default:
828 00f0146a 2010-11-09 rsc usage();
829 00f0146a 2010-11-09 rsc }ARGEND
830 00f0146a 2010-11-09 rsc
831 00f0146a 2010-11-09 rsc if(argc != 1)
832 00f0146a 2010-11-09 rsc usage();
833 00f0146a 2010-11-09 rsc if(rdconf(argv[0], &conf) < 0)
834 00f0146a 2010-11-09 rsc sysfatal("reading config: %r");
835 00f0146a 2010-11-09 rsc if(conf.httpaddr == nil)
836 00f0146a 2010-11-09 rsc sysfatal("config has no httpaddr");
837 00f0146a 2010-11-09 rsc if(conf.smtp != nil && conf.mailfrom == nil)
838 00f0146a 2010-11-09 rsc sysfatal("config has smtp but no mailfrom");
839 00f0146a 2010-11-09 rsc if(conf.smtp != nil && conf.mailto == nil)
840 00f0146a 2010-11-09 rsc sysfatal("config has smtp but no mailto");
841 00f0146a 2010-11-09 rsc if((mirrorprog = regcomp(mirrorregexp)) == nil)
842 bd51695c 2011-11-21 rsc sysfatal("mirrorregexp did not complete");
843 bd51695c 2011-11-21 rsc if((verifyprog = regcomp(verifyregexp)) == nil)
844 bd51695c 2011-11-21 rsc sysfatal("verifyregexp did not complete");
845 00f0146a 2010-11-09 rsc if(conf.nverify > 0 && conf.verifyfreq == 0)
846 00f0146a 2010-11-09 rsc sysfatal("config has no verifyfreq");
847 00f0146a 2010-11-09 rsc if(conf.nmirror > 0 && conf.mirrorfreq == 0)
848 00f0146a 2010-11-09 rsc sysfatal("config has no mirrorfreq");
849 00f0146a 2010-11-09 rsc
850 00f0146a 2010-11-09 rsc time0 = time(0);
851 00f0146a 2010-11-09 rsc // sendmail("startup", "mgr is starting\n");
852 00f0146a 2010-11-09 rsc
853 00f0146a 2010-11-09 rsc logbuf = vtmalloc(LogSize+1); // +1 for NUL
854 00f0146a 2010-11-09 rsc
855 00f0146a 2010-11-09 rsc errlog = vtlogopen("errors", LogSize);
856 00f0146a 2010-11-09 rsc job = vtmalloc((conf.nmirror+conf.nverify)*sizeof job[0]);
857 00f0146a 2010-11-09 rsc prog = smprint("%s/mirrorarenas", bin);
858 00f0146a 2010-11-09 rsc for(i=0; i<conf.nmirror; i++) {
859 00f0146a 2010-11-09 rsc // job: /bin/venti/mirrorarenas -v src dst
860 00f0146a 2010-11-09 rsc // filter output
861 00f0146a 2010-11-09 rsc j = &job[njob++];
862 bd51695c 2011-11-21 rsc mkjob(j, prog, "-v", conf.mirror[i].src, conf.mirror[i].dst, nil);
863 00f0146a 2010-11-09 rsc j->name = smprint("mirror %s %s", conf.mirror[i].src, conf.mirror[i].dst);
864 00f0146a 2010-11-09 rsc j->ok = mirrorok;
865 00f0146a 2010-11-09 rsc j->freq = conf.mirrorfreq; // 4 hours // TODO: put in config
866 00f0146a 2010-11-09 rsc j->offset = (double)i/conf.nmirror;
867 00f0146a 2010-11-09 rsc }
868 00f0146a 2010-11-09 rsc
869 00f0146a 2010-11-09 rsc prog = smprint("%s/verifyarena", bin);
870 00f0146a 2010-11-09 rsc for(i=0; i<conf.nverify; i++) {
871 00f0146a 2010-11-09 rsc // job: /bin/venti/verifyarena -b 64M -s 1000 -v arena
872 00f0146a 2010-11-09 rsc // filter output
873 00f0146a 2010-11-09 rsc j = &job[njob++];
874 bd51695c 2011-11-21 rsc mkjob(j, prog, "-b64M", "-s1000", conf.verify[i], nil);
875 00f0146a 2010-11-09 rsc j->name = smprint("verify %s", conf.verify[i]);
876 00f0146a 2010-11-09 rsc j->ok = verifyok;
877 00f0146a 2010-11-09 rsc j->freq = conf.verifyfreq;
878 00f0146a 2010-11-09 rsc j->offset = (double)i/conf.nverify;
879 00f0146a 2010-11-09 rsc }
880 00f0146a 2010-11-09 rsc
881 00f0146a 2010-11-09 rsc httpdobj("/mgr", hmanager);
882 00f0146a 2010-11-09 rsc httpdobj("/log", xlog);
883 00f0146a 2010-11-09 rsc vtproc(httpdproc, conf.httpaddr);
884 00f0146a 2010-11-09 rsc vtproc(waitproc, threadwaitchan());
885 00f0146a 2010-11-09 rsc if(nofork)
886 00f0146a 2010-11-09 rsc manager(nil);
887 00f0146a 2010-11-09 rsc else
888 00f0146a 2010-11-09 rsc vtproc(manager, nil);
889 00f0146a 2010-11-09 rsc }
890 00f0146a 2010-11-09 rsc
891 00f0146a 2010-11-09 rsc
892 00f0146a 2010-11-09 rsc void
893 00f0146a 2010-11-09 rsc qp(Biobuf *b, char *p)
894 00f0146a 2010-11-09 rsc {
895 00f0146a 2010-11-09 rsc int n, nspace;
896 fa325e9b 2020-01-10 cross
897 fa325e9b 2020-01-10 cross nspace = 0;
898 00f0146a 2010-11-09 rsc n = 0;
899 00f0146a 2010-11-09 rsc for(; *p; p++) {
900 00f0146a 2010-11-09 rsc if(*p == '\n') {
901 00f0146a 2010-11-09 rsc if(nspace > 0) {
902 00f0146a 2010-11-09 rsc nspace = 0;
903 00f0146a 2010-11-09 rsc Bprint(b, "=\n");
904 00f0146a 2010-11-09 rsc }
905 00f0146a 2010-11-09 rsc Bputc(b, '\n');
906 00f0146a 2010-11-09 rsc n = 0;
907 00f0146a 2010-11-09 rsc continue;
908 00f0146a 2010-11-09 rsc }
909 00f0146a 2010-11-09 rsc if(n > 70) {
910 00f0146a 2010-11-09 rsc Bprint(b, "=\n");
911 00f0146a 2010-11-09 rsc nspace = 0;
912 00f0146a 2010-11-09 rsc continue;
913 00f0146a 2010-11-09 rsc }
914 00f0146a 2010-11-09 rsc if(33 <= *p && *p <= 126 && *p != '=') {
915 00f0146a 2010-11-09 rsc Bputc(b, *p);
916 00f0146a 2010-11-09 rsc n++;
917 00f0146a 2010-11-09 rsc nspace = 0;
918 00f0146a 2010-11-09 rsc continue;
919 00f0146a 2010-11-09 rsc }
920 00f0146a 2010-11-09 rsc if(*p == ' ' || *p == '\t') {
921 00f0146a 2010-11-09 rsc Bputc(b, *p);
922 00f0146a 2010-11-09 rsc n++;
923 00f0146a 2010-11-09 rsc nspace++;
924 00f0146a 2010-11-09 rsc continue;
925 00f0146a 2010-11-09 rsc }
926 00f0146a 2010-11-09 rsc Bprint(b, "=%02X", (uchar)*p);
927 00f0146a 2010-11-09 rsc n += 3;
928 00f0146a 2010-11-09 rsc nspace = 0;
929 00f0146a 2010-11-09 rsc }
930 00f0146a 2010-11-09 rsc }
931 00f0146a 2010-11-09 rsc
932 00f0146a 2010-11-09 rsc int
933 00f0146a 2010-11-09 rsc smtpread(Biobuf *b, int code)
934 00f0146a 2010-11-09 rsc {
935 00f0146a 2010-11-09 rsc char *p, *q;
936 00f0146a 2010-11-09 rsc int n;
937 fa325e9b 2020-01-10 cross
938 00f0146a 2010-11-09 rsc while((p = Brdstr(b, '\n', 1)) != nil) {
939 00f0146a 2010-11-09 rsc n = strtol(p, &q, 10);
940 00f0146a 2010-11-09 rsc if(n == 0 || q != p+3) {
941 00f0146a 2010-11-09 rsc error:
942 00f0146a 2010-11-09 rsc vtlogprint(errlog, "sending mail: %s\n", p);
943 00f0146a 2010-11-09 rsc free(p);
944 00f0146a 2010-11-09 rsc return -1;
945 00f0146a 2010-11-09 rsc }
946 00f0146a 2010-11-09 rsc if(*q == ' ') {
947 00f0146a 2010-11-09 rsc if(n == code) {
948 00f0146a 2010-11-09 rsc free(p);
949 00f0146a 2010-11-09 rsc return 0;
950 00f0146a 2010-11-09 rsc }
951 00f0146a 2010-11-09 rsc goto error;
952 00f0146a 2010-11-09 rsc }
953 00f0146a 2010-11-09 rsc if(*q != '-') {
954 00f0146a 2010-11-09 rsc goto error;
955 00f0146a 2010-11-09 rsc }
956 00f0146a 2010-11-09 rsc }
957 00f0146a 2010-11-09 rsc return -1;
958 00f0146a 2010-11-09 rsc }
959 00f0146a 2010-11-09 rsc
960 fa325e9b 2020-01-10 cross
961 00f0146a 2010-11-09 rsc void
962 00f0146a 2010-11-09 rsc sendmail(char *content, char *subject, char *msg)
963 00f0146a 2010-11-09 rsc {
964 00f0146a 2010-11-09 rsc int fd;
965 00f0146a 2010-11-09 rsc Biobuf *bin, *bout;
966 fa325e9b 2020-01-10 cross
967 00f0146a 2010-11-09 rsc if((fd = dial(conf.smtp, 0, 0, 0)) < 0) {
968 00f0146a 2010-11-09 rsc vtlogprint(errlog, "dial %s: %r\n", conf.smtp);
969 00f0146a 2010-11-09 rsc return;
970 00f0146a 2010-11-09 rsc }
971 00f0146a 2010-11-09 rsc bin = vtmalloc(sizeof *bin);
972 00f0146a 2010-11-09 rsc bout = vtmalloc(sizeof *bout);
973 00f0146a 2010-11-09 rsc Binit(bin, fd, OREAD);
974 00f0146a 2010-11-09 rsc Binit(bout, fd, OWRITE);
975 00f0146a 2010-11-09 rsc if(smtpread(bin, 220) < 0){
976 00f0146a 2010-11-09 rsc error:
977 00f0146a 2010-11-09 rsc close(fd);
978 00f0146a 2010-11-09 rsc Bterm(bin);
979 00f0146a 2010-11-09 rsc Bterm(bout);
980 00f0146a 2010-11-09 rsc return;
981 00f0146a 2010-11-09 rsc }
982 fa325e9b 2020-01-10 cross
983 00f0146a 2010-11-09 rsc Bprint(bout, "HELO venti-mgr\n");
984 00f0146a 2010-11-09 rsc Bflush(bout);
985 00f0146a 2010-11-09 rsc if(smtpread(bin, 250) < 0)
986 00f0146a 2010-11-09 rsc goto error;
987 00f0146a 2010-11-09 rsc
988 00f0146a 2010-11-09 rsc Bprint(bout, "MAIL FROM:<%s>\n", conf.mailfrom);
989 00f0146a 2010-11-09 rsc Bflush(bout);
990 00f0146a 2010-11-09 rsc if(smtpread(bin, 250) < 0)
991 00f0146a 2010-11-09 rsc goto error;
992 00f0146a 2010-11-09 rsc
993 00f0146a 2010-11-09 rsc Bprint(bout, "RCPT TO:<%s>\n", conf.mailfrom);
994 00f0146a 2010-11-09 rsc Bflush(bout);
995 00f0146a 2010-11-09 rsc if(smtpread(bin, 250) < 0)
996 00f0146a 2010-11-09 rsc goto error;
997 fa325e9b 2020-01-10 cross
998 00f0146a 2010-11-09 rsc Bprint(bout, "DATA\n");
999 00f0146a 2010-11-09 rsc Bflush(bout);
1000 00f0146a 2010-11-09 rsc if(smtpread(bin, 354) < 0)
1001 00f0146a 2010-11-09 rsc goto error;
1002 fa325e9b 2020-01-10 cross
1003 00f0146a 2010-11-09 rsc Bprint(bout, "From: \"venti mgr\" <%s>\n", conf.mailfrom);
1004 00f0146a 2010-11-09 rsc Bprint(bout, "To: <%s>\n", conf.mailto);
1005 00f0146a 2010-11-09 rsc Bprint(bout, "Subject: %s\n", subject);
1006 00f0146a 2010-11-09 rsc Bprint(bout, "MIME-Version: 1.0\n");
1007 00f0146a 2010-11-09 rsc Bprint(bout, "Content-Type: %s; charset=\"UTF-8\"\n", content);
1008 00f0146a 2010-11-09 rsc Bprint(bout, "Content-Transfer-Encoding: quoted-printable\n");
1009 bd51695c 2011-11-21 rsc Bprint(bout, "Message-ID: %08lux%08lux@venti.swtch.com\n", fastrand(), fastrand());
1010 00f0146a 2010-11-09 rsc Bprint(bout, "\n");
1011 00f0146a 2010-11-09 rsc qp(bout, msg);
1012 00f0146a 2010-11-09 rsc Bprint(bout, ".\n");
1013 00f0146a 2010-11-09 rsc Bflush(bout);
1014 00f0146a 2010-11-09 rsc if(smtpread(bin, 250) < 0)
1015 00f0146a 2010-11-09 rsc goto error;
1016 fa325e9b 2020-01-10 cross
1017 00f0146a 2010-11-09 rsc Bprint(bout, "QUIT\n");
1018 00f0146a 2010-11-09 rsc Bflush(bout);
1019 00f0146a 2010-11-09 rsc Bterm(bin);
1020 00f0146a 2010-11-09 rsc Bterm(bout);
1021 00f0146a 2010-11-09 rsc close(fd);
1022 00f0146a 2010-11-09 rsc }