Make sure database and environment are properly closed by statdbput.
[statserve.git] / statserve.c
CommitLineData
34d725a5
FT
1#include <stdlib.h>
2#include <stdio.h>
3#include <unistd.h>
4#include <errno.h>
5#include <string.h>
6#include <ashd/req.h>
7#include <ashd/resp.h>
8#include <ashd/log.h>
9#include <ashd/mt.h>
10#include <ashd/mtio.h>
11
12#include "statserve.h"
13
14static struct source *sources = NULL;
15
16static struct source *parsesource(char *arg)
17{
18 if(arg[strlen(arg) - 1] == '/') {
19 return(mkfssrc(arg));
20 } else {
21 return(mkdbsrc(arg, NULL));
22 }
23}
24
25static void serve(struct muth *muth, va_list args)
26{
27 vavar(struct hthead *, req);
28 vavar(int, fd);
29 FILE *out;
30 struct source *src;
31 struct fileinfo f;
32
33 out = NULL;
34 for(src = sources; src != NULL; src = src->next) {
35 f = src->serve(src, req->rest);
36 if(f.data != NULL)
37 break;
38 }
39 if(src == NULL) {
40 simpleerror(fd, 404, "Resource not found", "The resource %s was not found", htmlquote(req->rest));
41 goto out;
42 }
43 out = mtstdopen(fd, 1, 60, "r+");
44 fprintf(out, "HTTP/1.1 200 OK\n");
45 fprintf(out, "Content-Type: %s\n", f.ctype);
46 fprintf(out, "Content-Length: %zi\n", f.sz);
47 fprintf(out, "Last-Modified: %s\n", fmthttpdate(f.mtime));
48 fprintf(out, "\n");
49 fwrite(f.data, 1, f.sz, out);
50 free(f.data);
51
52out:
53 if(out != NULL)
54 fclose(out);
55 else
56 close(fd);
57 freehthead(req);
58}
59
60static void usage(FILE *out)
61{
ea4e0b71 62 fprintf(out, "usage: statserve [-h] [-P PAGESIZE] SOURCE...\n");
34d725a5
FT
63}
64
65static void listenloop(struct muth *muth, va_list args)
66{
67 vavar(int, lfd);
68 int fd;
69 struct hthead *req;
70 struct source *src;
71
72 while(1) {
73 block(0, EV_READ, 0);
74 if((fd = recvreq(lfd, &req)) < 0) {
75 if(errno != 0)
76 flog(LOG_ERR, "recvreq: %s", strerror(errno));
77 break;
78 }
79 mustart(serve, req, fd);
80 for(src = sources; src != NULL; src = src->next) {
81 if(src->idle)
82 src->idle(src);
83 }
84 }
85}
86
87int main(int argc, char **argv)
88{
89 int c;
90 struct source *last, *src;
91
ea4e0b71 92 while((c = getopt(argc, argv, "+hP:")) >= 0) {
34d725a5 93 switch(c) {
ea4e0b71
FT
94 case 'P':
95 dbpagesize = atoi(optarg);
96 break;
34d725a5
FT
97 case 'h':
98 usage(stdout);
99 return(0);
100 default:
101 usage(stderr);
102 return(1);
103 }
104 }
105 last = NULL;
106 while(optind < argc) {
107 src = parsesource(argv[optind++]);
108 if(!sources)
109 sources = src;
110 if(last)
111 last->next = src;
112 last = src;
113 }
114 if(!sources) {
115 usage(stderr);
116 return(1);
117 }
118 mustart(listenloop, 0);
119 ioloop();
120 return(0);
121}