/dev/null') ?: ''); if ($ip) return $ip; $out = shell_exec('tailscale status 2>/dev/null') ?: ''; foreach (explode("\n", $out) as $line) { $cols = preg_split('/\s+/', trim($line)); if (isset($cols[1]) && stripos($cols[1], $h . '.') === 0) return $cols[0]; } return ''; } function vv_detect_host(): string { // Reads master.conf for HOST1="name" (or HOST1_NAME="name") and matches running hostname. // Returns 'host1', 'host2', 'host3', ... or 'unknown'. Works for any number of hosts. $master = vv_read_conf_raw('master.conf'); preg_match_all('/^\s*(HOST\d+)(?:_NAME)?\s*=\s*["\']?(\S+?)["\']?\s*$/m', $master, $m); $hostname = vv_get_hostname(); foreach ($m[1] as $i => $key) { if (strcasecmp($hostname, trim($m[2][$i])) === 0) return strtolower($key); } return 'unknown'; } function vv_is_owner(): bool { return vv_detect_host() === 'host1'; } function vv_read_conf_raw(string $filename): string { $path = CONF_DIR . '/' . $filename; return file_exists($path) ? file_get_contents($path) : ''; } function vv_write_conf_raw(string $filename, string $content): bool { $path = CONF_DIR . '/' . $filename; return file_put_contents($path, $content) !== false; } function vv_get_conf_files(): array { // Returns conf files this host is allowed to view/edit $host = vv_detect_host(); $files = []; if ($host === 'host1') { // Owner sees master.conf + their own host conf $files[] = 'master.conf'; $files[] = 'host1.conf'; } elseif (preg_match('/^host(\d+)$/', $host)) { // Any other numbered host sees only their own conf $files[] = $host . '.conf'; } else { // Unknown host — show all for dev/debug foreach (glob(CONF_DIR . '/*.conf') as $f) { $files[] = basename($f); } } return $files; } // Parse conf into key=>value map for $VAR substitution in docs function vv_conf_vars(): array { $vars = []; $files = ['master.conf']; $host = vv_detect_host(); if (preg_match('/^host\d+$/', $host)) $files[] = $host . '.conf'; foreach ($files as $f) { $raw = vv_read_conf_raw($f); // Match: VAR_NAME="value" or VAR_NAME=value (no quotes) preg_match_all('/^\s*([A-Z0-9_]+)\s*=\s*["\']?([^"\'#\n]*?)["\']?\s*(?:#.*)?$/m', $raw, $m); foreach ($m[1] as $i => $key) { $vars[$key] = trim($m[2][$i]); } } return $vars; }