Subject: bin/13871: rc.d/bootconf.sh can destroy etc.current
To: None <gnats-bugs@gnats.netbsd.org>
From: None <kre@munnari.OZ.AU>
List: netbsd-bugs
Date: 09/05/2001 20:47:17
>Number:         13871
>Category:       bin
>Synopsis:       rc.d/bootconf.sh can cause etc.current -> etc.current
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Sep 05 06:43:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Robert Elz
>Release:        <NetBSD-current source date>
>Organization:
	University of Melbourne, Computer Science
>Environment:
	

System (PR sent from): NetBSD brandenburg.cs.mu.OZ.AU 1.5_BETA NetBSD 1.5_BETA (BRANDENBURG) #4: Mon Dec 4 17:01:12 EST 2000 kre@brandenburg.cs.mu.OZ.AU:/usr/src/sys/arch/i386/compile/BRANDENBURG i386

System (tested on): NetBSD jade.coe.psu.ac.th 1.5W NetBSD 1.5W (KRE) #4: Fri Jun 22 11:56:33 ICT 2001     kre@kre.coe.psu.ac.th:/usr/obj/sys/compile/KRE i386

Using sources from NetBSD-current as of 2001-09-04 (via anon cvs)

>Description:
	bootconf.sh almost supports arranging for the default boot
	configuration to be whatever was used last time, either by
	simply not having an etc.default (default boot config) or
	by having the default boot config be the current boot config
	(as in etc.default -> etc.current along with etc.current -> etc.network)

	However, if either of those is used, then when bootconf runs
	next, it will change etc.current -> etc.network into
	etc.current -> etc.current

	That's because of the following two lines

		rm -f /etc/etc.current
		ln -s /etc/etc.$conf /etc/etc.current

	when $conf == current.

>How-To-Repeat:
	cd /etc
	rm etc.default
	reboot

		bad things happen

	Same would happen if

	ln -s etc.current etc.default

>Fix:

	Three different patches are appended.  Pick one, any one ...

	The first avoids the problem, by making sure the bad 2 lines
	don't get executed in the problem case.

	The second avoids the problem by avoiding the pre-condition
	for the problem ($conf should never be "current" in this case).
	This one also causes the config prompt to tell you which config
	will actually be used (so you know which is the default) in these
	cases, which wasn't happening before.

	The third is both of the above - just to make it easier for
	whoever applies the patch (Luke??) if you take my advice
	and fix this both ways.   The 2nd patch is nicer to use,
	but isn't an absolute guarantee.  The first is.

	There's another possible problem that I don't encounter as
	I replaced the use of the read/trap method of obtaining the
	desired configuration long ago, but with the current distributed
	scripts it is possible for the user to type "default" at the
	prompt.

	That will cause

		ln -s etc.default etc.current

	which will probably work the first time, but next boot it
	would not be pretty I think.   A minor modification to the
	first or third patches would avoid that (don't do the symlink
	if $conf == "default" )

	ps: these could be redone using if statements, I grew up on
	case as the way to do string tests in sh, so that's what I use...


--- bootconf.sh.WAS	Mon Oct  9 12:30:17 2000
+++ bootconf.sh	Wed Sep  5 20:21:58 2001
@@ -55,8 +55,15 @@
 			conf=${_DUMMY}
 		fi
 	done
-	rm -f /etc/etc.current
-	ln -s /etc/etc.$conf /etc/etc.current
+
+	case "$conf" in
+	current)
+		;;
+	*)	rm -f /etc/etc.current
+		ln -s /etc/etc."$conf" /etc/etc.current
+		;;
+	esac
+
 	if [ -f /etc/rc.conf ] ; then
 		. /etc/rc.conf
 	fi

--- bootconf.sh.WAS	Mon Oct  9 12:30:17 2000
+++ bootconf.sh.ALT	Wed Sep  5 20:24:17 2001
@@ -20,6 +20,14 @@
 	else
 		default=current
 	fi
+
+	case "$default" in
+	current)
+		def=`ls -ld /etc/etc.current  2>&1`
+		default="${def##*-> etc.}"
+		;;
+	esac
+
 	spc=""
 	for i in /etc/etc.*
 	do

--- bootconf.sh.WAS	Mon Oct  9 12:30:17 2000
+++ bootconf.sh.BOTH	Wed Sep  5 20:25:26 2001
@@ -20,6 +20,14 @@
 	else
 		default=current
 	fi
+
+	case "$default" in
+	current)
+		def=`ls -ld /etc/etc.current  2>&1`
+		default="${def##*-> etc.}"
+		;;
+	esac
+
 	spc=""
 	for i in /etc/etc.*
 	do
@@ -55,8 +63,15 @@
 			conf=${_DUMMY}
 		fi
 	done
-	rm -f /etc/etc.current
-	ln -s /etc/etc.$conf /etc/etc.current
+
+	case "$conf" in
+	current)
+		;;
+	*)	rm -f /etc/etc.current
+		ln -s /etc/etc."$conf" /etc/etc.current
+		;;
+	esac
+
 	if [ -f /etc/rc.conf ] ; then
 		. /etc/rc.conf
 	fi
>Release-Note:
>Audit-Trail:
>Unformatted: