blob: a2ea1515980c135b1145cb520addc0b7c387778b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
#!/bin/sh -e
# Enter a chroot
# shellcheck disable=2004
## SYNOPSIS:
## .Nm cpt-chroot
## .Op Fl m
## .Op Ar dir
## DESCRIPTION:
## .Nm
## is a wrapper script to chroot inside other root filesystems. It automatically
## mounts important filesystems in to the chroot directory, and unmounts them
## when the user exits the chroot and cleans up leftover host files. If the flag
## .Fl m
## is given,
## .Nm
## does not try to mount or unmount any filesystems.
# We generate the parser into the script, because we don't want this script to
# depend on cpt-lib.
nomount=''
REST=''
parse() {
OPTIND=$(($#+1))
while OPTARG= && [ $# -gt 0 ]; do
case $1 in
--?*=*) OPTARG=$1; shift
eval 'set -- "${OPTARG%%\=*}" "${OPTARG#*\=}"' ${1+'"$@"'}
;;
--no-*) unset OPTARG ;;
-[mh]?*) OPTARG=$1; shift
eval 'set -- "${OPTARG%"${OPTARG#??}"}" -"${OPTARG#??}"' ${1+'"$@"'}
OPTARG= ;;
esac
case $1 in
'-m')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG='1' || OPTARG=''
nomount="$OPTARG"
;;
'-h'|'--help')
usage
exit 0 ;;
--)
shift
while [ $# -gt 0 ]; do
REST="${REST} \"\${$(($OPTIND-$#))}\""
shift
done
break ;;
[-]?*)
set "unknown" "$1"; break ;;
*)
REST="${REST} \"\${$(($OPTIND-$#))}\""
esac
shift
done
[ $# -eq 0 ] && { OPTIND=1; unset OPTARG; return 0; }
case $1 in
unknown) set "Unrecognized option: $2" "$@" ;;
noarg) set "Does not allow an argument: $2" "$@" ;;
required) set "Requires an argument: $2" "$@" ;;
pattern:*) set "Does not match the pattern (${1#*:}): $2" "$@" ;;
notcmd) set "Not a command: $2" "$@" ;;
*) set "Validation error ($1): $2" "$@"
esac
echo "$1" >&2
exit 1
}
usage() { printf '%s\n' "usage: ${0##*/} [-m] [dir]" "" "Options:" \
" -m Don't mount or unmount directories"
}
parser_definition() {
setup REST help:usage -- "usage: ${0##*/} [-m] [dir]"
msg -- '' 'Options:'
flag nomount -m -- "Don't mount or unmount directories"
disp :usage -h --help hidden:1
}
log() {
printf '\033[32m->\033[m %s.\n' "$*"
}
die() {
log "$*" >&2
exit 1
}
clean() {
log Unmounting /dev, /proc and /sys from chroot; {
umount "$1/dev" ||:
umount "$1/proc" ||:
umount "$1/sys" ||:
}
log Cleaning leftover host files; {
rm -f "$1/root/.ash_history"
}
}
main() {
parse "$@" && eval set -- "$REST"
[ -d "$1" ] || die Given path does not exist
[ "$(id -u)" = 0 ] || die Script needs to be run as root
[ "$2" ] || {
march=$(uname -m 2>/dev/null) ||:
case "$march" in
'') march=native ;;
x86_64) march=x86-64 ;;
i*86) march=i686 ;;
esac
}
[ -z "$nomount" ] && {
trap 'clean "$1"' EXIT INT
log Mounting /dev, /proc and /sys from host; {
mountpoint -q "$1/dev" || mount -o bind /dev "$1/dev"
mountpoint -q "$1/proc" || mount -t proc proc "$1/proc"
mountpoint -q "$1/sys" || mount -t sysfs sys "$1/sys"
}
log Copying /etc/resolv.conf from host; {
[ -f "$1/etc/resolv.conf" ] || cp /etc/resolv.conf "$1/etc"
}
}
log Entering chroot; {
chroot "$1" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
SHELL=/bin/sh \
USER=root \
CFLAGS="${CFLAGS:--march=$march -mtune=generic -pipe -Os}" \
CXXFLAGS="${CXXFLAGS:--march=$march -mtune=generic -pipe -Os}" \
MAKEFLAGS="${MAKFLAGS:--j$(nproc 2>/dev/null || echo 1)}" \
/bin/sh -l
}
}
main "$@"
|