Module Name:    src
Committed By:   apb
Date:           Sun Jul 27 07:46:46 UTC 2014

Modified Files:
        src/etc: rc rc.subr

Log Message:
In rc.subr, add _have_rc_postprocessor function and use it instead of
inline tests like [ -n "${_rc_postprocessor_fd}" ]. The new function
performs a few new tests, including verifying that /etc/rc is still
running (using a new _rc_pid variable set by /etc/rc).

This is intended to deal with the case that a script run from /etc/rc
spawns a background process, then /etc/rc exits, but the background
process still has environment variables inherited from /etc/rc.

Fixes PR 46546.


To generate a diff of this commit:
cvs rdiff -u -r1.168 -r1.169 src/etc/rc
cvs rdiff -u -r1.93 -r1.94 src/etc/rc.subr

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/etc/rc
diff -u src/etc/rc:1.168 src/etc/rc:1.169
--- src/etc/rc:1.168	Wed Apr  9 12:45:05 2014
+++ src/etc/rc	Sun Jul 27 07:46:46 2014
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# $NetBSD: rc,v 1.168 2014/04/09 12:45:05 apb Exp $
+# $NetBSD: rc,v 1.169 2014/07/27 07:46:46 apb Exp $
 #
 # rc --
 #	Run the scripts in /etc/rc.d with rcorder, and log output
@@ -84,6 +84,7 @@ rc_real_work()
 	# with redirected output.
 	#
 	_rc_postprocessor_fd=9 ; export _rc_postprocessor_fd
+	_rc_pid=$$ ; export _rc_pid
 	eval "exec ${_rc_postprocessor_fd}>&1"
 
 	# Print a metadata line when we exit

Index: src/etc/rc.subr
diff -u src/etc/rc.subr:1.93 src/etc/rc.subr:1.94
--- src/etc/rc.subr:1.93	Tue Jul 22 17:11:09 2014
+++ src/etc/rc.subr	Sun Jul 27 07:46:46 2014
@@ -1,4 +1,4 @@
-# $NetBSD: rc.subr,v 1.93 2014/07/22 17:11:09 wiz Exp $
+# $NetBSD: rc.subr,v 1.94 2014/07/27 07:46:46 apb Exp $
 #
 # Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -786,6 +786,35 @@ $command $rc_flags $command_args"
 }
 
 #
+# _have_rc_postprocessor
+#	Test whether the current script is running in a context that
+#	was invoked from /etc/rc with a postprocessor.
+#
+#	If the test fails, some variables may be unset to make
+#	such tests more efficient in future.
+#
+_have_rc_postprocessor()
+{
+	# Cheap tests that fd and pid are set, fd is writable.
+	[ -n "${_rc_postprocessor_fd}" ] || return 1
+	[ -n "${_rc_pid}" ] || return 1
+	eval ": >&${_rc_postprocessor_fd}" 2>/dev/null || return 1
+
+	# More expensive test that pid is running.
+	# Unset _rc_pid if this fails.
+	kill -0 "${_rc_pid}" 2>/dev/null \
+	|| { unset _rc_pid; return 1; }
+
+	# More expensive test that pid appears to be
+	# a shell running an rc script.
+	# Unset _rc_pid if this fails.
+	expr "$(ps -p "${_rc_pid}" -o command=)" : ".*sh .*/rc.*" >/dev/null \
+	|| { unset _rc_pid; return 1; }
+
+	return 0
+}
+
+#
 # run_rc_script file arg
 #	Start the script `file' with `arg', and correctly handle the
 #	return value from the script.  If `file' ends with `.sh', it's
@@ -794,9 +823,8 @@ $command $rc_flags $command_args"
 #	executable run as a child process.
 #
 #	If `file' contains "KEYWORD: interactive" and if we are
-#	running inside /etc/rc with postprocessing (as signified by
-#	_rc_postprocessor_fd being defined) then the script's stdout
-#	and stderr are redirected to $_rc_original_stdout_fd and
+#	running inside /etc/rc with postprocessing, then the script's
+#	stdout and stderr are redirected to $_rc_original_stdout_fd and
 #	$_rc_original_stderr_fd, so the output will be displayed on the
 #	console but not intercepted by /etc/rc's postprocessor.
 #
@@ -816,7 +844,7 @@ run_rc_script()
 	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
 
 	_must_redirect=false
-	if [ -n "${_rc_postprocessor_fd}" ] \
+	if _have_rc_postprocessor \
 	    && _has_rcorder_keyword interactive $_file
 	then
 		_must_redirect=true
@@ -1114,7 +1142,7 @@ print_rc_metadata()
 	# _rc_postprocessor fd, if defined, is the fd to which we must
 	# print, prefixing the output with $_rc_metadata_prefix.
 	#
-	if [ -n "$_rc_postprocessor_fd" ]; then
+	if _have_rc_postprocessor; then
 		command printf "%s%s\n" "$rc_metadata_prefix" "$1" \
 			>&${_rc_postprocessor_fd}
 	fi
@@ -1154,10 +1182,11 @@ _flush_rc_output()
 #
 print_rc_normal()
 {
-	# If _rc_postprocessor_fd is defined, then it is the fd
-	# to which we must print; otherwise print to stdout.
+	# print to stdout or _rc_postprocessor_fd, depending on
+	# whether not we have an rc postprocessor.
 	#
-	local fd="${_rc_postprocessor_fd:-1}"
+	local fd=1
+	_have_rc_postprocessor && fd="${_rc_postprocessor_fd}"
 	case "$1" in
 	"-n")
 		command printf "%s" "$2" >&${fd}
@@ -1186,7 +1215,7 @@ print_rc_normal()
 #
 no_rc_postprocess()
 {
-	if [ -n "${_rc_postprocessor_fd}" ]; then
+	if _have_rc_postprocessor; then
 		"$@" >&${_rc_original_stdout_fd} 2>&${_rc_original_stderr_fd}
 	else
 		"$@"

Reply via email to