Initial commit
[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     iwconfig ${INTERFACE} ap off essid ""
74     iwlist ${INTERFACE} scan | \
75         sed -e "s/^[\t ]*//"  | grep ^"Cell\|ESSID\|Quality\|Encryption" | \
76         sed \
77         -e "s/Cell [0-9]* - Address: \([0-9]*\)/AP,\1/" \
78         -e "s/^ *ESSID:\\\"\([^\\\"]*\)\\\".*$/ESSID,\1/" \
79         -e "s/Quality=\([0-9]*\).*$/QUALITY,\1/" \
80         -e "s/Encryption key:/ENCRYPTION,/" | \
81         awk 'BEGIN { FS="," }
82          {
83            if($1 == "ESSID") { essid=$2 }
84            else if($1 == "AP") { ap=$2 }
85            else if($1 == "QUALITY") { quality=$2; }
86            else if($1 == "ENCRYPTION") {
87              if($2 == "off") {
88                open="        "
89                printf("%d,%s,%s,%s\n",quality,open,essid,ap);
90              } else {
91                if('${SHOW_CLOSED}') {
92                  open="(closed)"
93                  printf("%d,%s,%s,%s\n",quality,open,essid,ap);
94                }
95              }
96            }
97          }' | \
98              sort -rn > ${SCAN_OUTPUT}
99
100     number_of_aps=$(wc -l ${SCAN_OUTPUT} | awk '{print $1}')
101
102     chmod a+rw ${SCAN_OUTPUT}
103 }
104
105 function redisplay () {
106     clear
107
108     echo
109     echo -n "  ${VT_UNDERLINE}Hotspot selection${VT_RESET}"
110     if [[ $SHOW_CLOSED == 0 ]]; then
111         echo " (show only open networks)"
112     else
113         echo
114     fi
115     echo
116     echo "  [s,r] scan  [m] switch the free-only view and scan    [q] quit"
117     echo "  [e] select essid + dhcp  [a] selects essid/ap + dhcp  [k] kill dhcp and quit"
118     echo
119
120     for i in $(ifconfig -s | grep -E -v ^lo\|Iface\|wmaster | awk '{print $1}'); do
121         echo "  Warning: $i is up"
122     done
123     echo
124
125     if [[ ${number_of_aps} == "0" ]]; then
126         echo "  ${VT_RED_FG}${VT_BOLD}No access point detected.${VT_RESET}"
127     else
128
129         awk < ${SCAN_OUTPUT} 'BEGIN { nb=1; FS="," }
130          {
131              if(nb == '$current_ap') {
132                printf(" =>");
133              } else {
134                printf("   ");
135              }
136              if($2 == "(closed)") {
137                printf("'${VT_RED_FG}'");
138                printf("% 3s %s \"%s\" %s'${VT_RESET}'\n", $1, $2, $3, $4);
139                  } else {
140                printf("'${VT_GREEN_FG}'");
141                printf("% 3s %s \"%s\" %s'${VT_RESET}'\n", $1, $2, $3, $4);
142              }
143              nb=nb+1;
144          }'
145     fi
146 }
147
148 function get-selected-essid-ap () {
149     cat ${SCAN_OUTPUT}  | \
150         awk 'BEGIN { nb=1; FS="," }
151          {
152              if(nb == '$current_ap') {
153                printf("%s,%s\n", $3, $4);
154              }
155              nb=nb+1;
156          }'
157 }
158
159 function kill-dhcp () {
160     PID=$(pidof dhclient)
161     if [[ ${PID} ]]; then
162         echo "Killing dhclient"
163         dhclient -x ${INTERFACE}
164     fi
165 }
166
167 ######################################################################
168
169 function process-key () {
170
171     case $1 in
172         e) # Selects essid + dhcp
173             SELECTED=$(get-selected-essid-ap)
174             ESSID=$(echo ${SELECTED} | cut -f 1 -d,)
175             echo "Running DHCP on ${INTERFACE} for ESSID ${ESSID}."
176             iwconfig ${INTERFACE} ap auto essid "${ESSID}"
177             kill-dhcp
178             echo
179             dhclient ${INTERFACE}
180             # if [[ $? == 0 ]]; then
181                 # iwconfig ${INTERFACE} > ~/.hotspot-ap
182             # fi
183             ifconfig ${INTERFACE} mtu ${MTU}
184             interface_was_up=1
185             cont=0
186             ;;
187
188         "return"|a) # Selects essid/ap + dhcp
189             SELECTED=$(get-selected-essid-ap)
190             ESSID=$(echo ${SELECTED} | cut -f 1 -d,)
191             AP=$(echo ${SELECTED} | cut -f 2 -d,)
192             echo "Running DHCP on ${INTERFACE} for ESSID ${ESSID} and AP ${AP}."
193             iwconfig ${INTERFACE} ap ${AP} essid "${ESSID}"
194             kill-dhcp
195             echo
196             dhclient ${INTERFACE}
197             # if [[ $? == 0 ]]; then
198                 # iwconfig ${INTERFACE} > ~/.hotspot-ap
199             # fi
200             ifconfig ${INTERFACE} mtu ${MTU}
201             interface_was_up=1
202             cont=0
203             ;;
204
205         k) # kill dhcp
206             echo "Killing DHCP and bringing down ${INTERFACE}."
207             kill-dhcp
208             ifconfig ${INTERFACE} down
209             cont=0
210             ;;
211
212         r|s) # re-scanning the access points
213             echo "Scanning ..."
214             scan
215             redisplay
216             ;;
217
218         m) # Switching the mode to show the protected spots
219             SHOW_CLOSED=$((1-SHOW_CLOSED))
220             echo "Scanning ..."
221             scan
222             redisplay
223             ;;
224
225         "down"|n)
226             current_ap=$((current_ap+1))
227             if [[ $current_ap -gt $number_of_aps ]]; then
228                 current_ap=$number_of_aps
229             fi
230             redisplay
231             ;;
232
233         "up"|p)
234             current_ap=$((current_ap-1))
235             if [[ $current_ap -lt 1 ]]; then
236                 current_ap=1
237             fi
238             redisplay
239             ;;
240
241         "esc-esc"|q)
242             echo "quit"
243             cont=0
244             ;;
245
246         *)
247             ;;
248     esac
249 }
250
251 ######################################################################
252 ## The main
253
254 if [[ $1 == "-k" ]]; then
255     echo "Killing DHCP and bringing down ${INTERFACE}."
256     kill-dhcp
257     ifconfig ${INTERFACE} down
258     exit 1
259 fi
260
261 stty_state=$(stty -g)
262
263 trap sigint-handler SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
264
265 stty -echo -icrnl -icanon -xcase min 1 time 0
266
267 echo ${VT_CURSOR_OFF}
268
269 current_ap=1
270 cont=1
271 current_keymap=default
272
273 interface_was_up=$(ifconfig | grep ${INTERFACE})
274
275 ifconfig ${INTERFACE} up
276
277 scan
278
279 redisplay
280
281 while [[ ${cont} == 1 ]]; do
282
283     CHAR=$(dd bs=1 count=1 2>/dev/null)
284
285     case ${current_keymap} in
286         default) ##################################################
287             case ${CHAR} in
288
289                 [a-z])
290                     process-key ${CHAR}
291                     ;;
292
293                 "\r")
294                     process-key "return"
295                     ;;
296
297                 "\ e")
298                 process-key "down"
299                 ;;
300
301                 "\10")
302                 process-key "up"
303                 ;;
304
305                 "\e") #$'\033'")
306                 current_keymap=escape
307                 ;;
308
309                 *)
310                 ;;
311                 esac
312                 ;;
313
314                 escape) ##################################################
315                 case ${CHAR} in
316                     "$'\033'")
317                     process-key "esc-esc"
318                     ;;
319                     "[")
320                     current_keymap=cursor
321                     ;;
322                     *)
323                     current_keymap=default
324                     ;;
325                 esac
326                 ;;
327
328                 cursor) ##################################################
329
330                 current_keymap=default
331
332                 case ${CHAR} in
333                     A)
334                     process-key "up"
335                     ;;
336                     B)
337                     process-key "down"
338                     ;;
339                     *)
340                     ;;
341                 esac
342                 ;;
343
344                 *)
345                 echo "Unknown keymap. This is an internal and weird bug."
346                 cont=0
347                 ;;
348                 esac
349
350                 done
351
352                 cleanup-before-quit