- return(rv);
-}
-
-static struct child *findchild(char *file, char *name)
-{
- char *buf, *p;
- struct config *cf;
- struct child *ch;
-
- buf = sstrdup(file);
- while(1) {
- ch = NULL;
- if(!strcmp(buf, "."))
- break;
- if((p = strrchr(buf, '/')) != NULL)
- *p = 0;
- else
- strcpy(buf, ".");
- cf = getconfig(buf);
- if(cf == NULL)
- continue;
- if((ch = getchild(cf, name)) != NULL)
- break;
- }
- free(buf);
- return(ch);
-}
-
-static struct pattern *findmatch(char *file, int trydefault)
-{
- int i;
- char *buf, *p, *bn;
- struct config *cf;
- struct pattern *pat;
- struct rule *rule;
-
- if((bn = strrchr(file, '/')) != NULL)
- bn++;
- else
- bn = file;
- buf = sstrdup(file);
- while(1) {
- pat = NULL;
- if(!strcmp(buf, "."))
- break;
- if((p = strrchr(buf, '/')) != NULL)
- *p = 0;
- else
- strcpy(buf, ".");
- cf = getconfig(buf);
- if(cf == NULL)
- continue;
- for(pat = cf->patterns; pat != NULL; pat = pat->next) {
- for(i = 0; (rule = pat->rules[i]) != NULL; i++) {
- if(rule->type == PAT_BASENAME) {
- if(fnmatch(rule->pattern, bn, 0))
- break;
- } else if(rule->type == PAT_PATHNAME) {
- if(fnmatch(rule->pattern, file, FNM_PATHNAME))
- break;
- } else if(rule->type == PAT_ALL) {
- } else if(rule->type == PAT_DEFAULT) {
- if(!trydefault)
- break;
- }
- }
- if(!rule)
- goto out;
- }
- }
-
-out:
- free(buf);
- return(pat);
-}
-
-static void forkchild(struct child *ch)
-{
- ch->fd = stdmkchild(ch->argv);
-}
-
-static void passreq(struct child *ch, struct hthead *req, int fd)
-{
- if(ch->fd < 0)
- forkchild(ch);
- if(sendreq(ch->fd, req, fd)) {
- if(errno == EPIPE) {
- /* Assume that the child has crashed and restart it. */
- forkchild(ch);
- if(!sendreq(ch->fd, req, fd))
- return;
- }
- flog(LOG_ERR, "could not pass on request to child %s: %s", ch->name, strerror(errno));
- close(ch->fd);
- ch->fd = -1;
- }
-}
-
-static void serve(struct hthead *req, int fd)
-{
- char *file;
- struct stat sb;
- struct pattern *pat;
- struct child *ch;
-
- if((file = findfile(req)) == NULL) {
- /* XXX: Do 404 handling */
- return;
- }
- if(stat(file, &sb)) {
- flog(LOG_ERR, "could not stat previously found file %s: %s", file, strerror(errno));
- free(file);
- return;
- }
- if(!S_ISREG(sb.st_mode)) {
- /* XXX: Handle default files or similar stuff. */
- free(file);
- return;
- }
- headappheader(req, "X-Ash-File", file);
- if(((pat = findmatch(file, 0)) == NULL) && ((pat = findmatch(file, 1)) == NULL)) {
- /* XXX: Send a 500 error? 404? */
- free(file);
- return;
- }
- if((ch = findchild(file, pat->childnm)) == NULL) {
- /* XXX: Send a 500 error. */
- flog(LOG_ERR, "child %s requested, but was not declared", pat->childnm);
- free(file);
- return;
- }
-
- if(ch->type == CH_SOCKET) {
- passreq(ch, req, fd);
- } else if(ch->type == CH_FORK) {
- stdforkserve(ch->argv, req, fd);
- }
-
- free(file);