/* As of FreeBSD 13.2, sigaction(2) still conforms to IEEE Std * 1003.1-1990 (POSIX.1), which did not define SA_RESTART. * FreeBSD supports it as an extension, but then _POSIX_C_SOURCE must * not be defined. */ #ifndef __FreeBSD__ #define _POSIX_C_SOURCE 200809L #endif #include #include #include #include #include #include #include #include #include #include static int on_put(const struct http_payload *const pl, struct http_response *const r, void *const user) { if (pl->expect_continue) { *r = (const struct http_response) { .status = HTTP_STATUS_CONTINUE }; return 0; } printf("File uploaded to %s\n", pl->u.put.tmpname); *r = (const struct http_response) { .status = HTTP_STATUS_OK }; return 0; } static int on_length(const enum http_op op, const char *const res, const unsigned long long len, const struct http_cookie *const c, struct http_response *const r, void *const user) { *r = (const struct http_response) { .status = HTTP_STATUS_OK }; return 0; } struct handler *handler; static void handle_signal(const int signum) { switch (signum) { case SIGINT: /* Fall through. */ case SIGTERM: handler_notify_close(handler); break; default: break; } } static int init_signals(void) { struct sigaction sa = { .sa_handler = handle_signal, .sa_flags = SA_RESTART }; sigemptyset(&sa.sa_mask); static const struct signal { int signal; const char *name; } signals[] = { {.signal = SIGINT, .name = "SIGINT"}, {.signal = SIGTERM, .name = "SIGTERM"}, {.signal = SIGPIPE, .name = "SIGPIPE"} }; for (size_t i = 0; i < sizeof signals / sizeof *signals; i++) { const struct signal *const s = &signals[i]; if (sigaction(s->signal, &sa, NULL)) { fprintf(stderr, "%s: sigaction(2) %s: %s\n", __func__, s->name, strerror(errno)); return -1; } } return 0; } int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; const struct handler_cfg cfg = { .tmpdir = "/tmp", .length = on_length }; static const char *const urls[] = {"/*"}; if (!(handler = handler_alloc(&cfg))) { fprintf(stderr, "%s: handler_alloc failed\n", __func__); goto end; } else if (init_signals()) { fprintf(stderr, "%s: init_signals failed\n", __func__); goto end; } for (size_t i = 0; i < sizeof urls / sizeof *urls; i++) if (handler_add(handler, urls[i], HTTP_OP_PUT, on_put, NULL)) { fprintf(stderr, "%s: handler_add failed\n", __func__); goto end; } unsigned short outport; if (handler_listen(handler, 0, &outport)) { fprintf(stderr, "%s: handler_listen failed\n", __func__); goto end; } printf("Listening on port %hu\n", outport); if (handler_loop(handler)) { fprintf(stderr, "%s: handler_loop failed\n", __func__); goto end; } ret = EXIT_SUCCESS; end: handler_free(handler); return ret; }