summaryrefslogtreecommitdiff
path: root/old-school/init.functions
blob: 3b5027b8ba3f3783556442a45847df40fd4feddd (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
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
#!/bin/sh
. common.sh
mountvirt()
{
  # TODO: simply put these dirs on the initrd itself
  mkdir -m 0755 -p /dev /sys /proc /tmp /var /run
  mkdir -m 0700 -p /root

  mount -t sysfs -o nodev,noexec,nosuid none /sys 
  mount -t proc  -o nodev,noexec,nosuid none /proc 
  tmpfs_size="10M"
# [ -f /etc/udev/udev.conf ] && . /etc/udev/udev.conf
  mount -t tmpfs -o size=$tmpfs_size,mode=0755 udev /dev
  mount -t tmpfs -o size=64M,mode=0755 run /run
  mkdir -m 0755 /dev/pts /run/lock
  mount -t devpts devpts /dev/pts
  ln -s /run /run/lock /var/
}
makedev()
{
  # TODO: simply put these nodes on the initrd itself
  mkdir -m 0755 -p /dev
  mknod /dev/null    c 1 3
  mknod /dev/zero    c 1 5
  mknod /dev/tty     c 5 0
  if [ "$FUCK_devconsole" ]; then # FUCK /dev/console
    mknod /dev/console c 4 1 # tty1 is console; a saner alternative (TODO: fix shutdown to chvt)
  else
    mknod /dev/console c 5 1
  fi
  for i in 0 1 2 3 4 5 6 7 8; do
    mknod /dev/tty${i} c 4 ${i}
  done
  # TODO: wait for udev?  pft.
  for i in 0 1 2 3 4 5 6 7; do
    mknod /dev/loop${i} b 7 ${i}
  done
}
loadenv()
{
  # TODO: filter the wheat from the chaff here; most of this is unused.
  # TODO: implement the various boot args

  # Load config files
# export DPKG_ARCH=
# . /conf/arch.conf
# export ROOT=
# . /conf/initramfs.conf
# for conf in conf/conf.d/*; do
#   [ -f ${conf} ] && . ${conf}
# done
  # Make modprobe quiet
  export MODPROBE_OPTIONS="-qb"
  # Export constants
  export rootmnt=/root
  # Export bootparam variables
  export init=/sbin/init
  export readonly=y
  export blacklist=

  # Parse command line options
  for x in $(cat /proc/cmdline); do
    case $x in
      init=*) init=${x#init=} ;;
      root=*)
	ROOT=${x#root=}
	case $ROOT in
	  LABEL=*) ROOT="/dev/disk/by-label/${ROOT#LABEL=}" ;;
	  UUID=*) ROOT="/dev/disk/by-uuid/${ROOT#UUID=}" ;;
	  /dev/nfs) [ -z "${BOOT}" ] && BOOT=nfs ;;
	esac
      ;;
      rootflags=*) ROOTFLAGS="-o ${x#rootflags=}" ;;
      rootfstype=*) ROOTFSTYPE="${x#rootfstype=}" ;;
      ro) readonly=y ;;
      rw) readonly=n ;;

      nfsroot=*) NFSROOT="${x#nfsroot=}" ;;
      ip=*) IPOPTS="${x#ip=}" ;;
      boot=*) BOOT=${x#boot=} ;;

      resume=*) RESUME="${x#resume=}" ;;
      noresume) noresume=y ;;
      blacklist=*) blacklist=${x#blacklist=} ;;

      hostname=*)
	hostname=${x#hostname=}
	hostname "$hostname"
      ;;
      bootcd_device=*) bootcd_device=${x#bootcd_device=}
	mkdir -p /cdrom &&
	mount -r -t hostfs -o "${bootcd_device#hostfs=}" hostfs /cdrom &&
	bootdone samizdat-cdrom
      ;;
      overlay_device=*) overlay_device=${x#overlay_device=}
	mkdir -p /overlay &&
	mount -t hostfs -o "${overlay_device#hostfs=}" hostfs /overlay &&
	bootdone rw-overlay
      ;;
      uml_modules=*) uml_modules=${x#uml_modules=}
	mount -t hostfs -o "${uml_modules#hostfs=}" hostfs /lib/modules ;;
    esac
  done

  if [ -z "${noresume}" ]; then
    export resume=${RESUME}
  else
    export noresume
  fi
}
mountunionroot()
{
  bootwait samizdat-cdrom squashfs-root

  ufs=
  if grep -q aufs /proc/filesystems || modprobe aufs; then
    ufs=aufs
  elif grep -q unionfs /proc/filesystems || modprobe unionfs; then
    ufs=unionfs
  fi

  case $ufs in
    unionfs) ro=ro;;
    aufs) ro=rr;;
    *) panic "mountunionroot: unionfs module not found";;
  esac

  dirs=;
  if [ -f /squashes/filesystem.module ]; then
    while read img; do
      d=/squashes/"${img%.squashfs}" 
      mountpoint -q /squashes/"${img%.squashfs}" || continue;
      dirs="$d=$ro${dirs:+:$dirs}"
    done < /squashes/filesystem.module
  else
    for d in /squashes/*; do
      mountpoint -q "$d" || continue
      dirs="$d=$ro${dirs:+:$dirs}"
    done
  fi
  [ -n "$dirs" ] ||
    panic "no squashes.  missing/broken images on cdrom?"

  if true; then
#   overlay_tmp=$(mktemp -d /overlay.XXXXXX) &&
    overlay_tmp=/overlay.$$ && mkdir -p $overlay_tmp &&
    mount -t tmpfs tmpfs $overlay_tmp &&
    touch $overlay_tmp/samizdat-filesystem-is-new
    dirs="$overlay_tmp:$dirs" ||
    { rmdir $overlay_tmp;
      panic "mountunionroot: failure creating tmpfs overlay"; }
  fi

  mount -t $ufs -o rw,dirs="$dirs" $ufs "$rootmnt" ||
    panic "mountunionroot: $ufs: mount (dirs=$dirs): error: $?"
}
insertoverlay() # TODO: copy-up and umount tmpfs.  MASSIVELY IMPORTANT!
{
  if ! mountpoint -q /overlay; then
    # rw-overlay was signalled without a mount on /overlay
    # thus, boot with the current tmpfs overlay
    mkdir -p /overlay
    mount -o move $overlay_tmp /overlay
    return 0
  fi

  ufs=$(sed -ne 's?^[^ ]* '"$rootmnt"' \(unionfs\|aufs\) .*?\1?p' /proc/mounts)

  case $ufs in
    unionfs)
      panic 'insertoverlay: TODO: implement unionfs support'

      mount -o remount,rw,add=/overlay "$rootmnt" ||
      panic "insertoverlay: remount unionfs (add=/overlay): error: $?"

      #mount -o remount,del=$overlay_tmp && # NO, WRONG, COPY-UP FIRST
      #umount $overlay_tmp && rmdir $overlay_tmp
      ;;
    aufs)
      mount -o remount,rw,prepend:/overlay=rw "$rootmnt" ||
        panic "insertoverlay: remount aufs (prepend:/overlay=rw): error: $?"

      mount -o remount,mod:"$overlay_tmp"=ro+wh "$rootmnt" ||
        panic "insertoverlay: couldn't set aufs branch read-only: $overlay_tmp"

      # copy everything the user reads (not just writes) to the overlay
      # (this is appropriate for CD-ROM but not testing.  TODO: enable)
      #mount -o remount,coo=all "$rootmnt"

      mkdir -p "$rootmnt"/xino && mount -o move "$overlay_tmp" "$rootmnt"/xino ||
        panic "insertoverlay: couldn't move mount $overlay_tmp to $rootmnt/xino"
      ;;
    *) panic "insertoverlay: unrecognized filesystem ($ufs)";;
  esac

  bootdone root-mounted
}
AppendIfNoSuchLine()
{
  local filename="$1"
  shift
  if grep -vqF "$1" < "$filename"; then 
    printf '%s\n' "$@" >> "$filename"
  fi
}
gpg_agent_chroot()
{
  chroot "$rootmnt" sh -c \
    'export PATH=/usr/local/sbin:/usr/local/bin:$PATH;
     killall gpg-agent;
     samizdat-gpg-agent;
     killall -USR2 samizdat-pinentry;'
}
remove_squashfs_mistakes()
{
  # Workaround for bad samizdat-generated upstream squashfs:
  rm -f "$rootmnt"/etc/ipsec.conf
  rm -rf "$rootmnt"/etc/samizdat/samizdat-receive-hooks
  rm -f "$rootmnt"/etc/adjtime
}
patchroot()
{
  test -e "$rootmnt"/samizdat-filesystem-is-new || return
  echo Patching livecd root -- $(date) >> /dev/tty7
  rm -f /dev/console; mknod /dev/console c 4 1

  remove_squashfs_mistakes

  if [ -e /etc/adjtime -a ! -e "$rootmnt"/etc/adjtime ]; then
    cp /etc/adjtime "$rootmnt"/etc/adjtime
  fi

  if [ -f "$rootmnt"/cdrom/samizdat/skel.tgz ]; then
    chroot "$rootmnt" bin/tar -C / --no-same-owner -zxf /cdrom/samizdat/skel.tgz
  fi
  chroot "$rootmnt" hostname -F /etc/hostname

  chroot "$rootmnt" update-rc.d samizdat-pids start 15 S

  # We need debian-tor user so that hidden service directory can have the right owner
  chroot "$rootmnt" adduser --quiet --system --disabled-password  --home /var/lib/tor \
                --no-create-home --shell /bin/bash  --group  debian-tor

  # TODO: check errors here
  chroot "$rootmnt" sh -c \
    'export PATH=/usr/local/sbin:/usr/local/bin:"$PATH" GNUPGHOME=/gpg/gnupghome verbose=1;
     samizdat-receive -v < /cdrom/samizdat/secrets.mime && samizdat-receive -v < /cdrom/samizdat/public.mime'

  for diversion in /etc/kernel/postinst.d/initramfs-tools /etc/init.d/live-boot /sbin/halt; do
    chroot "$rootmnt" dpkg-divert --rename --package samizdat --add "$diversion"
  done
  cp /bin/halt.montecarlo "$rootmnt"/sbin/halt

  if ! [ -f "$rootmnt"/var/lib/dpkg/info/linux-image-"$(uname -r)".list ]; then
    chroot "$rootmnt" sh -c \
      'dpkg --fsys-tarfile /cdrom/samizdat/debs/linux-image-$(uname -r)_*.deb | tar -C / -x; depmod -a'
  fi

  # disable some of GRML's many consoles.
# sed -i -e 's/^\([3456789]\|1[012]\):/#\1:/' "$rootmnt"/etc/inittab
# sed -i -e 's/^NUM_CONSOLES=12/NUM_CONSOLES=0/' "$rootmnt"/usr/bin/zsh-login

  # these GRML scripts implement a "sendsigs" which does not respect omit.d
  sed -i -e 's/^\(l0:.*\)grml-halt$/\1rc 0/' "$rootmnt"/etc/inittab
  sed -i -e 's/^\(l6:.*\)grml-reboot$/\1rc 6/' "$rootmnt"/etc/inittab
  chroot "$rootmnt" update-rc.d sendsigs stop 20 0 6

  echo Done patching livecd root -- $(date) >>/dev/tty7
  rm "$rootmnt"/samizdat-filesystem-is-new
}
movemounts()
{
  # Move mounted filesystems to the root filesystem
  while read dev mp rest; do
    case "$mp" in
      "$rootmnt"|"$rootmnt"/*|/|/proc|/dev|/dev/pts|/sys) continue ;;
      /mnt.samizdat.*)
        #umount -l "$mp"
	target="$rootmnt/media/${dev##*/}"
      ;;
      /overlay.*) umount -l $mp; continue ;;
      *) target="$rootmnt$mp" ;;
    esac
    mkdir -p "$target"
    mount -n -o move "$mp" "$target"
  done </proc/mounts
  mount --rbind /dev "$rootmnt"/dev
  mount --bind /proc "$rootmnt"/proc
  ln -sf /proc/mounts "$rootmnt"/etc/mtab
}
launch_init()
{
  # bad init= command line?
  if [ ! -x "$rootmnt$init" ]; then
    panic "init does not exist or is not executable (init=$init)"
  fi
  ln -sf /proc/mounts "$rootmnt"/etc/mtab
  export CONSOLE=/dev/tty1
  exec chroot "$rootmnt" "$init" "$@" <"$rootmnt$CONSOLE" >"$rootmnt$CONSOLE" 2>&1
  panic "exec init failed (init=$init)"
# exec run-init -c "$CONSOLE" "$rootmnt" "$init" "$@"
# panic "exec run-init failed (init=$init)"
}
start_udev()
{
  echo > /proc/sys/kernel/hotplug
  mkdir -p /dev/.udev/db/ /dev/.udev/queue/
# mkdir -p "$LOGBASE"; sh -c "udevd --resolve-names=never --debug >$LOGBASE/udevd."'$$'".log 2>&1" &
  udevd --resolve-names=never --daemon
  udevadm trigger --action=add
# udevadm settle
}
stop_udev()
{
  for proc in /proc/[0-9]*; do
    [ -x $proc/exe ] || continue
    [ "$(readlink $proc/exe)" = /sbin/udevd ] && kill ${proc#/proc/}
  done
  # ignore any failed event because the init script will trigger again all events
  nuke /dev/.udev/queue/
}
killeverything()
{
  # TODO: exempt: interactive shell(s) (AND CHILDREN) (or: anything with
  # a tty?), samizdat-agent, fsck(!!), ...?

# exempt_cmdline="$(printf "sh\0-i\0")"
  force=
  while true; do
    killme=
    for proc in /proc/[0-9]*; do
      [ $proc != /proc/1 -a $proc != /proc/$$ -a -x $proc/exe ] || continue
#     [ "$(cat $proc/cmdline)" != "$exempt_cmdline" ] || continue
      read pid tcomm state ppid pgrp sid tty_nr tty_pgrp rest < $proc/stat
      [ $tty_nr = 0 ] || continue
      killme="$killme ${proc#/proc/}"
    done
    if [ -n "$killme" ]; then
      kill $force $killme
    else
      break
    fi
    force=-KILL
  done
}