root/luci2/zhttpd/zhttpd.c @ 5830

Revision 5830, 3.3 KB (checked in by Cyrus, 3 years ago)

zhttpd: More stuff, uhtbl: Qualifier change

Line 
1#include <signal.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <stdio.h>
6#include <sys/epoll.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10
11#include "zhttpd.h"
12#include "tcp.h"
13
14static volatile int running;
15zhttpd_context_t zhttpd = {.handler = NULL};
16
17static void daemonize() {
18    pid_t pid;
19    FILE *fp;
20    switch ((pid = fork())) {
21        case -1:
22            exit(1);
23        case 0:
24            break;
25        default:
26            fp = fopen(zhttpd.pidfile, "w");
27            if (fp) {
28                fprintf(fp, "%i\n", (int)pid);
29                fclose(fp);
30            }
31            exit(0);
32    }
33    setsid();
34    chdir("/");
35    int devnull = open("/dev/null", O_RDWR);
36    dup2(devnull, STDIN_FILENO);
37    dup2(devnull, STDOUT_FILENO);
38    dup2(devnull, STDERR_FILENO);
39    close(devnull);
40}
41
42static void sighandler(int signal) {
43    if (signal == SIGHUP) {
44        running = 2;
45    } else {
46        running = 0;
47    }
48}
49
50static void configure() {
51    zhttpd.threads = 32;
52    zhttpd.timeout = 5;
53    zhttpd.daemonize = 1;
54}
55
56static void cleanup() {
57    close(zhttpd.epollfd);
58    zthread_destroy(zhttpd.threadpool);
59    zhttpd_vfs_t *d = NULL;
60    for (zhttpd_vfs_t *c = zhttpd.vfs; c; c = d) {
61        c->handler->vfs_context_destroy(c->context);
62        d = c->next;
63        free(c);
64    }
65}
66
67static void run() {
68    running = 1;
69    zhttpd.threadpool = zthread_create(zhttpd.threads);
70    zhttpd.epollfd = epoll_create(0);
71    zhttpd_tcp_cloexec(zhttpd.epollfd);
72    struct epoll_event *events = malloc
73            (sizeof(struct epoll_event) * zhttpd.threads);
74
75    do {
76        int ready = zthread_step(zhttpd.threadpool, zhttpd.timeout);
77        int signals = epoll_wait(zhttpd.epollfd, events, zhttpd.threads,
78                (ready) ? 0 : 1000);
79        for (int i = 0; i < signals; i++) {
80            ((zthread_t*)events[i].data.ptr)->status = ZTHREAD_READY;
81        }
82    } while(running == 1);
83    free(events);
84}
85
86int main() {
87    struct sigaction action;
88    memset(&action, 0, sizeof(action));
89    action.sa_handler = sighandler;
90    sigaction(SIGHUP, &action, NULL);
91    sigaction(SIGTERM, &action, NULL);
92    action.sa_handler = SIG_IGN;
93    sigaction(SIGPIPE, &action, NULL);
94
95    zhttpd.pidfile = "/var/run/zhttpd.pid";
96    int firstrun = 1;
97    do {
98        configure();
99        if (firstrun && zhttpd.daemonize) {
100            daemonize();
101            firstrun = 0;
102        }
103        run();
104        cleanup();
105    } while(running);
106    return 0;
107}
108
109int zhttpd_vfs_mount(const char *point, zhttpd_options_t *options) {
110    size_t pointlen = strlen(point);
111    const char *handlername = zhttpd_options_get(options, "handler");
112    if (!handlername) {
113        return ZHTTPD_EINVAL;
114    }
115
116    zhttpd_handler_t *handler = NULL;
117    for (zhttpd_handler_t *c = zhttpd.handler; c; c = c->next) {
118        if (!strcmp(handlername, c->name)) {
119            handler = c;
120            break;
121        }
122    }
123
124    if (!handler) {
125        return ZHTTPD_ENOENT;
126    }
127
128    zhttpd_vfs_t *mount = calloc(1, sizeof(zhttpd_vfs_t) + pointlen + 2);
129    if (!mount) {
130        return ZHTTPD_ENOMEM;
131    }
132
133    memcpy(mount->pattern, point, pointlen);
134    if (point[pointlen - 1] != '/') {
135        mount->pattern[pointlen++] = '/';
136    }
137    mount->patternlen = pointlen;
138    mount->handler = handler;
139    mount->context = handler->vfs_context_create(options);
140    mount->next = zhttpd.vfs;
141    zhttpd.vfs = mount;
142
143    return ZHTTPD_OK;
144}
145
146const char* zhttpd_options_get(zhttpd_options_t *options, const char *key) {
147    size_t keylen = strlen(key);
148    for (; options; options = options->next) {
149        if (!strcmp(key, options->option) && options->option[keylen] == '=') {
150            return &options->option[keylen + 1];
151        }
152    }
153    return NULL;
154}
155
156void zhttpd_register(zhttpd_handler_t *handler) {
157    handler->next = zhttpd.handler;
158    zhttpd.handler = handler;
159}
Note: See TracBrowser for help on using the browser.