diff options
author | David Härdeman <david@hardeman.nu> | 2020-06-05 14:09:18 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2020-06-05 14:09:18 +0200 |
commit | db66484c4300f5f0e857eff01d15fd3593002a79 (patch) | |
tree | a787b9f0da1243ae0391d5931ecb9cb0f29d3ee4 /main.c |
Initial commit
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 284 |
1 files changed, 284 insertions, 0 deletions
@@ -0,0 +1,284 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdbool.h> +#include <getopt.h> +#include <sys/signalfd.h> +#include <sys/eventfd.h> +#include <signal.h> + +#include "main.h" +#include "uring.h" +#include "config.h" +#include "server.h" + +int debuglvl = 0; + +void +debug(unsigned lvl, const char *fmt, ...) +{ + va_list ap; + + if (lvl > debuglvl) + return; + + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); +} + +#define info(...) fprintf(stderr, __VA_ARGS__) +#define error(...) fprintf(stderr, __VA_ARGS__) + +__attribute__((noreturn)) +void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(EXIT_FAILURE); +}; + +#define perrordie(msg) die("%s: %m\n", msg) + +static void +cfg_free(struct uring_task *task) +{ + struct cfg *cfg = container_of(task, struct cfg, task); + + free(cfg); + exit(EXIT_SUCCESS); +} + +static void +cfg_read(struct cfg *cfg) +{ + FILE *cfgfile; + + cfgfile = fopen("./mcproxy.conf", "r"); + if (!cfgfile) { + if (errno == ENOENT) + return; + else + perrordie("fopen"); + } + + printf("Opened config file\n"); + fclose(cfgfile); +} + +static struct cfg * +cfg_init(int argc, char **argv) +{ + struct cfg *cfg; + int c; + + cfg = zmalloc(sizeof(*cfg)); + if (!cfg) { + perror("malloc"); + return NULL; + } + uring_task_init(&cfg->task, "cfg", NULL, cfg_free); + list_init(&cfg->servers); + + while (true) { + int option_index = 0; + static struct option long_options[] = { + { "homedir", required_argument, 0, 'h' }, + { "debug", no_argument, 0, 'd' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, ":h:d", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + cfg->homedir = optarg; + break; + case 'd': + debuglvl++; + break; + default: + die("Invalid arguments\n"); + } + + } + + if (optind < argc) + die("Invalid arguments\n"); + + if (!cfg->homedir) + cfg->homedir = "/home/david/intest"; + + printf("Homedir is %s\n", cfg->homedir); + if (chdir(cfg->homedir)) + perrordie("chdir"); + + return cfg; +} + +struct signalfd_ev { + struct uring_task task; + //struct signalfd_siginfo buf; + uint64_t buf; +}; + +static void +signalfd_free(struct uring_task *task) +{ + struct signalfd_ev *sev = container_of(task, struct signalfd_ev, task); + + debug(2, "Freeing signalfd\n"); + free(sev); +} + +static void +dump_tree(struct cfg *cfg) +{ + struct server *server; + + fprintf(stderr, "\n\n\n\n"); + fprintf(stderr, "Dumping Tree\n"); + fprintf(stderr, "============\n"); + uring_task_refdump(&cfg->task); + uring_task_refdump(&cfg->sev->task); + uring_refdump(cfg->uev); + if (cfg->iev) + inotify_refdump(cfg->iev); + list_for_each_entry(server, &cfg->servers, list) + server_refdump(server); + fprintf(stderr, "============\n"); + fprintf(stderr, "\n\n\n\n"); +} + +static void +signalfd_read(struct cfg *cfg, struct uring_task *task, int res) +{ + struct signalfd_ev *sev = container_of(task, struct signalfd_ev, task); + struct server *server, *stmp; + static int count = 0; + + count++; + if (count > 5) + exit(EXIT_FAILURE); + + if (res != sizeof(sev->buf)) + die("Error in signalfd (%i)\n", res); + + if (sev->buf < 1000) { + fprintf(stderr, "Got a signal to quit\n"); + exit(EXIT_SUCCESS); + } else { + fprintf(stderr, "Got a signal to dump tree\n"); + dump_tree(cfg); + scfg_stop_monitor_dir(cfg); + list_for_each_entry_safe(server, stmp, &cfg->servers, list) + server_delete(cfg, server); + uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), 0, signalfd_read); + } +} + +static int hack_efd = -1; + +static void +hack_handler(int signum) +{ + uint64_t val; + + switch (signum) { + case SIGINT: + fprintf(stderr, "Got a SIGINT\n"); + val = 1000; + break; + case SIGHUP: + fprintf(stderr, "Got a SIGHUP\n"); + val = 1000; + break; + case SIGTERM: + fprintf(stderr, "Got a SIGTERM\n"); + val = 1; + break; + default: + fprintf(stderr, "Got an unknown sig (%i)\n", signum); + val = 1; + break; + } + + write(hack_efd, &val, sizeof(val)); +} + +static void +signalfd_init(struct cfg *cfg) +{ + int sfd; + //sigset_t mask; + struct signalfd_ev *sev; + + sev = zmalloc(sizeof(*sev)); + if (!sev) + perrordie("malloc"); + + /* + sigfillset(&mask); + if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) + perrordie("sigprocmask"); + + sfd = signalfd(-1, &mask, SFD_CLOEXEC); + if (sfd < 0) + perrordie("signalfd"); + */ + + struct sigaction action; + sigfillset(&action.sa_mask); + action.sa_handler = hack_handler; + action.sa_flags = 0; + + sigaction(SIGINT, &action, NULL); + sigaction(SIGHUP, &action, NULL); + sigaction(SIGTERM, &action, NULL); + + sfd = eventfd(0, EFD_CLOEXEC); + if (sfd < 0) + perrordie("eventfd"); + + fprintf(stderr, "signalfd init: %i\n", sfd); + uring_task_init(&sev->task, "sev", &cfg->task, signalfd_free); + uring_task_set_fd(&sev->task, sfd); + cfg->sev = sev; + hack_efd = sfd; + uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), 0, signalfd_read); +} + +int +main(int argc, char **argv) +{ + struct cfg *cfg; + + cfg = cfg_init(argc, argv); + + cfg_read(cfg); + + uring_init(cfg); + + signalfd_init(cfg); + + scfg_monitor_dir(cfg); + + scfg_read_all(cfg); + + uring_event_loop(cfg); + + exit(EXIT_SUCCESS); +} |