1*325ce30bSDavid van Moolenbroek#!/bin/sh 2*325ce30bSDavid van Moolenbroek# 3*325ce30bSDavid van Moolenbroek# $NetBSD: rc,v 1.170 2014/07/29 20:39:16 apb Exp $ 4*325ce30bSDavid van Moolenbroek# 5*325ce30bSDavid van Moolenbroek# rc -- 6*325ce30bSDavid van Moolenbroek# Run the scripts in /etc/rc.d with rcorder, and log output 7*325ce30bSDavid van Moolenbroek# to /var/run/rc.log. 89865aeaaSBen Gras 9*325ce30bSDavid van Moolenbroek# System startup script run by init(8) on autoboot or after single-user. 10*325ce30bSDavid van Moolenbroek# Output and error are redirected to console by init, and the console 11*325ce30bSDavid van Moolenbroek# is the controlling terminal. 12a7a79fa1SJean-Baptiste Boric 13*325ce30bSDavid van Moolenbroekexport HOME=/ 14*325ce30bSDavid van Moolenbroekexport PATH=/sbin:/bin:/usr/sbin:/usr/bin 159865aeaaSBen Grasumask 022 16a5f47c23SLionel Sambuc 17*325ce30bSDavid van Moolenbroekif [ -e ./rc.subr ] ; then 18*325ce30bSDavid van Moolenbroek . ./rc.subr # for testing 19*325ce30bSDavid van Moolenbroekelse 20*325ce30bSDavid van Moolenbroek . /etc/rc.subr 213de6a807SCristiano Giuffridafi 22*325ce30bSDavid van Moolenbroek. /etc/rc.conf 23*325ce30bSDavid van Moolenbroek_rc_conf_loaded=true 2474711a3bSJorrit Herder 25*325ce30bSDavid van Moolenbroek: ${RC_LOG_FILE:="/var/run/rc.log"} 2674711a3bSJorrit Herder 27*325ce30bSDavid van Moolenbroek# rc.subr redefines echo and printf. Undo that here. 28*325ce30bSDavid van Moolenbroekunset echo ; unalias echo 29*325ce30bSDavid van Moolenbroekunset printf ; unalias printf 303de6a807SCristiano Giuffrida 31*325ce30bSDavid van Moolenbroekif ! checkyesno rc_configured; then 32*325ce30bSDavid van Moolenbroek echo "/etc/rc.conf is not configured. Multiuser boot aborted." 33*325ce30bSDavid van Moolenbroek exit 1 34a06e2ab3SBen Grasfi 358edaaa30SLionel Sambuc 36*325ce30bSDavid van Moolenbroekif [ "$1" = autoboot ]; then 37*325ce30bSDavid van Moolenbroek autoboot=yes 38*325ce30bSDavid van Moolenbroek rc_fast=yes # run_rc_command(): do fast booting 398edaaa30SLionel Sambucfi 403de6a807SCristiano Giuffrida 41*325ce30bSDavid van Moolenbroek# 42*325ce30bSDavid van Moolenbroek# Completely ignore INT and QUIT at the outer level. The rc_real_work() 43*325ce30bSDavid van Moolenbroek# function should do something different. 44*325ce30bSDavid van Moolenbroek# 45*325ce30bSDavid van Moolenbroektrap '' INT QUIT 46*325ce30bSDavid van Moolenbroek 47*325ce30bSDavid van Moolenbroek# 48*325ce30bSDavid van Moolenbroek# This string will be used to mark lines of meta-data sent over the pipe 49*325ce30bSDavid van Moolenbroek# from the rc_real_work() function to the rc_postprocess() function. Lines 50*325ce30bSDavid van Moolenbroek# not so marked are assumed to be output from rc.d scripts. 51*325ce30bSDavid van Moolenbroek# 52*325ce30bSDavid van Moolenbroek# This string is long and unique to ensure that it does not accidentally 53*325ce30bSDavid van Moolenbroek# appear in output from any rc.d script. It must not contain any 54*325ce30bSDavid van Moolenbroek# characters that are special to glob expansion ('*', '?', '[', or ']'). 55*325ce30bSDavid van Moolenbroek# 56*325ce30bSDavid van Moolenbroekrc_metadata_prefix="$0:$$:metadata:"; 57*325ce30bSDavid van Moolenbroek 58*325ce30bSDavid van Moolenbroek# Child scripts may sometimes want to print directly to the original 59*325ce30bSDavid van Moolenbroek# stdout and stderr, bypassing the pipe to the postprocessor. These 60*325ce30bSDavid van Moolenbroek# _rc_*_fd variables are private, shared with /etc/rc.subr, but not 61*325ce30bSDavid van Moolenbroek# intended to be used directly by child scripts. (Child scripts 62*325ce30bSDavid van Moolenbroek# may use rc.subr's no_rc_postprocess function.) 63*325ce30bSDavid van Moolenbroek# 64*325ce30bSDavid van Moolenbroek_rc_original_stdout_fd=7; export _rc_original_stdout_fd 65*325ce30bSDavid van Moolenbroek_rc_original_stderr_fd=8; export _rc_original_stderr_fd 66*325ce30bSDavid van Moolenbroekeval "exec ${_rc_original_stdout_fd}>&1" 67*325ce30bSDavid van Moolenbroekeval "exec ${_rc_original_stderr_fd}>&2" 68*325ce30bSDavid van Moolenbroek 69*325ce30bSDavid van Moolenbroek# 70*325ce30bSDavid van Moolenbroek# rc_real_work 71*325ce30bSDavid van Moolenbroek# Do the real work. Output from this function will be piped into 72*325ce30bSDavid van Moolenbroek# rc_postprocess(), and some of the output will be marked as 73*325ce30bSDavid van Moolenbroek# metadata. 74*325ce30bSDavid van Moolenbroek# 75*325ce30bSDavid van Moolenbroek# The body of this function is defined using (...), not {...}, to force 76*325ce30bSDavid van Moolenbroek# it to run in a subshell. 77*325ce30bSDavid van Moolenbroek# 78*325ce30bSDavid van Moolenbroekrc_real_work() 79*325ce30bSDavid van Moolenbroek( 80*325ce30bSDavid van Moolenbroek stty status '^T' 81*325ce30bSDavid van Moolenbroek 82*325ce30bSDavid van Moolenbroek # print_rc_metadata() wants to be able to print to the pipe 83*325ce30bSDavid van Moolenbroek # that goes to our postprocessor, even if its in a context 84*325ce30bSDavid van Moolenbroek # with redirected output. 85*325ce30bSDavid van Moolenbroek # 86*325ce30bSDavid van Moolenbroek _rc_postprocessor_fd=9 ; export _rc_postprocessor_fd 87*325ce30bSDavid van Moolenbroek _rc_pid=$$ ; export _rc_pid 88*325ce30bSDavid van Moolenbroek eval "exec ${_rc_postprocessor_fd}>&1" 89*325ce30bSDavid van Moolenbroek 90*325ce30bSDavid van Moolenbroek # Print a metadata line when we exit 91*325ce30bSDavid van Moolenbroek # 92*325ce30bSDavid van Moolenbroek trap 'es=$?; print_rc_metadata "exit:$es"; trap "" 0; exit $es' 0 93*325ce30bSDavid van Moolenbroek 94*325ce30bSDavid van Moolenbroek # Set shell to ignore SIGINT, but children will not ignore it. 95*325ce30bSDavid van Moolenbroek # Shell catches SIGQUIT and returns to single user. 96*325ce30bSDavid van Moolenbroek # 97*325ce30bSDavid van Moolenbroek trap : INT 98*325ce30bSDavid van Moolenbroek trap '_msg="Boot interrupted at $(date)"; 99*325ce30bSDavid van Moolenbroek print_rc_metadata "interrupted:${_msg}"; 100*325ce30bSDavid van Moolenbroek exit 1' QUIT 101*325ce30bSDavid van Moolenbroek 102*325ce30bSDavid van Moolenbroek print_rc_metadata "start:$(date)" 103*325ce30bSDavid van Moolenbroek 104*325ce30bSDavid van Moolenbroek # 105*325ce30bSDavid van Moolenbroek # The stop_boot() function in rc.subr may kill $RC_PID. We want 106*325ce30bSDavid van Moolenbroek # it to kill the subshell running this rc_real_work() function, 107*325ce30bSDavid van Moolenbroek # rather than killing the parent shell, because we want the 108*325ce30bSDavid van Moolenbroek # rc_postprocess() function to be able to log the error 109*325ce30bSDavid van Moolenbroek # without being killed itself. 110*325ce30bSDavid van Moolenbroek # 111*325ce30bSDavid van Moolenbroek # "$$" is the pid of the top-level shell, not the pid of the 112*325ce30bSDavid van Moolenbroek # subshell that's executing this function. The command below 113*325ce30bSDavid van Moolenbroek # tentatively assumes that the parent of the "/bin/sh -c ..." 114*325ce30bSDavid van Moolenbroek # process will be the current subshell, and then uses "kill -0 115*325ce30bSDavid van Moolenbroek # ..." to check the result. If the "/bin/sh -c ..." process 116*325ce30bSDavid van Moolenbroek # fails, or returns the pid of an ephemeral process that exits 117*325ce30bSDavid van Moolenbroek # before the "kill" command, then we fall back to using "$$". 118*325ce30bSDavid van Moolenbroek # 119*325ce30bSDavid van Moolenbroek RC_PID=$(/bin/sh -c 'ps -p $$ -o ppid=') || RC_PID=$$ 120*325ce30bSDavid van Moolenbroek kill -0 $RC_PID >/dev/null 2>&1 || RC_PID=$$ 121*325ce30bSDavid van Moolenbroek 122*325ce30bSDavid van Moolenbroek # 123*325ce30bSDavid van Moolenbroek # As long as process $RC_PID is still running, send a "nop" 124*325ce30bSDavid van Moolenbroek # metadata message to the postprocessor every few seconds. 125*325ce30bSDavid van Moolenbroek # This should help flush partial lines that may appear when 126*325ce30bSDavid van Moolenbroek # rc.d scripts that are NOT marked with "KEYWORD: interactive" 127*325ce30bSDavid van Moolenbroek # nevertheless attempt to print prompts and wait for input. 128*325ce30bSDavid van Moolenbroek # 129*325ce30bSDavid van Moolenbroek ( 130*325ce30bSDavid van Moolenbroek # First detach from tty, to avoid intercepting SIGINFO. 131*325ce30bSDavid van Moolenbroek eval "exec ${_rc_original_stdout_fd}<&-" 132*325ce30bSDavid van Moolenbroek eval "exec ${_rc_original_stderr_fd}<&-" 133*325ce30bSDavid van Moolenbroek exec </dev/null >/dev/null 2>&1 134*325ce30bSDavid van Moolenbroek while kill -0 $RC_PID ; do 135*325ce30bSDavid van Moolenbroek print_rc_metadata "nop" 136*325ce30bSDavid van Moolenbroek sleep 3 137*325ce30bSDavid van Moolenbroek done 138*325ce30bSDavid van Moolenbroek ) & 139*325ce30bSDavid van Moolenbroek 140*325ce30bSDavid van Moolenbroek # 141*325ce30bSDavid van Moolenbroek # Get a list of all rc.d scripts, and use rcorder to choose 142*325ce30bSDavid van Moolenbroek # what order to execute them. 143*325ce30bSDavid van Moolenbroek # 144*325ce30bSDavid van Moolenbroek # For testing, allow RC_FILES_OVERRIDE from the environment to 145*325ce30bSDavid van Moolenbroek # override this. 146*325ce30bSDavid van Moolenbroek # 147*325ce30bSDavid van Moolenbroek print_rc_metadata "cmd-name:rcorder" 148*325ce30bSDavid van Moolenbroek scripts=$(for rcd in ${rc_directories:-/etc/rc.d}; do 149*325ce30bSDavid van Moolenbroek test -d ${rcd} && echo ${rcd}/*; 150*325ce30bSDavid van Moolenbroek done) 151*325ce30bSDavid van Moolenbroek files=$(rcorder -s nostart ${rc_rcorder_flags} ${scripts}) 152*325ce30bSDavid van Moolenbroek print_rc_metadata "cmd-status:rcorder:$?" 153*325ce30bSDavid van Moolenbroek 154*325ce30bSDavid van Moolenbroek if [ -n "${RC_FILES_OVERRIDE}" ]; then 155*325ce30bSDavid van Moolenbroek files="${RC_FILES_OVERRIDE}" 156*325ce30bSDavid van Moolenbroek fi 157*325ce30bSDavid van Moolenbroek 158*325ce30bSDavid van Moolenbroek # 159*325ce30bSDavid van Moolenbroek # Run the scripts in order. 160*325ce30bSDavid van Moolenbroek # 161*325ce30bSDavid van Moolenbroek for _rc_elem in $files; do 162*325ce30bSDavid van Moolenbroek print_rc_metadata "cmd-name:$_rc_elem" 163*325ce30bSDavid van Moolenbroek run_rc_script $_rc_elem start 164*325ce30bSDavid van Moolenbroek print_rc_metadata "cmd-status:$_rc_elem:$?" 165*325ce30bSDavid van Moolenbroek done 166*325ce30bSDavid van Moolenbroek 167*325ce30bSDavid van Moolenbroek print_rc_metadata "end:$(date)" 168*325ce30bSDavid van Moolenbroek exit 0 169*325ce30bSDavid van Moolenbroek) 170*325ce30bSDavid van Moolenbroek 171*325ce30bSDavid van Moolenbroek# 172*325ce30bSDavid van Moolenbroek# rc_postprocess 173*325ce30bSDavid van Moolenbroek# Post-process the output from the rc_real_work() function. For 174*325ce30bSDavid van Moolenbroek# each line of input, we have to decide whether to print the line 175*325ce30bSDavid van Moolenbroek# to the console, print a twiddle on the console, print a line to 176*325ce30bSDavid van Moolenbroek# the log, or some combination of these. 177*325ce30bSDavid van Moolenbroek# 178*325ce30bSDavid van Moolenbroek# If rc_silent is true, then suppress most output, instead running 179*325ce30bSDavid van Moolenbroek# rc_silent_cmd (typically "twiddle") for each line. 180*325ce30bSDavid van Moolenbroek# 181*325ce30bSDavid van Moolenbroek# The body of this function is defined using (...), not {...}, to force 182*325ce30bSDavid van Moolenbroek# it to run in a subshell. 183*325ce30bSDavid van Moolenbroek# 184*325ce30bSDavid van Moolenbroek# We have to deal with the following constraints: 185*325ce30bSDavid van Moolenbroek# 186*325ce30bSDavid van Moolenbroek# * There may be no writable file systems early in the boot, so 187*325ce30bSDavid van Moolenbroek# any use of temporary files would be problematic. 188*325ce30bSDavid van Moolenbroek# 189*325ce30bSDavid van Moolenbroek# * Scripts run during the boot may clear /tmp and/var/run, so even 190*325ce30bSDavid van Moolenbroek# if they are writable, using those directories too early may be 191*325ce30bSDavid van Moolenbroek# problematic. We assume that it's safe to write to our log file 192*325ce30bSDavid van Moolenbroek# after the mountcritlocal script has run. 193*325ce30bSDavid van Moolenbroek# 194*325ce30bSDavid van Moolenbroek# * /usr/bin/tee cannot be used because the /usr file system may not 195*325ce30bSDavid van Moolenbroek# be mounted early in the boot. 196*325ce30bSDavid van Moolenbroek# 197*325ce30bSDavid van Moolenbroek# * All calls to the rc_log_message and rc_log_flush functions must be 198*325ce30bSDavid van Moolenbroek# from the same subshell, otherwise the use of a shell variable to 199*325ce30bSDavid van Moolenbroek# buffer log messages will fail. 200*325ce30bSDavid van Moolenbroek# 201*325ce30bSDavid van Moolenbroekrc_postprocess() 202*325ce30bSDavid van Moolenbroek( 203*325ce30bSDavid van Moolenbroek local line 204*325ce30bSDavid van Moolenbroek local before after 205*325ce30bSDavid van Moolenbroek local IFS='' 206*325ce30bSDavid van Moolenbroek 207*325ce30bSDavid van Moolenbroek # Try quite hard to flush the log to disk when we exit. 208*325ce30bSDavid van Moolenbroek trap 'es=$?; rc_log_flush FORCE; trap "" 0; exit $es' 0 209*325ce30bSDavid van Moolenbroek 210*325ce30bSDavid van Moolenbroek yesno_to_truefalse rc_silent 2>/dev/null 211*325ce30bSDavid van Moolenbroek 212*325ce30bSDavid van Moolenbroek while read -r line ; do 213*325ce30bSDavid van Moolenbroek case "$line" in 214*325ce30bSDavid van Moolenbroek "${rc_metadata_prefix}"*) 215*325ce30bSDavid van Moolenbroek after="${line#*"${rc_metadata_prefix}"}" 216*325ce30bSDavid van Moolenbroek rc_postprocess_metadata "${after}" 217*325ce30bSDavid van Moolenbroek ;; 218*325ce30bSDavid van Moolenbroek *"${rc_metadata_prefix}"*) 219*325ce30bSDavid van Moolenbroek # magic string is present, but not at the start of 220*325ce30bSDavid van Moolenbroek # the line. Treat it as a partial line of 221*325ce30bSDavid van Moolenbroek # ordinary data, followed by a line of metadata. 222*325ce30bSDavid van Moolenbroek before="${line%"${rc_metadata_prefix}"*}" 223*325ce30bSDavid van Moolenbroek rc_postprocess_partial_line "${before}" 224*325ce30bSDavid van Moolenbroek after="${line#*"${rc_metadata_prefix}"}" 225*325ce30bSDavid van Moolenbroek rc_postprocess_metadata "${after}" 226*325ce30bSDavid van Moolenbroek ;; 227*325ce30bSDavid van Moolenbroek *) 228*325ce30bSDavid van Moolenbroek rc_postprocess_plain_line "${line}" 229*325ce30bSDavid van Moolenbroek ;; 2309865aeaaSBen Gras esac 2319865aeaaSBen Gras done 2329865aeaaSBen Gras 233*325ce30bSDavid van Moolenbroek # If we get here, then the rc_real_work() function must have 234*325ce30bSDavid van Moolenbroek # exited uncleanly. A clean exit would have been accompanied by 235*325ce30bSDavid van Moolenbroek # a line of metadata that would have prevented us from getting 236*325ce30bSDavid van Moolenbroek # here. 237*325ce30bSDavid van Moolenbroek # 238*325ce30bSDavid van Moolenbroek exit 1 239*325ce30bSDavid van Moolenbroek) 240*325ce30bSDavid van Moolenbroek 241*325ce30bSDavid van Moolenbroek# 242*325ce30bSDavid van Moolenbroek# rc_postprocess_plain_line string 243*325ce30bSDavid van Moolenbroek# $1 is a string representing a line of output from one of the 244*325ce30bSDavid van Moolenbroek# rc.d scripts. Append the line to the log, and also either 245*325ce30bSDavid van Moolenbroek# display the line on the console, or run $rc_silent_cmd, 246*325ce30bSDavid van Moolenbroek# depending on the value of $rc_silent. 247*325ce30bSDavid van Moolenbroek# 248*325ce30bSDavid van Moolenbroekrc_postprocess_plain_line() 249*325ce30bSDavid van Moolenbroek{ 250*325ce30bSDavid van Moolenbroek local line="$1" 251*325ce30bSDavid van Moolenbroek rc_log_message "${line}" 252*325ce30bSDavid van Moolenbroek if $rc_silent; then 253*325ce30bSDavid van Moolenbroek eval "$rc_silent_cmd" 254*325ce30bSDavid van Moolenbroek else 255*325ce30bSDavid van Moolenbroek printf "%s\n" "${line}" 256*325ce30bSDavid van Moolenbroek fi 257*325ce30bSDavid van Moolenbroek} 258*325ce30bSDavid van Moolenbroek 259*325ce30bSDavid van Moolenbroek# 260*325ce30bSDavid van Moolenbroek# rc_postprocess_partial_line string 261*325ce30bSDavid van Moolenbroek# This is just like rc_postprocess_plain_line, except that 262*325ce30bSDavid van Moolenbroek# a newline is not appended to the string. 263*325ce30bSDavid van Moolenbroek# 264*325ce30bSDavid van Moolenbroekrc_postprocess_partial_line() 265*325ce30bSDavid van Moolenbroek{ 266*325ce30bSDavid van Moolenbroek local line="$1" 267*325ce30bSDavid van Moolenbroek rc_log_message_n "${line}" 268*325ce30bSDavid van Moolenbroek if $rc_silent; then 269*325ce30bSDavid van Moolenbroek eval "$rc_silent_cmd" 270*325ce30bSDavid van Moolenbroek else 271*325ce30bSDavid van Moolenbroek printf "%s" "${line}" 272*325ce30bSDavid van Moolenbroek fi 273*325ce30bSDavid van Moolenbroek} 274*325ce30bSDavid van Moolenbroek 275*325ce30bSDavid van Moolenbroek# 276*325ce30bSDavid van Moolenbroek# rc_postprocess_metadata string 277*325ce30bSDavid van Moolenbroek# $1 is a string containing metadata from the rc_real_work() 278*325ce30bSDavid van Moolenbroek# function. The rc_metadata_prefix marker should already 279*325ce30bSDavid van Moolenbroek# have been removed before the string is passed to this function. 280*325ce30bSDavid van Moolenbroek# Take appropriate action depending on the content of the string. 281*325ce30bSDavid van Moolenbroek# 282*325ce30bSDavid van Moolenbroekrc_postprocess_metadata() 283*325ce30bSDavid van Moolenbroek{ 284*325ce30bSDavid van Moolenbroek local metadata="$1" 285*325ce30bSDavid van Moolenbroek local keyword args 286*325ce30bSDavid van Moolenbroek local msg 287*325ce30bSDavid van Moolenbroek local IFS=':' 288*325ce30bSDavid van Moolenbroek 289*325ce30bSDavid van Moolenbroek # given metadata="bleep:foo bar:baz", 290*325ce30bSDavid van Moolenbroek # set keyword="bleep", args="foo bar:baz", 291*325ce30bSDavid van Moolenbroek # $1="foo bar", $2="baz" 292*325ce30bSDavid van Moolenbroek # 293*325ce30bSDavid van Moolenbroek keyword="${metadata%%:*}" 294*325ce30bSDavid van Moolenbroek args="${metadata#*:}" 295*325ce30bSDavid van Moolenbroek set -- $args 296*325ce30bSDavid van Moolenbroek 297*325ce30bSDavid van Moolenbroek case "$keyword" in 298*325ce30bSDavid van Moolenbroek start) 299*325ce30bSDavid van Moolenbroek # Marks the start of the entire /etc/rc script. 300*325ce30bSDavid van Moolenbroek # $args contains a date/time. 301*325ce30bSDavid van Moolenbroek rc_log_message "[$0 starting at $args]" 302*325ce30bSDavid van Moolenbroek if ! $rc_silent; then 303*325ce30bSDavid van Moolenbroek # MINIX 3: the clock has not been set yet! 304*325ce30bSDavid van Moolenbroek #printf "%s\n" "$args" 305*325ce30bSDavid van Moolenbroek # MINIX 3: end 306*325ce30bSDavid van Moolenbroek fi 3079865aeaaSBen Gras ;; 308*325ce30bSDavid van Moolenbroek cmd-name) 309*325ce30bSDavid van Moolenbroek # Marks the start of a child script (usually one of 310*325ce30bSDavid van Moolenbroek # the /etc/rc.d/* scripts). 311*325ce30bSDavid van Moolenbroek rc_log_message "[running $1]" 3123e78f1aaSJorrit Herder ;; 313*325ce30bSDavid van Moolenbroek cmd-status) 314*325ce30bSDavid van Moolenbroek # Marks the end of a child script. 315*325ce30bSDavid van Moolenbroek # $1 is a command name, $2 is the command's exit status. 316*325ce30bSDavid van Moolenbroek # If the command failed, report it, and add it to a list. 317*325ce30bSDavid van Moolenbroek if [ "$2" != 0 ]; then 318*325ce30bSDavid van Moolenbroek rc_failures="${rc_failures}${rc_failures:+ }$1" 319*325ce30bSDavid van Moolenbroek msg="$1 $(human_exit_code $2)" 320*325ce30bSDavid van Moolenbroek rc_log_message "$msg" 321*325ce30bSDavid van Moolenbroek if ! $rc_silent; then 322*325ce30bSDavid van Moolenbroek printf "%s\n" "$msg" 323*325ce30bSDavid van Moolenbroek fi 324*325ce30bSDavid van Moolenbroek fi 325*325ce30bSDavid van Moolenbroek # After the mountcritlocal script has finished, it's 326*325ce30bSDavid van Moolenbroek # OK to flush the log to disk 327*325ce30bSDavid van Moolenbroek case "$1" in 328*325ce30bSDavid van Moolenbroek */mountcritlocal) 329*325ce30bSDavid van Moolenbroek rc_log_flush OK 330*325ce30bSDavid van Moolenbroek ;; 331*325ce30bSDavid van Moolenbroek esac 332*325ce30bSDavid van Moolenbroek ;; 333*325ce30bSDavid van Moolenbroek nop) 334*325ce30bSDavid van Moolenbroek # Do nothing. 335*325ce30bSDavid van Moolenbroek # This has the side effect of flushing partial lines, 336*325ce30bSDavid van Moolenbroek # and the echo() and printf() functions in rc.subr take 337*325ce30bSDavid van Moolenbroek # advantage of this. 338*325ce30bSDavid van Moolenbroek ;; 339*325ce30bSDavid van Moolenbroek note) 340*325ce30bSDavid van Moolenbroek # Unlike most metadata messages, which should be used 341*325ce30bSDavid van Moolenbroek # only by /etc/rc and rc.subr, the "note" message may be 342*325ce30bSDavid van Moolenbroek # used directly by /etc.rc.d/* and similar scripts. 343*325ce30bSDavid van Moolenbroek # It adds a note to the log file, without displaying 344*325ce30bSDavid van Moolenbroek # it to stdout. 345*325ce30bSDavid van Moolenbroek rc_log_message "[NOTE: $args]" 346*325ce30bSDavid van Moolenbroek ;; 347*325ce30bSDavid van Moolenbroek end) 348*325ce30bSDavid van Moolenbroek # Marks the end of processing, after the last child script. 349*325ce30bSDavid van Moolenbroek # If any child scripts (or other commands) failed, report them. 350*325ce30bSDavid van Moolenbroek # 351*325ce30bSDavid van Moolenbroek if [ -n "$rc_failures" ]; then 352*325ce30bSDavid van Moolenbroek rc_log_message "[failures]" 353*325ce30bSDavid van Moolenbroek msg="The following components reported failures:" 354*325ce30bSDavid van Moolenbroek msg="${msg}${nl}$( echo " ${rc_failures}" | fmt )" 355*325ce30bSDavid van Moolenbroek msg="${msg}${nl}See ${RC_LOG_FILE} for more information." 356*325ce30bSDavid van Moolenbroek rc_log_message "${msg}" 357*325ce30bSDavid van Moolenbroek printf "%s\n" "${msg}" 35877506577SKees Jongenburger fi 35977506577SKees Jongenburger # 360*325ce30bSDavid van Moolenbroek # Report the end date/time, even in silent mode 361*325ce30bSDavid van Moolenbroek # 362*325ce30bSDavid van Moolenbroek rc_log_message "[$0 finished at $args]" 363*325ce30bSDavid van Moolenbroek printf "%s\n" "$args" 364*325ce30bSDavid van Moolenbroek ;; 365*325ce30bSDavid van Moolenbroek exit) 366*325ce30bSDavid van Moolenbroek # Marks an exit from the rc_real_work() function. 367*325ce30bSDavid van Moolenbroek # This may be a normal or abnormal exit. 368*325ce30bSDavid van Moolenbroek # 369*325ce30bSDavid van Moolenbroek rc_log_message "[$0 exiting with status $1]" 370*325ce30bSDavid van Moolenbroek exit $1 371*325ce30bSDavid van Moolenbroek ;; 372*325ce30bSDavid van Moolenbroek interrupted) 373*325ce30bSDavid van Moolenbroek # Marks an interrupt trapped by the rc_real_work() function. 374*325ce30bSDavid van Moolenbroek # $args is a human-readable message. 375*325ce30bSDavid van Moolenbroek rc_log_message "$args" 376*325ce30bSDavid van Moolenbroek printf "%s\n" "$args" 377*325ce30bSDavid van Moolenbroek ;; 378*325ce30bSDavid van Moolenbroek *) 379*325ce30bSDavid van Moolenbroek # an unrecognised line of metadata 380*325ce30bSDavid van Moolenbroek rc_log_message "[metadata:${metadata}]" 381*325ce30bSDavid van Moolenbroek ;; 382*325ce30bSDavid van Moolenbroek esac 383*325ce30bSDavid van Moolenbroek} 3845acaa081SBen Gras 385*325ce30bSDavid van Moolenbroek# 386*325ce30bSDavid van Moolenbroek# rc_log_message string [...] 387*325ce30bSDavid van Moolenbroek# Write a message to the log file, or buffer it for later. 388*325ce30bSDavid van Moolenbroek# This function appends a newline to the message. 389*325ce30bSDavid van Moolenbroek# 390*325ce30bSDavid van Moolenbroekrc_log_message() 391*325ce30bSDavid van Moolenbroek{ 392*325ce30bSDavid van Moolenbroek _rc_log_buffer="${_rc_log_buffer}${*}${nl}" 393*325ce30bSDavid van Moolenbroek rc_log_flush 394*325ce30bSDavid van Moolenbroek} 395489a81f5SKees Jongenburger 396*325ce30bSDavid van Moolenbroek# 397*325ce30bSDavid van Moolenbroek# rc_log_message_n string [...] 398*325ce30bSDavid van Moolenbroek# Just like rc_log_message, except without appending a newline. 399*325ce30bSDavid van Moolenbroek# 400*325ce30bSDavid van Moolenbroekrc_log_message_n() 401*325ce30bSDavid van Moolenbroek{ 402*325ce30bSDavid van Moolenbroek _rc_log_buffer="${_rc_log_buffer}${*}" 403*325ce30bSDavid van Moolenbroek rc_log_flush 404*325ce30bSDavid van Moolenbroek} 405*325ce30bSDavid van Moolenbroek 406*325ce30bSDavid van Moolenbroek# 407*325ce30bSDavid van Moolenbroek# rc_log_flush [OK|FORCE] 408*325ce30bSDavid van Moolenbroek# save outstanding messages from $_rc_log_buffer to $RC_LOG_FILE. 409*325ce30bSDavid van Moolenbroek# 410*325ce30bSDavid van Moolenbroek# The log file is expected to reside in the /var/run directory, which 411*325ce30bSDavid van Moolenbroek# may not be writable very early in the boot sequence, and which is 412*325ce30bSDavid van Moolenbroek# erased a little later in the boot sequence. We therefore avoid 413*325ce30bSDavid van Moolenbroek# writing to the file until we believe it's safe to do so. We also 414*325ce30bSDavid van Moolenbroek# assume that it's reasonable to always append to the file, never 415*325ce30bSDavid van Moolenbroek# truncating it. 416*325ce30bSDavid van Moolenbroek# 417*325ce30bSDavid van Moolenbroek# Optional argument $1 may be "OK" to report that writing to the log 418*325ce30bSDavid van Moolenbroek# file is expected to be safe from now on, or "FORCE" to force writing 419*325ce30bSDavid van Moolenbroek# to the log file even if it may be unsafe. 420*325ce30bSDavid van Moolenbroek# 421*325ce30bSDavid van Moolenbroek# Returns a non-zero status if messages could not be written to the 422*325ce30bSDavid van Moolenbroek# file. 423*325ce30bSDavid van Moolenbroek# 424*325ce30bSDavid van Moolenbroekrc_log_flush() 425*325ce30bSDavid van Moolenbroek{ 426*325ce30bSDavid van Moolenbroek # 427*325ce30bSDavid van Moolenbroek # If $_rc_log_flush_ok is false, then it's probably too early to 428*325ce30bSDavid van Moolenbroek # write to the log file, so don't do it, unless $1 is "FORCE". 429*325ce30bSDavid van Moolenbroek # 430*325ce30bSDavid van Moolenbroek : ${_rc_log_flush_ok=false} 431*325ce30bSDavid van Moolenbroek case "$1:$_rc_log_flush_ok" in 432*325ce30bSDavid van Moolenbroek OK:*) 433*325ce30bSDavid van Moolenbroek _rc_log_flush_ok=true 434*325ce30bSDavid van Moolenbroek ;; 435*325ce30bSDavid van Moolenbroek FORCE:*) 436*325ce30bSDavid van Moolenbroek : OK just this once 437*325ce30bSDavid van Moolenbroek ;; 438*325ce30bSDavid van Moolenbroek *:true) 439*325ce30bSDavid van Moolenbroek : OK 440*325ce30bSDavid van Moolenbroek ;; 441*325ce30bSDavid van Moolenbroek *) 442*325ce30bSDavid van Moolenbroek # it's too early in the boot sequence, so don't flush 443*325ce30bSDavid van Moolenbroek return 1 4443e78f1aaSJorrit Herder ;; 4459865aeaaSBen Gras esac 4469865aeaaSBen Gras 447*325ce30bSDavid van Moolenbroek # 448*325ce30bSDavid van Moolenbroek # Now append the buffer to the file. The buffer should already 449*325ce30bSDavid van Moolenbroek # contain a trailing newline, so don't add an extra newline. 450*325ce30bSDavid van Moolenbroek # 451*325ce30bSDavid van Moolenbroek if [ -n "$_rc_log_buffer" ]; then 452*325ce30bSDavid van Moolenbroek if { printf "%s" "${_rc_log_buffer}" >>"${RC_LOG_FILE}" ; } \ 453*325ce30bSDavid van Moolenbroek 2>/dev/null 454*325ce30bSDavid van Moolenbroek then 455*325ce30bSDavid van Moolenbroek _rc_log_buffer="" 456*325ce30bSDavid van Moolenbroek else 457*325ce30bSDavid van Moolenbroek return 1 458a06e2ab3SBen Gras fi 459a06e2ab3SBen Gras fi 460*325ce30bSDavid van Moolenbroek return 0 461*325ce30bSDavid van Moolenbroek} 462e0e9e78dSBen Gras 463*325ce30bSDavid van Moolenbroek# 464*325ce30bSDavid van Moolenbroek# Most of the action is in the rc_real_work() and rc_postprocess() 465*325ce30bSDavid van Moolenbroek# functions. 466*325ce30bSDavid van Moolenbroek# 467*325ce30bSDavid van Moolenbroekrc_real_work "$@" 2>&1 | rc_postprocess 468*325ce30bSDavid van Moolenbroekexit $? 469