]> git.wh0rd.org Git - home.git/blob - .bin/custom-chroot
custom-chroot: do not init /root if a git repo is there
[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         if [[ ! -d root/.git ]] ; then
76                 f="${HOME}/.profile.d/aliases.sh"
77                 if [[ -e ${f} ]] ; then
78                         cat "${f}" > root/.bash_profile
79                 fi
80         fi
81 }
82
83 usage() {
84         cat <<-EOF
85         Usage: ${0##*/} [options] [program to run]
86
87         Sets up common mount points and then chroots in and runs a program.
88         If no program is specified, then launch a login shell.
89
90         Options:
91           -u          Unmount all paths in the chroot
92           -m <path>   Add path to mount list
93           -d <dir>    Use <dir> as chroot (defaults to ${0%/*})
94           -h          This help screen
95         EOF
96         exit
97 }
98
99 main() {
100         bootstrap "$@"
101
102         local mounts=( proc sys tmp dev dev/pts dev/shm run usr/portage usr/portage/distfiles usr/local/src )
103
104         local chroot=${0%/*}
105         case ${chroot} in
106         .) chroot=${PWD} ;;
107         ./*) chroot=${PWD}/${chroot#./} ;;
108         esac
109
110         local cmd
111         while [[ -n $1 ]] ; do
112                 case $1 in
113                 -u) cmd='umount' ;;
114                 -m) mounts+=( "$2" ); shift ;;
115                 -d) chroot=$(realpath "$2"); shift ;;
116                 --help|-h) usage ;;
117                 -*) echo "${0##*/}: unknown option $1"; exit 1 ;;
118                 *)  break ;;
119                 esac
120                 shift
121         done
122         cd "${chroot}"
123
124         case ${cmd} in
125         umount) exec "${0%/*}/umount-tree" -y "${chroot}" ;;
126         esac
127
128         local m
129         for m in "${mounts[@]}" ; do
130                 maybe_mount ${m}
131         done
132
133         init_chroot
134
135         local setarch
136         if type -P setarch &>/dev/null ; then
137                 local bin_dst=$(get_type bin/bash)
138                 if [[ -n ${bin_dst} ]] ; then
139                         setarch="setarch ${bin_dst}"
140                 fi
141         fi
142
143         # Doubtful these settings we want to leak into the chroot.
144         unset ROOT PORTAGE_CONFIGROOT LD_LIBRARY_PATH
145         unset LS_COLORS # format changes over time
146         [[ $# -eq 0 ]] && set -- env HOME=/root /bin/bash -l
147         exec \
148                 ${setarch} \
149                 chroot "${chroot}" \
150                 "$@"
151 }
152
153 main "$@"