A simple yet powerful UI overlay made for Wayland WMs built with Quickshell
wayland qs linux ui ux
at main 301 lines 9.0 kB view raw
1#!/usr/bin/env bash 2 3set -u 4 5cmd="${1:-}" 6 7have_nmcli() { command -v nmcli >/dev/null 2>&1; } 8have() { command -v "$1" >/dev/null 2>&1; } 9 10wifi_power() { 11 local onoff="${1:-off}" 12 nmcli radio wifi "$onoff" >/dev/null 2>&1 || true 13} 14 15wifi_scan() { 16 local ifname="${1:-}" 17 [ -n "$ifname" ] || exit 0 18 nmcli radio wifi on >/dev/null 2>&1 || true 19 sleep 0.2 20 nmcli dev wifi rescan ifname "$ifname" >/dev/null 2>&1 || true 21} 22 23wifi_disconnect() { 24 local ifname="${1:-}" 25 [ -n "$ifname" ] || exit 0 26 nmcli dev disconnect "$ifname" >/dev/null 2>&1 || true 27} 28 29bar_status() { 30 pick_default_iface() { 31 ip route show default 2>/dev/null | 32 awk '{ 33 dev=""; metric=0; 34 for(i=1;i<=NF;i++){ 35 if($i=="dev") dev=$(i+1); 36 if($i=="metric") metric=$(i+1); 37 } 38 if(dev!="") print metric "\t" dev; 39 }' | 40 while IFS=$'\t' read -r metric dev; do 41 weight=1 42 case "$dev" in 43 usb*|rndis*|wwan*) weight=0 ;; 44 *) 45 if [ -d "/sys/class/net/$dev/wireless" ]; then 46 weight=2 47 else 48 devpath="$(readlink -f "/sys/class/net/$dev/device" 2>/dev/null || true)" 49 if printf '%s' "$devpath" | grep -qi "/usb"; then 50 weight=0 51 else 52 driver="$(basename "$(readlink -f "/sys/class/net/$dev/device/driver" 2>/dev/null || true)" 2>/dev/null || true)" 53 case "$driver" in 54 rndis_host|cdc_ether|cdc_ncm|ipheth|r8152|asix|ax88179_178a) weight=0 ;; 55 esac 56 fi 57 fi 58 ;; 59 esac 60 printf "%s\t%s\t%s\n" "$metric" "$weight" "$dev" 61 done | 62 sort -n -k1,1 -k2,2 | 63 head -n1 | 64 cut -f3 65 } 66 67 iface="$(pick_default_iface || true)" 68 if [ -z "${iface:-}" ]; then 69 iface="$(ip -o route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}' || true)" 70 fi 71 72 if [ -z "${iface:-}" ] || [ ! -e "/sys/class/net/$iface" ]; then 73 printf "none\t\t0\t0\n\n" 74 exit 0 75 fi 76 77 rx="$(cat "/sys/class/net/$iface/statistics/rx_bytes" 2>/dev/null || echo 0)" 78 tx="$(cat "/sys/class/net/$iface/statistics/tx_bytes" 2>/dev/null || echo 0)" 79 80 kind="ethernet" 81 ssid="" 82 83 if [ -d "/sys/class/net/$iface/wireless" ]; then 84 kind="wifi" 85 fi 86 87 if [ "$kind" = "ethernet" ]; then 88 case "$iface" in 89 usb*|rndis*|wwan*) kind="tether" ;; 90 *) 91 devpath="$(readlink -f "/sys/class/net/$iface/device" 2>/dev/null || true)" 92 if printf '%s' "$devpath" | grep -qi "/usb"; then 93 kind="tether" 94 else 95 driver="$(basename "$(readlink -f "/sys/class/net/$iface/device/driver" 2>/dev/null || true)" 2>/dev/null || true)" 96 case "$driver" in 97 rndis_host|cdc_ether|cdc_ncm|ipheth|r8152|asix|ax88179_178a) kind="tether" ;; 98 esac 99 fi 100 ;; 101 esac 102 fi 103 104 if [ "$kind" = "wifi" ]; then 105 if have iw; then 106 ssid="$(timeout 0.25 iw dev "$iface" link 2>/dev/null | awk -F": " '/SSID:/{print $2; exit}' || true)" 107 fi 108 if [ -z "${ssid:-}" ] && have_nmcli; then 109 ssid="$(nmcli -t -f ACTIVE,SSID dev wifi 2>/dev/null | awk -F: '$1=="yes"{print $2; exit}' || true)" 110 fi 111 fi 112 113 ssid="${ssid//$'\t'/ }" 114 115 printf "%s\t%s\t%s\t%s\n" "$kind" "$iface" "$rx" "$tx" 116 printf "%s\n" "$ssid" 117} 118 119status() { 120 if ! have_nmcli; then 121 echo 'NONMCLI|1' 122 exit 0 123 fi 124 125 local wifi 126 wifi="$(nmcli -t -f WIFI general status 2>/dev/null | head -n1 | tr -d $'\r')" 127 case "$wifi" in 128 enabled|*enabled*) echo 'WIFIPWR|1' ;; 129 *) echo 'WIFIPWR|0' ;; 130 esac 131 132 local wifidev 133 wifidev="$(nmcli -t -f DEVICE,TYPE dev status 2>/dev/null | awk -F: '$2=="wifi"{print $1; exit}')" 134 echo "WIFIDEV|${wifidev:-}" 135 136 local act adev atype 137 act="$(nmcli -t -f DEVICE,TYPE,STATE dev status 2>/dev/null | awk -F: '$3=="connected"{print $1":"$2; exit}')" 138 adev="$(printf '%s' "$act" | awk -F: '{print $1}')" 139 atype="$(printf '%s' "$act" | awk -F: '{print $2}')" 140 141 if [ "$atype" = "wifi" ] && [ -n "${adev:-}" ]; then 142 local assid 143 assid="$(nmcli -t -f ACTIVE,SSID dev wifi list ifname "$adev" 2>/dev/null | awk -F: '$1=="yes"{print $2; exit}')" 144 if [ -z "${assid:-}" ]; then 145 assid="$(nmcli -t -f GENERAL.CONNECTION dev show "$adev" 2>/dev/null | awk -F: '{print $2; exit}')" 146 fi 147 echo "ACTIVE|wifi|${adev}|${assid:-}" 148 elif [ "$atype" = "ethernet" ]; then 149 case "$adev" in 150 usb*|enx*) echo 'ACTIVE|tether||Tether' ;; 151 *) echo 'ACTIVE|ethernet||Ethernet' ;; 152 esac 153 elif [ "$atype" = "gsm" ] || [ "$atype" = "wwan" ]; then 154 echo 'ACTIVE|tether||Tether' 155 elif [ -n "${atype:-}" ]; then 156 echo "ACTIVE|other||${atype}" 157 else 158 echo 'ACTIVE|none||' 159 fi 160 161 if [ -n "${wifidev:-}" ]; then 162 nmcli -t -f IN-USE,SSID,SECURITY,SIGNAL dev wifi list ifname "$wifidev" 2>/dev/null | 163 while IFS=: read -r inuse ssid2 sec sig; do 164 [ -n "${ssid2:-}" ] || continue 165 echo "AP|${inuse:-}|${ssid2:-}|${sec:---}|${sig:-0}" 166 done 167 fi 168 169 true 170} 171 172wifi_connect() { 173 local iface="${1:-}" 174 local ssid="${2:-}" 175 local sec="${3:-}" 176 local pass="${4:-}" 177 178 set +e 179 180 local conn out ec 181 conn="$( 182 nmcli -t -f NAME,TYPE con show 2>/dev/null | awk -F: '$2=="802-11-wireless"{print $1}' | 183 while IFS= read -r c; do 184 [ -n "$c" ] || continue 185 local cs 186 cs="$(nmcli -g 802-11-wireless.ssid con show "$c" 2>/dev/null | tr -d $'\r')" 187 [ "$cs" = "$ssid" ] && { printf '%s' "$c"; exit 0; } 188 done 189 )" 190 191 verify() { 192 local i=0 cur 193 while [ $i -lt 12 ]; do 194 cur="$(nmcli -t -f ACTIVE,SSID dev wifi list ifname "$iface" 2>/dev/null | awk -F: '$1=="yes"{print $2; exit}')" 195 [ "$cur" = "$ssid" ] && return 0 196 sleep 0.3 197 i=$((i+1)) 198 done 199 return 1 200 } 201 202 if [ "$sec" = "--" ] || [ "$sec" = "OPEN" ] || [ -z "$sec" ]; then 203 if [ -n "$conn" ]; then 204 out="$(nmcli --wait 25 con up "$conn" 2>&1)"; ec=$? 205 else 206 out="$(nmcli --wait 25 dev wifi connect "$ssid" ifname "$iface" 2>&1)"; ec=$? 207 fi 208 209 if [ $ec -eq 0 ] && verify; then 210 printf 'EC|0\nMSG|connected\n' 211 exit 0 212 fi 213 214 local msg 215 msg="$(printf '%s' "$out" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g' | cut -c1-360)" 216 [ -n "$msg" ] || msg="nmcli returned exit code $ec" 217 printf 'EC|%s\nMSG|%s\n' "$ec" "$msg" 218 exit 0 219 fi 220 221 if [ -z "$pass" ]; then 222 if [ -n "$conn" ]; then 223 out="$(nmcli --wait 25 con up "$conn" 2>&1)"; ec=$? 224 if [ $ec -eq 0 ] && verify; then 225 printf 'EC|0\nMSG|connected\n' 226 exit 0 227 fi 228 229 if printf '%s' "$out" | grep -Eqi 'secrets.*required|not provided|No agents were available'; then 230 local msg 231 msg="$(printf '%s' "$out" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g' | cut -c1-360)" 232 [ -n "$msg" ] || msg='Secrets required.' 233 printf 'EC|%s\nMSG|%s\nPROMPT|1\n' "$ec" "$msg" 234 exit 0 235 fi 236 237 local msg 238 msg="$(printf '%s' "$out" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g' | cut -c1-360)" 239 [ -n "$msg" ] || msg="nmcli returned exit code $ec" 240 printf 'EC|%s\nMSG|%s\n' "$ec" "$msg" 241 exit 0 242 else 243 printf 'EC|1\nMSG|Password required.\nPROMPT|1\n' 244 exit 0 245 fi 246 fi 247 248 if [ -n "$conn" ]; then 249 out="$(printf '%s\n%s\n' "$pass" "$pass" | nmcli --wait 25 --ask con up "$conn" 2>&1)"; ec=$? 250 if [ $ec -eq 0 ] && verify; then 251 printf 'EC|0\nMSG|connected\n' 252 exit 0 253 fi 254 local msg 255 msg="$(printf '%s' "$out" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g' | cut -c1-360)" 256 [ -n "$msg" ] || msg="nmcli returned exit code $ec" 257 printf 'EC|%s\nMSG|%s\nPROMPT|1\n' "$ec" "$msg" 258 exit 0 259 fi 260 261 local key='wpa-psk' 262 echo "$sec" | grep -Eqi 'WPA3|SAE' && key='sae' 263 264 nmcli -t -f NAME con show 2>/dev/null | grep -Fx "$ssid" >/dev/null 2>&1 && nmcli con delete "$ssid" >/dev/null 2>&1 || true 265 266 local outa eca outb ecb msg 267 outa="$(nmcli con add type wifi ifname "$iface" con-name "$ssid" ssid "$ssid" wifi-sec.key-mgmt "$key" wifi-sec.psk "$pass" 2>&1)"; eca=$? 268 if [ $eca -ne 0 ]; then 269 msg="$(printf '%s' "$outa" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g' | cut -c1-360)" 270 [ -n "$msg" ] || msg="nmcli returned exit code $eca" 271 printf 'EC|%s\nMSG|%s\n' "$eca" "$msg" 272 exit 0 273 fi 274 275 outb="$(nmcli --wait 25 con up "$ssid" 2>&1)"; ecb=$? 276 if [ $ecb -eq 0 ] && verify; then 277 printf 'EC|0\nMSG|connected\n' 278 exit 0 279 fi 280 281 nmcli con delete "$ssid" >/dev/null 2>&1 || true 282 283 msg="$(printf '%s' "$outb" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g' | cut -c1-360)" 284 [ -n "$msg" ] || msg="nmcli returned exit code $ecb" 285 printf 'EC|%s\nMSG|%s\nPROMPT|1\n' "$ecb" "$msg" 286 exit 0 287} 288 289case "$cmd" in 290 bar) bar_status ;; 291 292 status) status ;; 293 wifi_power) wifi_power "${2:-}" ;; 294 wifi_scan) wifi_scan "${2:-}" ;; 295 wifi_disconnect) wifi_disconnect "${2:-}" ;; 296 wifi_connect) shift; wifi_connect "$@" ;; 297 *) 298 echo "MSG|unknown command" 299 exit 0 300 ;; 301esac