lib: Check for ECONNRESET as well to detect crashed children.
[ashd.git] / lib / cf.c
index 82e5fba..fd53c54 100644 (file)
--- a/lib/cf.c
+++ b/lib/cf.c
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <glob.h>
+#include <libgen.h>
 #include <errno.h>
 
 #ifdef HAVE_CONFIG_H
 #define CH_SOCKET 0
 #define CH_FORK 1
 
-static int parsefile(struct cfstate *s, FILE *in)
+static int parsefile(struct cfstate *s, FILE *in);
+
+static int doinclude(struct cfstate *s, char *spec)
 {
-    int i, o, ret;
+    int rv, i;
+    FILE *inc;
     glob_t globm;
+    char *fbk, *dir, *fspec;
+
+    rv = 0;
+    fbk = s->file;
+    if(spec[0] == '/') {
+       fspec = spec;
+    } else {
+       dir = sstrdup(fbk);
+       fspec = sprintf3("%s/%s", dirname(dir), spec);
+       free(dir);
+    }
+    if(glob(fspec, 0, NULL, &globm))
+       return(0);
+    for(i = 0; i < globm.gl_pathc; i++) {
+       if((inc = fopen(globm.gl_pathv[i], "r")) != NULL) {
+           s->file = globm.gl_pathv[i];
+           if(parsefile(s, inc)) {
+               fclose(inc);
+               rv = 1;
+               goto out;
+           }
+           fclose(inc);
+           inc = NULL;
+       }
+    }
+    
+out:
+    globfree(&globm);
+    s->file = fbk;
+    return(rv);
+}
+
+static int parsefile(struct cfstate *s, FILE *in)
+{
+    int i;
     char line[1024];
     int eof, argc;
     int ind, indst[80], indl;
-    char *p, **w, *fbk;
-    FILE *inc;
+    char *p, **w;
     
     s->lno = 0;
     indst[indl = 0] = 0;
@@ -55,11 +93,13 @@ static int parsefile(struct cfstate *s, FILE *in)
            line[0] = 0;
        }
        s->lno++;
-       for(p = line + strlen(line) - 1; p >= line; p--) {
-           if(isspace(*p))
-               *p = 0;
-           else
-               break;
+       if(line[0]) {
+           for(p = line + strlen(line) - 1; p >= line; p--) {
+               if(isspace(*p))
+                   *p = 0;
+               else
+                   break;
+           }
        }
        for(ind = 0, p = line; *p; p++) {
            if(*p == ' ') {
@@ -114,26 +154,13 @@ static int parsefile(struct cfstate *s, FILE *in)
        
        if(indl == 0) {
            if(!strcmp(w[0], "include")) {
-               fbk = s->file;
                for(i = 1; i < argc; i++) {
-                   if((ret = glob(w[i], 0, NULL, &globm)) == 0) {
-                       for(o = 0; o < globm.gl_pathc; o++) {
-                           if((inc = fopen(globm.gl_pathv[o], "r")) != NULL) {
-                               s->file = globm.gl_pathv[o];
-                               if(parsefile(s, inc)) {
-                                   fclose(inc);
-                                   globfree(&globm);
-                                   freeca(w);
-                                   return(1);
-                               }
-                               fclose(inc);
-                           }
-                       }
-                       globfree(&globm);
+                   if(doinclude(s, w[i])) {
+                       freeca(w);
+                       return(1);
                    }
                }
                freeca(w);
-               s->file = fbk;
                continue;
            }
        }
@@ -194,6 +221,27 @@ void freecfparser(struct cfstate *s)
     free(s);
 }
 
+char *findstdconf(char *name)
+{
+    char *path, *p, *p2, *t;
+    
+    if((path = getenv("PATH")) == NULL)
+       return(NULL);
+    path = sstrdup(path);
+    for(p = strtok(path, ":"); p != NULL; p = strtok(NULL, ":")) {
+       if((p2 = strrchr(p, '/')) == NULL)
+           continue;
+       *p2 = 0;
+       if(!access(t = sprintf2("%s/etc/%s", p, name), R_OK)) {
+           free(path);
+           return(t);
+       }
+       free(t);
+    }
+    free(path);
+    return(NULL);
+}
+
 static struct child *newchild(char *name, int type)
 {
     struct child *ch;
@@ -278,16 +326,16 @@ struct child *parsechild(struct cfstate *s)
     return(ch);
 }
 
-int childhandle(struct child *ch, struct hthead *req, int fd)
+int childhandle(struct child *ch, struct hthead *req, int fd, void (*chinit)(void *), void *idata)
 {
     if(ch->type == CH_SOCKET) {
        if(ch->fd < 0)
-           ch->fd = stdmkchild(ch->argv);
+           ch->fd = stdmkchild(ch->argv, chinit, idata);
        if(sendreq(ch->fd, req, fd)) {
-           if(errno == EPIPE) {
+           if((errno == EPIPE) || (errno == ECONNRESET)) {
                /* Assume that the child has crashed and restart it. */
                close(ch->fd);
-               ch->fd = stdmkchild(ch->argv);
+               ch->fd = stdmkchild(ch->argv, chinit, idata);
                if(!sendreq(ch->fd, req, fd))
                    return(0);
            }
@@ -297,7 +345,7 @@ int childhandle(struct child *ch, struct hthead *req, int fd)
            return(-1);
        }
     } else if(ch->type == CH_FORK) {
-       if(stdforkserve(ch->argv, req, fd) < 0)
+       if(stdforkserve(ch->argv, req, fd, chinit, idata) < 0)
            return(-1);
     }
     return(0);