lib: Fixed minor bug in expandargs.
[ashd.git] / lib / cf.c
index 5a6388e..b809d33 100644 (file)
--- a/lib/cf.c
+++ b/lib/cf.c
@@ -24,6 +24,7 @@
 #include <glob.h>
 #include <libgen.h>
 #include <sys/socket.h>
+#include <time.h>
 #include <errno.h>
 
 #ifdef HAVE_CONFIG_H
@@ -43,6 +44,8 @@ struct stdchild {
     char **argv;
     char **envp;
     int fd;
+    int agains;
+    time_t lastrep;
 };
 
 static int parsefile(struct cfstate *s, FILE *in);
@@ -325,8 +328,10 @@ static char **expandargs(struct stdchild *sd)
            for(p2 = sd->argv[i]; p != NULL; p2 = np, p = strchr(np, '$')) {
                bufcat(exp, p2, p - p2);
                if(p[1] == '{') {
-                   if((p3 = strchr((p += 2), '}')) == NULL)
+                   if((p3 = strchr((p += 2), '}')) == NULL) {
+                       np = p;
                        break;
+                   }
                    np = p3 + 1;
                } else {
                    for(p3 = ++p; *p3; p3++) {
@@ -354,26 +359,35 @@ static char **expandargs(struct stdchild *sd)
     return(ret);
 }
 
-static int stdhandle(struct child *ch, struct hthead *req, int fd, void (*chinit)(void *), void *idata)
+struct sidata {
+    struct stdchild *sd;
+    void (*sinit)(void *);
+    void *sdata;
+};
+
+static void stdinit(void *data)
+{
+    struct sidata *d = data;
+    int i;
+       
+    for(i = 0; d->sd->envp[i]; i += 2)
+       putenv(sprintf2("%s=%s", d->sd->envp[i], d->sd->envp[i + 1]));
+    if(d->sinit != NULL)
+       d->sinit(d->sdata);
+}
+
+static int stdhandle(struct child *ch, struct hthead *req, int fd, void (*chinit)(void *), void *sdata)
 {
     struct stdchild *sd = ch->pdata;
     int serr;
     char **args;
-    
-    void stdinit(void *data)
-    {
-       int i;
-       
-       for(i = 0; sd->envp[i]; i += 2)
-           putenv(sprintf2("%s=%s", sd->envp[i], sd->envp[i + 1]));
-       if(chinit != NULL)
-           chinit(data);
-    }
+    struct sidata idat;
     
     if(sd->type == CH_SOCKET) {
+       idat = (struct sidata) {.sd = sd, .sinit = chinit, .sdata = sdata};
        if(sd->fd < 0) {
            args = expandargs(sd);
-           sd->fd = stdmkchild(args, stdinit, idata);
+           sd->fd = stdmkchild(args, stdinit, &idat);
            freeca(args);
        }
        if(sendreq2(sd->fd, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT)) {
@@ -382,22 +396,32 @@ static int stdhandle(struct child *ch, struct hthead *req, int fd, void (*chinit
                /* Assume that the child has crashed and restart it. */
                close(sd->fd);
                args = expandargs(sd);
-               sd->fd = stdmkchild(args, stdinit, idata);
+               sd->fd = stdmkchild(args, stdinit, &idat);
                freeca(args);
                if(!sendreq2(sd->fd, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT))
-                   return(0);
+                   goto ok;
                serr = errno;
            }
-           if(serr != EAGAIN) {
+           if(serr == EAGAIN) {
+               if(sd->agains++ == 0) {
+                   flog(LOG_WARNING, "request to child %s denied due to buffer overload", ch->name);
+                   sd->lastrep = time(NULL);
+               }
+           } else {
                flog(LOG_ERR, "could not pass on request to child %s: %s", ch->name, strerror(serr));
                close(sd->fd);
                sd->fd = -1;
            }
            return(-1);
        }
+    ok:
+       if((sd->agains > 0) && ((time(NULL) - sd->lastrep) > 10)) {
+           flog(LOG_WARNING, "%i requests to child %s were denied due to buffer overload", sd->agains, ch->name);
+           sd->agains = 0;
+       }
     } else if(sd->type == CH_FORK) {
        args = expandargs(sd);
-       if(stdforkserve(args, req, fd, chinit, idata) < 0) {
+       if(stdforkserve(args, req, fd, chinit, sdata) < 0) {
            freeca(args);
            return(-1);
        }