From b5d0fc983e683690c2e1c5dae375d25a8aa14f9f Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Wed, 22 Apr 2026 17:06:18 +0200 Subject: [PATCH] back to working --- nwwebui.c | 143 ++++++++++++++++++++++++++++++++++------------- smart.conf.cmake | 3 + 2 files changed, 106 insertions(+), 40 deletions(-) diff --git a/nwwebui.c b/nwwebui.c index 0fd8921..dffbfe0 100644 --- a/nwwebui.c +++ b/nwwebui.c @@ -34,6 +34,7 @@ typedef struct { char cert_file[512]; char key_file[512]; char pid_file[512]; + char log_file[512]; char smart_conf[512]; char smart_perl_path[512]; @@ -41,6 +42,7 @@ typedef struct { static FILE *g_log_fp = NULL; static int g_log_level = LOG_LEVEL_DEFAULT; +static char g_log_path[512] = LOG_PATH_DEFAULT; static volatile sig_atomic_t g_terminate = 0; static volatile sig_atomic_t g_got_signal = 0; @@ -52,7 +54,8 @@ static char g_pid_file_path[512] = { 0 }; /* Console lifecycle output */ /* ------------------------------------------------------------ */ -static void console_msg(const char *fmt, ...) { +static void console_msg(const char *fmt, ...) +{ va_list ap; va_start(ap, fmt); @@ -67,28 +70,42 @@ static void console_msg(const char *fmt, ...) { /* Logging */ /* ------------------------------------------------------------ */ -static void log_open(void) { +static void log_open(void) +{ if (!g_log_fp) { - g_log_fp = fopen(LOG_PATH_DEFAULT, "a"); + g_log_fp = fopen(g_log_path, "a"); if (!g_log_fp) { g_log_fp = stderr; } } } -static void log_msg(int level, const char *fmt, ...) { +static void log_reopen(const char *path) +{ + if (g_log_fp && g_log_fp != stderr) { + fclose(g_log_fp); + } + g_log_fp = NULL; + + snprintf(g_log_path, sizeof(g_log_path), "%s", path); + log_open(); +} + +static void log_msg(int level, const char *fmt, ...) +{ + time_t now; + struct tm tm_now; + char tbuf[64]; + const char *lvl = "INFO"; + va_list ap; + if (level > g_log_level) { return; } log_open(); - time_t now = time(NULL); - struct tm tm_now; - char tbuf[64]; - const char *lvl = "INFO"; - va_list ap; - + now = time(NULL); localtime_r(&now, &tm_now); strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", &tm_now); @@ -108,12 +125,14 @@ static void log_msg(int level, const char *fmt, ...) { fflush(g_log_fp); } -static void die(const char *msg) { +static void die(const char *msg) +{ log_msg(LOG_LEVEL_ERROR, "%s: %s", msg, strerror(errno)); exit(EXIT_FAILURE); } -static void ssl_die(const char *msg) { +static void ssl_die(const char *msg) +{ log_msg(LOG_LEVEL_ERROR, "%s", msg); ERR_print_errors_fp(g_log_fp ? g_log_fp : stderr); exit(EXIT_FAILURE); @@ -123,7 +142,8 @@ static void ssl_die(const char *msg) { /* Helpers */ /* ------------------------------------------------------------ */ -static void trim(char *s) { +static void trim(char *s) +{ char *p = s; size_t len; @@ -142,7 +162,8 @@ static void trim(char *s) { } } -static void strip_quotes(char *s) { +static void strip_quotes(char *s) +{ size_t len = strlen(s); if (len >= 2) { @@ -154,7 +175,8 @@ static void strip_quotes(char *s) { } } -static int parse_perl_assignment(const char *line, char *key, size_t ksz, char *val, size_t vsz) { +static int parse_perl_assignment(const char *line, char *key, size_t ksz, char *val, size_t vsz) +{ const char *p = line; size_t ki = 0; size_t vi = 0; @@ -202,11 +224,13 @@ static int parse_perl_assignment(const char *line, char *key, size_t ksz, char * return key[0] != '\0'; } -static int file_exists_and_executable(const char *path) { +static int file_exists_and_executable(const char *path) +{ return access(path, X_OK) == 0; } -static int set_nonblocking(int fd) { +static int set_nonblocking(int fd) +{ int flags = fcntl(fd, F_GETFL, 0); if (flags < 0) { return -1; @@ -217,18 +241,20 @@ static int set_nonblocking(int fd) { return 0; } -static void print_usage(const char *progname) { +static void print_usage(const char *progname) +{ fprintf(stdout, "%s %s\n" "\n" - "Usage: %s [-h] [-d] [-s] [-c ] [-p ]\n" + "Usage: %s [-h] [-d] [-s] [-c ] [-p ] [-l ]\n" "\n" "Options:\n" " -h, --help Show this help text and exit\n" " -d, --daemon Run in daemon mode\n" " -s, --stop Stop the running nwwebui instance\n" " -c, --config Use an alternate smart.conf path\n" - " -p, --pidfile Override PID file path\n", + " -p, --pidfile Override PID file path\n" + " -l, --logfile Override log file path\n", NWWEBUI_NAME, NWWEBUI_VERSION, progname); } @@ -236,14 +262,16 @@ static void print_usage(const char *progname) { /* PID file handling */ /* ------------------------------------------------------------ */ -static void remove_pid_file(void) { +static void remove_pid_file(void) +{ if (g_pid_file_written) { unlink(g_pid_file_path); g_pid_file_written = 0; } } -static void write_pid_file(const char *path) { +static void write_pid_file(const char *path) +{ FILE *fp = fopen(path, "w"); if (!fp) { die("fopen pid file"); @@ -256,7 +284,8 @@ static void write_pid_file(const char *path) { g_pid_file_written = 1; } -static pid_t read_pid_file(const char *path) { +static pid_t read_pid_file(const char *path) +{ FILE *fp; long pid = -1; @@ -279,7 +308,8 @@ static pid_t read_pid_file(const char *path) { return (pid_t)pid; } -static int process_exists(pid_t pid) { +static int process_exists(pid_t pid) +{ if (pid <= 0) { return 0; } @@ -295,7 +325,8 @@ static int process_exists(pid_t pid) { return 0; } -static int pid_is_nwwebui(pid_t pid) { +static int pid_is_nwwebui(pid_t pid) +{ char path[128]; char name[256]; FILE *fp; @@ -319,7 +350,8 @@ static int pid_is_nwwebui(pid_t pid) { return strcmp(name, "nwwebui") == 0; } -static int stop_running_instance(const char *pid_file) { +static int stop_running_instance(const char *pid_file) +{ pid_t pid = read_pid_file(pid_file); if (pid <= 0) { @@ -353,7 +385,8 @@ static int stop_running_instance(const char *pid_file) { /* Daemonization */ /* ------------------------------------------------------------ */ -static void daemonize_process(void) { +static void daemonize_process(void) +{ pid_t pid; pid = fork(); @@ -395,7 +428,8 @@ static void daemonize_process(void) { /* smart.conf loading */ /* ------------------------------------------------------------ */ -static void init_defaults(nw_config_t *cfg, const char *smart_conf_path) { +static void init_defaults(nw_config_t *cfg, const char *smart_conf_path) +{ memset(cfg, 0, sizeof(*cfg)); snprintf(cfg->bind_ip, sizeof(cfg->bind_ip), "%s", DEFAULT_BIND_IP); @@ -408,12 +442,16 @@ static void init_defaults(nw_config_t *cfg, const char *smart_conf_path) { snprintf(cfg->cert_file, sizeof(cfg->cert_file), "%s", DEFAULT_CERT_FILE); snprintf(cfg->key_file, sizeof(cfg->key_file), "%s", DEFAULT_KEY_FILE); snprintf(cfg->pid_file, sizeof(cfg->pid_file), "%s", DEFAULT_PID_FILE); + snprintf(cfg->log_file, sizeof(cfg->log_file), "%s", LOG_PATH_DEFAULT); snprintf(cfg->smart_perl_path, sizeof(cfg->smart_perl_path), "%s", DEFAULT_SMART_PERL); snprintf(cfg->smart_conf, sizeof(cfg->smart_conf), "%s", smart_conf_path); + + snprintf(g_log_path, sizeof(g_log_path), "%s", LOG_PATH_DEFAULT); } -static void load_smart_conf(nw_config_t *cfg) { +static void load_smart_conf(nw_config_t *cfg) +{ FILE *fp = fopen(cfg->smart_conf, "r"); char line[2048]; @@ -434,6 +472,8 @@ static void load_smart_conf(nw_config_t *cfg) { snprintf(cfg->bind_ip, sizeof(cfg->bind_ip), "%s", val); } else if (strcmp(key, "nw_log_level") == 0) { g_log_level = atoi(val); + } else if (strcmp(key, "nw_log_file") == 0) { + snprintf(cfg->log_file, sizeof(cfg->log_file), "%s", val); } else if (strcmp(key, "nw_ssl_enable") == 0) { cfg->ssl_enable = atoi(val); } else if (strcmp(key, "nw_http_port") == 0) { @@ -468,13 +508,16 @@ static void load_smart_conf(nw_config_t *cfg) { if (g_log_level > LOG_LEVEL_DEBUG) { g_log_level = LOG_LEVEL_DEBUG; } + + snprintf(g_log_path, sizeof(g_log_path), "%s", cfg->log_file); } /* ------------------------------------------------------------ */ /* Listener / socket helpers */ /* ------------------------------------------------------------ */ -static int create_listener(const char *bind_ip, int port) { +static int create_listener(const char *bind_ip, int port) +{ int fd = socket(AF_INET, SOCK_STREAM, 0); int yes = 1; struct sockaddr_in addr; @@ -515,7 +558,8 @@ static int create_listener(const char *bind_ip, int port) { return fd; } -static ssize_t write_all_fd(int fd, const unsigned char *buf, size_t len) { +static ssize_t write_all_fd(int fd, const unsigned char *buf, size_t len) +{ size_t off = 0; while (off < len) { @@ -538,7 +582,8 @@ static ssize_t write_all_fd(int fd, const unsigned char *buf, size_t len) { return (ssize_t)off; } -static ssize_t send_all_ssl(SSL *ssl, const unsigned char *buf, size_t len) { +static ssize_t send_all_ssl(SSL *ssl, const unsigned char *buf, size_t len) +{ size_t off = 0; while (off < len) { @@ -560,7 +605,8 @@ static ssize_t send_all_ssl(SSL *ssl, const unsigned char *buf, size_t len) { /* Perl launcher */ /* ------------------------------------------------------------ */ -static pid_t spawn_smart_perl(const nw_config_t *cfg, int *child_stdin_fd, int *child_stdout_fd) { +static pid_t spawn_smart_perl(const nw_config_t *cfg, int *child_stdin_fd, int *child_stdout_fd) +{ int inpipe[2] = { -1, -1 }; int outpipe[2] = { -1, -1 }; pid_t pid; @@ -622,7 +668,8 @@ static pid_t spawn_smart_perl(const nw_config_t *cfg, int *child_stdin_fd, int * /* Shared child cleanup */ /* ------------------------------------------------------------ */ -static void cleanup_child_process(int *child_stdin_fd, int *child_stdout_fd, pid_t *child_pid) { +static void cleanup_child_process(int *child_stdin_fd, int *child_stdout_fd, pid_t *child_pid) +{ if (*child_stdin_fd >= 0) { close(*child_stdin_fd); *child_stdin_fd = -1; @@ -652,7 +699,8 @@ static void cleanup_child_process(int *child_stdin_fd, int *child_stdout_fd, pid /* Plain HTTP handler */ /* ------------------------------------------------------------ */ -static void handle_connection_plain(int client_fd, const nw_config_t *cfg) { +static void handle_connection_plain(int client_fd, const nw_config_t *cfg) +{ int child_stdin_fd = -1; int child_stdout_fd = -1; pid_t child_pid = -1; @@ -739,7 +787,8 @@ cleanup: /* TLS handler */ /* ------------------------------------------------------------ */ -static void handle_connection_tls(SSL_CTX *ctx, int client_fd, const nw_config_t *cfg) { +static void handle_connection_tls(SSL_CTX *ctx, int client_fd, const nw_config_t *cfg) +{ SSL *ssl = NULL; int child_stdin_fd = -1; int child_stdout_fd = -1; @@ -853,7 +902,8 @@ cleanup: /* Signal handlers */ /* ------------------------------------------------------------ */ -static void reap_children(int sig) { +static void reap_children(int sig) +{ (void)sig; for (;;) { @@ -864,7 +914,8 @@ static void reap_children(int sig) { } } -static void term_handler(int sig) { +static void term_handler(int sig) +{ g_got_signal = sig; g_terminate = 1; } @@ -873,9 +924,11 @@ static void term_handler(int sig) { /* Main */ /* ------------------------------------------------------------ */ -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ const char *smart_conf_path = DEFAULT_SMART_CONF; const char *pidfile_override = NULL; + const char *logfile_override = NULL; int http_fd = -1; int https_fd = -1; SSL_CTX *ctx = NULL; @@ -895,6 +948,8 @@ int main(int argc, char **argv) { smart_conf_path = argv[++i]; } else if ((strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--pidfile") == 0) && i + 1 < argc) { pidfile_override = argv[++i]; + } else if ((strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--logfile") == 0) && i + 1 < argc) { + logfile_override = argv[++i]; } else { fprintf(stderr, "Unknown argument: %s\n", argv[i]); print_usage(argv[0]); @@ -949,6 +1004,12 @@ int main(int argc, char **argv) { snprintf(cfg.pid_file, sizeof(cfg.pid_file), "%s", pidfile_override); } + if (logfile_override) { + snprintf(cfg.log_file, sizeof(cfg.log_file), "%s", logfile_override); + } + + log_reopen(cfg.log_file); + if (stop_mode) { return stop_running_instance(cfg.pid_file); } @@ -963,7 +1024,7 @@ int main(int argc, char **argv) { log_msg(LOG_LEVEL_INFO, "%s version %s starting", NWWEBUI_NAME, NWWEBUI_VERSION); log_msg(LOG_LEVEL_INFO, "Using SMArT Perl path: %s", cfg.smart_perl_path); log_msg(LOG_LEVEL_INFO, - "%s version %s config loaded: bind=%s log_level=%d ssl_enable=%d http_port=%d https_port=%d daemonize=%d cert=%s key=%s pid_file=%s smart.conf=%s", + "%s version %s config loaded: bind=%s log_level=%d ssl_enable=%d http_port=%d https_port=%d daemonize=%d cert=%s key=%s pid_file=%s log_file=%s smart.conf=%s", NWWEBUI_NAME, NWWEBUI_VERSION, cfg.bind_ip, @@ -975,11 +1036,13 @@ int main(int argc, char **argv) { cfg.cert_file, cfg.key_file, cfg.pid_file, + cfg.log_file, cfg.smart_conf); if (cfg.daemonize) { console_msg("%s %s switching to daemon mode", NWWEBUI_NAME, NWWEBUI_VERSION); daemonize_process(); + log_reopen(cfg.log_file); } write_pid_file(cfg.pid_file); diff --git a/smart.conf.cmake b/smart.conf.cmake index 1d716c4..4297614 100644 --- a/smart.conf.cmake +++ b/smart.conf.cmake @@ -92,6 +92,9 @@ $nw_daemonize = 0; # PID file written by nwwebui. $nw_pid_file = '@MARS_NWE_PID_DIR@/nwwebui.pid'; +# Log file written by nwwebui. +$nw_log_file = '@MARS_NWE_LOG_DIR@/nwwebui.log'; + # Enable or disable TLS/SSL support. # 1 = enable HTTPS listener # 0 = disable HTTPS listener