Found in crybaby's working tree.
[distorted-keys] / keys.delete-keeper
index 1e3f3ec..908e22e 100755 (executable)
@@ -32,34 +32,61 @@ KEEPER
 Delete the keeper set named KEEPER.
 HELP
 
+## Parse the command line.
 case $# in 1) ;; *) usage_err ;; esac
 keeper=$1
 checkword "keeper set label" "$keeper"
 
+## Check that the set actually exists.
 cd $KEYS/keeper
 if [ ! -d $keeper ]; then
   echo >&2 "$quis: unknown keeper set \`$keeper'"
   exit 1
 fi
 
-unset deps
+## Make sure that there aren't recovery keys which would be orphaned by
+## deleting this keeper set.  Also, build a data structure of recovery keys
+## and their instances: `$recov' is a space-separated list of recovery key
+## labels, and for each such label R, `$ri_R' is a space-separated list of
+## its instances.
+unset deps; recov=" "
 if [ -d $KEYS/recov ]; then
   cd $KEYS/recov
-  for r in $(find . -type l -name current -print); do
-    r=${r#./}; r=${r%/current}
-    if ! expr >/dev/null "Q$r" : "Q$R_LABEL"; then continue; fi
+
+  ## Work through the available recovery keys.
+  for r in *; do
+    if ! expr >/dev/null "Q$r" : "Q$R_WORD"; then continue; fi
+    if [ ! -l $r/current ]; then continue; fi
+
+    ## Add the key to our list.
+    recov="$recov$r "
+
+    ## Now work through the instances.
+    ii=""
     for ri in $r/*; do
-      i=${ri##*/}
+      i=${ri#*/}
       case "$i" in *[!0-9]*) continue ;; esac
+
+      ## Add the instance to our list.
+      ii="$ii $i"
+
+      ## For each recovery key, make sure that: either it doesn't depend on
+      ## this keeper set, or it also depends on at least one other set.  If
+      ## not, add it to the `deps' list.
       this=nil others=nil
-      for kp in $r/current/*.param; do
+      for kp in $ri/*.param; do
        k=${kp##*/}; k=${k%.param}
        case $k in $keeper) this=t ;; *) others=t ;; esac
       done
       case $this,$others in t,nil) deps="$deps $ri" ;; esac
     done
+
+    ## Record the list of instances.
+    eval "ri_$r=\$ii"
   done
 fi
+
+## If we found any hard dependencies, report a failure.
 case "${deps+t}" in
   t)
     echo >&2 "$quis: deleting keeper \`$keeper' would orphan recovery keys:"
@@ -68,27 +95,26 @@ case "${deps+t}" in
     ;;
 esac
 
-if [ -d $KEYS/recov ]; then
-  cd $KEYS/recov
-  for r in $(find . -type l -name current -print); do
-    r=${r#./}; r=${r%/current}
-    if ! expr >/dev/null "Q$r" : "Q$R_LABEL"; then continue; fi
-    for ri in $i/*; do
-      i=${ri##*/}
-      case "$i" in *[!0-9]*) continue ;; esac
-      rm -f $ri/$keeper.*
-    done
-    changep=nil
-    while read k rest; do
-      case $k in $keeper) changep=t ;; *) echo "$k $rest" ;; esac
-    done <$r/keepers >$r/keepers.new
-    case $changep in
-      t) mv $r/keepers.new $r/keepers ;;
-      nil) rm $r/keepers.new ;;
-    esac
-  done
-fi
+## Disentangle the dependent recovery keys from this keeper set.
+for r in $recov; do
+
+  ## Remove the keeper data from the key's instances.
+  eval "ii=\$ri_$r"
+  for i in $ii; do rm -f $r/$i/$keeper.*; done
+
+  ## Work through the current keepers, and remove our keeper's name from the
+  ## list.
+  changep=nil
+  while read k rest; do
+    case $k in $keeper) changep=t ;; *) echo "$k $rest" ;; esac
+  done <$r/keepers >$r/keepers.new
+  case $changep in
+    t) mv $r/keepers.new $r/keepers ;;
+    nil) rm $r/keepers.new ;;
+  esac
+done
 
+## Finally, actually delete the keeper keys.
 cd $KEYS/keeper
 rm -r $keeper