diff --git a/README-en.md b/README-en.md index b4c08ca..f4710af 100644 --- a/README-en.md +++ b/README-en.md @@ -50,17 +50,21 @@ for example) and repeated safely: to `sshcontrol` and caches the passphrase for one hour. `.bashrc` already points `SSH_AUTH_SOCK` at the agent. If `~/.gnupg` does not exist yet, it does nothing. -6. `sistema` (system): copies `sistema/` into `/`, enables the runit services - (dbus, elogind, polkitd, NetworkManager, bluetoothd, acpid, chronyd, tlp, - automontaje, cupsd), removes dhcpcd and wpa_supplicant (NetworkManager - already manages the network) and adds the user to the audio, video, input, - network, bluetooth and lpadmin (printer management) groups. `doas.conf` +6. `sistema` (system): copies `sistema/` into `/`, sets up + `wpa_supplicant.conf` so wheel users can use `wpa_cli` without root and + save networks, enables the runit services (dbus, elogind, wpa_supplicant, + dhcpcd, bluetoothd, acpid, chronyd, tlp, automontaje, cupsd), removes + NetworkManager and polkitd (if something asks for polkit, like udisks2 or + libvirt, D-Bus starts it on its own) and adds the user to the audio, + video, input, network, bluetooth, lpadmin (printer management) and + `_pipewire` (realtime priority for audio without rtkit) groups. `doas.conf` is checked with `doas -C` before it is installed with mode 400. 7. `quitar` (remove): uninstalls what the repo no longer uses because something else replaces it: sudo (doas), feh (xwallpaper and nsxiv), gammastep (sct), autorandr (`pantallas`), blueman and pavucontrol (the `bluetooth` and `volumen` scripts), pinentry-gtk (pinentry-dmenu), vlc - (mpv) and btop. sudo can be removed thanks to + (mpv), btop, NetworkManager and tlp-rdw (wpa_supplicant, dhcpcd and the + `wifi` script) and rtkit. sudo can be removed thanks to `sistema/etc/xbps.d/sin-sudo.conf` (base-system depends on it), and it is only removed once `/etc/doas.conf` is installed. @@ -125,7 +129,7 @@ which is dmenu with the dwm font and colours. | Area | Left | Middle | Right | Wheel | |---|---|---|---|---| -| Network | Connect to a network | | Full menu | | +| Network | Connect to a network (`wifi`) | | `wpa_cli` | | | VOL | Pick the audio output (`volumen salida`) | Mute | Mute the mic | Volume ± | | BT | Bluetooth menu (`bluetooth`): connect, disconnect, scan and pair, power off | | Power on or off | | | Date | This month's calendar | | | | @@ -145,6 +149,11 @@ shown in a notification. (the laptop one on the left and as primary) at startup and whenever one is plugged or unplugged (udev rule in `sistema/`), then repaints the wallpaper with `xwallpaper`. +- WiFi: `wifi` scans with `wpa_cli` and lists the networks in dmenu by + signal (`*` is the current one). For a new network it asks for the + password (hidden while typing) and saves it in + `/etc/wpa_supplicant/wpa_supplicant.conf` only if the connection works. + dhcpcd handles the cable on its own. - Left click on the date in the bar: this month's calendar in a notification (`calendario`), with today in green. - bash: 10 000-entry history, without duplicates and shared between diff --git a/README.md b/README.md index 81df8ad..1733a3d 100644 --- a/README.md +++ b/README.md @@ -47,16 +47,20 @@ Hace siete pasos, que también se pueden lanzar por separado subclaves de autenticación y hace que recuerde la contraseña una hora. `.bashrc` ya apunta `SSH_AUTH_SOCK` al agente. Si `~/.gnupg` no existe todavía, no hace nada. -6. `sistema`: copia `sistema/` en `/`, activa los servicios de runit (dbus, - elogind, polkitd, NetworkManager, bluetoothd, acpid, chronyd, tlp, - automontaje, cupsd), quita dhcpcd y wpa_supplicant (NetworkManager ya - gestiona la red) y añade el usuario a los grupos audio, video, input, - network, bluetooth y lpadmin (para gestionar impresoras). `doas.conf` se +6. `sistema`: copia `sistema/` en `/`, prepara `wpa_supplicant.conf` para + que los de wheel usen `wpa_cli` sin root y guarden redes, activa los + servicios de runit (dbus, elogind, wpa_supplicant, dhcpcd, bluetoothd, + acpid, chronyd, tlp, automontaje, cupsd), quita NetworkManager y polkitd + (si algo pide polkit, como udisks2 o libvirt, D-Bus lo arranca solo) y + añade el usuario a los grupos audio, video, input, network, bluetooth, + lpadmin (para gestionar impresoras) y `_pipewire` (prioridad de tiempo + real para el audio sin rtkit). `doas.conf` se valida con `doas -C` antes de instalarlo con modo 400. 7. `quitar`: desinstala lo que el repo ya no usa porque lo sustituye otra cosa: sudo (doas), feh (xwallpaper y nsxiv), gammastep (sct), autorandr (`pantallas`), blueman y pavucontrol (scripts `bluetooth` y `volumen`), - pinentry-gtk (pinentry-dmenu), vlc (mpv) y btop. sudo se puede quitar + pinentry-gtk (pinentry-dmenu), vlc (mpv), btop, NetworkManager y + tlp-rdw (wpa_supplicant, dhcpcd y el script `wifi`) y rtkit. sudo se puede quitar gracias a `sistema/etc/xbps.d/sin-sudo.conf` (base-system depende de él), y solo se quita si `/etc/doas.conf` ya está instalado. @@ -122,7 +126,7 @@ Los menús de los scripts (`apagado`, `bluetooth`, `volumen salida`...) usan | Zona | Izquierdo | Central | Derecho | Rueda | |---|---|---|---|---| -| Red | Conectarse a una red | | Menú completo | | +| Red | Conectarse a una red (`wifi`) | | `wpa_cli` | | | VOL | Elegir la salida de audio (`volumen salida`) | Silenciar | Silenciar el micro | Volumen ± | | BT | Menú de bluetooth (`bluetooth`): conectar, desconectar, buscar y emparejar, apagar | | Encender o apagar | | | Fecha | Calendario del mes | | | | @@ -142,6 +146,10 @@ y muestran una notificación. `xrandr` (la del portátil a la izquierda y como principal) al arrancar y cada vez que se conecta o desconecta una (regla de udev en `sistema/`), y vuelve a pintar el fondo con `xwallpaper`. +- WiFi: `wifi` busca redes con `wpa_cli` y las enseña en dmenu por señal + (`*` la actual). Si la red es nueva pide la contraseña (no se ve al + escribirla) y la guarda en `/etc/wpa_supplicant/wpa_supplicant.conf` solo + si la conexión va bien. El cable lo coge dhcpcd solo. - Clic izquierdo en la fecha de la barra: calendario del mes en una notificación (`calendario`), con el día de hoy en verde. - bash: historial de 10 000 órdenes, sin duplicados y compartido entre diff --git a/home/.local/bin/wifi b/home/.local/bin/wifi new file mode 100755 index 0000000..09969d4 --- /dev/null +++ b/home/.local/bin/wifi @@ -0,0 +1,73 @@ +#!/bin/sh +# Menú de WiFi con dmenu y wpa_cli (clic izquierdo en la red de la barra). +# Busca redes y las ordena por señal; * marca la actual. Si la elegida ya está +# guardada se conecta; si no, pide la contraseña (no se ve al escribirla) y la +# guarda en /etc/wpa_supplicant/wpa_supplicant.conf cuando la conexión va bien. +# wpa_cli funciona sin root para los de wheel (ctrl_interface_group, lo pone +# install.sh en el paso sistema). + +avisar() { + notify-send -h string:x-dunst-stack-tag:wifi -i network-wireless "WiFi" "$1" +} + +IF= +for w in /sys/class/net/*/wireless; do + [ -e "$w" ] && IF=${w%/wireless} && IF=${IF##*/} && break +done +[ -n "$IF" ] || { avisar "No hay tarjeta WiFi"; exit 1; } + +wpa() { wpa_cli -i "$IF" "$@"; } + +wpa scan >/dev/null || { avisar "wpa_supplicant no responde"; exit 1; } +sleep 3 +actual=$(wpa status | sed -n 's/^ssid=//p') + +# scan_results: bssid, frecuencia, señal, flags y ssid, separados por tabuladores +resultados=$(wpa scan_results | tail -n +2) +ssid=$(printf '%s\n' "$resultados" | sort -t "$(printf '\t')" -k3,3nr | + awk -F '\t' -v a="$actual" '$5 != "" && !visto[$5]++ { + print ($5 == a ? "* " : " ") $5 + }' | menu -l 15 -p WiFi:) +[ -n "$ssid" ] || exit 0 +ssid=${ssid#??} + +id=$(wpa list_networks | awk -F '\t' -v s="$ssid" 'NR > 1 && $2 == s { print $1; exit }') +nueva= +if [ -z "$id" ]; then + nueva=1 + id=$(wpa add_network | tail -1) + wpa set_network "$id" ssid "\"$ssid\"" >/dev/null + flags=$(printf '%s\n' "$resultados" | awk -F '\t' -v s="$ssid" '$5 == s { print $4; exit }') + case $flags in + *WPA* | *RSN* | *SAE*) + clave=$(menu -p "Contraseña de $ssid:" -nf "#2d353b" /dev/null + exit 0 + fi + wpa set_network "$id" psk "\"$clave\"" >/dev/null + ;; + *) wpa set_network "$id" key_mgmt NONE >/dev/null ;; + esac +fi + +avisar "Conectando a $ssid..." +wpa select_network "$id" >/dev/null +i=0 +while [ "$i" -lt 20 ] && ! wpa status | grep -qx wpa_state=COMPLETED; do + sleep 1 + i=$((i + 1)) +done + +# select_network deshabilita las demás redes: se vuelven a habilitar para que +# siga cambiando sola a la que haya. +if wpa status | grep -qx wpa_state=COMPLETED; then + wpa enable_network all >/dev/null + wpa save_config >/dev/null + avisar "Conectado a $ssid" +else + [ -n "$nueva" ] && wpa remove_network "$id" >/dev/null + wpa enable_network all >/dev/null + avisar "No se pudo conectar a $ssid" +fi +pkill -USR1 -x slstatus diff --git a/install.sh b/install.sh index 48df111..5312bd1 100755 --- a/install.sh +++ b/install.sh @@ -17,10 +17,10 @@ PAQUETES=" libXfixes-devel libxcb-devel freetype-devel fontconfig-devel harfbuzz-devel libXrender-devel xorgproto imlib2-devel zlib-devel libxcrypt-devel - xorg xinit setxkbmap xrandr dbus elogind polkit + xorg xinit setxkbmap xrandr dbus elogind picom dunst libnotify xwallpaper nsxiv maim xclip sct xss-lock - pipewire wireplumber libspa-bluetooth alsa-pipewire rtkit - NetworkManager bluez acpid chrony tlp tlp-rdw + pipewire wireplumber libspa-bluetooth alsa-pipewire + wpa_supplicant dhcpcd bluez acpid chrony tlp cups cups-filters hplip font-firacode nerd-fonts-symbols-ttf papirus-icon-theme papirus-folders sassc gnome-themes-extra qt5ct qt6ct @@ -34,16 +34,21 @@ SUCKLESS="dwm st dmenu slstatus slock scroll clipmenu" # Tema GTK Everforest, en una versión fija para que siempre salga igual GTK_TEMA_REPO=https://github.com/Fausto-Korpsvart/Everforest-GTK-Theme GTK_TEMA_COMMIT=9b8be4d6648ae9eaae3dd550105081f8c9054825 -SERVICIOS="dbus elogind polkitd NetworkManager bluetoothd acpid chronyd tlp automontaje cupsd" -# NetworkManager gestiona la red él solo; estos servicios se pelean con él. -SERVICIOS_FUERA="dhcpcd wpa_supplicant" -GRUPOS="audio video input network bluetooth lpadmin" +SERVICIOS="dbus elogind wpa_supplicant dhcpcd bluetoothd acpid chronyd tlp automontaje cupsd" +# La red la llevan wpa_supplicant y dhcpcd. polkitd no hace falta como +# servicio: si algo lo pide (udisks2, libvirt), D-Bus lo arranca. +SERVICIOS_FUERA="NetworkManager polkitd" +# _pipewire da prioridad de tiempo real al audio sin rtkit +# (/etc/security/limits.d/25-pw-rlimits.conf, de pipewire). +GRUPOS="audio video input network bluetooth lpadmin _pipewire" # Lo que sustituyen otras cosas del repo: sudo (doas), feh (xwallpaper y # nsxiv), gammastep (sct), autorandr (pantallas), blueman y pavucontrol -# (scripts bluetooth y volumen), pinentry-gtk (pinentry-dmenu), vlc (mpv). +# (scripts bluetooth y volumen), pinentry-gtk (pinentry-dmenu), vlc (mpv), +# NetworkManager (wpa_supplicant, dhcpcd y el script wifi) y rtkit (el grupo +# _pipewire). QUITAR=" sudo feh gammastep autorandr blueman pavucontrol pinentry-gtk - gtk-engine-murrine vlc btop + gtk-engine-murrine vlc btop NetworkManager tlp-rdw rtkit " msg() { printf '\033[1;32m==>\033[0m %s\n' "$*"; } @@ -197,6 +202,18 @@ sistema() { done cd "$DIR" + # wpa_cli sin root para los de wheel (script wifi) y guardar las redes + # nuevas. El archivo tiene las contraseñas: se edita en su sitio. + msg "Configurando wpa_supplicant" + w=/etc/wpa_supplicant/wpa_supplicant.conf + cabecera="ctrl_interface=/run/wpa_supplicant +ctrl_interface_group=wheel +update_config=1" + # shellcheck disable=SC2016 + root sh -c 'umask 077; touch "$1" + { printf "%s\n" "$2"; grep -v -e "^ctrl_interface" -e "^update_config" "$1"; } >"$1.nuevo" + mv "$1.nuevo" "$1"' sh "$w" "$cabecera" + msg "Activando servicios" for s in $SERVICIOS; do [ -d "/etc/sv/$s" ] || die "no existe el servicio $s (¿faltan paquetes?)" diff --git a/suckless/dwm/config.h b/suckless/dwm/config.h index 539ee6f..9d81a25 100644 --- a/suckless/dwm/config.h +++ b/suckless/dwm/config.h @@ -38,7 +38,7 @@ static const Rule rules[] = { * hasta que se cierra; noswallow = 1 lo evita para esa ventana. */ /* class instance title tags mask isfloating isterminal noswallow monitor */ { "st-256color", NULL, NULL, 0, 0, 1, 0, -1 }, - { "st-float", NULL, NULL, 0, 1, 0, 1, -1 }, /* st -c st-float (p. ej. nmtui) */ + { "st-float", NULL, NULL, 0, 1, 0, 1, -1 }, /* st -c st-float (p. ej. wpa_cli) */ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, { "Firefox", "Places", NULL, 0, 1, 0, 0, -1 }, /* biblioteca/descargas */ { "Firefox", "Toolkit", NULL, 0, 1, 0, 0, -1 }, /* picture-in-picture */ @@ -96,10 +96,10 @@ static const char *lockcmd[] = { "slock", NULL }; * (1 izquierdo, 2 central, 3 derecho, 4/5 rueda arriba/abajo). */ static const StatusCmd statuscmds[] = { - /* red: izquierdo conectarse a una red, derecho el menú completo de nmtui */ + /* red: izquierdo conectarse a una red (script wifi), derecho wpa_cli */ { "case $BUTTON in " - "1) st -c st-float -g 90x30 -e nmtui connect ;; " - "3) st -c st-float -g 90x30 -e nmtui ;; " + "1) wifi ;; " + "3) st -c st-float -g 90x30 -e wpa_cli ;; " "esac", 1 }, /* volumen: izquierdo elegir la salida, central silenciar, derecho micro, rueda subir/bajar */ { "case $BUTTON in "