callfcgi: Improved recvrec implementation.
[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>
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include <utils.h>
31#include <log.h>
32#include <req.h>
33#include <proc.h>
34
35static void usage(FILE *out)
36{
37 fprintf(out, "usage: httimed [-h] [-t TIMEOUT] CHILD [ARGS...]\n");
38}
39
40int main(int argc, char **argv)
41{
42 int c, t, ret;
43 int ch, fd;
44 struct hthead *req;
45 struct pollfd pfd[2];
46 time_t lreq, now;
47
48 t = 300;
49 while((c = getopt(argc, argv, "+ht:")) >= 0) {
50 switch(c) {
51 case 'h':
52 usage(stdout);
53 exit(0);
54 case 't':
55 t = atoi(optarg);
56 if(t < 1) {
57 fprintf(stderr, "httimed: timeout must be positive\n");
58 exit(1);
59 }
60 break;
61 }
62 }
63 if(argc - optind < 1) {
64 usage(stderr);
65 exit(1);
66 }
67 if((ch = stdmkchild(argv + optind, NULL, NULL)) < 0) {
68 flog(LOG_ERR, "httimed: could not fork child: %s", strerror(errno));
69 exit(1);
70 }
71 lreq = time(NULL);
72 while(1) {
73 memset(pfd, 0, sizeof(pfd));
74 pfd[0].fd = 0;
75 pfd[0].events = POLLIN;
76 pfd[1].fd = ch;
77 pfd[1].events = POLLHUP;
78 if((ret = poll(pfd, 2, (t + 1 - (time(NULL) - lreq)) * 1000)) < 0) {
79 if(errno != EINTR) {
80 flog(LOG_ERR, "httimed: error in poll: %s", strerror(errno));
81 exit(1);
82 }
83 }
84 now = time(NULL);
85 if(pfd[0].revents) {
86 if((fd = recvreq(0, &req)) < 0) {
87 if(errno == 0)
88 break;
89 flog(LOG_ERR, "httimed: error in recvreq: %s", strerror(errno));
90 exit(1);
91 }
92 if(sendreq(ch, req, fd)) {
93 flog(LOG_ERR, "httimed: could not pass request to child: %s", strerror(errno));
94 exit(1);
95 }
96 freehthead(req);
97 close(fd);
98 }
99 if(pfd[1].revents & POLLHUP)
100 break;
101 if(now - lreq > t)
102 break;
103 lreq = now;
104 }
105 return(0);
106}