-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiplinux-bootstrap
executable file
·454 lines (369 loc) · 11.3 KB
/
iplinux-bootstrap
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
#!/bin/sh -e
#
# iplinux-bootstrap
# © 2008-2009 Mikhail Gusarov <[email protected]>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
VERSION=0.2.3
PATH=$PATH:libshell
. shell-error
. shell-getopt
# --- Utils ---
# Our little config.guess
guess_hostarch() {
if [ $(uname -s) != "Linux" ]; then
echo unknown
return
fi
case "$(uname -m)" in
i?86|pentium*) echo i386;;
x86_64) echo amd64;;
*) echo unknown;;
esac
}
hostarch() {
dpkg --print-architecture 2>/dev/null || guess_hostarch
}
find_prog() {
type "$1" >/dev/null 2>/dev/null
}
in_list() {
LIST="$1"
ITEM="$2"
expr " $LIST " : ".* $ITEM " >/dev/null
}
car() {
echo "$@" | cut -d' ' -f1
}
cdr() {
echo "$@" | cut -d' ' -f2-
}
# --- Config parsing ---
#
# Quirks in distribution configs:
#
# * _first_ source in distribution is special, as it is used for debootstrap.
# - it is expected that it is possible to debootstrap it
# - it should provide package 'sudo'
# - it should contain /usr/sbin/adduser
#
parse_repositories() {
repositories=$(cd distributions/repositories; find * -maxdepth 0 -type f -printf '%f ')
for r in $repositories; do
. distributions/repositories/$r
eval "${r}_URL=\"$DEFAULT_URL\""
eval "${r}_DEFAULT_URL=\"$DEFAULT_URL\""
eval "${r}_NAME=\"$NAME\""
unset DEFAULT_URL NAME
done
}
parse_sources() {
sources=$(cd distributions/sources; find * -maxdepth 0 -type f -printf '%f ')
for s in $sources; do
. distributions/sources/$s
eval "${s}_ADD_PKGS=\"$ADD_PKGS\""
eval "${s}_REPO=\"$REPO\""
eval "${s}_SECTIONS=\"$SECTIONS\""
eval "${s}_SUITE=\"$SUITE\""
unset ADD_PKGS REPO SECTIONS SUITE
done
}
parse_distributions() {
distributions=$(cd distributions; find * -maxdepth 0 -type f -printf '%f ')
for d in $distributions; do
. distributions/$d
eval "${d}_NAME=\"$NAME\""
eval "${d}_SOURCES=\"$SOURCES\""
eval "${d}_CROSS_SHELL_SOURCE=\"$CROSS_SHELL_SOURCE\""
unset NAME SOURCES CROSS_SHELL_SOURCE
done
}
# --- Bootstrap ---
check_env_name="Checking environment"
check_env() {
if [ -e $work_dir ]; then
echo "$work_dir already exists. Remove it before proceeding."
return 1
fi
[ -n "$UID" ] || UID=$(id -u)
if [ $UID -eq 0 ]; then
echo "Refusing to work as root. Run under ordinary user with sudo privileges."
return 1
fi
return 0
}
PROGS="ar mktemp sudo"
check_progs_name="Checking prerequisites"
check_progs() {
err=0
for prog in $PROGS; do
echo -n "$prog: "
if find_prog "$prog"; then
echo found
else
echo not found.
err=1
fi
done
#sudo check
sudo -K
if sudo -h 2>&1 | grep -q -- '\[-A'; then
SUDO_ENV=SUDO_ASKPASS=/bin/true
SUDO_ARG=-A
fi
if ! env $SUDO_ENV sudo $SUDO_ARG -l >/dev/null; then
echo "sudo: need passwordless sudo!"
err=1
fi
return $err
}
#
# Bootstraps chroot and performs configuration enough to run $work_dir/enter
#
generate_chroot_name="Generating chroot"
generate_chroot() {
distro_name=$(eval echo \${distribution}_NAME)
src=$(car $(eval echo \$${distribution}_SOURCES))
suite=$(eval echo \$${src}_SUITE)
sections=$(eval echo \$${src}_SECTIONS)
sections=$(echo $sections | sed -e 's/ +/,/g')
repo=$(eval echo \$${src}_REPO)
repo_url=$(eval echo \$${repo}_URL)
repo_name=$(eval echo \$${repo}_NAME)
$root_cmd sh -c "$chroot_env DEBOOTSTRAP_DIR=$(pwd)/debootstrap debootstrap/debootstrap --include=sudo --arch=$chroot_arch --components=$sections $suite $work_dir $repo_url"
if [ "$?" != 0 ]; then
echo "Failed to bootstrap $repo_name from $repo_url to $work_dir"
exit 1
fi
# -- hostname (for sudo) --
HOSTNAME=$(hostname)
$root_sh "echo 127.0.0.1 localhost $HOSTNAME >> $work_dir/etc/hosts"
# -- 'build' user --
[ -n "$UID" ] || UID=`id -u`
$root_cmd $chroot_cmd $work_dir /usr/sbin/adduser --home /build --uid $UID --disabled-password --disabled-login --gecos "$src build user" build
# -- sudo --
TMPFILE=$(mktemp)
echo "Defaults env_keep+=http_proxy, env_keep+=ftp_proxy, env_keep+=\"DEB_*\"" > $TMPFILE
echo "build ALL=(ALL) NOPASSWD:ALL" >> $TMPFILE
$root_cmd mv $TMPFILE $work_dir/etc/sudoers
$root_cmd chown root:root $work_dir/etc/sudoers
$root_cmd chmod 440 $work_dir/etc/sudoers
# -- $work_dir/enter --
TMPFILE=$(mktemp)
sed -e "s,@@HTTP_PROXY@@,$http_proxy,g" \
-e "s,@@FTP_PROXY@@,$ftp_proxy,g" < enter.in > $TMPFILE
$root_cmd mv $TMPFILE $work_dir/.enter.real
$root_cmd chmod +x $work_dir/.enter.real
TMPFILE=$(mktemp)
echo '#!/bin/sh
echo "Chroot generation did not finish!"
echo "Do not try to use this chroot, remove it and build another."
exit 1' > $TMPFILE
$root_cmd mv $TMPFILE $work_dir/enter
$root_cmd chmod +x $work_dir/enter
}
populate_chroot_name="Populating chroot"
populate_chroot() {
# -- sources.list --
TMPFILE=$(mktemp)
for s in $(eval echo \$${distribution}_SOURCES); do
src_repo=$(eval echo \$${s}_REPO)
src_url=$(eval echo \$${src_repo}_URL)
src_suite=$(eval echo \$${s}_SUITE)
src_sections=$(eval echo \$${s}_SECTIONS)
echo "deb $src_url $src_suite $src_sections" >> $TMPFILE
done
$root_cmd mv $TMPFILE $work_dir/etc/apt/sources.list
# -- no APT recommends by default
echo "APT { Install-Recommends 'false'; };" > $TMPFILE
$root_cmd mv $TMPFILE $work_dir/etc/apt/apt.conf.d/02no-recommends
# -- GPG key --
for s in $(eval echo \$${distribution}_SOURCES); do
keyfile=distributions/keys/$s
[ ! -f $keyfile ] || cat $keyfile >> $work_dir/tmp/gpgkey
done
$work_dir/.enter.real sudo apt-key add /tmp/gpgkey
rm -f $work_dir/tmp/gpgkey
# -- packages --
host_packages=''
for s in $(eval echo \$${distribution}_SOURCES); do
host_packages="$host_packages "$(eval echo \$${s}_ADD_PKGS)
done
$work_dir/.enter.real sudo apt-get update
$work_dir/.enter.real sudo apt-get dist-upgrade --yes --force-yes
$work_dir/.enter.real sudo apt-get install --yes --force-yes $host_packages
}
configure_chroot_name="Configuring chroot"
configure_chroot() {
src=$(eval echo \$${distribution}_CROSS_SHELL_SOURCE)
repo=$(eval echo \$${src}_REPO)
repo_url=$(eval echo \$${repo}_URL)
suite=$(eval echo \$${src}_SUITE)
TMPFILE=$(mktemp)
echo "SUITE=$suite
REPO=$repo_url
ROOT_CMD=sudo" > $TMPFILE
$root_cmd mv $TMPFILE $work_dir/etc/cross-shell/config
# -- Prompt --
cp $work_dir/build/.profile $work_dir/tmp/profile
echo "export PS1=\"<devenv: \w>\$ \"" >> $work_dir/tmp/profile
$work_dir/.enter.real mv -f /tmp/profile /build/.profile
}
enable_chroot_name="Enabling chroot"
enable_chroot() {
$root_cmd rm $work_dir/enter
$root_cmd mv $work_dir/.enter.real $work_dir/enter
}
usage() {
echo "Usage: ${0##*/} [OPTION]... <distribution> <target-dir>"
echo "Bootstrap IPlinux devenv chroot"
echo
cat <<EOF
-h|--help display this help and exit
-V|--version display version information and exit
-v|--verbose don't turn off the output of tools
--http-proxy=P http proxy to use to obtain packages
--ftp-proxy=P ftp proxy to use to obtain packages
--root-cmd=C command to gain root (defaults to '$root_cmd')
EOF
for r in $repositories; do
echo " --${r}-mirror=U"
url=$(eval echo \$${r}_DEFAULT_URL)
name=$(eval echo \$${r}_NAME)
echo " URL of $name repository"
echo " (defaults to $url)"
done
cat <<EOF
List of available distributions: $distributions
EOF
}
export LC_ALL=C
parse_repositories
parse_sources
parse_distributions
cmdline_options="help,version,verbose,http-proxy:,ftp-proxy:,root:,root-cmd:"
for r in $repositories; do
cmdline_options="$cmdline_options,$r-mirror:"
done
TMP=$(getopt --long $cmdline_options -o hvV -- "$@")
if [ $? != 0 ]; then
exit 1
fi
eval set -- "$TMP"
root_cmd=sudo
chroot_env=
while true; do
case "$1" in
-h|--help)
usage
exit 0
;;
-V|--version)
echo "iplinux-bootstrap $VERSION"
exit 0
;;
-v|--verbose)
verbose=true
export verbose
shift
;;
--http-proxy)
http_proxy="$2"
chroot_env="$chroot_env http_proxy=$2"
shift 2
;;
--ftp-proxy)
ftp_proxy="$2"
chroot_env="$chroot_env ftp_proxy=$2"
shift 2
;;
--*-mirror)
r=${1#--}
r=${r%-mirror}
eval "${r}_URL=\"$2\""
shift 2
;;
--no-bootstrap-rootfs)
no_bootstrap_rootfs=1
shift
;;
--root-cmd)
root_cmd="$2"
shift 2
;;
--)
shift
break
;;
*)
echo "Unexpected argument in arguments list: $1"
exit 1
;;
esac
done
if [ $# != 2 ]; then
usage
exit 0
fi
distribution="$1"
if ! in_list "$distributions" "$distribution"; then
echo "Unknown distribution: $distribution"
exit 1
fi
case "$2" in
/*) work_dir="$2";;
*) work_dir=$(pwd)/$2;;
esac
root_sh="$root_cmd sh -c"
case "$(hostarch)" in
i386|amd64)
chroot_cmd="chroot"
chroot_arch=$(hostarch)
;;
*)
echo "Unable to detect the host architecture."
echo "Please file a bug report with output of"
echo "* dpkg --print-architecture (if you use a Debian-based system)"
echo "* uname -s; uname -m (in all other cases)"
exit 1
esac
check_ok() {
RET=$?
if [ $RET -ne 0 ]; then
echo "Chroot generation failed"
fi
exit $RET
}
trap check_ok 0 HUP PIPE INT QUIT TERM
echo
echo "** If script stops without \"You can enter newly created...\", then it broke."
echo
tasks="check_env check_progs generate_chroot populate_chroot configure_chroot enable_chroot"
tasknum=0
tasksnum=$(echo $tasks | wc -w)
for task in $tasks; do
tasknum=$(($tasknum+1))
echo "=>> "$(eval "echo $"$task"_name")" [$tasknum/$tasksnum]"
$task
done
distro_name=$(eval echo \$${distribution}_NAME)
echo
echo
echo "You can enter newly created $distro_name build environment by issuing"
echo "the following command:"
echo " $work_dir/enter"
echo
echo