Merge branch 'master' into timeheap
[ashd.git] / src / httimed.c
CommitLineData
c1fc9826
FT
1/*
2 ashd - A Sane HTTP Daemon
3 Copyright (C) 2008 Fredrik Tolf <fredrik@dolda2000.com>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <unistd.h>
22#include <errno.h>
23#include <string.h>
24#include <time.h>
25#include <sys/poll.h>
c4149d4a 26#include <sys/socket.h>
c1fc9826
FT
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <utils.h>
32#include <log.h>
33#include <req.h>
34#include <proc.h>
35
36static void usage(FILE *out)
37{
38 fprintf(out, "usage: httimed [-h] [-t TIMEOUT] CHILD [ARGS...]\n");
39}
40
41int main(int argc, char **argv)
42{
c4149d4a 43 int c, timeout, ret;
c1fc9826
FT
44 int ch, fd;
45 struct hthead *req;
46 struct pollfd pfd[2];
47 time_t lreq, now;
48
c4149d4a 49 timeout = 300;
c1fc9826
FT
50 while((c = getopt(argc, argv, "+ht:")) >= 0) {
51 switch(c) {
52 case 'h':
53 usage(stdout);
54 exit(0);
55 case 't':
c4149d4a
FT
56 timeout = atoi(optarg);
57 if(timeout < 1) {
c1fc9826
FT
58 fprintf(stderr, "httimed: timeout must be positive\n");
59 exit(1);
60 }
61 break;
62 }
63 }
64 if(argc - optind < 1) {
65 usage(stderr);
66 exit(1);
67 }
68 if((ch = stdmkchild(argv + optind, NULL, NULL)) < 0) {
69 flog(LOG_ERR, "httimed: could not fork child: %s", strerror(errno));
70 exit(1);
71 }
72 lreq = time(NULL);
73 while(1) {
74 memset(pfd, 0, sizeof(pfd));
75 pfd[0].fd = 0;
76 pfd[0].events = POLLIN;
77 pfd[1].fd = ch;
78 pfd[1].events = POLLHUP;
c4149d4a 79 if((ret = poll(pfd, 2, (timeout < 0)?-1:((timeout + 1 - (time(NULL) - lreq)) * 1000))) < 0) {
c1fc9826
FT
80 if(errno != EINTR) {
81 flog(LOG_ERR, "httimed: error in poll: %s", strerror(errno));
82 exit(1);
83 }
84 }
85 now = time(NULL);
86 if(pfd[0].revents) {
87 if((fd = recvreq(0, &req)) < 0) {
88 if(errno == 0)
89 break;
90 flog(LOG_ERR, "httimed: error in recvreq: %s", strerror(errno));
91 exit(1);
92 }
93 if(sendreq(ch, req, fd)) {
94 flog(LOG_ERR, "httimed: could not pass request to child: %s", strerror(errno));
95 exit(1);
96 }
97 freehthead(req);
98 close(fd);
99 }
c4149d4a
FT
100 if((pfd[1].revents & POLLHUP) || (now - lreq > timeout)) {
101 timeout = -1;
102 shutdown(0, SHUT_RDWR);
103 }
c1fc9826
FT
104 lreq = now;
105 }
106 return(0);
107}