diff options
Diffstat (limited to 'modules/scripts')
| -rw-r--r-- | modules/scripts/lib.nix | 59 | ||||
| -rw-r--r-- | modules/scripts/usque-warp/completion.zsh | 17 | ||||
| -rw-r--r-- | modules/scripts/usque-warp/default.nix | 1 | ||||
| -rw-r--r-- | modules/scripts/usque-warp/script.sh | 45 |
4 files changed, 94 insertions, 28 deletions
diff --git a/modules/scripts/lib.nix b/modules/scripts/lib.nix index 70affba..77c0a20 100644 --- a/modules/scripts/lib.nix +++ b/modules/scripts/lib.nix @@ -1,9 +1,7 @@ { lib, pkgs }: let - shell = pkgs.runtimeShell; - mkScript = - name: path: description: env: deps: + name: path: description: env: deps: completion: let descLines = lib.filter (s: s != "") (lib.splitString "\n" description); descComment = @@ -11,17 +9,35 @@ let envVars = lib.concatStringsSep "\n" ( lib.mapAttrsToList (n: v: "export ${n}=${lib.escapeShellArg (toString v)}") env ); + base = pkgs.writeShellApplication { + inherit name; + runtimeInputs = deps; + text = '' + #!/usr/bin/env bash + ${descComment}${envVars} + ${builtins.readFile path} + ''; + }; + completionDrv = + pkgs.runCommand "${name}-completion" + { + nativeBuildInputs = [ pkgs.installShellFiles ]; + } + '' + installShellCompletion --zsh --name _${name} ${pkgs.writeText "_${name}" completion} + ''; in - pkgs.writeShellApplication { - inherit name; - runtimeInputs = deps; - text = '' - #!${shell} - ${descComment}${envVars} - ${builtins.readFile path} - ''; - }; - + if completion == null then + base + else + pkgs.symlinkJoin { + name = name; + paths = [ + base + completionDrv + ]; + meta = base.meta or { }; + }; mkScriptModule = { name, @@ -32,9 +48,10 @@ let extraLinks ? [ ], config, description ? "", + completion ? null, }: let - scriptDrv = mkScript name path description env deps; + scriptDrv = mkScript name path description env deps completion; in { options.scripts.${name} = { @@ -48,6 +65,13 @@ let readOnly = true; description = "The derivation for the ${name} script."; }; + completion = { + enable = lib.mkOption { + type = lib.types.bool; + default = completion != null; + description = "Whether to install a zsh completion for the ${name} script."; + }; + }; desktop = { enable = lib.mkOption { type = lib.types.bool; @@ -66,7 +90,6 @@ let }; }; }; - moduleConfig = { scripts.${name} = lib.mkIf config.scripts.${name}.enable ( { @@ -74,7 +97,6 @@ let } // lib.optionalAttrs (desktop != null) { inherit desktop; } ); - home.file = lib.mkIf config.scripts.${name}.enable ( builtins.listToAttrs ( map (linkPath: { @@ -85,7 +107,6 @@ let }) extraLinks ) ); - assertions = [ { assertion = @@ -94,6 +115,10 @@ let || config.terminal.kitty.enable; message = "scripts.${name}.desktop.enable requires terminal.kitty.enable because desktop entries launch scripts in kitty."; } + { + assertion = !config.scripts.${name}.completion.enable || completion != null; + message = "scripts.${name}.completion.enable is true but no completion text was provided to mkScriptModule."; + } ]; }; }; diff --git a/modules/scripts/usque-warp/completion.zsh b/modules/scripts/usque-warp/completion.zsh new file mode 100644 index 0000000..fbb340e --- /dev/null +++ b/modules/scripts/usque-warp/completion.zsh @@ -0,0 +1,17 @@ +#compdef usque-warp + +_arguments \ + '1: :->cmds' \ + '*::arg:->args' + +case $state in + cmds) + local -a commands + commands=( + 'connect:Connect to WARP' + 'disconnect:Disconnect from WARP' + 'status:Show connection status' + ) + _describe 'command' commands + ;; +esac diff --git a/modules/scripts/usque-warp/default.nix b/modules/scripts/usque-warp/default.nix index 77bf341..f5cb988 100644 --- a/modules/scripts/usque-warp/default.nix +++ b/modules/scripts/usque-warp/default.nix @@ -14,6 +14,7 @@ let config.networking.usque.package pkgs.bash ]; + completion = builtins.readFile ./completion.zsh; inherit config; }; in diff --git a/modules/scripts/usque-warp/script.sh b/modules/scripts/usque-warp/script.sh index 01b298e..9d32872 100644 --- a/modules/scripts/usque-warp/script.sh +++ b/modules/scripts/usque-warp/script.sh @@ -50,6 +50,7 @@ remove_tun_default_routes() { } connect() { + sudo -v ensure_config if [[ -f "$PID_FILE" ]]; then OLD_PID=$(cat "$PID_FILE") @@ -133,6 +134,7 @@ connect() { } disconnect() { + sudo -v echo "Disconnecting..." local dev if [[ -f "$IFACE_FILE" ]]; then @@ -141,28 +143,49 @@ disconnect() { dev=$(list_tun_ifaces | head -n1) fi + # Kill usque FIRST so the kernel tears down tun0 (and every route + # bound to it) as a single atomic operation, instead of us racing + # it by pulling routes out from under a device that's still up. + if [[ -f "$PID_FILE" ]]; then + PID=$(cat "$PID_FILE") + if sudo kill -0 "$PID" 2>/dev/null; then + echo "Stopping usque..." + sudo kill "$PID" 2>/dev/null || true + for _ in {1..20}; do + sudo kill -0 "$PID" 2>/dev/null || break + sleep 0.2 + done + fi + rm -f "$PID_FILE" + fi + + # Belt-and-braces: if the interface (or any of its routes) somehow + # survived, clean them up explicitly. No-ops if tun0 is already gone. if [[ -n "${dev:-}" ]]; then - echo "Removing $dev routes..." + echo "Flushing $dev routes..." + sudo ip route flush dev "$dev" 2>/dev/null || true remove_tun_default_routes "$dev" fi if [[ -f "$STATE_FILE" ]]; then MASQUE_IP=$(grep -oP 'MASQUE_IP=\K[0-9.]+' "$STATE_FILE" || true) if [[ -n "$MASQUE_IP" ]]; then - echo "Removing MASQUE route: $MASQUE_IP" - sudo ip route del "$MASQUE_IP" 2>/dev/null || true + echo "Removing MASQUE route: $MASQUE_IP" + sudo ip route del "$MASQUE_IP" 2>/dev/null || true fi - rm -f "$STATE_FILE" - fi - if [[ -f "$PID_FILE" ]]; then - PID=$(cat "$PID_FILE") - if sudo kill -0 "$PID" 2>/dev/null; then - echo "Stopping usque..." - sudo kill "$PID" 2>/dev/null || true + # Explicitly restore the pre-connect default route rather than + # assuming it's still intact. 'replace' is idempotent. + ORIGINAL_DEFAULT=$(head -n1 "$STATE_FILE") + if [[ "$ORIGINAL_DEFAULT" == default* ]]; then + echo "Restoring original default route..." + sudo ip route replace "$ORIGINAL_DEFAULT" \ + || echo "Warning: could not restore original default route" fi - rm -f "$PID_FILE" + + rm -f "$STATE_FILE" fi + rm -f "$IFACE_FILE" echo "Disconnected" } |
