#!/usr/bin/env bash set -u AGENT_DIR="/OGP" PIDFILE="${1:-/OGP/ogp_agent_run.pid}" PREFS_FILE="$AGENT_DIR/Cfg/bash_prefs.cfg" START_LOG_NATIVE="${GSP_AGENT_START_LOG_NATIVE:-}" REPO_URL_DEFAULT="http://forge.runlevelsystems.com/dev/GSP.git" REPO_BRANCH_DEFAULT="Panel-unstable" RAW_AGENT_URL_DEFAULT="http://forge.runlevelsystems.com/dev/GSP/raw/branch/Panel-unstable/Agent-Windows/OGP64/OGP/ogp_agent.pl" REPO_AGENT_PATH="Agent-Windows/OGP64/OGP/ogp_agent.pl" warn() { printf 'WARNING: %s\n' "$*" >&2 } fail() { printf 'ERROR: %s\n' "$*" >&2 exit 1 } setup_startup_log() { local default_log="/var/log/gsp_agent_start.log" local log_path="${default_log}" if [ -n "$START_LOG_NATIVE" ] && command -v cygpath >/dev/null 2>&1; then log_path="$(cygpath -u "$START_LOG_NATIVE" 2>/dev/null || printf '%s' "$default_log")" elif [ -n "$START_LOG_NATIVE" ]; then log_path="$START_LOG_NATIVE" fi mkdir -p "$(dirname "$log_path")" 2>/dev/null || true touch "$log_path" 2>/dev/null || true exec > >(tee -a "$log_path") 2>&1 printf 'GSP Windows Agent startup log: %s\n' "$log_path" printf 'Cygwin root detected by batch: %s\n' "${GSP_AGENT_CYGWIN_ROOT:-unknown}" } normalize_text_files() { local root="$1" [ -d "$root" ] || return 0 find "$root" -type f \( -name '*.pl' -o -name '*.pm' -o -name '*.sh' -o -name '*.cfg' \) -print0 2>/dev/null | while IFS= read -r -d '' file; do sed -i 's/\r$//' "$file" 2>/dev/null || warn "Could not normalize line endings for $file" done } normalize_bash_preferences() { [ -f "$PREFS_FILE" ] || return 0 sed -i 's/\r$//' "$PREFS_FILE" 2>/dev/null || warn "Could not normalize CRLF in $PREFS_FILE" sed -i -E 's/^[[:space:]]+([A-Za-z_][A-Za-z0-9_]*=)/\1/' "$PREFS_FILE" 2>/dev/null || warn "Could not normalize assignments in $PREFS_FILE" } install_default_config_if_missing() { local target="$1" local template="$2" if [ -f "$target" ]; then return 0 fi if [ ! -f "$template" ]; then warn "Missing template $template; cannot create $target" return 0 fi mkdir -p "$(dirname "$target")" 2>/dev/null || { warn "Cannot create config directory for $target" return 0 } cp "$template" "$target" 2>/dev/null || { warn "Cannot create default config $target from $template" return 0 } sed -i 's/\r$//' "$target" 2>/dev/null || true } ensure_default_configs() { install_default_config_if_missing "$AGENT_DIR/Cfg/Config.pm" "$AGENT_DIR/Cfg/Config.pm.default" install_default_config_if_missing "$AGENT_DIR/Cfg/Preferences.pm" "$AGENT_DIR/Cfg/Preferences.pm.default" install_default_config_if_missing "$AGENT_DIR/Cfg/bash_prefs.cfg" "$AGENT_DIR/Cfg/bash_prefs.cfg.default" normalize_bash_preferences } validate_required_config() { if [ ! -f "$AGENT_DIR/Cfg/Config.pm" ]; then fail "Missing $AGENT_DIR/Cfg/Config.pm. Run agent_conf.sh or copy Config.pm.default and set the Panel agent key." fi if grep -Eq "CHANGE_ME_PANEL_AGENT_KEY|key[[:space:]]*=>[[:space:]]*''" "$AGENT_DIR/Cfg/Config.pm"; then fail "$AGENT_DIR/Cfg/Config.pm still contains placeholder values. Set key/listen settings to match the Panel remote server record." fi } load_agent_preferences() { agent_auto_update=0 agent_update_repo_url="$REPO_URL_DEFAULT" agent_update_branch="$REPO_BRANCH_DEFAULT" agent_update_raw_url="$RAW_AGENT_URL_DEFAULT" if [ -f "$PREFS_FILE" ]; then # shellcheck disable=SC1090 . "$PREFS_FILE" fi agent_auto_update="${agent_auto_update:-0}" agent_update_repo_url="${agent_update_repo_url:-$REPO_URL_DEFAULT}" agent_update_branch="${agent_update_branch:-$REPO_BRANCH_DEFAULT}" agent_update_raw_url="${agent_update_raw_url:-$RAW_AGENT_URL_DEFAULT}" } validate_agent_file() { local candidate="$1" [ -s "$candidate" ] || { warn "Candidate agent file is empty: $candidate" return 1 } if head -5 "$candidate" | grep -Eiq '(/dev/null || true perl -c "$candidate" >/tmp/gsp-agent-perl-check.log 2>&1 || { warn "Candidate agent failed perl validation:" cat /tmp/gsp-agent-perl-check.log >&2 2>/dev/null || true return 1 } return 0 } download_agent_with_curl() { local target="$1" if ! command -v curl >/dev/null 2>&1; then return 1 fi echo "Downloading Windows agent from $agent_update_raw_url..." curl -fsSL "$agent_update_raw_url" -o "$target" } download_agent_with_git() { local target="$1" if ! command -v git >/dev/null 2>&1; then return 1 fi local repo_dir source_file repo_dir="$(dirname "$target")/repo" echo "Checking for Windows agent update from $agent_update_repo_url ($agent_update_branch)..." if ! git clone --depth 1 --branch "$agent_update_branch" "$agent_update_repo_url" "$repo_dir"; then return 1 fi source_file="$repo_dir/$REPO_AGENT_PATH" if [ ! -f "$source_file" ]; then warn "Updated Windows agent source was not found at $REPO_AGENT_PATH" return 1 fi cp "$source_file" "$target" } auto_update_windows_agent() { [ "$agent_auto_update" = "1" ] || { echo "Agent auto-update is disabled." return 0 } local tmp_dir candidate_file target_file backup_file tmp_dir="$(mktemp -d /tmp/gsp-agent-update.XXXXXX 2>/dev/null)" || { warn "Could not create temporary update directory; skipping auto-update." return 0 } candidate_file="$tmp_dir/ogp_agent.pl" target_file="$AGENT_DIR/ogp_agent.pl" backup_file="$AGENT_DIR/ogp_agent.pl.bak.$(date +%Y%m%d%H%M%S)" if ! download_agent_with_curl "$candidate_file"; then warn "curl download failed or curl is unavailable; trying git fallback." if ! download_agent_with_git "$candidate_file"; then warn "Agent auto-update download failed; using the current agent." rm -rf "$tmp_dir" return 0 fi fi if ! validate_agent_file "$candidate_file"; then warn "Downloaded Windows agent was rejected; using the current agent." rm -rf "$tmp_dir" return 0 fi if [ -f "$target_file" ] && ! validate_agent_file "$target_file"; then warn "Current Windows agent does not validate. Auto-update can still replace it if backup succeeds." fi if [ -f "$target_file" ]; then cp "$target_file" "$backup_file" 2>/dev/null || { warn "Could not backup $target_file; skipping auto-update." rm -rf "$tmp_dir" return 0 } else warn "$target_file is missing; installing validated agent without a local backup." backup_file="" fi if ! cp "$candidate_file" "$target_file"; then warn "Could not copy updated Windows agent; restoring backup." [ -n "$backup_file" ] && cp "$backup_file" "$target_file" 2>/dev/null rm -rf "$tmp_dir" return 0 fi if ! validate_agent_file "$target_file"; then warn "Updated Windows agent failed validation after install; restoring backup." [ -n "$backup_file" ] && cp "$backup_file" "$target_file" 2>/dev/null rm -rf "$tmp_dir" return 0 fi echo "Windows agent auto-update completed." rm -rf "$tmp_dir" return 0 } cd "$AGENT_DIR" || fail "Could not enter $AGENT_DIR. Is the Windows agent installed under Cygwin /OGP?" setup_startup_log normalize_text_files "$AGENT_DIR" normalize_text_files "/Install" ensure_default_configs load_agent_preferences auto_update_windows_agent validate_required_config echo "Validating $AGENT_DIR/ogp_agent.pl..." validate_agent_file "$AGENT_DIR/ogp_agent.pl" || fail "Perl syntax/dependency validation failed. Install missing Cygwin Perl packages or restore a valid Windows agent file." echo "Launching GSP Windows Agent..." exec perl "$AGENT_DIR/ogp_agent.pl" -pidfile "$PIDFILE"