From 1865a2fc790e80b4c2209d470daa0065aae4e93b Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Wed, 22 Apr 2026 13:42:38 +0200 Subject: [PATCH] feat: add configurable nwwebui logfile support --- README.md | 277 ++++++++++++++++++++++++++++++++++++++++++++++- nwwebui.c | 143 +++++++++++++++++------- smart.conf.cmake | 3 + 3 files changed, 381 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index a8c91fd..78eea4d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,276 @@ -# mars-smart +# SMArT -SMArT is a web configuration tool for MARS_NWE, a Novell NetWare 3.x emulator for Linux and FreeBSD. \ No newline at end of file +SMArT is the web-based configuration interface for **MARS_NWE**, a Novell NetWare 3.x emulator for Linux and FreeBSD. + +In the current setup, this repository is no longer treated as a standalone component only. It is integrated into the main `mars_nwe` project as a **Git submodule** and is therefore included in the normal **mars_nwe release** process. + +## Project status and integration + +This repository is intended to be embedded into the main `mars_nwe` Git repository: + +- Main project: `mars_nwe` +- Submodule role: provides the SMArT web UI and helper tools +- Release model: shipped as part of the integrated **MARS_NWE** release, not as a separate end-user release artifact + +The build and install rules show that the web UI binaries, Perl helpers, configuration, static assets, and PAM file are installed as part of the overall build and installation flow. + +## Architecture overview + +SMArT consists of two main parts: + +1. **Perl-based application logic** for configuration pages and helper scripts +2. **`nwwebui` service** as the web frontend that exposes the application over HTTP and HTTPS + +The current implementation adds a dedicated `nwwebui` service that can serve the application directly over: + +- **HTTP on port 9080** +- **HTTPS on port 9443** + +The service supports TLS via OpenSSL and can run both listeners in parallel. HTTPS is the preferred mode because authentication happens more securely over an encrypted connection, while plain HTTP may still be useful for testing or trusted internal environments. + +## Security model + +SMArT uses PAM-based authentication through the `check_login` helper. The supplied PAM policy is a standard `pam_unix` stack for authentication, account, password, and session handling. During installation with **MARS_NWE**, this file is installed automatically as: + +- `/etc/pam.d/smart` + +That means no manual PAM file deployment is normally required when SMArT is installed through the integrated `mars_nwe` package or release. + +## Installed components + +The install rules include the following relevant components. + +### Binaries + +- `nwwebui` – dedicated web service frontend +- `check_login` – PAM authentication helper + +### Perl helpers + +- `smart` +- `apply.pl` +- `readconfig.pl` +- `settings.pl` +- `static.pl` + +### Configuration and assets + +- `smart.conf` +- static HTML and image assets for the web UI +- optional `mars-nwe-webui.service` systemd unit +- PAM file installed as `/etc/pam.d/smart` + +These components are all installed by the build system as part of the same integrated installation target. + +## Typical runtime paths + +The original templates use CMake placeholders. For documentation, the following standard example paths can be used in a typical Linux installation: + +- Main MARS_NWE config directory: `/etc/mars_nwe` +- SMArT config file: `/etc/mars_nwe/smart.conf` +- Main MARS_NWE server config: `/etc/mars_nwe/nwserv.conf` +- Helper binaries and scripts: `/usr/libexec/mars_nwe` +- Static SMArT assets: `/usr/libexec/mars_nwe/static` +- Log directory: `/var/log/mars_nwe` +- PID directory: `/run/mars_nwe` +- TLS certificate: `/etc/mars_nwe/server.crt` +- TLS private key: `/etc/mars_nwe/server.key` +- PAM file: `/etc/pam.d/smart` + +These values are sensible standard defaults for documentation. Packaging may still adjust them depending on the target distribution. + +## The `smart.conf` file + +The `smart.conf` file controls both the SMArT frontend behavior and the `nwwebui` listener settings. + +A documented example with standard installation paths is shown below: + +```perl +# SMArT / nwwebui configuration file + +# ------------------------------------------------------------ +# UI colors +# ------------------------------------------------------------ +$COLOR_BACK = "#F0F0FF"; +$COLOR_HEAD_BACK = "#C0C0FF"; +$COLOR_HEAD_FORE = "#000000"; +$COLOR_SUBH_BACK = "#D0D0FF"; +$COLOR_SUBH_FORE = "#000000"; +$COLOR_TEXT_BACK = "#E0E0FF"; +$COLOR_TEXT_FORE = "#000000"; + +# ------------------------------------------------------------ +# Main MARS_NWE configuration +# ------------------------------------------------------------ +$mars_config = '/etc/mars_nwe/nwserv.conf'; +$nonroot_user = 'nobody'; +$smart_compact_nwservconf = 0; + +# ------------------------------------------------------------ +# SMArT internal file layout +# ------------------------------------------------------------ +$smart_conf_path = '/etc/mars_nwe/smart.conf'; +$smart_nwclient_path = '/etc/mars_nwe/.nwclient'; +$smart_static_dir = '/usr/libexec/mars_nwe/static'; +$smart_log_path = '/var/log/mars_nwe/smart.log'; +$smart_check_login = '/usr/libexec/mars_nwe/check_login'; + +# Optional override, usually not needed +# $smart_perl_path = '/usr/libexec/mars_nwe/smart'; + +# ------------------------------------------------------------ +# nwwebui listener settings +# ------------------------------------------------------------ +$nw_bind_ip = '0.0.0.0'; +$nw_log_level = 1; +$nw_daemonize = 0; +$nw_pid_file = '/run/mars_nwe/nwwebui.pid'; +$nw_log_file = '/var/log/mars_nwe/nwwebui.log'; + +$nw_ssl_enable = 0; +$nw_http_port = 9080; +$nw_https_port = 9443; + +$nw_cert_file = '/etc/mars_nwe/server.crt'; +$nw_key_file = '/etc/mars_nwe/server.key'; +``` + +## `smart.conf` settings explained + +### UI colors + +These variables define the default SMArT page colors: + +- `$COLOR_BACK` – page background +- `$COLOR_HEAD_BACK` / `$COLOR_HEAD_FORE` – main section header colors +- `$COLOR_SUBH_BACK` / `$COLOR_SUBH_FORE` – subsection header colors +- `$COLOR_TEXT_BACK` / `$COLOR_TEXT_FORE` – regular content row colors + +### Main MARS_NWE configuration + +- `$mars_config` – path to the main `nwserv.conf` file that SMArT reads and updates +- `$nonroot_user` – unprivileged user account used when SMArT drops privileges +- `$smart_compact_nwservconf` – controls how `nwserv.conf` is written back: + - `0` keeps comments, spacing, and the original structure as much as possible + - `1` writes a more compact version without the original long comment layout + +### SMArT internal file layout + +- `$smart_conf_path` – absolute path to `smart.conf` +- `$smart_nwclient_path` – file used to store bindery login information for SMArT helper tools +- `$smart_static_dir` – directory containing HTML, icons, and other static assets +- `$smart_log_path` – log file used by the Perl-based SMArT frontend +- `$smart_check_login` – PAM-based authentication helper path +- `$smart_perl_path` – optional override for the main SMArT Perl executable; usually not needed + +### `nwwebui` listener settings + +- `$nw_bind_ip` – bind address for HTTP and HTTPS listeners, for example `0.0.0.0` for all IPv4 interfaces or `127.0.0.1` for localhost-only access +- `$nw_log_level` – service log verbosity: + - `0` = errors only + - `1` = informational messages + - `2` = debug output +- `$nw_daemonize` – whether `nwwebui` detaches into the background +- `$nw_pid_file` – location of the PID file +- `$nw_log_file` – log file written by `nwwebui` +- `$nw_ssl_enable` – enables or disables HTTPS support +- `$nw_http_port` – HTTP listener port; set to `0` to disable plain HTTP +- `$nw_https_port` – HTTPS listener port; set to `0` to disable HTTPS +- `$nw_cert_file` – PEM certificate path for TLS +- `$nw_key_file` – PEM private key path for TLS + +The current code and template show that: + +- `nwwebui` listens on `9080` for HTTP by default +- `9443` is used for HTTPS +- the log file can be configured with `$nw_log_file` +- the log path can also be overridden at runtime with `-l` + +Because passwords may be transmitted during login, HTTPS is the recommended way to access the interface. + +## Starting the service + +Depending on the installation method, `nwwebui` can be started either via **systemd** or directly from the **command line**. The build system installs a `mars-nwe-webui.service` unit when systemd support is enabled. + +### Starting with systemd + +A typical installed system uses the `mars-nwe-webui.service` unit. The unit starts `nwwebui`, prepares the needed runtime directories, and loads the standard `smart.conf` file. + +Typical commands: + +```bash +systemctl enable --now mars-nwe-webui.service +systemctl start mars-nwe-webui.service +systemctl stop mars-nwe-webui.service +systemctl restart mars-nwe-webui.service +systemctl status mars-nwe-webui.service +``` + +The service unit starts `nwwebui` with the equivalent of: + +```bash +/usr/sbin/nwwebui -c /etc/mars_nwe/smart.conf +``` + +### Starting from the command line + +`nwwebui` can also be launched manually. The built-in usage text documents the supported options: + +```text +Usage: nwwebui [-h] [-d] [-s] [-c ] [-p ] [-l ] + +Options: + -h, --help Show this help text and exit + -d, --daemon Run in daemon mode + -s, --stop Stop the running nwwebui instance + -c, --config Use an alternate smart.conf path + -p, --pidfile Override PID file path + -l, --logfile Override log file path +``` + +Typical examples: + +```bash +# start in foreground with the standard configuration +/usr/sbin/nwwebui -c /etc/mars_nwe/smart.conf + +# start in daemon mode +/usr/sbin/nwwebui -d -c /etc/mars_nwe/smart.conf + +# stop a running instance +/usr/sbin/nwwebui -s -c /etc/mars_nwe/smart.conf + +# use a custom PID file +/usr/sbin/nwwebui -d -c /etc/mars_nwe/smart.conf -p /run/mars_nwe/nwwebui.pid + +# use a custom log file +/usr/sbin/nwwebui -c /etc/mars_nwe/smart.conf -l /var/log/mars_nwe/custom-nwwebui.log + +# override both PID and log file +/usr/sbin/nwwebui -d -c /etc/mars_nwe/smart.conf -p /run/mars_nwe/nwwebui.pid -l /var/log/mars_nwe/nwwebui.log +``` + +The `-l` option overrides `$nw_log_file` from `smart.conf` at runtime. + +Typical access URLs: + +- `http://:9080/` +- `https://:9443/` + +For production use, HTTPS should be preferred. + +## Build and installation notes + +This repository is built as part of the main `mars_nwe` build. The build system: + +- generates `smart.conf` from the template +- generates the `smart` launcher script +- builds `nwwebui` +- builds `check_login` +- installs the PAM file and static UI assets + +Because this repository is integrated as a Git submodule in `mars_nwe`, end users normally consume it through the main `mars_nwe` source tree and release packages rather than using it as a standalone project. + +## Summary + +SMArT is now an integrated part of the `mars_nwe` release and includes a dedicated `nwwebui` service that can expose the interface over both HTTP and HTTPS. The standard listener ports are **9080** for HTTP and **9443** for HTTPS. Authentication is handled through PAM, and the required `/etc/pam.d/smart` file is installed automatically together with the integrated MARS_NWE installation. 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