2 ashd - A Sane HTTP Daemon
3 Copyright (C) 2008 Fredrik Tolf <fredrik@dolda2000.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
39 static int parsefile(struct cfstate *s, FILE *in)
45 int ind, indst[80], indl;
53 if(fgets(line, sizeof(line), in) == NULL) {
58 for(p = line + strlen(line) - 1; p >= line; p--) {
64 for(ind = 0, p = line; *p; p++) {
67 } else if(*p == '\t') {
68 ind = ind - (ind % 8) + 8;
73 if(!eof && (!*p || (*p == '#')))
77 if(ind > indst[indl]) {
80 s->res = tokenize("start");
88 s->res = tokenize("end");
93 while(ind < indst[indl]) {
95 s->res = tokenize("end");
99 if(ind > indst[indl]) {
100 flog(LOG_WARNING, "%s:%i: unexpected indentation level", s->file, s->lno);
108 argc = calen(w = tokenize(line));
110 /* Shouldn't happen, but... */
116 if(!strcmp(w[0], "include")) {
118 for(i = 1; i < argc; i++) {
119 if((ret = glob(w[i], 0, NULL, &globm)) == 0) {
120 for(o = 0; o < globm.gl_pathc; o++) {
121 if((inc = fopen(globm.gl_pathv[o], "r")) != NULL) {
122 s->file = globm.gl_pathv[o];
123 if(parsefile(s, inc)) {
141 if(!strcmp(w[0], "start") ||
142 !strcmp(w[0], "end") ||
143 !strcmp(w[0], "eof")) {
144 flog(LOG_WARNING, "%s:%i: illegal directive: %s", s->file, s->lno, w[0]);
153 static void parsefn(struct muth *mt, va_list args)
155 vavar(struct cfstate *, s);
159 s->file = sstrdup(file);
163 s->res = tokenize("eof");
170 char **getcfline(struct cfstate *s)
175 s->argc = calen(s->argv = s->res);
180 struct cfstate *mkcfparser(FILE *in, char *name)
185 s->pf = mustart(parsefn, s, in, name);
189 void freecfparser(struct cfstate *s)
197 static struct child *newchild(char *name, int type)
202 ch->name = sstrdup(name);
208 void freechild(struct child *ch)
219 void skipcfblock(struct cfstate *s)
225 if(!strcmp(w[0], "end") || !strcmp(w[0], "eof"))
230 struct child *parsechild(struct cfstate *s)
237 if(!strcmp(s->argv[0], "child")) {
240 flog(LOG_WARNING, "%s:%i: missing name in child declaration", s->file, s->lno);
244 ch = newchild(s->argv[1], CH_SOCKET);
245 } else if(!strcmp(s->argv[0], "fchild")) {
248 flog(LOG_WARNING, "%s:%i: missing name in child declaration", s->file, s->lno);
252 ch = newchild(s->argv[1], CH_FORK);
259 if(!strcmp(s->argv[0], "exec")) {
261 flog(LOG_WARNING, "%s:%i: too few parameters to `exec'", s->file, s->lno);
264 ch->argv = szmalloc(sizeof(*ch->argv) * s->argc);
265 for(i = 0; i < s->argc - 1; i++)
266 ch->argv[i] = sstrdup(s->argv[i + 1]);
267 } else if(!strcmp(s->argv[0], "end") || !strcmp(s->argv[0], "eof")) {
270 flog(LOG_WARNING, "%s:%i: unknown directive `%s' in child declaration", s->file, s->lno, s->argv[0]);
273 if(ch->argv == NULL) {
274 flog(LOG_WARNING, "%s:%i: missing `exec' in child declaration %s", s->file, sl, ch->name);
281 int childhandle(struct child *ch, struct hthead *req, int fd)
283 if(ch->type == CH_SOCKET) {
285 ch->fd = stdmkchild(ch->argv);
286 if(sendreq(ch->fd, req, fd)) {
288 /* Assume that the child has crashed and restart it. */
290 ch->fd = stdmkchild(ch->argv);
291 if(!sendreq(ch->fd, req, fd))
294 flog(LOG_ERR, "could not pass on request to child %s: %s", ch->name, strerror(errno));
299 } else if(ch->type == CH_FORK) {
300 if(stdforkserve(ch->argv, req, fd) < 0)