├── README.md └── locationchanger.sh /README.md: -------------------------------------------------------------------------------- 1 | # Location Changer 2 | 3 | It automatically changes OS X’s [network location](https://support.apple.com/en-us/HT202480) 4 | based on the name of Wi-Fi network and runs arbitrary scrips when it happens. 5 | 6 | ## Installation & Update 7 | 8 | ``` 9 | curl -L https://github.com/eprev/locationchanger/raw/master/locationchanger.sh | bash 10 | ``` 11 | 12 | It will ask you for a root password to install `locationchanger` to the */usr/local/bin* directory. 13 | 14 | ## Basic usage 15 | 16 | You have to name network locations after Wi-Fi networks. Let’s say, you need to have 17 | a specific network preferences for “Corp Wi-Fi” wireless network, then you have to create 18 | a location “Corp Wi-Fi”. Now, the network location will change to “Corp Wi-Fi” automatically, 19 | if you connect to that wireless network. And if you connect to the Wi-Fi network that you 20 | don’t have a location for, then the location will change to the default one (“Automatic”). 21 | 22 | If you want to run a script every time you connect to a specific Wi-Fi network, then put 23 | those scripts in *~/.locations* and name them after Wi-Fi networks (making sure you set 24 | corresponding network locations). For instance, you have a script that changes security 25 | preferences when you connect to the “Corp Wi-Fi” network: 26 | 27 | ```bash 28 | #!/usr/bin/env bash 29 | exec 2>&1 30 | 31 | # Require password immediately after sleep or screen saver begins 32 | osascript -e 'tell application "System Events" to set require password to wake of security preferences to true' 33 | ``` 34 | 35 | Then name this script as *~/.locations/Corp Wi-Fi*. And you might want to create 36 | *~/.locations/Automatic* that will reset those changes: 37 | 38 | ```bash 39 | #!/usr/bin/env bash 40 | exec 2>&1 41 | 42 | # Don’t require password immediately after sleep or screen saver begins 43 | osascript -e 'tell application "System Events" to set require password to wake of security preferences to false' 44 | ``` 45 | 46 | ## Aliasing 47 | 48 | If you want to share one network location between different wireless networks (for instance, you have a wireless router which broadcasts on 2.4 and 5GHz bands simultaneously), then you can create a configuration file *~/.locations/locations.conf* (plain text file with simple key-value pairs, no spaces in between): 49 | 50 | ```bash 51 | Wi-Fi_5GHz=Wi-Fi 52 | ``` 53 | 54 | Where the keys are the wireless network names and the values are the desired location names. 55 | 56 | ## Troubleshooting 57 | 58 | It writes quite extensive information to the log file every time the wireless network changes: 59 | 60 | ```bash 61 | tail -f ~/Library/Logs/LocationChanger.log 62 | ``` 63 | 64 | Sample output: 65 | 66 | ``` 67 | Connected to 'Wi-Fi_5GHz' 68 | Will switch the location to 'Wi-Fi' (configuration file) 69 | Changing the location to 'Wi-Fi' 70 | Running '~/.locations/Wi-Fi' 71 | ``` 72 | -------------------------------------------------------------------------------- /locationchanger.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | INSTALL_DIR=/usr/local/bin 4 | SCRIPT_NAME=$INSTALL_DIR/locationchanger 5 | LAUNCH_AGENTS_DIR=$HOME/Library/LaunchAgents 6 | PLIST_NAME=$LAUNCH_AGENTS_DIR/LocationChanger.plist 7 | 8 | sudo -v 9 | 10 | sudo mkdir -p $INSTALL_DIR 11 | cat << "EOT" | sudo tee $SCRIPT_NAME > /dev/null 12 | #!/bin/bash 13 | 14 | # This script changes network location based on the name of Wi-Fi network. 15 | 16 | exec 2>&1 >> $HOME/Library/Logs/LocationChanger.log 17 | 18 | sleep 3 19 | 20 | ts() { 21 | date +"[%Y-%m-%d %H:%M] $*" 22 | } 23 | 24 | ID=`whoami` 25 | ts "I am '$ID'" 26 | 27 | SSID=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | grep ' SSID' | cut -d : -f 2- | sed 's/^[ ]*//'` 28 | 29 | LOCATION_NAMES=`scselect | tail -n +2 | cut -d \( -f 2- | sed 's/)$//'` 30 | CURRENT_LOCATION=`scselect | tail -n +2 | egrep '^\ +\*' | cut -d \( -f 2- | sed 's/)$//'` 31 | 32 | ts "Connected to '$SSID'" 33 | 34 | CONFIG_FILE=$HOME/.locations/locations.conf 35 | ts "Probing '$CONFIG_FILE'" 36 | 37 | if [ -f $CONFIG_FILE ]; then 38 | ts "Reading to '$CONFIG_FILE'" 39 | ESSID=`echo "$SSID" | sed 's/[.[\*^$]/\\\\&/g'` 40 | NEW_SSID=`grep "^$ESSID=" $CONFIG_FILE | cut -d = -f 2` 41 | if [ "$NEW_SSID" != "" ]; then 42 | ts "Will switch the location to '$NEW_SSID' (configuration file)" 43 | SSID=$NEW_SSID 44 | else 45 | ts "Will switch the location to '$SSID'" 46 | fi 47 | fi 48 | 49 | ESSID=`echo "$SSID" | sed 's/[.[\*^$]/\\\\&/g'` 50 | if echo "$LOCATION_NAMES" | grep -q "^$ESSID$"; then 51 | NEW_LOCATION="$SSID" 52 | else 53 | if echo "$LOCATION_NAMES" | grep -q "^Automatic$"; then 54 | NEW_LOCATION=Automatic 55 | ts "Location '$SSID' was not found. Will default to 'Automatic'" 56 | else 57 | ts "Location '$SSID' was not found. The following locations are available: $LOCATION_NAMES" 58 | exit 1 59 | fi 60 | fi 61 | 62 | if [ "$NEW_LOCATION" != "" ]; then 63 | if [ "$NEW_LOCATION" != "$CURRENT_LOCATION" ]; then 64 | ts "Changing the location to '$NEW_LOCATION'" 65 | scselect "$NEW_LOCATION" 66 | SCRIPT="$HOME/.locations/$NEW_LOCATION" 67 | if [ -f "$SCRIPT" ]; then 68 | ts "Running '$SCRIPT'" 69 | "$SCRIPT" 70 | fi 71 | else 72 | ts "Already at '$NEW_LOCATION'" 73 | fi 74 | fi 75 | EOT 76 | 77 | sudo chmod +x $SCRIPT_NAME 78 | 79 | mkdir -p $LAUNCH_AGENTS_DIR 80 | cat > $PLIST_NAME << EOT 81 | 82 | 83 | 84 | 85 | Label 86 | org.eprev.locationchanger 87 | ProgramArguments 88 | 89 | /usr/local/bin/locationchanger 90 | 91 | WatchPaths 92 | 93 | /Library/Preferences/SystemConfiguration 94 | 95 | RunAtLoad 96 | 97 | 98 | 99 | EOT 100 | 101 | launchctl load -w $PLIST_NAME 102 | --------------------------------------------------------------------------------