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