summaryrefslogtreecommitdiff
path: root/src/unit.c
diff options
context:
space:
mode:
authorauric <auric@japegames.com>2026-02-22 22:11:01 -0600
committerauric <auric@japegames.com>2026-02-22 22:11:01 -0600
commit7ff4624e67a6452f77d330c84b2ce6aee900b638 (patch)
tree5305f03bace310b008aec89c5209eb52a9e700f0 /src/unit.c
parent551c8aece8f30f7495b8340e36fbabd5f49e4705 (diff)
log_tail: add log_dir + log_pattern directory-watch mode
Valve games (TF2, GMod) rotate into a new timestamped log file on every map change. The existing fixed-path inotify watch goes stale after the first rotation. This adds a directory-watch mode that auto-switches to the newest matching file whenever one appears. New YAML fields (mutually exclusive with logs:): log_dir: directory to watch for new log files log_pattern: fnmatch(3) glob for filenames; default "*" Changes: - umbrella.h: add log_dir[MAX_PATH] and log_dir_pattern[MAX_PATH] to Unit - log_tail.c: extend LogWatch with dir_wd/dir_path/pattern fields; add log_tail_drain, log_tail_scan_dir, log_tail_switch_file, log_tail_open_fixed_watch, log_tail_open_dir_watch, log_tail_reopen_fixed, log_tail_handle_rotation_dir; refactor log_tail_init, log_tail_handle, log_tail_cleanup - unit.c: parse log_dir and log_pattern YAML keys; warn and drop logs: if both are set on the same unit - AGENTS.md, README.md: document both log-tail modes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src/unit.c')
-rw-r--r--src/unit.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/unit.c b/src/unit.c
index b2cdd4c..1b4a603 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -176,6 +176,10 @@ int unit_load_file(const char *path, Unit *out) {
strncpy(out->broadcast_cmd, val, sizeof(out->broadcast_cmd) - 1);
else if (strcmp(last_key, "log_filter") == 0)
strncpy(out->log_filter, val, MAX_PATH - 1);
+ else if (strcmp(last_key, "log_dir") == 0)
+ strncpy(out->log_dir, val, MAX_PATH - 1);
+ else if (strcmp(last_key, "log_pattern") == 0)
+ strncpy(out->log_dir_pattern, val, MAX_PATH - 1);
break;
case SECTION_CONSOLE:
@@ -261,6 +265,13 @@ int unit_load_file(const char *path, Unit *out) {
out->name, out->console.password_env);
}
+ /* log_dir and logs: are mutually exclusive */
+ if (out->log_dir[0] && out->log_count > 0) {
+ log_warn("Unit %s: 'log_dir' and 'logs' are mutually exclusive; "
+ "ignoring 'logs'", out->name);
+ out->log_count = 0;
+ }
+
/* Allocate ring buffer */
out->output = ring_init();
if (!out->output) {