lib: Added variants of sendfd and sendreq that take sendmsg flags.
[ashd.git] / lib / proc.c
index f7b0d9b..a1dc336 100644 (file)
@@ -21,6 +21,8 @@
 #include <unistd.h>
 #include <sys/socket.h>
 #include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #include <utils.h>
 #include <log.h>
 #include <proc.h>
+#include <req.h>
 
-int stdmkchild(char **argv)
+int stdmkchild(char **argv, void (*chinit)(void *), void *idata)
 {
-    int i;
     pid_t pid;
     int fd[2];
     
-    if(socketpair(PF_UNIX, SOCK_DGRAM, 0, fd))
+    if(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fd))
        return(-1);
     if((pid = fork()) < 0)
        return(-1);
     if(pid == 0) {
-       for(i = 3; i < FD_SETSIZE; i++) {
-           if(i != fd[0])
-               close(i);
-       }
+       if(chinit != NULL)
+           chinit(idata);
        dup2(fd[0], 0);
        close(fd[0]);
+       close(fd[1]);
        execvp(argv[0], argv);
        flog(LOG_WARNING, "could not exec child program %s: %s", argv[0], strerror(errno));
        exit(127);
     }
     close(fd[0]);
+    fcntl(fd[1], F_SETFD, FD_CLOEXEC);
     return(fd[1]);
 }
 
-int sendfd(int sock, int fd, char *data, size_t datalen)
+int sendfd2(int sock, int fd, char *data, size_t datalen, int flags)
 {
     struct msghdr msg;
     struct cmsghdr *cmsg;
@@ -76,13 +78,18 @@ int sendfd(int sock, int fd, char *data, size_t datalen)
     *((int *)CMSG_DATA(cmsg)) = fd;
     msg.msg_controllen = cmsg->cmsg_len;
     
-    return(sendmsg(sock, &msg, MSG_NOSIGNAL | MSG_DONTWAIT));
+    return(sendmsg(sock, &msg, flags));
+}
+
+int sendfd(int sock, int fd, char *data, size_t datalen)
+{
+    return(sendfd2(sock, fd, data, datalen, MSG_NOSIGNAL | MSG_DONTWAIT));
 }
 
 int recvfd(int sock, char **data, size_t *datalen)
 {
     int ret, fd;
-    char *buf, cbuf[1024];;
+    char *buf, cbuf[1024];
     struct msghdr msg;
     struct cmsghdr *cmsg;
     struct iovec bufvec;
@@ -98,8 +105,10 @@ int recvfd(int sock, char **data, size_t *datalen)
     msg.msg_controllen = sizeof(cbuf);
     
     ret = recvmsg(sock, &msg, 0);
-    if(ret < 0) {
+    if(ret <= 0) {
        free(buf);
+       if(ret == 0)
+           errno = 0;
        return(-1);
     }
     
@@ -119,3 +128,47 @@ int recvfd(int sock, char **data, size_t *datalen)
     *datalen = ret;
     return(fd);
 }
+
+pid_t stdforkserve(char **argv, struct hthead *req, int fd, void (*chinit)(void *), void *idata)
+{
+    int i;
+    char *ebuf, *p;
+    pid_t pid;
+    struct charvbuf args;
+    
+    if((pid = fork()) < 0)
+       return(-1);
+    if(pid == 0) {
+       if(chinit != NULL)
+           chinit(idata);
+       
+       dup2(fd, 0);
+       dup2(fd, 1);
+       close(fd);
+       
+       bufinit(args);
+       for(i = 0; argv[i]; i++)
+           bufadd(args, argv[i]);
+       bufadd(args, req->method);
+       bufadd(args, req->url);
+       bufadd(args, req->rest);
+       bufadd(args, NULL);
+       
+       for(i = 0; i < req->noheaders; i++) {
+           ebuf = sstrdup(req->headers[i][0]);
+           for(p = ebuf; *p; p++) {
+               if(isalnum(*p))
+                   *p = toupper(*p);
+               else
+                   *p = '_';
+           }
+           putenv(sprintf2("REQ_%s=%s", ebuf, req->headers[i][1]));
+       }
+       putenv(sprintf2("HTTP_VERSION=%s", req->ver));
+       
+       execvp(args.b[0], args.b);
+       flog(LOG_WARNING, "could not exec child program %s: %s", argv[0], strerror(errno));
+       exit(127);
+    }
+    return(pid);
+}