grml-chroot: properly handle multiple chroots [Closes: issue659]
[grml-scripts.git] / usr_sbin / grml-chroot
index 0985924..2540957 100755 (executable)
@@ -9,8 +9,13 @@
 PROG_NAME_=$(basename $0)
 DEST_=""
 MOUNTED_=""     # all mounted destinations
-COMMAND_=""     # command to start in chroot
 
+function bailout
+{
+  umount_all
+  die "Bailout"
+}
+trap bailout 1 2 3 3 6 9 14 15
 
 function die
 {
@@ -18,6 +23,16 @@ function die
     exit 1
 }
 
+function isMounted
+{
+    local dir="$1"
+    if cut -d\  -f 2 /proc/mounts | grep -q "$dir"; then
+        return 0
+    else
+        return 1
+    fi
+}
+
 function printUsage
 {
     cat <<EOT
@@ -46,19 +61,23 @@ function mountit
 
     local all_options_=""
 
-    if [[ $options_ == "--bind" ]]; then
+    if ! isMounted "${DEST_}/$dest_"; then
+      if [[ $options_ == "--bind" ]]; then
         all_options_="--bind $type_"
-    else
+      else
         all_options_="-t $type_ none"
+      fi
+      mount $all_options_ "${DEST_}/$dest_" && storeMounts "$dest_"
     fi
-    mount $all_options_ "${DEST_}/$dest_" && storeMounts "$dest_"
 }
 
 function umount_all
 {
-    for i in $MOUNTED_; do
-        umount "${DEST_}/$i"
+    for i in /proc /sys /dev; do
+        umount "${DEST_}/${i}"
     done
+
+    rm -f "$DEST_"/etc/debian_chroot
 }
 
 
@@ -79,8 +98,7 @@ if (( $# < 1 )); then
     die "Wrong number of arguments."
 fi
 
-DEST_="$1"
-COMMAND_="${2}"
+DEST_="$1"; shift
 
 if [ ! -d "$DEST_" ]; then
     die "Target chroot does not exist: $DEST_"
@@ -90,6 +108,35 @@ fi
 mountit "proc"  "proc"
 mountit "sysfs" "sys"
 mountit "/dev"   "dev"   "--bind"
-chroot "$DEST_" $COMMAND_
-umount_all
 
+# do not write to /var/run of chroot if it's not present
+if [ -d "$DEST_/tmp" ] ; then
+  STATEDIR="tmp/grml-chroot"
+  mkdir -p "$DEST_/$STATEDIR"
+  touch "$DEST_/$STATEDIR/$$"
+fi
+
+if [ ! -e "$DEST_"/etc/debian_chroot ]; then
+    echo "Writing /etc/debian_chroot ..."
+    cat "$DEST_"/etc/hostname > "$DEST_"/etc/debian_chroot
+fi
+
+if (( $# < 1 )); then
+    chroot "$DEST_"
+    RC=$?
+else
+    chroot "$DEST_" "$@"
+    RC=$?
+fi
+
+if [ -z "$STATEDIR" ] ; then
+  umount_all
+else
+  rm "$DEST_/$STATEDIR/$$"
+
+  if rmdir "$DEST_/$STATEDIR" 2>/dev/null; then
+    umount_all
+  fi
+fi
+
+exit $RC