]> git.wh0rd.org - home.git/blob - .bin/custom-chroot
chroot: start bind mounting /run
[home.git] / .bin / custom-chroot
1 #!/bin/bash -e
2
3 bootstrap() {
4 [[ $(id -u) -eq 0 ]] || exec sudo env -uUNSHARE HOME="$HOME" "$0" "$@"
5
6 if [[ -z ${UNSHARE} ]] ; then
7 mount_args=
8 if type -P unshare >&/dev/null ; then
9 uargs=( -m )
10 unshare -u -- true >&/dev/null && uargs+=( -u )
11 unshare -i -- true >&/dev/null && uargs+=( -i )
12 unshare -p -- true >&/dev/null && uargs+=( -p -f --mount-proc )
13 UNSHARE=true exec unshare "${uargs[@]}" -- "$0" "$@"
14 fi
15 else
16 mount_args='-n'
17 fi
18 unset UNSHARE
19 }
20
21 maybe_mount() {
22 local src=/$1 dst=${chroot}/${2:-$1}
23 [[ -d ${src} ]] || return 0
24 if ! mkdir -p "${dst}" ; then
25 [[ -w ${chroot} ]] && exit 1 || return 0
26 fi
27 grep -sq "${dst}" /proc/mounts || mount ${mount_args} --bind "${src}" "${dst}"
28 }
29
30 get_type() {
31 case $(file "$1") in
32 *x86-64*) echo x86_64;;
33 *"Intel 80386"*) echo i386;;
34 *32-bit*PowerPC*) echo ppc;;
35 *64-bit*PowerPC*) echo ppc64;;
36 *32-bit*S/390*) echo s390;;
37 *64-bit*S/390*) echo s390x;;
38 esac
39 }
40
41 init_chroot() {
42 [[ -w . ]] || return 0
43
44 if [[ ! -L etc/mtab ]] ; then
45 ln -sfT /proc/mounts etc/mtab
46 fi
47 local f dst
48 local etc=(
49 hosts
50 locale.gen
51 localtime
52 resolv.conf
53 )
54 local home=(
55 .inputrc
56 .gdbinit
57 .gitconfig
58 .nanorc
59 )
60 for f in \
61 $(printf 'etc/%s ' "${etc[@]}") \
62 ; do
63 if [[ -e /${f} ]] ; then
64 cp "/${f}" "${f}"
65 fi
66 done
67 for f in "${home[@]}" ; do
68 df="root/${f}"
69 f="${HOME}/${f}"
70 if [[ -e ${f} ]] ; then
71 cp "${f}" "${df}"
72 fi
73 done
74
75 f="${HOME}/.profile.d/aliases.sh"
76 if [[ -e ${f} ]] ; then
77 cat "${f}" > root/.bash_profile
78 fi
79 }
80
81 usage() {
82 cat <<-EOF
83 Usage: ${0##*/} [options] [program to run]
84
85 Sets up common mount points and then chroots in and runs a program.
86 If no program is specified, then launch a login shell.
87
88 Options:
89 -u Unmount all paths in the chroot
90 -m <path> Add path to mount list
91 -d <dir> Use <dir> as chroot (defaults to ${0%/*})
92 -h This help screen
93 EOF
94 exit
95 }
96
97 main() {
98 bootstrap "$@"
99
100 local mounts=( proc sys tmp dev dev/pts dev/shm run usr/portage usr/portage/distfiles usr/local/src )
101
102 local chroot=${0%/*}
103 case ${chroot} in
104 .) chroot=${PWD} ;;
105 ./*) chroot=${PWD}/${chroot#./} ;;
106 esac
107
108 local cmd
109 while [[ -n $1 ]] ; do
110 case $1 in
111 -u) cmd='umount' ;;
112 -m) mounts+=( "$2" ); shift ;;
113 -d) chroot=$(realpath "$2"); shift ;;
114 --help|-h) usage ;;
115 -*) echo "${0##*/}: unknown option $1"; exit 1 ;;
116 *) break ;;
117 esac
118 shift
119 done
120 cd "${chroot}"
121
122 case ${cmd} in
123 umount) exec "${0%/*}/umount-tree" -y "${chroot}" ;;
124 esac
125
126 local m
127 for m in "${mounts[@]}" ; do
128 maybe_mount ${m}
129 done
130
131 init_chroot
132
133 local setarch
134 if type -P setarch &>/dev/null ; then
135 local bin_dst=$(get_type bin/bash)
136 if [[ -n ${bin_dst} ]] ; then
137 setarch="setarch ${bin_dst}"
138 fi
139 fi
140
141 # Doubtful these settings we want to leak into the chroot.
142 unset ROOT PORTAGE_CONFIGROOT LD_LIBRARY_PATH
143 unset LS_COLORS # format changes over time
144 [[ $# -eq 0 ]] && set -- env HOME=/root /bin/bash -l
145 exec \
146 ${setarch} \
147 chroot "${chroot}" \
148 "$@"
149 }
150
151 main "$@"