*** 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
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 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