iwd-dmenu

An interactive iwd menu using dmenu.
git clone git://mattcarlson.org/repos/iwd-dmenu.git
Log | Files | Refs | README

iwd-dmenu (5127B)


      1 #!/bin/sh
      2 #
      3 # iwd-dmenu
      4 
      5 NEWLINE='
      6 '
      7 
      8 iwd_dmenu() {
      9     main_menu() {
     10         while :; do
     11             # get first 802.11 capable device from /sys/class/net
     12             interface="$(for dev in /sys/class/net/*; do
     13                             [ -d "${dev}/wireless/" ] && printf '%s\n' "${dev##*/}"
     14                          done | head -n 1)"
     15 
     16             # user can connect, disconnect, or forget network
     17             # don't care bout access points or other stuff
     18             if ! show_menu 'iwd dmenu' 'Connect' 'Disconnect' 'Forget'; then break; fi
     19         done
     20     }
     21 
     22     connect() {
     23         get_network_info "iwctl station ${interface} get-networks"
     24 
     25         # user can choose network to connect to
     26         network="$(show_menu 'Connect' "${network_names}")"
     27 
     28         # if network starts with '> ' it means user is already on that network
     29         case "${network}" in '> '*) herbe 'Already connected to this network' & return ;; esac
     30 
     31         get_network_info 'iwctl known-networks list'
     32 
     33         # if network is known connect with no passphrase
     34         if printf '%s\n' "${network_info}" | awk -F '|' '{print $1}' | grep -iq "\<${network}\>"; then
     35             iwctl station "${interface}" connect "${network}"
     36             return
     37         fi
     38 
     39         get_network_info "iwctl station ${interface} get-networks"
     40 
     41         # if network is wep, psk, or 8021x get passphrase
     42         case "$(printf '%s\n' "${network_info}" | grep -i "\<${network}\>" | awk -F '|' '{print $2}')" in
     43             'wep'|'psk'|'8021x') get_passphrase                       ;;
     44         # if open just connect without passphrase
     45             'open') iwctl station "${interface}" connect "${network}" ;;
     46         esac
     47 
     48         # connect with passphrase
     49         [ -n "${passphrase}" ] && iwctl --passphrase "${passphrase}" station "${interface}" connect "${network}"
     50     }
     51 
     52     disconnect() {
     53         connected_network="$(iwctl station "${interface}" show | grep -i '\<Connected network\>' | awk '{ $1=""; $2=""; sub("  ", " "); { $1=$1; print } }')"
     54         if [ -n "${connected_network}" ]; then
     55             answer="$(show_menu "Disconnect from ${connected_network}?" 'Yes' 'No')"
     56             case "$(printf '%s\n' "${answer}" | tr '[:upper:]' '[:lower:]')" in
     57                 'yes') iwctl station "${interface}" disconnect ;;
     58                 'no')  return                                  ;;
     59             esac
     60         fi
     61     }
     62 
     63     forget() {
     64         get_network_info 'iwctl known-networks list'
     65 
     66         # if there are known networks
     67         if [ -n "${network_names}" ]; then
     68             # get network
     69             network="$(show_menu 'Forget' "${network_names}")"
     70 
     71             # get confirmation
     72             [ -n "${network}" ] && answer="$(show_menu "Forget ${network}?" 'Yes' 'No')"
     73 
     74             # forget if answer is yes
     75             [ "${answer}" = 'Yes' ] && iwctl known-networks "${network}" forget
     76         fi
     77     }
     78 
     79     # get network column separately
     80     get_network_column() {
     81         printf '%s\n' "${info}" | awk -v var="${1}" 'BEGIN { FS = "open|wep|psk|8021x" } { print $var }' | sed 's/^[ \t]*//;s/[ \t]*$//'
     82     }
     83 
     84     get_network_info() {
     85         # scan interface
     86         iwctl station "${interface}" scan
     87 
     88         printf '%s\n' "${1}"
     89 
     90         info="$(eval "${1}" | grep '\s' | tail +3 | awk '{ $1 = $1 }; 1' | sed -e 's/\x1b\[[0-9;]*m//g')"
     91 
     92         network_names="$(get_network_column '1')"
     93         network_types="$(printf '%s\n' "${info}" | awk '{ for (i=1;i<=NF;i++){ if ($i ~ /open|wep|psk|8021x/) { print $i } } }')"
     94         network_metas="$(get_network_column '2')"
     95 
     96         i=1
     97         network_info="$(printf '%s\n' "${network_names}" | ( while read -r name; do
     98             type_field="$(printf '%s\n' "${network_types}" | sed -n ${i}p)"
     99             meta_field="$(printf '%s\n' "${network_metas}" | sed -n ${i}p)"
    100 
    101             if [ ${i} -eq 1 ]; then network_info="${name}|${type_field}|${meta_field}"
    102             else network_info="${network_info}${NEWLINE}${name}|${type_field}|${meta_field}"
    103             fi
    104 
    105             i=$((i+1))
    106         done
    107         printf '%s\n' "${network_info}" ))"
    108     }
    109 
    110     # hide input with dmenu -P flag
    111     get_passphrase() { passphrase="$(dmenu -c -p 'Passphrase:' -P)" ; }
    112 
    113     show_menu() {
    114         # first arg is prompt
    115         prompt="${1}"
    116         shift
    117 
    118         # remaining opts are options
    119         options="$(for option in "${@}"; do
    120                     printf '%s\n' "${option}"
    121                 done)"
    122 
    123         # print using dmenu
    124         if ! answer="$(printf '%s\n' "${options}" | dmenu -c -l 10 -p "${prompt}")"; then return 1; fi
    125 
    126         # get user's answer
    127         printf '%s\n' "${options}" | while read -r line; do
    128             if [ "${line}" = "${answer}" ]; then
    129                 # if answer is a function run it else just print it
    130                 cmd="$(printf '%s\n' "${answer}" | tr '[:upper:]' '[:lower:]')"
    131                 if command -v "${cmd}" >/dev/null 2>&1 && [ "${cmd}" != 'yes' ]; then "${cmd}"
    132                 else printf '%s\n' "${answer}"
    133                 fi
    134                 break
    135             fi
    136         done
    137     }
    138 
    139     main_menu
    140 }
    141 
    142 main() { iwd_dmenu ; }
    143 
    144 main "${@}"