From 0197eab7a552d1b70cdda84e33e93c8328fe7b34 Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Sat, 23 May 2026 17:08:52 -0400 Subject: [PATCH] Read scheduler children from master.conf arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Orchestrators using dynamic dispatch (array_started, watchdog_orchestrator, daily/weekly/etc maintenance) iterate \${VARNAME_SCRIPTS[@]} arrays defined in master.conf. The previous regex only caught static hardcoded paths. Two-strategy approach, merged and deduped: 1. Static: \$VAR/../Category/script.sh and \$VAR/Category/script.sh patterns 2. Dynamic: detect \${VARNAME[@]} references in the orch, parse that array from master.conf — handles inline args and skips commented entries Changes to master.conf arrays are reflected immediately on next page load. --- .../plugins/varaverk/include/scheduler.php | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/Plugin/usr/local/emhttp/plugins/varaverk/include/scheduler.php b/Plugin/usr/local/emhttp/plugins/varaverk/include/scheduler.php index 88b36d2..5c03682 100644 --- a/Plugin/usr/local/emhttp/plugins/varaverk/include/scheduler.php +++ b/Plugin/usr/local/emhttp/plugins/varaverk/include/scheduler.php @@ -79,31 +79,37 @@ function vv_job_tree(): array { return $orchs; } +// Parse a bash array from master.conf content and return its script paths. +// Handles entries with inline args ("script.sh --flag") and skips commented lines (#"..."). +function vv_parse_conf_array(string $conf, string $varName): array { + if (!preg_match('/^\s*' . preg_quote($varName, '/') . '\s*=\s*\((.*?)\)/ms', $conf, $m)) { + return []; + } + $scripts = []; + preg_match_all('/^\s*(?!#)"([^"]+)"/m', $m[1], $entries); + foreach ($entries[1] as $entry) { + $parts = preg_split('/\s+/', trim($entry)); + $path = $parts[0] ?? ''; + if (substr($path, -3) === '.sh') $scripts[] = $path; + } + return $scripts; +} + // Parse an orchestrator script to find which child scripts it calls. -// Handles two common patterns: -// $SCRIPT_DIR/../Category/script.sh (relative via variable) -// $SCRIPTS_ROOT/Category/script.sh (absolute root via variable) -// Root-level files (load_config.sh, etc.) are excluded — must be in a subdirectory. -// Validates each candidate against the filesystem to filter false positives. +// Two strategies, merged and deduped: +// 1. Static paths: $SCRIPT_DIR/../Category/script.sh or $SCRIPTS_ROOT/Category/script.sh +// 2. master.conf arrays: detects ${VARNAME[@]} iteration and reads the array from master.conf +// Root-level files (load_config.sh etc.) excluded — must be in a subdirectory. +// Each candidate validated against the filesystem. function vv_script_children(string $orchPath, array $schedule): array { $scriptsDir = SCRIPTS_DIR; $content = file_get_contents($orchPath) ?: ''; $children = []; $seen = []; - // Match $ANY_VAR/../Category/script.sh or $ANY_VAR/Category/script.sh - // Capture only the Category/script.sh portion (requires at least one subdirectory) - preg_match_all( - '/\$[A-Z_]+\/(?:\.\.\/)?([A-Za-z][A-Za-z0-9_.\-]*\/[A-Za-z0-9_.\-]+\.sh)/', - $content, - $m - ); - - foreach ($m[1] as $rel) { - if (isset($seen[$rel])) continue; - if (!file_exists("$scriptsDir/$rel")) continue; + $addChild = function(string $rel) use ($scriptsDir, $schedule, &$children, &$seen) { + if (isset($seen[$rel]) || !file_exists("$scriptsDir/$rel")) return; $seen[$rel] = true; - $entry = $schedule[$rel] ?? ['enabled' => false, 'cron' => '']; $children[] = [ 'id' => $rel, @@ -112,6 +118,23 @@ function vv_script_children(string $orchPath, array $schedule): array { 'enabled' => (bool)($entry['enabled'] ?? false), 'cron' => $entry['cron'] ?? '', ]; + }; + + // Strategy 1: static variable paths ($VAR/../Category/script.sh or $VAR/Category/script.sh) + preg_match_all( + '/\$[A-Z_]+\/(?:\.\.\/)?([A-Za-z][A-Za-z0-9_.\-]*\/[A-Za-z0-9_.\-]+\.sh)/', + $content, $m + ); + foreach ($m[1] as $rel) $addChild($rel); + + // Strategy 2: master.conf arrays — find every ${VARNAME_SCRIPTS[@]} the orch iterates + preg_match_all('/\$\{([A-Z_]+_SCRIPTS)\[@\]\}/', $content, $refs); + if (!empty($refs[1])) { + $confRaw = file_get_contents(CONF_DIR . '/master.conf') ?: ''; + foreach (array_unique($refs[1]) as $varName) { + foreach (vv_parse_conf_array($confRaw, $varName) as $rel) $addChild($rel); + } } + return $children; }