summaryrefslogtreecommitdiff
path: root/daemons/runsystem.hurd
blob: f4f2771106c3dd991c943560e00c16e87b21f1b6 (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
#!/bin/bash
#
# This program is run by /hurd/init at boot time after the essential
# servers are up, and is responsible for running the "userland" parts of a
# normal system.  This includes running the single-user shell as well as a
# multi-user system.  This program is expected never to exit.
#


###
### Where to find programs, etc.
###

PATH=/bin:/sbin
export PATH

umask 022

# If we lose badly, try to exec each of these in turn.
fallback_shells='/bin/sh /bin/bash /bin/csh /bin/ash /bin/shd'

# Shell used for normal single-user startup.
SHELL=/bin/sh

# Programs that do multi-user startup.
RUNCOM=/libexec/rc
RUNTTYS=/libexec/runttys
# Signals that we should pass down to runttys.
runttys_sigs='TERM INT HUP TSTP'

###


# If we get a SIGLOST, attempt to reopen the console in case
# our console ports were revoked.  This lets us print messages.
function reopen_console ()
{
  exec 1>/dev/console 2>&1 || exit 3
}
trap 'reopen_console' SIGLOST


# Call this when we are losing badly enough that we want to punt normal
# startup entirely.  We exec a single-user shell, so we will not come back
# here.  The only way to get to multi-user from that shell will be
# explicitly exec this script or something like that.
function singleuser ()
{
  test $# -eq 0 || echo "$0: $*"
  for try in ${fallback_shells}; do
    SHELL=${try}
    exec ${SHELL}
  done
  exit 127
}


# See whether pflocal is set up already, and do so if not (install case)
#
# Normally this should be the case, but we better make sure since
# without the pflocal server, pipe(2) does not work.
if ! test -e /servers/socket/1 ; then
  # The root filesystem should be read-only at this point.
  if fsysopts / --update --writable ; then
    settrans -c /servers/socket/1 /hurd/pflocal
  else
    singleuser "Failed to create /servers/socket/1."
  fi
fi

# We expect to be started by console-run, which gives us no arguments and
# puts FALLBACK_CONSOLE=file-name in the environment if our console is
# other than a normal /dev/console.

if [ "${FALLBACK_CONSOLE+set}" = set ]; then
  singleuser "Running on fallback console ${FALLBACK_CONSOLE}"
fi


###
### Normal startup procedures
###

# Parse the multiboot command line.  We only pay attention to -s and -f.
# The first argument is the kernel file name; skip that.
shift
flags=
while [ $# -gt 0 ]; do
  arg="$1"
  shift
  case "$arg" in
  --*) ;;
  *=*) ;;
  -*)
    flags="${flags}${arg#-}"
    ;;
  'single'|'emergency') # Linux compat
    flags="${flags}s"
    ;;
  'fastboot')
    flags="${flags}f"
    ;;
  esac
done

# Check boot flags.
case "$flags" in
*s*)
  rc=false			# force single-user
  ;;
*f*)
  rc="${RUNCOM}"		# fastboot
  ;;
*)
  rc="${RUNCOM} autoboot"	# multi-user default
  ;;
esac

# Large infinite loop.  If this script ever exits, init considers that
# a serious bogosity and punts to a fallback single-user shell.
# We handle here the normal transitions between single-user and multi-user.
while : ; do

  # Run the rc script.  As long as it exits nonzero, punt to single-user.
  # After the single-user shell exits, we will start over attempting to
  # run rc; but later invocations strip the `autoboot' argument.
  until $rc; do
    rc=${RUNCOM}

    # Run single-user shell and repeat as long as it dies with a signal.
    until ${SHELL} || test $? -lt 128; do
      :
    done
  done

  # Now we are officially ready for normal multi-user operation.

  # Trap certain signals and send them on to runttys.  For this to work, we
  # must run it asynchronously and wait for it with the `wait' built-in.
  runttys_pid=0
  for sig in $runttys_sigs; do
    trap "kill -$sig \${runttys_pid}" $sig
  done

  # This program reads /etc/ttys and starts the programs it says to.
  ${RUNTTYS} &
  runttys_pid=$!

  # Wait for runttys to die, meanwhile handling trapped signals.
  wait

  # Go back to the top of the infinite loop, as if booting single-user.
  rc=false

done