Some random scripts which need a home.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 10 Jul 2011 22:23:19 +0000 (23:23 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 10 Jul 2011 22:23:19 +0000 (23:23 +0100)
do-slaves [new file with mode: 0755]
expand-list [new file with mode: 0755]
unlock-root [new file with mode: 0755]

diff --git a/do-slaves b/do-slaves
new file mode 100755 (executable)
index 0000000..de31424
--- /dev/null
+++ b/do-slaves
@@ -0,0 +1,23 @@
+#! /bin/sh
+set -e
+
+## Parse the command line.
+case "$#" in
+  0 | 1)
+    echo >&2 "Usage: $0 COMMAND SLAVE|:SET ..."
+    exit 1
+    ;;
+esac
+command=$1; shift
+
+## Expand slaves into a big list.
+slaves=$(expand-list /etc/slaves "$@")
+
+## Now do the stuff.
+for i in $slaves; do
+  { { { echo "starting..."
+       set +e; ssh "$i" "$command" 3>&-; rc=$?; set -e
+       echo "done (rc = $rc)"; } >&3; } 2>&1 | sed 's/^/!!! /'; } 3>&1 |
+  sed "s\a^\a$i: \a" &
+done
+wait
diff --git a/expand-list b/expand-list
new file mode 100755 (executable)
index 0000000..be54662
--- /dev/null
@@ -0,0 +1,39 @@
+#! /bin/sh
+###
+### Expand a list of symbolic references to other lists.
+
+expand () {
+  slaves=""
+  for i in "$@"; do
+    case "$i" in
+      :*)
+        name=${i#:}
+        eval found=\${set_$name+t}\${set_$name-nil} set=\${set_$name}
+        case "$found" in
+          nil) echo >&2 "$0: no such set \`$name'"; exit 1 ;;
+        esac
+        slaves="$slaves $set"
+        ;;
+      *)
+        slaves="$slaves $i"
+        ;;
+    esac
+  done
+  echo $slaves
+}
+
+defset () {
+  setname=$1; shift
+  eval set_$setname='$(expand "$@")'
+}
+
+case $# in
+  0 | 1)
+    echo >&2 "Usage: $0 FILE ITEM|:LIST ..."
+    exit 1
+    ;;
+esac
+
+. "$1"; shift
+expand "$@"
+
diff --git a/unlock-root b/unlock-root
new file mode 100755 (executable)
index 0000000..1502ae7
--- /dev/null
@@ -0,0 +1,91 @@
+#! /bin/sh
+###
+### unlock-root KEY-FILE
+
+set -e
+
+## Fetch the argument.
+case $# in
+  1) keyfile=$1 ;;
+  *) echo >&2 "Usage: $0 KEY-FILE"; exit 16 ;;
+esac
+
+## Some preflight checks.
+if [ ! -x /usr/bin/gpg ]; then
+  echo >&2 "$0: can't find GnuPG executable"
+  exit 8
+fi
+
+## Arrange to have somewhere for the key token.
+mkdir -p /mnt/keys
+
+## Now we try to find a token.
+lastuuid=no-match
+prompt=t
+win=nil
+while :; do
+
+  ## Wait for a different device to be inserted.  The first time through,
+  ## we'll accept any device.
+  while :; do
+
+    ## If there's a token already inserted then go with that.
+    if info=$(blkid -o full -t LABEL=keys); then
+      eval DEVICE=$info
+      case "$UUID" in
+       "$lastuuid") ;;
+       *) lastuuid=$UUID; break ;;
+      esac
+    else
+      lastuuid=no-token
+    fi
+
+    ## Otherwise we could be here for a while.
+    case "$prompt" in
+      t) echo >&2 -n "Waiting for key token..."; prompt=nil ;;
+    esac
+
+    ## Wait for a bit.
+    sleep 1
+    udevadm settle
+  done
+
+  ## Mount the device somewhere.
+  mount -o ro -t ext2 UUID="$UUID" /mnt/keys
+
+  ## If we have the key file, then we're done.
+  if [ -f /mnt/keys/"$keyfile".gpg ]; then
+    
+    ## Update the eyecandy, such as it is.
+    case "$prompt" in
+      nil) >&2 echo " ok"; prompt=t ;;
+    esac
+
+    ## Get GnuPG to decrypt the key.  The enormous `gpg' rune is taken from
+    ## the cryptsetup `decrypt_gnupg' script.  The here-document prevents
+    ## the key ending up in a ps(1) listing, though the expected use-case is
+    ## to run this script from an initramfs so there won't be anyone
+    ## watching.
+    while :; do
+      key=$(/lib/cryptsetup/askpass "Enter passphrase for key $1: ")
+      case "$key" in "") break ;; esac
+      if /usr/bin/gpg -q --batch --no-options --no-mdc-warning  \
+               --no-random-seed-file --no-default-keyring \
+               --keyring /dev/null --secret-keyring /dev/null \
+               --trustdb-name /dev/null --passphrase-fd 0 --decrypt \
+               /mnt/keys/"$keyfile".gpg <<EOF
+$key
+EOF
+      then win=t; break; fi
+    done
+  fi
+
+  ## Unmount the filesystem.
+  umount /mnt/keys
+
+  ## If we did anything, stop.
+  case "$win" in t) break ;; esac
+done
+
+## Done.
+exit 0