1#!/bin/sh
2# Enter a kiss chroot
3
4log() {
5 printf '\033[32m->\033[m %s.\n' "$*"
6}
7
8die() {
9 log "$*" >&2
10 exit 1
11}
12
13run() {
14 printf '%s\n' "$*"
15 "$@" || return "${_ret:=0}"
16}
17
18clean() {
19 {
20 run umount "$1/dev/shm" 2>/dev/null
21 run umount "$1/dev/pts"
22 run umount "$1/dev"
23 run umount "$1/proc"
24 run umount "$1/run"
25 run umount "$1/sys/firmware/efi/efivars" 2>/dev/null
26 run umount "$1/sys"
27 run umount "$1/tmp"
28 run umount "$1/etc/resolv.conf"
29 }
30}
31
32mounted() {
33 # This is a pure shell mountpoint implementation. We're dealing
34 # with basic (and fixed/known) input so this doesn't need to
35 # handle more complex cases.
36 [ -e "$1" ] || return 1
37 [ -e /proc/mounts ] || return 1
38
39 while read -r _ target _; do
40 [ "$target" = "$1" ] && return 0
41 done < /proc/mounts
42
43 return 1
44}
45
46mmount() {
47 dest=$1
48 shift
49 mounted "$dest" || run mount "$@" "$dest"
50}
51
52main() {
53 # Ensure input does not end in '/'.
54 set -- "${1%"${1##*[!/]}"}"
55
56 [ "$1" ] || die Need a path to the chroot
57 [ -d "$1" ] || die Given path does not exist
58 [ "$(id -u)" = 0 ] || die Script needs to be run as root
59
60 # Intended behaviour.
61 # shellcheck disable=SC2064
62 #trap "clean ${1%"${1##*[!/]}"}" EXIT INT
63
64 {
65 mmount "$1/dev" -o bind /dev
66 mmount "$1/dev/pts" -o bind /dev/pts
67 mmount "$1/dev/shm" -t tmpfs shmfs 2>/dev/null
68 mmount "$1/proc" -t proc proc
69 mmount "$1/run" -t tmpfs tmpfs
70 mmount "$1/sys" -t sysfs sys
71 mmount "$1/sys/firmware/efi/efivars" -t efivarfs efivarfs 2>/dev/null
72 mmount "$1/tmp" -o mode=1777,nosuid,nodev -t tmpfs tmpfs
73
74 touch "$1/etc/resolv.conf"
75 mmount "$1/etc/resolv.conf" -o bind /etc/resolv.conf
76 }
77
78}
79
80# unmount if 2nd arg passed
81[ $2 ] && { clean ${1%"${1##*[!/]}"}; exit 0; }
82main "$1"