forked from eprev/locationchanger
-
Notifications
You must be signed in to change notification settings - Fork 3
/
locationchanger.sh
executable file
·132 lines (111 loc) · 5.49 KB
/
locationchanger.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/bin/bash
INSTALL_DIR=/usr/local/bin
SCRIPT_NAME=$INSTALL_DIR/locationchanger
LAUNCH_AGENTS_DIR=$HOME/Library/LaunchAgents
PLIST_NAME=$LAUNCH_AGENTS_DIR/LocationChanger.plist
sudo -v
sudo mkdir -p ${INSTALL_DIR}
cat << "EOT" | sudo tee ${SCRIPT_NAME} > /dev/null
#!/bin/bash
# This script changes network Location based on the name of Wi-Fi network.
DEFAULT_LOCATION='Automatic'
ENABLE_NOTIFICATIONS=1 # To enable notifications, set to 1. For verbose notifications, set to 2. To disable, set to 0.
CONFIG_FILE=${HOME}/.locations/locations.conf
SCRIPT_DIR=${HOME}/.locations # directory for scripts attached to Locations
LOGFILE=${HOME}/Library/Logs/LocationChanger.log
exec 2>&1 >> ${LOGFILE}
sleep 3
ts() {
date +"[%Y-%m-%d %H:%M:%S] ${*}"
}
# get the SSID & BSSID of the current Wi-Fi network
WIFI_INFO=$(/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I)
SSID=$(echo "${WIFI_INFO}" | grep ' SSID' | cut -d : -f 2- | sed 's/^[ ]*//')
BSSID=$(echo "${WIFI_INFO}" | grep ' BSSID' | cut -d : -f 2- | sed 's/^[ ]*//' | sed 's/[[:<:]]\([0-9a-zA-Z]\)[[:>:]]/0\1/g' | tr '[:lower:]' '[:upper:]')
# escape the SSID string for better string handling in our logic below
ESSID=$(echo "${SSID}" | sed 's/[.[\*^$]/\\\\&/g')
# get a list of Locations configured on this machine
LOCATION_NAMES=$(scselect | tail -n +2 | cut -d \( -f 2- | sed 's/)$//')
# get the currently selected Location
CURRENT_LOCATION=$(scselect | tail -n +2 | egrep '^\ +\*' | cut -d \( -f 2- | sed 's/)$//')
ts "Connected to '${SSID}'"
# if a config file exists, consult it first
if [ -f ${CONFIG_FILE} ]; then
SSID_CONFIG_LOCATION=$(grep "^${ESSID}=" ${CONFIG_FILE} | cut -d = -f 2)
BSSID_CONFIG_LOCATION=$(grep -i "^${BSSID}=" ${CONFIG_FILE} | cut -d = -f 2) # we want `grep` to be case-insensitive here since users may put in lower or upper case for the BSSID/MAC address
if [ "${BSSID_CONFIG_LOCATION}" != "" ]; then
NEW_LOCATION=${BSSID_CONFIG_LOCATION}
NOTIFICATION_STRING="BSSID '${BSSID}' (SSID '${SSID}') has a manually configured Location; changing from '${CURRENT_LOCATION}' to '${NEW_LOCATION}'"
ts "Will switch the Location to '${NEW_LOCATION}' (BSSID found in configuration file)"
elif [ "${SSID_CONFIG_LOCATION}" != "" ]; then
NEW_LOCATION=${SSID_CONFIG_LOCATION}
NOTIFICATION_STRING="SSID '${SSID}' has a manually configured Location; changing from '${CURRENT_LOCATION}' to '${NEW_LOCATION}'"
ts "Will switch the Location to '${NEW_LOCATION}' (SSID found in configuration file)"
fi
fi
# if not found in the config file, check if there's a Location that matches the SSID
if echo "${LOCATION_NAMES}" | grep -q "^${ESSID}$" && [ -z "${NEW_LOCATION}" ]; then
NEW_LOCATION="${SSID}"
NOTIFICATION_STRING="Changing from '${CURRENT_LOCATION}' to '${NEW_LOCATION}', as the Location name matches the SSID"
ts "Location '${SSID}' was found and matches the SSID. Will switch the Location to '${NEW_LOCATION}'"
# if still not found, try to use the DEFAULT_LOCATION
elif echo "${LOCATION_NAMES}" | grep -q "^${DEFAULT_LOCATION}$" && [ -z "${NEW_LOCATION}" ]; then
NEW_LOCATION=${DEFAULT_LOCATION}
NOTIFICATION_STRING="Changing from '${CURRENT_LOCATION}' to default Location '${DEFAULT_LOCATION}'"
ts "Location '${SSID}' was not found. Will default to '${DEFAULT_LOCATION}'"
# if we arrived here, something went awry
elif [ -z "${NEW_LOCATION}" ]; then
NOTIFICATION_STRING="Something went wrong trying to automatically switch Locations. Please consult the log at: ${LOGFILE}"
ts "Location '${SSID}' and default Location ${DEFAULT_LOCATION} were not found. The following Locations are available:%n${LOCATION_NAMES}"
exit 1
fi
if [ "${NEW_LOCATION}" != "" ]; then
if [ "${NEW_LOCATION}" != "${CURRENT_LOCATION}" ]; then
ts "Changing the Location to '${NEW_LOCATION}'"
scselect "${NEW_LOCATION}"
if [ ${?} -ne 0 ]; then
NOTIFICATION_STRING="Something went wrong trying to automatically switch Location. Please consult the log at: ${LOGFILE}"
fi
SCRIPT="${SCRIPT_DIR}/${NEW_LOCATION}"
if [ -f "${SCRIPT}" ]; then
ts "Running script: '${SCRIPT}'"
$(${SCRIPT})
fi
else
ts "System is already set to the requested Location '${NEW_LOCATION}'. No change required."
# only notify on this event if verbose notifications are enabled
if [ ${ENABLE_NOTIFICATIONS} -eq 2 ]; then
NOTIFICATION_STRING="Location already set to '${NEW_LOCATION}'; not changing"
# otherwise, disable the notification for this run
elif [ ${ENABLE_NOTIFICATIONS} -eq 1 ]; then
ENABLE_NOTIFICATIONS=0
fi
fi
fi
# if notifications are enabled, let 'em know what's happenin'!
if [ ${ENABLE_NOTIFICATIONS} -ge 1 ]; then
osascript -e "display notification \"${NOTIFICATION_STRING}\" with title \"locationchanger\""
fi
exit 0
EOT
sudo chmod +x ${SCRIPT_NAME}
mkdir -p ${LAUNCH_AGENTS_DIR}
cat > ${PLIST_NAME} << EOT
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>locationchanger</string>
<key>ProgramArguments</key>
<array>
<string>${SCRIPT_NAME}</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
</array>
</dict>
</plist>
EOT
launchctl load ${PLIST_NAME}