Release new version 2.13.0
[grml-scripts.git] / usr_sbin / grml-chroot
1 #!/bin/bash
2 # Filename:      grml-chroot
3 # Purpose:       Program to chroot into another system
4 # Authors:       grml-team (grml.org), (c) Michael Gebetsroither <gebi@grml.org>
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2.
7 ################################################################################
8
9 PROG_NAME_=$(basename $0)
10 DEST_=""
11 MOUNTED_=""     # all mounted destinations
12
13
14 function die
15 {
16     echo "Error: $@" >&2
17     exit 1
18 }
19
20 function printUsage
21 {
22     cat <<EOT
23 Usage: "$PROG_NAME_" NEWROOT [COMMAND....]
24
25 $PROG_NAME_ is a chroot wrapper with proc/sys/pts/dev filesystem handling
26
27 EOT
28 }
29
30 function storeMounts
31 {
32     local to_append_="$1"
33     if [[ $MOUNTED_ == "" ]]; then
34         MOUNTED_="$to_append_"
35     else
36         MOUNTED_="$MOUNTED_ $to_append_"
37     fi
38 }
39
40 function mountit
41 {
42     local type_="$1" # type _or_ src
43     local dest_="$2"
44     local options_="$3"
45
46     local all_options_=""
47
48     if [[ $options_ == "--bind" ]]; then
49         all_options_="--bind $type_"
50     else
51         all_options_="-t $type_ none"
52     fi
53     mount $all_options_ "${DEST_}/$dest_" && storeMounts "$dest_"
54 }
55
56 function umount_all
57 {
58     local reverse=$(echo $MOUNTED_ | awk '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }')
59     for i in $reverse; do
60         umount "${DEST_}/$i"
61     done
62 }
63
64
65 ###
66 ### __MAIN
67 ###
68
69 while getopts "h" opt; do
70     case "$opt" in
71         h) printUsage; exit 0 ;;
72         ?) printUsage; exit 64 ;;
73     esac
74 done
75 shift $(($OPTIND - 1))
76
77 if (( $# < 1 )); then
78     printUsage
79     die "Wrong number of arguments."
80 fi
81
82 if ! which awk >/dev/null 2>&1 ; then
83   die "No awk binary found, required for execution."
84 fi
85
86 DEST_="$1"; shift
87
88 if [ ! -d "$DEST_" ]; then
89     die "Target chroot does not exist: $DEST_"
90 fi
91
92
93
94 if [ -f "$DEST_"/proc/cmdline ] ; then
95     echo "Looks like $DEST_ already has filesystems mounted, skipping."
96 else
97     mountit "proc"  "proc"
98     mountit "sysfs" "sys"
99     mountit "/dev"   "dev"   "--bind"
100     mountit "devpts" "dev/pts"
101     if [ -d "$DEST_"/run/udev ] && [ -d /run/udev ] ; then
102       mountit "/run/udev" "/run/udev" "--bind"
103     fi
104 fi
105
106 WROTE_DEBIAN_CHROOT=""
107 if [ ! -f "$DEST_"/etc/debian_chroot ]; then
108     WROTE_DEBIAN_CHROOT="yes"
109     echo "Writing /etc/debian_chroot ..."
110     cat "$DEST_"/etc/hostname > "$DEST_"/etc/debian_chroot
111 fi
112
113 if (( $# < 1 )); then
114     chroot "$DEST_"
115     RC=$?
116 else
117     chroot "$DEST_" "$@"
118     RC=$?
119 fi
120 umount_all
121
122 if [ ! -z "$WROTE_DEBIAN_CHROOT" ]; then
123     rm "$DEST_"/etc/debian_chroot
124 fi
125
126 exit $RC