You are not logged in.
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?
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 just to get PROFILE_DIR
. /usr/lib/network/network
[ -z "$PROFILE_DIR" ] && PROFILE_DIR='/etc/network.d/'
# awk code for parsing iwlist output
# putting it here removes the wifi-select dependency
# and allows for my own tweaking
# prints a list "essid=security=quality_as_percentage"
PARSER='
BEGIN { FS=":"; OFS="="; }
/\<Cell/ { if (essid) print essid, security, quality[2]/quality[3]*100; security="none" }
/\<ESSID:/ { essid=substr($2, 2, length($2) - 2) } # discard quotes
/\<Quality=/ { split($1, quality, "[=/]") }
/\<Encryption key:on/ { security="wep" }
/\<IE:.*WPA.*/ { security="wpa" }
END { if (essid) print essid, security, quality[2]/quality[3]*100 }
'
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 "$PARSER" | 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
local IFS='='
echo "<openbox_pipe_menu>"
while read ESSID SECURITY QUALITY; do
echo "<item label=\"$ESSID ($SECURITY) ${QUALITY/.*/}%\">" # trim decimals
echo " <action name=\"Execute\">"
echo " <command>sudo $0 $INTERFACE connect \"$ESSID\"</command>"
echo " </action>"
echo "</item>"
done < /tmp/networks.tmp
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"
while ! ifconfig | grep -q $INTERFACE; do sleep 1; done
fi
if [ "$1" = "connect" ]; then
ESSID="$2"
connect
else
print_menu
fi
Screenshots
removed -- Hi-res shots available on my site
NOTE - i have not tested this extensively but it was working for me in most cases. any updates/fixes will be edited right into this original post. enjoy!
UPDATE - 10/24/2009: i moved the awk statement from wifi-select directly into the script. this did two things: wifi-select is no longer needed on the system, and i could tweak the awk statement to be more accurate. it now prints a true percentange. iwlist prints something like Quality=17/70 and the original awk statement would just output 17 as the quality. i changed to print (17/70)*100 then bash trims the decimals so you get a true percentage.
Last edited by brisbin33 (2010-05-09 01:28:20)
//github/
Offline
now just install and set a decent gtk theme
I'll definitely test this one out... now I just need to figure netcfg out ^^
Offline
This is a great idea. I salute you! I never have to connect to that many wireless networks so I just use netcfg at home and USB 3G modem at school. Pipe menus are pretty cool though.
< Daenyth> tomkx: my girlfriend is linux
< Daenyth> srsly
< Daenyth> she loves the way I «make install»
< Daenyth> all her /dev entries are mode 7 for me
Offline
this is completely awesome! works very well, thanks a lot!
cheers
Barde
Offline
Great script!
Offline
Awesome, you should make a pkgbuld and up it to the AUR
Offline
Any chance for a PekWM version?
It would be awesome!!
archlinux on Macbook Pro 10,1
Offline
@FaN_OnLy1, seeing as installation is 10% copy/pasting a script and 90% configuring your system (rc.xml, visudo, and so forth) im not sure if this makes sense as an AUR pkg. but feel free to package it if you'd like (and credit me ).
@froli, i'm not sure if pekwm supports any sort of pipe-menu, might be an openbox only feature. i don't use that WM, so it probably wouldn't happen anyway .
@all, thanks for the compliments; i find it a pretty slick approach, im glad others like it too!
also, if anyone doesn't want to deal with copy/pasting, you can try this*:
wget -O ~/.config/openbox/wifi-pipe "http://pbrisbin.com:8080/shared/wifi-pipe" && chmod +x ~/.config/openbox/wifi-pipe
then proceed with the rc.xml and visudo configurations.
*FYI: not sure how long i'll leave that file up on my server, or if i'll push any updates to it.
//github/
Offline
@froli, i'm not sure if pekwm supports any sort of pipe-menu, might be an openbox only feature. i don't use that WM, so it probably wouldn't happen anyway
.
Yes PekWM support pipe-menu, but my question was not specific to you, it was for anyone who can adapt this script to PekWM.
I'll just try to adapt it to PekWM by myself and if it's successful, I'll post the results here.
archlinux on Macbook Pro 10,1
Offline
Did anybody succeed in making a pekwm edition? I would be quite interested. . .
Thanks,
Rasmus
Arch x64 on Thinkpad X200s/W530
Offline
so i did some quick pekwm research, looks like adjusting my script wouldn't be too hard; i may put it together myself, but here is some code that might help anyone interested in doing the work:
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 "Dynamic {"
IFS='='
cat /tmp/networks.tmp | while read ESSID SECURITY QUALITY; do
echo "Entry = \"$ESSID ($SECURITY) $QUALITY%\" {"
echo " Actions = \"Exec sudo $0 $INTERFACE connect \\\"$ESSID\\\"\"</command>"
echo "}"
done
unset IFS
echo "}"
}
SubMenu = "WiFi" {
Entry = { Actions = "Dynamic /path/to/wifi-pipe" }
NOTE: completely untested (and pretty much just a guess based on googling).
if i ever feel motivated enough to install pekwm and test, ill post complete pekwm script/instructions... but i wouldn't expect anything anytime soon
//github/
Offline
so i did some quick pekwm research, looks like adjusting my script wouldn't be too hard; i may put it together myself, but here is some code that might help anyone interested in doing the work:
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 "Dynamic {" IFS='=' cat /tmp/networks.tmp | while read ESSID SECURITY QUALITY; do echo "Entry = \"$ESSID ($SECURITY) $QUALITY%\" {" echo " Actions = \"Exec sudo $0 $INTERFACE connect \\\"$ESSID\\\"\"</command>" echo "}" done unset IFS echo "}" }
SubMenu = "WiFi" { Entry = { Actions = "Dynamic /path/to/wifi-pipe" }
NOTE: completely untested (and pretty much just a guess based on googling).
if i ever feel motivated enough to install pekwm and test, ill post complete pekwm script/instructions... but i wouldn't expect anything anytime soon
I think the script's not working ... When I type
sh wifi-pipe
in a term it returns nothing
archlinux on Macbook Pro 10,1
Offline
I think the script's not working
... When I type
sh wifi-pipe
in a term it returns nothing
well, just to be sure you're doing it right...
he above is only an adjustment to the OB script's print_menu() function, it's not an entire script to itself. so, if the original OB script shows output for you with
sh ./wifi-pipe
then using the above pint_menu() function (with all the other supporting code) should also show output, (only really only changes the echo's so they print the info in the pekwm format).
oh, and if neither version shows output when you rut it in a term, then you've got other issues... ;P
here's an entire [untested] pekwm script:
#!/bin/bash
#
# pbrisbin 2009
#
# simplified version of wifi-select designed to output as an pekwm pipe menu
#
# required:
# netcfg
# zenity
# NOPASSWD entries for this and netcfg through visudo
#
# the following in pekwm config file:
# SubMenu = "WiFi" {
# Entry = { Actions = "Dynamic /path/to/wifi-pipe" }
#
# 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 "Dynamic {"
echo " Entry = \"$1\""
echo "}"
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 "Dynamic {"
IFS='='
cat /tmp/networks.tmp | while read ESSID SECURITY QUALITY; do
echo "Entry = \"$ESSID ($SECURITY) $QUALITY%\" {"
echo " Actions = \"Exec sudo $0 $INTERFACE connect \\\"$ESSID\\\"\"</command>"
echo "}"
done
unset IFS
echo "}"
}
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
//github/
Offline
Hey that's awesome, thanks for testing Pank!
currently it's sorted by signal strength, and note: i took out any "profile exists / auto generated" stuff, as i don't really care about that. i'm sorry if that's what you were hoping to sort on.
//github/
Offline
No, as I wrote here want I really want is a dynamic netcfg-menu/wifi-select which only shows relevant networks; that is networks that has a profile already.
--Rasmus
Arch x64 on Thinkpad X200s/W530
Offline
@brisbin33 Thanks a lot for this pekwm!!
archlinux on Macbook Pro 10,1
Offline
brisbin33,
How do I limit the output to networks with already existing profiles. I tried to mess around with your script but I did not succeed.
It is useful when you have got a lot of profiles and rarely connects to new networks.
Would it be possible?
Thanks,
Rasmus
Arch x64 on Thinkpad X200s/W530
Offline
Pank, i would just change:
cat /tmp/networks.tmp | while read ESSID SECURITY QUALITY; do
echo "Entry = \"$ESSID ($SECURITY) $QUALITY%\" {"
echo " Actions = \"Exec sudo $0 $INTERFACE connect \\\"$ESSID\\\"\"</command>"
echo "}"
to:
cat /tmp/networks.tmp | while read ESSID SECURITY QUALITY; do
# if a profile file does not exist for the ESSID, don't print it
PROFILE_FILE="$(grep -REl "ESSID=[\"']?$ESSID[\"']?" "$PROFILE_DIR" | grep -v '~$' | head -n1)"
[ -z "$PROFILE_FILE" ] && continue
echo "Entry = \"$ESSID ($SECURITY) $QUALITY%\" {"
echo " Actions = \"Exec sudo $0 $INTERFACE connect \\\"$ESSID\\\"\"</command>"
echo "}"
in the pint_menu() function; this does duplicate code from the connect() function, but it's easier than rewriting both parts .
//github/
Offline
It works as a charm.
Last question and I promise I won't bother you no more
Would it be possible to use the description label of the profile rather than the ESSID?
Thanks,
Rasmus
Arch x64 on Thinkpad X200s/W530
Offline
Would it be possible to use the description label of the profile rather than the ESSID?
anything's possible, something like:
cat /tmp/networks.tmp | while read ESSID SECURITY QUALITY; do
# if a profile file does not exist for the ESSID, don't print it
PROFILE_FILE="$(grep -REl "ESSID=[\"']?$ESSID[\"']?" "$PROFILE_DIR" | grep -v '~$' | head -n1)"
if [ -z "$PROFILE_FILE" ]; then
continue
else
DESC="$(awk -F '"' '/^DESCRIPTION/ {print $2}' "$PROFILE_FILE")"
fi
echo "Entry = \"$DESC ($SECURITY) $QUALITY%\" {"
echo " Actions = \"Exec sudo $0 $INTERFACE connect \\\"$ESSID\\\"\"</command>"
echo "}"
might work. again, untested.
//github/
Offline
Hello,
The script seems to work, but it is slowing down my menu. Everytime when I open my menu, the script starts to search for the available networks. The menu freezes untill the script lists the available networks.
Any solution?
Arch x86_64 on HP 6820s and on HP nx9420. Registered Linux User 350155, since 24-03-2004
"Everyone said that it could not be done, until someone came along who didn't know that."
Offline
i believe the menu is not created (and the scan not started) until you actually mouse over the parent entry.
try putting the wifi entry towards the bottom of your root menu, then don't mouse over it when you open the menu and see if the delay still exists.
if the wifi entry is first in the menu, right click puts your mouse right on it to begin with and a wait-for-scan is probably unavoidable.
//github/
Offline
That's what I already figured out. I changed it to be a submenu under my system-menu and now it doesn't bother me anymore. Thxs.
Last edited by NeoXP (2009-10-01 18:03:05)
Arch x86_64 on HP 6820s and on HP nx9420. Registered Linux User 350155, since 24-03-2004
"Everyone said that it could not be done, until someone came along who didn't know that."
Offline
Nice, thanks for the script!
Offline