#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;
*((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;
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);
}
*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);
+}