mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 19:09:43 +00:00
156 lines
5.5 KiB
Bash
156 lines
5.5 KiB
Bash
#!/bin/bash
|
|
# System Configuration Maintenance Module
|
|
# Fix broken preferences and broken login items
|
|
|
|
set -euo pipefail
|
|
|
|
# ============================================================================
|
|
# Broken Preferences Detection and Cleanup
|
|
# Find and remove corrupted .plist files
|
|
# ============================================================================
|
|
|
|
# Clean broken preference files
|
|
# Uses plutil -lint to validate plist files
|
|
# Returns: count of broken files fixed
|
|
fix_broken_preferences() {
|
|
local prefs_dir="$HOME/Library/Preferences"
|
|
[[ -d "$prefs_dir" ]] || return 0
|
|
|
|
local broken_count=0
|
|
|
|
# Check main preferences directory
|
|
while IFS= read -r plist_file; do
|
|
[[ -f "$plist_file" ]] || continue
|
|
|
|
# Skip system preferences
|
|
local filename
|
|
filename=$(basename "$plist_file")
|
|
case "$filename" in
|
|
com.apple.* | .GlobalPreferences* | loginwindow.plist)
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
# Validate plist using plutil
|
|
plutil -lint "$plist_file" > /dev/null 2>&1 && continue
|
|
|
|
# Remove broken plist
|
|
rm -f "$plist_file" 2> /dev/null || true
|
|
((broken_count++))
|
|
done < <(run_with_timeout 10 sh -c "find '$prefs_dir' -maxdepth 1 -name '*.plist' -type f 2> /dev/null || true")
|
|
|
|
# Check ByHost preferences with timeout protection
|
|
local byhost_dir="$prefs_dir/ByHost"
|
|
if [[ -d "$byhost_dir" ]]; then
|
|
while IFS= read -r plist_file; do
|
|
[[ -f "$plist_file" ]] || continue
|
|
|
|
local filename
|
|
filename=$(basename "$plist_file")
|
|
case "$filename" in
|
|
com.apple.* | .GlobalPreferences*)
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
plutil -lint "$plist_file" > /dev/null 2>&1 && continue
|
|
|
|
rm -f "$plist_file" 2> /dev/null || true
|
|
((broken_count++))
|
|
done < <(run_with_timeout 10 sh -c "find '$byhost_dir' -name '*.plist' -type f 2> /dev/null || true")
|
|
fi
|
|
|
|
echo "$broken_count"
|
|
}
|
|
|
|
# ============================================================================
|
|
# Broken Login Items Cleanup
|
|
# Find and remove login items pointing to non-existent files
|
|
# ============================================================================
|
|
|
|
# Clean broken login items (LaunchAgents pointing to missing executables)
|
|
# Returns: count of broken items fixed
|
|
fix_broken_login_items() {
|
|
local launch_agents_dir="$HOME/Library/LaunchAgents"
|
|
[[ -d "$launch_agents_dir" ]] || return 0
|
|
|
|
local broken_count=0
|
|
|
|
while IFS= read -r plist_file; do
|
|
[[ -f "$plist_file" ]] || continue
|
|
|
|
# Skip system items
|
|
local filename
|
|
filename=$(basename "$plist_file")
|
|
case "$filename" in
|
|
com.apple.*)
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
# Extract Program or ProgramArguments[0] from plist using plutil
|
|
local program=""
|
|
program=$(plutil -extract Program raw "$plist_file" 2> /dev/null || echo "")
|
|
|
|
if [[ -z "$program" ]]; then
|
|
# Try ProgramArguments array (first element)
|
|
program=$(plutil -extract ProgramArguments.0 raw "$plist_file" 2> /dev/null || echo "")
|
|
fi
|
|
|
|
# Skip if no program found or program exists
|
|
[[ -z "$program" ]] && continue
|
|
[[ -e "$program" ]] && continue
|
|
|
|
# Program doesn't exist - this is a broken login item
|
|
launchctl unload "$plist_file" 2> /dev/null || true
|
|
rm -f "$plist_file" 2> /dev/null || true
|
|
((broken_count++))
|
|
done < <(run_with_timeout 10 sh -c "find '$launch_agents_dir' -name '*.plist' -type f 2> /dev/null || true")
|
|
|
|
echo "$broken_count"
|
|
}
|
|
|
|
# ============================================================================
|
|
# Check for broken configurations
|
|
# Returns: JSON line if issues found, empty otherwise
|
|
# ============================================================================
|
|
|
|
check_broken_configs() {
|
|
local prefs_dir="$HOME/Library/Preferences"
|
|
local launch_agents_dir="$HOME/Library/LaunchAgents"
|
|
|
|
local broken_prefs=0
|
|
local broken_items=0
|
|
|
|
# Count broken preferences
|
|
if [[ -d "$prefs_dir" ]]; then
|
|
while IFS= read -r plist_file; do
|
|
[[ -f "$plist_file" ]] || continue
|
|
local filename=$(basename "$plist_file")
|
|
case "$filename" in
|
|
com.apple.* | .GlobalPreferences* | loginwindow.plist) continue ;;
|
|
esac
|
|
plutil -lint "$plist_file" > /dev/null 2>&1 || ((broken_prefs++))
|
|
done < <(run_with_timeout 10 sh -c "find '$prefs_dir' -maxdepth 1 -name '*.plist' -type f 2> /dev/null || true")
|
|
fi
|
|
|
|
# Count broken login items
|
|
if [[ -d "$launch_agents_dir" ]]; then
|
|
while IFS= read -r plist_file; do
|
|
[[ -f "$plist_file" ]] || continue
|
|
local filename=$(basename "$plist_file")
|
|
case "$filename" in com.apple.*) continue ;; esac
|
|
|
|
local program=$(plutil -extract Program raw "$plist_file" 2> /dev/null || echo "")
|
|
[[ -z "$program" ]] && program=$(plutil -extract ProgramArguments.0 raw "$plist_file" 2> /dev/null || echo "")
|
|
[[ -z "$program" ]] && continue
|
|
[[ -e "$program" ]] || ((broken_items++))
|
|
done < <(run_with_timeout 10 sh -c "find '$launch_agents_dir' -name '*.plist' -type f 2> /dev/null || true")
|
|
fi
|
|
|
|
local total=$((broken_prefs + broken_items))
|
|
if [[ $total -gt 0 ]]; then
|
|
echo "fix_broken_configs|Fix Broken Configurations|Fix $total broken preference/login item files|false"
|
|
fi
|
|
}
|