Scan for and connect to networks from an openbox pipe menu
So the other day when i was using wifi-select (awesome tool) to connect to a friends hot-spot, i realized “hey! this would be great as an openbox pipe menu.” i’m fairly decent in bash and i knew both netcfg and wifi-select were in bash so why not rewrite it that way?
Screenshots
Here’s some screens to show what this does:
Wifi-Pipe
A simplified version of wifi-select which will scan for networks and populate an openbox right-click menu item with available networks. displays security type and signal strength. click on a network to connect via netcfg the same way wifi-select does it.
zenity is used to ask for a password and notify of a bad connection. one can optionally remove the netcfg profile if the connection fails.
What’s needed
– you have to be using netcfg to manage your wireless
– you have to install zenity
– you have to save the script as ~/.config/openbox/wifi-pipe and make it executable:
chmod +x ~/.config/openbox/wifi-pipe
– you have to add a sudoers entry to allow passwordless sudo on this script and netcfg (!)
USERNAME ALL=(ALL) NOPASSWD: /usr/bin/netcfg USERNAME ALL=(ALL) NOPASSWD: /home/USERNAME/.config/openbox/wifi-pipe
– you have to adjust ~/.config/openbox/menu.xml like so:
<menu id="root-menu" label="Openbox 3">
<menu id="pipe-wifi" label="Wifi" execute="sudo /home/USERNAME/.config/openbox/wifi-pipe INTERFACE" />
<menu id="term-menu"/>
<item label="Run...">
<action name="Execute">
<command>gmrun</command>
</action>
</item>
...
where USERNAME is you and INTERFACE is probably wlan0 or similar
openbox –reconfigure and you should be good to go.
The Script:
#!/bin/bash
#
# pbrisbin 2009
#
# simplified version of wifi-select designed to output as an openbox pipe menu
#
# required:
# netcfg
# zenity
# NOPASSWD entries for this and netcfg through visudo
#
# the following in menu.xml:
# <menu id="pipe-wifi" label="Wifi" execute="sudo /path/to/wifi-pipe interface"/>
#
# the idea is to run this script once to scan/print, then again immediately to connect.
# therefore, if you scan but don't connect, a temp file is left in /tmp. the next scan
# will overwrite it, and the next connect will remove it.
#
###
# source this to get PROFILE_DIR and SUBR_DIR
. /usr/lib/network/network
errorout() {
echo "<openbox_pipe_menu>"
echo "<item label=\"$1\" />"
echo "</openbox_pipe_menu>"
exit 1
}
create_profile() {
ESSID="$1"; INTERFACE="$2"; SECURITY="$3"; KEY="$4"
PROFILE_FILE="$PROFILE_DIR$ESSID"
cat > "$PROFILE_FILE" << END_OF_PROFILE
CONNECTION="wireless"
ESSID="$ESSID"
INTERFACE="$INTERFACE"
DESCRIPTION="Automatically generated profile"
SCAN="yes"
IP="dhcp"
TIMEOUT="10"
SECURITY="$SECURITY"
END_OF_PROFILE
# i think wifi-select should adopt these perms too...
if [ -n "$KEY" ]; then
echo "KEY=\"$KEY\"" >> "$PROFILE_FILE"
chmod 600 "$PROFILE_FILE"
else
chmod 644 "$PROFILE_FILE"
fi
}
print_menu() {
# scan for networks
iwlist $INTERFACE scan 2>/dev/null | awk -f $SUBR_DIR/parse-iwlist.awk | sort -t= -nrk3 > /tmp/networks.tmp
# exit if none found
if [ ! -s /tmp/networks.tmp ]; then
rm /tmp/networks.tmp
errorout "no networks found."
fi
# otherwise print the menu
echo "<openbox_pipe_menu>"
IFS='='
cat /tmp/networks.tmp | while read ESSID SECURITY QUALITY; do
echo "<item label=\"$ESSID ($SECURITY) $QUALITY%\">"
echo " <action name=\"Execute\">"
echo " <command>sudo $0 $INTERFACE connect \"$ESSID\"</command>"
echo " </action>"
echo "</item>"
done
unset IFS
echo "</openbox_pipe_menu>"
}
connect() {
# check for an existing profile
PROFILE_FILE="$(grep -REl "ESSID=[\"']?$ESSID[\"']?" "$PROFILE_DIR" | grep -v '~$' | head -n1)"
# if found use it, else create a new profile
if [ -n "$PROFILE_FILE" ]; then
PROFILE=$(basename "$PROFILE_FILE")
else
PROFILE="$ESSID"
SECURITY="$(awk -F '=' "/$ESSID/"'{print $2}' /tmp/networks.tmp | head -n1)"
# ask for the security key if needed
if [ "$SECURITY" != "none" ]; then
KEY="$(zenity --entry --title="Authentication" --text="Please enter $SECURITY key for $ESSID" --hide-text)"
fi
# create the new profile
create_profile "$ESSID" "$INTERFACE" "$SECURITY" "$KEY"
fi
# connect
netcfg2 "$PROFILE" >/tmp/output.tmp
# if failed, ask about removal of created profile
if [ $? -ne 0 ]; then
zenity --question \
--title="Connection failed" \
--text="$(grep -Eo "[\-\>]\ .*$" /tmp/output.tmp) \n Remove $PROFILE_FILE?" \
--ok-label="Remove profile"
[ $? -eq 0 ] && rm $PROFILE_FILE
fi
rm /tmp/output.tmp
rm /tmp/networks.tmp
}
[ $(id -u) -ne 0 ] && errorout "root access required."
[ -z "$1" ] && errorout "usage: $0 [interface]"
INTERFACE="$1"; shift
# i added a sleep if we need to explicitly bring it up
# b/c youll get "no networks found" when you scan right away
# this only happens if we aren't up already
if ! ifconfig | grep -q $INTERFACE; then
ifconfig $INTERFACE up &>/dev/null || errorout "$INTERFACE not up"
sleep 3
fi
if [ "$1" = "connect" ]; then
ESSID="$2"
connect
else
print_menu
fi
exit 0











