Added some process control functions to libht.
authorFredrik Tolf <fredrik@dolda2000.com>
Tue, 16 Dec 2008 15:41:29 +0000 (16:41 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Tue, 16 Dec 2008 15:41:29 +0000 (16:41 +0100)
lib/Makefile.am
lib/proc.c [new file with mode: 0644]
lib/proc.h [new file with mode: 0644]

index d234043..30c1dee 100644 (file)
@@ -1,4 +1,4 @@
 noinst_LIBRARIES = libht.a
 
-libht_a_SOURCES = utils.c mt.c log.c req.c
+libht_a_SOURCES = utils.c mt.c log.c req.c proc.c
 libht_a_CFLAGS = -fPIC
diff --git a/lib/proc.c b/lib/proc.c
new file mode 100644 (file)
index 0000000..f7b0d9b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+    ashd - A Sane HTTP Daemon
+    Copyright (C) 2008  Fredrik Tolf <fredrik@dolda2000.com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <utils.h>
+#include <log.h>
+#include <proc.h>
+
+int stdmkchild(char **argv)
+{
+    int i;
+    pid_t pid;
+    int fd[2];
+    
+    if(socketpair(PF_UNIX, SOCK_DGRAM, 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);
+       }
+       dup2(fd[0], 0);
+       close(fd[0]);
+       execvp(argv[0], argv);
+       flog(LOG_WARNING, "could not exec child program %s: %s", argv[0], strerror(errno));
+       exit(127);
+    }
+    close(fd[0]);
+    return(fd[1]);
+}
+
+int sendfd(int sock, int fd, char *data, size_t datalen)
+{
+    struct msghdr msg;
+    struct cmsghdr *cmsg;
+    char cmbuf[CMSG_SPACE(sizeof(int))];
+    struct iovec bufvec;
+    
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = &bufvec;
+    msg.msg_iovlen = 1;
+    bufvec.iov_base = data;
+    bufvec.iov_len = datalen;
+    
+    msg.msg_control = cmbuf;
+    msg.msg_controllen = sizeof(cmbuf);
+    cmsg = CMSG_FIRSTHDR(&msg);
+    cmsg->cmsg_level = SOL_SOCKET;
+    cmsg->cmsg_type = SCM_RIGHTS;
+    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+    *((int *)CMSG_DATA(cmsg)) = fd;
+    msg.msg_controllen = cmsg->cmsg_len;
+    
+    return(sendmsg(sock, &msg, MSG_NOSIGNAL | MSG_DONTWAIT));
+}
+
+int recvfd(int sock, char **data, size_t *datalen)
+{
+    int ret, fd;
+    char *buf, cbuf[1024];;
+    struct msghdr msg;
+    struct cmsghdr *cmsg;
+    struct iovec bufvec;
+    
+    buf = smalloc(65536);
+    memset(&msg, 0, sizeof(msg));
+
+    msg.msg_iov = &bufvec;
+    msg.msg_iovlen = 1;
+    bufvec.iov_base = buf;
+    bufvec.iov_len = 65536;
+    msg.msg_control = cbuf;
+    msg.msg_controllen = sizeof(cbuf);
+    
+    ret = recvmsg(sock, &msg, 0);
+    if(ret < 0) {
+       free(buf);
+       return(-1);
+    }
+    
+    fd = -1;
+    for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+       if((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) {
+           fd = *((int *)CMSG_DATA(cmsg));
+       }
+    }
+    if(fd < 0) {
+       free(buf);
+       errno = EPROTO;
+       return(-1);
+    }
+    buf = realloc(buf, ret);
+    *data = buf;
+    *datalen = ret;
+    return(fd);
+}
diff --git a/lib/proc.h b/lib/proc.h
new file mode 100644 (file)
index 0000000..943e598
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _LIB_PROC_H
+#define _LIB_PROC_H
+
+int stdmkchild(char **argv);
+int sendfd(int sock, int fd, char *data, size_t datalen);
+int recvfd(int sock, char **data, size_t *datalen);
+
+#endif