#!/bin/bash # This is a modified version of: # https://github.com/march-linux/connman_dmenu # # changes: # * include DEBUG=1 env var switch # * use menu (my bemenu wrapper) # * replace dmenu_notify with notify-send # * include icons in menu prompts # * report script errors instead of failing silently # * make use of bemenu's password mode set -e [ -n "$DEBUG" ] && set -x export UNSAFE=1 readonly SCAN_RESULT=/tmp/connman.scan readonly STORAGE_PATH=/var/lib/connman readonly VPN_STORAGE_PATH=/var/lib/connman-vpn dmenu() { menu "$@" } notifysend() { [ -z "$notifyicon" ] && notifyicon=wifi local msg=$1 shift 1 notification_id=$(notify-send "connman" "$msg" -i "$(iconez -sn "$notifyicon")" --print-id "$@") } get_services() { if [[ -f $SCAN_RESULT ]]; then notifysend 'another connman_dmenu is running' exit 1 fi local notification_id local notifyicon=wifi-sync notifysend "scanning for wifi services..." --expire-time=0 trap "rm -f $SCAN_RESULT" EXIT connmanctl enable wifi &>/dev/null connmanctl scan wifi &>/dev/null clear-notification "$notification_id" connmanctl services | awk -F ' +' '{ service_id=$NF; $NF=""; info=$1; $1=""; name=substr($0, 2, length-2); gsub(/[^a-zA-Z0-9-]/, "_", name); if (substr(info, 0, 1) == "*") {name="*" name} } name { print name, service_id }' >$SCAN_RESULT } # $1 = index index_to_name() { [[ -f $SCAN_RESULT ]] || exit 1 awk -v line="$1" 'NR == line { print $1 }' $SCAN_RESULT } # $1 = index index_to_service() { [[ -f $SCAN_RESULT ]] || exit 1 awk -v line="$1" 'NR == line { print $2 }' $SCAN_RESULT } # $1 = service id get_service_security() { cut -d _ -f 5 <<<"$1" } # $1 = service id get_service_signal() { connmanctl services "$1" | awk '$1 == "Strength" { print $3 }' } # $1 = service id get_service_state() { connmanctl services "$1" | awk '$1 == "State" { print $3 }' } create_dmenu() { [[ -f $SCAN_RESULT ]] || exit 1 # echo 'setup vpn pptp' local order=1 local name local service_id local security local signal local disconnect while read -r name service_id; do security='' signal='' disconnect='' [[ ! "$(get_service_state "$service_id")" =~ ^(idle|failure)$ ]] && disconnect='(disconnect)' case "$service_id" in wifi_*) security="$(get_service_security "$service_id")" signal="$(get_service_signal "$service_id")" ;; vpn_*) security=vpn ;; esac printf '%2s %-40s%9s %-3s %s\n' "$order" "$name" "$security" "$signal" "$disconnect" ((order++)) done <$SCAN_RESULT } # $1 = question # $2 = var name dmenu_ask() { local msg=$1 local var=$2 shift 2 IFS= read -r "${var?}" < <(: | dmenu -p "󱛆 $msg" "$@") if [[ ! "${!var}" ]]; then ( notifyicon=wifi-alert notifysend "invalid $var" ) exit 1 fi } trap '{ notify-send connman "an error occured" -c error -i "$(iconez -sn wifi-alert)"; }' ERR get_services index="$(create_dmenu | dmenu -l 10 -i -p '󱛆 select wifi service' | sed 's/^ *//g' | cut -d ' ' -f 1)" # if [[ "$index" == setup ]]; then # # create vpn mode # dmenu_ask 'name this PPTP VPN' name # name="${name// /_}" # dmenu_ask 'please provide VPN domain' domain # dmenu_ask 'please provide identity' identity # dmenu_ask 'please provide password' password --password # cat >"$VPN_STORAGE_PATH/$name.config" <<-EOF # [provider_$name] # Type = PPTP # Name = $name # Host = $(dig +short A "$domain" | sort -n | head -n1) # Domain = $domain # PPTP.User = $identity # PPTP.Password = $password # EOF # notifysend "VPN $name is created" # exit 0 # fi service_id="$(index_to_service "$index")" [[ "$service_id" ]] || exit 1 name="$(index_to_name "$index")" echo "$name { $service_id }" if [[ ! "$(get_service_state "$service_id")" =~ ^(idle|failure)$ ]]; then connmanctl disconnect "$service_id" ( notifyicon=wifi-remove notifysend "$name disconnected" ) exit 0 fi security="$(get_service_security "$service_id")" # create service file for encryption if [[ ! "$name" =~ ^\* ]] && [[ "$security" =~ ^(ieee8021x|psk|wep)$ ]]; then notifysend 'setting up connection not implemented' -c error # config_file="$STORAGE_PATH/$name-$security.config" # if [[ -f "$config_file" && no != "$(echo -e 'yes\nno' | dmenu -p '󱛆 use previous profile?')" ]]; then # echo "use old profile: $config_file" # else # dmenu_ask 'please provide password' password --password # case "$security" in # ieee8021x) # dmenu_ask 'please provide identity' identity # case "$(echo -e 'PEAP/MSCHAPV2\nTTLS/PAP' | dmenu -p '󱛆 please specify EAP type')" in # PEAP/MSCHAPV2) # eap=peap # phase2=MSCHAPV2 # ;; # TTLS/PAP) # eap=ttls # phase2=PAP # ;; # *) # ( # notifyicon=wifi-alert # notifysend 'invalid EAP' -c error # ) # exit 1 # ;; # esac # cat >"$config_file" <<-EOF # [service_$service_id] # Type = wifi # Name = $name # EAP = $eap # Phase2 = $phase2 # Identity = $identity # Passphrase = $password # EOF # ;; # psk | wep) # cat >"$config_file" <<-EOF # [service_$service_id] # Type = wifi # Name = $name # Passphrase = $password # EOF # ;; # esac # chmod 600 "$config_file" # fi fi connman_msg="$(timeout 10 connmanctl connect "$service_id" 2>&1 | head -n 1)" if [[ "$connman_msg" == Connected* ]]; then ( notifyicon=wifi-check notifysend "connected to $name" ) else error_msg='automatic timeout for connman_dmenu' [[ "$connman_msg" ]] && error_msg="$(cut -d ' ' -f 3- <<<"$connman_msg")" ( notifyicon=wifi-cancel notifysend "cannot connect to $name ($error_msg)" -c error ) fi