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