1e66f31c5Sopenharmony_ci#include <inttypes.h>
2e66f31c5Sopenharmony_ci#include <stdio.h>
3e66f31c5Sopenharmony_ci#include <stdlib.h>
4e66f31c5Sopenharmony_ci#include <string.h>
5e66f31c5Sopenharmony_ci#include <uv.h>
6e66f31c5Sopenharmony_ci
7e66f31c5Sopenharmony_ciuv_loop_t *loop;
8e66f31c5Sopenharmony_ciuv_process_t child_req;
9e66f31c5Sopenharmony_ciuv_process_options_t options;
10e66f31c5Sopenharmony_ci
11e66f31c5Sopenharmony_civoid cleanup_handles(uv_process_t *req, int64_t exit_status, int term_signal) {
12e66f31c5Sopenharmony_ci    fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
13e66f31c5Sopenharmony_ci    uv_close((uv_handle_t*) req->data, NULL);
14e66f31c5Sopenharmony_ci    uv_close((uv_handle_t*) req, NULL);
15e66f31c5Sopenharmony_ci}
16e66f31c5Sopenharmony_ci
17e66f31c5Sopenharmony_civoid invoke_cgi_script(uv_tcp_t *client) {
18e66f31c5Sopenharmony_ci    char path[500];
19e66f31c5Sopenharmony_ci    size_t size = sizeof(path);
20e66f31c5Sopenharmony_ci    uv_exepath(path, &size);
21e66f31c5Sopenharmony_ci    strcpy(path + (strlen(path) - strlen("cgi")), "tick");
22e66f31c5Sopenharmony_ci
23e66f31c5Sopenharmony_ci    char* args[2];
24e66f31c5Sopenharmony_ci    args[0] = path;
25e66f31c5Sopenharmony_ci    args[1] = NULL;
26e66f31c5Sopenharmony_ci
27e66f31c5Sopenharmony_ci    /* ... finding the executable path and setting up arguments ... */
28e66f31c5Sopenharmony_ci
29e66f31c5Sopenharmony_ci    options.stdio_count = 3;
30e66f31c5Sopenharmony_ci    uv_stdio_container_t child_stdio[3];
31e66f31c5Sopenharmony_ci    child_stdio[0].flags = UV_IGNORE;
32e66f31c5Sopenharmony_ci    child_stdio[1].flags = UV_INHERIT_STREAM;
33e66f31c5Sopenharmony_ci    child_stdio[1].data.stream = (uv_stream_t*) client;
34e66f31c5Sopenharmony_ci    child_stdio[2].flags = UV_IGNORE;
35e66f31c5Sopenharmony_ci    options.stdio = child_stdio;
36e66f31c5Sopenharmony_ci
37e66f31c5Sopenharmony_ci    options.exit_cb = cleanup_handles;
38e66f31c5Sopenharmony_ci    options.file = args[0];
39e66f31c5Sopenharmony_ci    options.args = args;
40e66f31c5Sopenharmony_ci
41e66f31c5Sopenharmony_ci    // Set this so we can close the socket after the child process exits.
42e66f31c5Sopenharmony_ci    child_req.data = (void*) client;
43e66f31c5Sopenharmony_ci    int r;
44e66f31c5Sopenharmony_ci    if ((r = uv_spawn(loop, &child_req, &options))) {
45e66f31c5Sopenharmony_ci        fprintf(stderr, "%s\n", uv_strerror(r));
46e66f31c5Sopenharmony_ci        return;
47e66f31c5Sopenharmony_ci    }
48e66f31c5Sopenharmony_ci}
49e66f31c5Sopenharmony_ci
50e66f31c5Sopenharmony_civoid on_new_connection(uv_stream_t *server, int status) {
51e66f31c5Sopenharmony_ci    if (status == -1) {
52e66f31c5Sopenharmony_ci        // error!
53e66f31c5Sopenharmony_ci        return;
54e66f31c5Sopenharmony_ci    }
55e66f31c5Sopenharmony_ci
56e66f31c5Sopenharmony_ci    uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
57e66f31c5Sopenharmony_ci    uv_tcp_init(loop, client);
58e66f31c5Sopenharmony_ci    if (uv_accept(server, (uv_stream_t*) client) == 0) {
59e66f31c5Sopenharmony_ci        invoke_cgi_script(client);
60e66f31c5Sopenharmony_ci    }
61e66f31c5Sopenharmony_ci    else {
62e66f31c5Sopenharmony_ci        uv_close((uv_handle_t*) client, NULL);
63e66f31c5Sopenharmony_ci    }
64e66f31c5Sopenharmony_ci}
65e66f31c5Sopenharmony_ci
66e66f31c5Sopenharmony_ciint main() {
67e66f31c5Sopenharmony_ci    loop = uv_default_loop();
68e66f31c5Sopenharmony_ci
69e66f31c5Sopenharmony_ci    uv_tcp_t server;
70e66f31c5Sopenharmony_ci    uv_tcp_init(loop, &server);
71e66f31c5Sopenharmony_ci
72e66f31c5Sopenharmony_ci    struct sockaddr_in bind_addr;
73e66f31c5Sopenharmony_ci    uv_ip4_addr("0.0.0.0", 7000, &bind_addr);
74e66f31c5Sopenharmony_ci    uv_tcp_bind(&server, (const struct sockaddr *)&bind_addr, 0);
75e66f31c5Sopenharmony_ci    int r = uv_listen((uv_stream_t*) &server, 128, on_new_connection);
76e66f31c5Sopenharmony_ci    if (r) {
77e66f31c5Sopenharmony_ci        fprintf(stderr, "Listen error %s\n", uv_err_name(r));
78e66f31c5Sopenharmony_ci        return 1;
79e66f31c5Sopenharmony_ci    }
80e66f31c5Sopenharmony_ci    return uv_run(loop, UV_RUN_DEFAULT);
81e66f31c5Sopenharmony_ci}
82