*** empty log message ***
[scripts.git] / hotspot.sh
1 #!/bin/bash
2
3 #########################################################################
4 # This program is free software: you can redistribute it and/or modify  #
5 # it under the terms of the version 3 of the GNU General Public License #
6 # as published by the Free Software Foundation.                         #
7 #                                                                       #
8 # This program is distributed in the hope that it will be useful, but   #
9 # WITHOUT ANY WARRANTY; without even the implied warranty of            #
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      #
11 # General Public License for more details.                              #
12 #                                                                       #
13 # You should have received a copy of the GNU General Public License     #
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.  #
15 #                                                                       #
16 # Written by and Copyright (C) Francois Fleuret                         #
17 # Contact <francois@fleuret.org> for comments & bug reports             #
18 #########################################################################
19
20 INTERFACE=wlan0
21 MTU=512
22
23 SCAN_OUTPUT=$(mktemp /tmp/scanresult.XXXXXX)
24 SHOW_CLOSED=0
25
26 ######################################################################
27
28 VT_CURSOR_OFF=$'\033[?25l'
29 VT_CURSOR_ON=$'\033[?25h'
30
31 VT_RESET=$'\033[0m'
32 VT_BOLD=$'\033[1m'
33 VT_UNDERLINE=$'\033[4m'
34 VT_BLINK=$'\033[5m'
35
36 VT_BLACK_FG=$'\033[30m'
37 VT_RED_FG=$'\033[31m'
38 VT_GREEN_FG=$'\033[32m'
39 VT_YELLOW_FG=$'\033[33m'
40 VT_BLUE_FG=$'\033[34m'
41 VT_MAGENTA_FG=$'\033[35m'
42 VT_CYAN_FG=$'\033[36m'
43 VT_WHITE_FG=$'\033[37m'
44
45 VT_BLACK_BG=$'\033[40m'
46 VT_RED_BG=$'\033[41m'
47 VT_GREEN_BG=$'\033[42m'
48 VT_YELLOW_BG=$'\033[43m'
49 VT_BLUE_BG=$'\033[44m'
50 VT_MAGENTA_BG=$'\033[45m'
51 VT_CYAN_BG=$'\033[46m'
52 VT_WHITE_BG=$'\033[47m'
53
54 ######################################################################
55
56 function cleanup-before-quit () {
57     echo ${VT_CURSOR_ON}
58     stty "$stty_state"
59     rm -f ${SCAN_OUTPUT}
60     if [[ "${interface_was_up}" == "" ]]; then
61         echo "The interface was down."
62         ifconfig ${INTERFACE} down
63     fi
64 }
65
66 function sigint-handler () {
67     cleanup-before-quit
68     echo "Interrupted"
69     exit 0
70 }
71
72 function scan () {
73     echo "  Scanning ..."
74     iwconfig ${INTERFACE} ap off essid ""
75     iwlist ${INTERFACE} scan | \
76         sed -e "s/^[\t ]*//"  | grep ^"Cell\|ESSID\|Quality\|Encryption" | \
77         sed \
78         -e "s/Cell [0-9]* - Address: \([0-9]*\)/AP,\1/" \
79         -e "s/^ *ESSID:\\\"\([^\\\"]*\)\\\".*$/ESSID,\1/" \
80         -e "s/Quality=\([0-9]*\).*$/QUALITY,\1/" \
81         -e "s/Encryption key:/ENCRYPTION,/" | \
82         awk 'BEGIN { FS="," }
83          {
84            if($1 == "ESSID") { essid=$2 }
85            else if($1 == "AP") { ap=$2 }
86            else if($1 == "QUALITY") { quality=$2; }
87            else if($1 == "ENCRYPTION") {
88              if($2 == "off") {
89                open="        "
90                printf("%d,%s,%s,%s\n",quality,open,essid,ap);
91              } else {
92                if('${SHOW_CLOSED}') {
93                  open="(closed)"
94                  printf("%d,%s,%s,%s\n",quality,open,essid,ap);
95                }
96              }
97            }
98          }' | \
99              sort -rn > ${SCAN_OUTPUT}
100
101     number_of_aps=$(wc -l ${SCAN_OUTPUT} | awk '{print $1}')
102
103     chmod a+rw ${SCAN_OUTPUT}
104 }
105
106 function redisplay () {
107     clear
108
109     echo
110     echo -n "  ${VT_UNDERLINE}Hotspot selection${VT_RESET}"
111     if [[ $SHOW_CLOSED == 0 ]]; then
112         echo " (show only open networks)"
113     else
114         echo
115     fi
116     echo
117     echo "  [s,r] scan  [m] switch the free-only view and scan    [q] quit"
118     echo "  [e] select essid + dhcp  [a] selects essid/ap + dhcp  [k] kill dhcp and quit"
119     echo
120
121     for i in $(ifconfig -s | grep -E -v ^lo\|Iface\|wmaster | awk '{print $1}'); do
122         echo "  Warning: $i is up"
123     done
124     echo
125
126     if [[ ${number_of_aps} == "0" ]]; then
127         echo "  ${VT_RED_FG}${VT_BOLD}No access point detected.${VT_RESET}"
128     else
129
130         awk < ${SCAN_OUTPUT} 'BEGIN { nb=1; FS="," }
131          {
132              if(nb == '$current_ap') {
133                printf(" =>");
134              } else {
135                printf("   ");
136              }
137              if($2 == "(closed)") {
138                printf("'${VT_RED_FG}'");
139                printf("% 3s %s \"%s\" %s'${VT_RESET}'\n", $1, $2, $3, $4);
140                  } else {
141                printf("'${VT_GREEN_FG}'");
142                printf("% 3s %s \"%s\" %s'${VT_RESET}'\n", $1, $2, $3, $4);
143              }
144              nb=nb+1;
145          }'
146     fi
147 }
148
149 function get-selected-essid-ap () {
150     cat ${SCAN_OUTPUT}  | \
151         awk 'BEGIN { nb=1; FS="," }
152          {
153              if(nb == '$current_ap') {
154                printf("%s,%s\n", $3, $4);
155              }
156              nb=nb+1;
157          }'
158 }
159
160 function kill-dhcp () {
161     PID=$(pidof dhclient)
162     if [[ ${PID} ]]; then
163         echo "Killing dhclient"
164         dhclient -x ${INTERFACE}
165     fi
166 }
167
168 ######################################################################
169
170 function process-key () {
171
172     case $1 in
173         e) # Selects essid + dhcp
174             SELECTED=$(get-selected-essid-ap)
175             ESSID=$(echo ${SELECTED} | cut -f 1 -d,)
176             echo "Running DHCP on ${INTERFACE} for ESSID ${ESSID}."
177             iwconfig ${INTERFACE} ap auto essid "${ESSID}"
178             kill-dhcp
179             echo
180             dhclient ${INTERFACE}
181             # if [[ $? == 0 ]]; then
182                 # iwconfig ${INTERFACE} > ~/.hotspot-ap
183             # fi
184             ifconfig ${INTERFACE} mtu ${MTU}
185             interface_was_up=1
186             cont=0
187             ;;
188
189         "return"|a) # Selects essid/ap + dhcp
190             SELECTED=$(get-selected-essid-ap)
191             ESSID=$(echo ${SELECTED} | cut -f 1 -d,)
192             AP=$(echo ${SELECTED} | cut -f 2 -d,)
193             echo "Running DHCP on ${INTERFACE} for ESSID ${ESSID} and AP ${AP}."
194             iwconfig ${INTERFACE} ap ${AP} essid "${ESSID}"
195             kill-dhcp
196             echo
197             dhclient ${INTERFACE}
198             # if [[ $? == 0 ]]; then
199                 # iwconfig ${INTERFACE} > ~/.hotspot-ap
200             # fi
201             ifconfig ${INTERFACE} mtu ${MTU}
202             interface_was_up=1
203             cont=0
204             ;;
205
206         k) # kill dhcp
207             echo "Killing DHCP and bringing down ${INTERFACE}."
208             kill-dhcp
209             ifconfig ${INTERFACE} down
210             cont=0
211             ;;
212
213         r|s) # re-scanning the access points
214             scan
215             redisplay
216             ;;
217
218         m) # Switching the mode to show the protected spots
219             SHOW_CLOSED=$((1-SHOW_CLOSED))
220             scan
221             redisplay
222             ;;
223
224         "down"|n)
225             current_ap=$((current_ap+1))
226             if [[ $current_ap -gt $number_of_aps ]]; then
227                 current_ap=$number_of_aps
228             fi
229             redisplay
230             ;;
231
232         "up"|p)
233             current_ap=$((current_ap-1))
234             if [[ $current_ap -lt 1 ]]; then
235                 current_ap=1
236             fi
237             redisplay
238             ;;
239
240         "esc-esc"|q)
241             echo "  Quit."
242             cont=0
243             ;;
244
245         *)
246             ;;
247     esac
248 }
249
250 ######################################################################
251 ## The main
252
253 if [[ $1 == "-k" ]]; then
254     echo "Killing DHCP and bringing down ${INTERFACE}."
255     kill-dhcp
256     ifconfig ${INTERFACE} down
257     exit 1
258 fi
259
260 stty_state=$(stty -g)
261
262 trap sigint-handler SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
263
264 stty -echo -icrnl -icanon -xcase min 1 time 0
265
266 echo ${VT_CURSOR_OFF}
267
268 current_ap=1
269 cont=1
270 current_keymap=default
271
272 interface_was_up=$(ifconfig | grep ${INTERFACE})
273
274 ifconfig ${INTERFACE} up
275
276 scan
277
278 redisplay
279
280 while [[ ${cont} == 1 ]]; do
281
282     CHAR=$(dd bs=1 count=1 2>/dev/null)
283
284     case ${current_keymap} in
285         default) ##################################################
286             case ${CHAR} in
287
288                 [a-z])
289                     process-key ${CHAR}
290                     ;;
291
292                 "\r")
293                     process-key "return"
294                     ;;
295
296                 "\ e")
297                 process-key "down"
298                 ;;
299
300                 "\10")
301                 process-key "up"
302                 ;;
303
304                 "\e") #$'\033'")
305                 current_keymap=escape
306                 ;;
307
308                 *)
309                 ;;
310                 esac
311                 ;;
312
313                 escape) ##################################################
314                 case ${CHAR} in
315                     "$'\033'")
316                     process-key "esc-esc"
317                     ;;
318                     "[")
319                     current_keymap=cursor
320                     ;;
321                     *)
322                     current_keymap=default
323                     ;;
324                 esac
325                 ;;
326
327                 cursor) ##################################################
328
329                 current_keymap=default
330
331                 case ${CHAR} in
332                     A)
333                     process-key "up"
334                     ;;
335                     B)
336                     process-key "down"
337                     ;;
338                     *)
339                     ;;
340                 esac
341                 ;;
342
343                 *)
344                 echo "Unknown keymap. This is an internal and weird bug."
345                 cont=0
346                 ;;
347                 esac
348
349                 done
350
351                 cleanup-before-quit