diff options
Diffstat (limited to 'src/initrd/init.functions')
-rw-r--r-- | src/initrd/init.functions | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/src/initrd/init.functions b/src/initrd/init.functions new file mode 100644 index 0000000..7209b04 --- /dev/null +++ b/src/initrd/init.functions | |||
@@ -0,0 +1,345 @@ | |||
1 | #!/bin/sh | ||
2 | . common.sh | ||
3 | mountvirt() | ||
4 | { | ||
5 | # TODO: simply put these dirs on the initrd itself | ||
6 | mkdir -m 0755 -p /dev /sys /proc /tmp /var /run | ||
7 | mkdir -m 0700 -p /root | ||
8 | |||
9 | mount -t sysfs -o nodev,noexec,nosuid none /sys | ||
10 | mount -t proc -o nodev,noexec,nosuid none /proc | ||
11 | tmpfs_size="10M" | ||
12 | # [ -f /etc/udev/udev.conf ] && . /etc/udev/udev.conf | ||
13 | mount -t tmpfs -o size=$tmpfs_size,mode=0755 udev /dev | ||
14 | mount -t tmpfs -o size=64M,mode=0755 run /run | ||
15 | mkdir -m 0755 /dev/pts /run/lock | ||
16 | mount -t devpts devpts /dev/pts | ||
17 | ln -s /run /run/lock /var/ | ||
18 | } | ||
19 | makedev() | ||
20 | { | ||
21 | # TODO: simply put these nodes on the initrd itself | ||
22 | mkdir -m 0755 -p /dev | ||
23 | mknod /dev/null c 1 3 | ||
24 | mknod /dev/zero c 1 5 | ||
25 | mknod /dev/tty c 5 0 | ||
26 | if [ "$FUCK_devconsole" ]; then # FUCK /dev/console | ||
27 | mknod /dev/console c 4 1 # tty1 is console; a saner alternative (TODO: fix shutdown to chvt) | ||
28 | else | ||
29 | mknod /dev/console c 5 1 | ||
30 | fi | ||
31 | for i in 0 1 2 3 4 5 6 7 8; do | ||
32 | mknod /dev/tty${i} c 4 ${i} | ||
33 | done | ||
34 | # TODO: wait for udev? pft. | ||
35 | for i in 0 1 2 3 4 5 6 7; do | ||
36 | mknod /dev/loop${i} b 7 ${i} | ||
37 | done | ||
38 | } | ||
39 | loadenv() | ||
40 | { | ||
41 | # TODO: filter the wheat from the chaff here; most of this is unused. | ||
42 | # TODO: implement the various boot args | ||
43 | |||
44 | # Load config files | ||
45 | # export DPKG_ARCH= | ||
46 | # . /conf/arch.conf | ||
47 | # export ROOT= | ||
48 | # . /conf/initramfs.conf | ||
49 | # for conf in conf/conf.d/*; do | ||
50 | # [ -f ${conf} ] && . ${conf} | ||
51 | # done | ||
52 | # Make modprobe quiet | ||
53 | export MODPROBE_OPTIONS="-qb" | ||
54 | # Export constants | ||
55 | export rootmnt=/root | ||
56 | # Export bootparam variables | ||
57 | export init=/sbin/init | ||
58 | export readonly=y | ||
59 | export blacklist= | ||
60 | |||
61 | # Parse command line options | ||
62 | for x in $(cat /proc/cmdline); do | ||
63 | case $x in | ||
64 | init=*) init=${x#init=} ;; | ||
65 | root=*) | ||
66 | ROOT=${x#root=} | ||
67 | case $ROOT in | ||
68 | LABEL=*) ROOT="/dev/disk/by-label/${ROOT#LABEL=}" ;; | ||
69 | UUID=*) ROOT="/dev/disk/by-uuid/${ROOT#UUID=}" ;; | ||
70 | /dev/nfs) [ -z "${BOOT}" ] && BOOT=nfs ;; | ||
71 | esac | ||
72 | ;; | ||
73 | rootflags=*) ROOTFLAGS="-o ${x#rootflags=}" ;; | ||
74 | rootfstype=*) ROOTFSTYPE="${x#rootfstype=}" ;; | ||
75 | ro) readonly=y ;; | ||
76 | rw) readonly=n ;; | ||
77 | |||
78 | nfsroot=*) NFSROOT="${x#nfsroot=}" ;; | ||
79 | ip=*) IPOPTS="${x#ip=}" ;; | ||
80 | boot=*) BOOT=${x#boot=} ;; | ||
81 | |||
82 | resume=*) RESUME="${x#resume=}" ;; | ||
83 | noresume) noresume=y ;; | ||
84 | blacklist=*) blacklist=${x#blacklist=} ;; | ||
85 | |||
86 | hostname=*) | ||
87 | hostname=${x#hostname=} | ||
88 | hostname "$hostname" | ||
89 | ;; | ||
90 | bootcd_device=*) bootcd_device=${x#bootcd_device=} | ||
91 | mkdir -p /cdrom && | ||
92 | mount -r -t hostfs -o "${bootcd_device#hostfs=}" hostfs /cdrom && | ||
93 | bootdone samizdat-cdrom | ||
94 | ;; | ||
95 | overlay_device=*) overlay_device=${x#overlay_device=} | ||
96 | mkdir -p /overlay && | ||
97 | mount -t hostfs -o "${overlay_device#hostfs=}" hostfs /overlay && | ||
98 | bootdone rw-overlay | ||
99 | ;; | ||
100 | uml_modules=*) uml_modules=${x#uml_modules=} | ||
101 | mount -t hostfs -o "${uml_modules#hostfs=}" hostfs /lib/modules ;; | ||
102 | esac | ||
103 | done | ||
104 | |||
105 | if [ -z "${noresume}" ]; then | ||
106 | export resume=${RESUME} | ||
107 | else | ||
108 | export noresume | ||
109 | fi | ||
110 | } | ||
111 | mountunionroot() | ||
112 | { | ||
113 | bootwait samizdat-cdrom squashfs-root | ||
114 | |||
115 | ufs= | ||
116 | if grep -q aufs /proc/filesystems || modprobe aufs; then | ||
117 | ufs=aufs | ||
118 | elif grep -q unionfs /proc/filesystems || modprobe unionfs; then | ||
119 | ufs=unionfs | ||
120 | fi | ||
121 | |||
122 | case $ufs in | ||
123 | unionfs) ro=ro;; | ||
124 | aufs) ro=rr;; | ||
125 | *) panic "mountunionroot: unionfs module not found";; | ||
126 | esac | ||
127 | |||
128 | dirs=; | ||
129 | if [ -f /squashes/filesystem.module ]; then | ||
130 | while read img; do | ||
131 | d=/squashes/"${img%.squashfs}" | ||
132 | mountpoint -q /squashes/"${img%.squashfs}" || continue; | ||
133 | dirs="$d=$ro${dirs:+:$dirs}" | ||
134 | done < /squashes/filesystem.module | ||
135 | else | ||
136 | for d in /squashes/*; do | ||
137 | mountpoint -q "$d" || continue | ||
138 | dirs="$d=$ro${dirs:+:$dirs}" | ||
139 | done | ||
140 | fi | ||
141 | [ -n "$dirs" ] || | ||
142 | panic "no squashes. missing/broken images on cdrom?" | ||
143 | |||
144 | if true; then | ||
145 | # overlay_tmp=$(mktemp -d /overlay.XXXXXX) && | ||
146 | overlay_tmp=/overlay.$$ && mkdir -p $overlay_tmp && | ||
147 | mount -t tmpfs tmpfs $overlay_tmp && | ||
148 | touch $overlay_tmp/samizdat-filesystem-is-new | ||
149 | dirs="$overlay_tmp:$dirs" || | ||
150 | { rmdir $overlay_tmp; | ||
151 | panic "mountunionroot: failure creating tmpfs overlay"; } | ||
152 | fi | ||
153 | |||
154 | mount -t $ufs -o rw,dirs="$dirs" $ufs "$rootmnt" || | ||
155 | panic "mountunionroot: $ufs: mount (dirs=$dirs): error: $?" | ||
156 | } | ||
157 | insertoverlay() # TODO: copy-up and umount tmpfs. MASSIVELY IMPORTANT! | ||
158 | { | ||
159 | if ! mountpoint -q /overlay; then | ||
160 | # rw-overlay was signalled without a mount on /overlay | ||
161 | # thus, boot with the current tmpfs overlay | ||
162 | mkdir -p /overlay | ||
163 | mount -o move $overlay_tmp /overlay | ||
164 | return 0 | ||
165 | fi | ||
166 | |||
167 | ufs=$(sed -ne 's?^[^ ]* '"$rootmnt"' \(unionfs\|aufs\) .*?\1?p' /proc/mounts) | ||
168 | |||
169 | case $ufs in | ||
170 | unionfs) | ||
171 | panic 'insertoverlay: TODO: implement unionfs support' | ||
172 | |||
173 | mount -o remount,rw,add=/overlay "$rootmnt" || | ||
174 | panic "insertoverlay: remount unionfs (add=/overlay): error: $?" | ||
175 | |||
176 | #mount -o remount,del=$overlay_tmp && # NO, WRONG, COPY-UP FIRST | ||
177 | #umount $overlay_tmp && rmdir $overlay_tmp | ||
178 | ;; | ||
179 | aufs) | ||
180 | mount -o remount,rw,prepend:/overlay=rw "$rootmnt" || | ||
181 | panic "insertoverlay: remount aufs (prepend:/overlay=rw): error: $?" | ||
182 | |||
183 | mount -o remount,mod:"$overlay_tmp"=ro+wh "$rootmnt" || | ||
184 | panic "insertoverlay: couldn't set aufs branch read-only: $overlay_tmp" | ||
185 | |||
186 | # copy everything the user reads (not just writes) to the overlay | ||
187 | # (this is appropriate for CD-ROM but not testing. TODO: enable) | ||
188 | #mount -o remount,coo=all "$rootmnt" | ||
189 | |||
190 | mkdir -p "$rootmnt"/xino && mount -o move "$overlay_tmp" "$rootmnt"/xino || | ||
191 | panic "insertoverlay: couldn't move mount $overlay_tmp to $rootmnt/xino" | ||
192 | ;; | ||
193 | *) panic "insertoverlay: unrecognized filesystem ($ufs)";; | ||
194 | esac | ||
195 | |||
196 | bootdone root-mounted | ||
197 | } | ||
198 | AppendIfNoSuchLine() | ||
199 | { | ||
200 | local filename="$1" | ||
201 | shift | ||
202 | if grep -vqF "$1" < "$filename"; then | ||
203 | printf '%s\n' "$@" >> "$filename" | ||
204 | fi | ||
205 | } | ||
206 | gpg_agent_chroot() | ||
207 | { | ||
208 | chroot "$rootmnt" sh -c \ | ||
209 | 'export PATH=/usr/local/sbin:/usr/local/bin:$PATH; | ||
210 | killall gpg-agent; | ||
211 | samizdat-gpg-agent; | ||
212 | killall -USR2 samizdat-pinentry;' | ||
213 | } | ||
214 | remove_squashfs_mistakes() | ||
215 | { | ||
216 | # Workaround for bad samizdat-generated upstream squashfs: | ||
217 | rm -f "$rootmnt"/etc/ipsec.conf | ||
218 | rm -rf "$rootmnt"/etc/samizdat/samizdat-receive-hooks | ||
219 | rm -f "$rootmnt"/etc/adjtime | ||
220 | } | ||
221 | patchroot_UNUSED() | ||
222 | { | ||
223 | test -e "$rootmnt"/samizdat-filesystem-is-new || return | ||
224 | echo Patching livecd root -- $(date) >> /dev/tty7 | ||
225 | rm -f /dev/console; mknod /dev/console c 4 1 | ||
226 | |||
227 | remove_squashfs_mistakes | ||
228 | |||
229 | if [ -e /etc/adjtime -a ! -e "$rootmnt"/etc/adjtime ]; then | ||
230 | cp /etc/adjtime "$rootmnt"/etc/adjtime | ||
231 | fi | ||
232 | |||
233 | if [ -f "$rootmnt"/cdrom/samizdat/skel.tgz ]; then | ||
234 | chroot "$rootmnt" bin/tar -C / --no-same-owner -zxf /cdrom/samizdat/skel.tgz | ||
235 | fi | ||
236 | chroot "$rootmnt" hostname -F /etc/hostname | ||
237 | |||
238 | chroot "$rootmnt" update-rc.d samizdat-pids start 15 S | ||
239 | |||
240 | # We need debian-tor user so that hidden service directory can have the right owner | ||
241 | chroot "$rootmnt" adduser --quiet --system --disabled-password --home /var/lib/tor \ | ||
242 | --no-create-home --shell /bin/bash --group debian-tor | ||
243 | |||
244 | # TODO: check errors here | ||
245 | chroot "$rootmnt" sh -c \ | ||
246 | 'export PATH=/usr/local/sbin:/usr/local/bin:"$PATH" GNUPGHOME=/gpg/gnupghome verbose=1; | ||
247 | samizdat-receive -v < /cdrom/samizdat/secrets.mime && samizdat-receive -v < /cdrom/samizdat/public.mime' | ||
248 | |||
249 | for diversion in /etc/kernel/postinst.d/initramfs-tools /etc/init.d/live-boot /sbin/halt; do | ||
250 | chroot "$rootmnt" dpkg-divert --rename --package samizdat --add "$diversion" | ||
251 | done | ||
252 | cp /bin/halt.montecarlo "$rootmnt"/sbin/halt | ||
253 | |||
254 | if ! [ -f "$rootmnt"/var/lib/dpkg/info/linux-image-"$(uname -r)".list ]; then | ||
255 | chroot "$rootmnt" sh -c \ | ||
256 | 'dpkg --fsys-tarfile /cdrom/samizdat/debs/linux-image-$(uname -r)_*.deb | tar -C / -x; depmod -a' | ||
257 | fi | ||
258 | |||
259 | # disable some of GRML's many consoles. | ||
260 | # sed -i -e 's/^\([3456789]\|1[012]\):/#\1:/' "$rootmnt"/etc/inittab | ||
261 | # sed -i -e 's/^NUM_CONSOLES=12/NUM_CONSOLES=0/' "$rootmnt"/usr/bin/zsh-login | ||
262 | |||
263 | # these GRML scripts implement a "sendsigs" which does not respect omit.d | ||
264 | sed -i -e 's/^\(l0:.*\)grml-halt$/\1rc 0/' "$rootmnt"/etc/inittab | ||
265 | sed -i -e 's/^\(l6:.*\)grml-reboot$/\1rc 6/' "$rootmnt"/etc/inittab | ||
266 | chroot "$rootmnt" update-rc.d sendsigs stop 20 0 6 | ||
267 | |||
268 | echo Done patching livecd root -- $(date) >>/dev/tty7 | ||
269 | rm "$rootmnt"/samizdat-filesystem-is-new | ||
270 | } | ||
271 | movemounts() | ||
272 | { | ||
273 | # Move mounted filesystems to the root filesystem | ||
274 | while read dev mp rest; do | ||
275 | case "$mp" in | ||
276 | "$rootmnt"|"$rootmnt"/*|/|/proc|/dev|/dev/pts|/sys) continue ;; | ||
277 | /mnt.samizdat.*) | ||
278 | #umount -l "$mp" | ||
279 | target="$rootmnt/media/${dev##*/}" | ||
280 | ;; | ||
281 | /overlay.*) umount -l $mp; continue ;; | ||
282 | *) target="$rootmnt$mp" ;; | ||
283 | esac | ||
284 | mkdir -p "$target" | ||
285 | mount -n -o move "$mp" "$target" | ||
286 | done </proc/mounts | ||
287 | mount --rbind /dev "$rootmnt"/dev | ||
288 | mount --bind /proc "$rootmnt"/proc | ||
289 | ln -sf /proc/mounts "$rootmnt"/etc/mtab | ||
290 | } | ||
291 | launch_init() | ||
292 | { | ||
293 | # bad init= command line? | ||
294 | if [ ! -x "$rootmnt$init" ]; then | ||
295 | panic "init does not exist or is not executable (init=$init)" | ||
296 | fi | ||
297 | ln -sf /proc/mounts "$rootmnt"/etc/mtab | ||
298 | export CONSOLE=/dev/tty1 | ||
299 | exec chroot "$rootmnt" "$init" "$@" <"$rootmnt$CONSOLE" >"$rootmnt$CONSOLE" 2>&1 | ||
300 | panic "exec init failed (init=$init)" | ||
301 | # exec run-init -c "$CONSOLE" "$rootmnt" "$init" "$@" | ||
302 | # panic "exec run-init failed (init=$init)" | ||
303 | } | ||
304 | start_udev() | ||
305 | { | ||
306 | echo > /proc/sys/kernel/hotplug | ||
307 | mkdir -p /dev/.udev/db/ /dev/.udev/queue/ | ||
308 | # mkdir -p "$LOGBASE"; sh -c "udevd --resolve-names=never --debug >$LOGBASE/udevd."'$$'".log 2>&1" & | ||
309 | udevd --resolve-names=never --daemon | ||
310 | udevadm trigger --action=add | ||
311 | # udevadm settle | ||
312 | } | ||
313 | stop_udev() | ||
314 | { | ||
315 | for proc in /proc/[0-9]*; do | ||
316 | [ -x $proc/exe ] || continue | ||
317 | [ "$(readlink $proc/exe)" = /sbin/udevd ] && kill ${proc#/proc/} | ||
318 | done | ||
319 | # ignore any failed event because the init script will trigger again all events | ||
320 | nuke /dev/.udev/queue/ | ||
321 | } | ||
322 | killeverything() | ||
323 | { | ||
324 | # TODO: exempt: interactive shell(s) (AND CHILDREN) (or: anything with | ||
325 | # a tty?), samizdat-agent, fsck(!!), ...? | ||
326 | |||
327 | # exempt_cmdline="$(printf "sh\0-i\0")" | ||
328 | force= | ||
329 | while true; do | ||
330 | killme= | ||
331 | for proc in /proc/[0-9]*; do | ||
332 | [ $proc != /proc/1 -a $proc != /proc/$$ -a -x $proc/exe ] || continue | ||
333 | # [ "$(cat $proc/cmdline)" != "$exempt_cmdline" ] || continue | ||
334 | read pid tcomm state ppid pgrp sid tty_nr tty_pgrp rest < $proc/stat | ||
335 | [ $tty_nr = 0 ] || continue | ||
336 | killme="$killme ${proc#/proc/}" | ||
337 | done | ||
338 | if [ -n "$killme" ]; then | ||
339 | kill $force $killme | ||
340 | else | ||
341 | break | ||
342 | fi | ||
343 | force=-KILL | ||
344 | done | ||
345 | } | ||