From edwin@mavetju.org  Tue Jan 29 12:51:11 2008
Return-Path: <edwin@mavetju.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id A1BF116A419
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 29 Jan 2008 12:51:11 +0000 (UTC)
	(envelope-from edwin@mavetju.org)
Received: from mail5out.barnet.com.au (mail5.barnet.com.au [202.83.178.78])
	by mx1.freebsd.org (Postfix) with ESMTP id F29AE13C469
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 29 Jan 2008 12:51:10 +0000 (UTC)
	(envelope-from edwin@mavetju.org)
Received: by mail5out.barnet.com.au (Postfix, from userid 1001)
	id 4CD8D22189E5; Tue, 29 Jan 2008 23:51:10 +1100 (EST)
Received: from mail5auth.barnet.com.au (mail5.barnet.com.au [202.83.178.78])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(Client CN "mail5auth.barnet.com.au", Issuer "*.barnet.com.au" (verified OK))
	by mail5.barnet.com.au (Postfix) with ESMTP id 029D121B1AF0
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 29 Jan 2008 23:51:10 +1100 (EST)
Received: from k7.mavetju (k7.mavetju.org [10.251.1.18])
	by mail5auth.barnet.com.au (Postfix) with ESMTP id 031492218803
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 29 Jan 2008 23:51:09 +1100 (EST)
Received: by k7.mavetju (Postfix, from userid 1001)
	id 822C3356; Tue, 29 Jan 2008 23:51:08 +1100 (EST)
Message-Id: <20080129125108.822C3356@k7.mavetju>
Date: Tue, 29 Jan 2008 23:51:08 +1100 (EST)
From: Edwin Groothuis <edwin@mavetju.org>
Reply-To: Edwin Groothuis <edwin@mavetju.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] sbin/reboot - add features available in Solaris.
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         120114
>Category:       bin
>Synopsis:       [patch] reboot(8) - add features available in Solaris.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jan 29 13:00:05 UTC 2008
>Closed-Date:    
>Last-Modified:  Thu May 01 06:29:46 UTC 2008
>Originator:     Edwin Groothuis
>Release:        FreeBSD 6.2-RELEASE-p4 i386
>Organization:
-
>Environment:
System: FreeBSD k7.mavetju 6.2-RELEASE-p4 FreeBSD 6.2-RELEASE-p4 #0: Thu Apr 26 17:55:55 UTC 2007 root@i386-builder.daemonology.net:/usr/obj/usr/src/sys/SMP i386

>Description:

Solaris has the feature of being able to set boot loader options
with the -o option or after the command.

Nextboot -k and reboot -k can only specify the directory (/boot/kernel),
but not the kernel name (/boot/kernel/kernel.debug)

Nextboot insists on having the -k option for the kernel directory,
but that can be grabbed from the kern.bootfile sysctl.

Add -c option to reboot which reboots with the current kernel instaed
of the one specified in /boot/loader.conf. (to ease the use of -k
and -b option)

I will handle this with mentor (grog@)

>How-To-Repeat:
>Fix:

Index: nextboot.8
===================================================================
RCS file: /home/ncvs/src/sbin/reboot/nextboot.8,v
retrieving revision 1.4
diff -u -r1.4 nextboot.8
--- nextboot.8	12 Dec 2002 17:25:56 -0000	1.4
+++ nextboot.8	29 Jan 2008 12:50:23 -0000
@@ -34,23 +34,29 @@
 .Nm
 .Op Fl f
 .Op Fl o Ar options
-.Fl k Ar kernel
+.Op Fl b Ar bootfile
+.Op Fl k Ar kernel
 .Nm
 .Fl D
 .Sh DESCRIPTION
 The
 .Nm
-utility allows specifying an alternate kernel and/or boot flags for the
-next time the machine is booted.
+utility allows specifying an alternate kernel, kernel bootfile and/or boot
+flags for the next time the machine is booted.
 Once the
 .Xr loader 8
-loads in the new kernel
-information, it is deleted so in case the new kernel hangs the machine,
-once it is rebooted, the machine will automatically revert to its previous
-configuration.
+loads in the new kernel information, it is deleted so in case the
+new kernel hangs the machine, once it is rebooted, the machine will
+automatically revert to its previous configuration.
 .Pp
 The options are as follows:
-.Bl -tag -width ".Fl o Ar options"
+.Bl -tag -width ".Fl b Ar bootfile"
+.It Fl b Ar bootfile
+This option specifies the kernel name, relative to
+.Pa /boot/kernel
+or whatever the
+.Fl k
+option sets the kernel directory to.
 .It Fl D
 Invoking
 .Nm
@@ -90,7 +96,11 @@
 .Pp
 To enable into single user mode with the normal kernel:
 .Pp
-.Dl "nextboot -o ""-s"" -k kernel"
+.Dl "nextboot -o ""-s"""
+.Pp
+To boot a kernel with debugging symbols:
+.Pp
+.Dl "nextboot -b kernel.debug"
 .Pp
 To remove an existing nextboot configuration:
 .Pp
Index: nextboot.sh
===================================================================
RCS file: /home/ncvs/src/sbin/reboot/nextboot.sh,v
retrieving revision 1.3
diff -u -r1.3 nextboot.sh
--- nextboot.sh	18 Jan 2006 04:48:45 -0000	1.3
+++ nextboot.sh	29 Jan 2008 12:50:23 -0000
@@ -10,12 +10,15 @@
 nextboot_file="/boot/nextboot.conf"
 
 display_usage() {
-	echo "Usage: nextboot [-f] [-o options] -k kernel"
+	echo "Usage: nextboot [-f] [-o options] [-b bootfile] [-k kernel]"
 	echo "       nextboot -D"
 }
 
-while getopts "Dfk:o:" argument ; do
+while getopts "b:Dfk:o:" argument ; do
 	case "${argument}" in
+	b)
+		bootfile="${OPTARG}"
+		;;
 	D)
 		delete="YES"
 		;;
@@ -40,9 +43,13 @@
 	exit 0
 fi
 
-if [ "xxx${kernel}" = "xxx" ]; then
-	display_usage
-	exit 1
+if [ -z "${bootfile}" ]; then
+	bootfile=`sysctl -n kern.bootfile | sed -e 's,^.*/,,'`
+fi
+
+if [ -z "${kernel}" ]; then
+	kernel=`sysctl -n kern.bootfile | \
+		sed -e 's,/boot/,,' | sed -e 's,/.*$,,`
 fi
 
 if [ ${force} = "NO" -a ! -d /boot/${kernel} ]; then
@@ -50,8 +57,14 @@
 	exit 1
 fi
 
+if [ ${force} = "NO" -a ! -f /boot/${kernel}/${bootfile} ]; then
+	echo "Error: /boot/${kernel}/${bootfile} doesn't exist. Use -f to override."
+	exit 1
+fi
+
 cat > ${nextboot_file} << EOF
 nextboot_enable="YES"
 kernel="${kernel}"
+bootfile="${bootfile}"
 kernel_options="${kernel_options}"
 EOF
Index: reboot.8
===================================================================
RCS file: /home/ncvs/src/sbin/reboot/reboot.8,v
retrieving revision 1.24
diff -u -r1.24 reboot.8
--- reboot.8	22 Nov 2006 13:12:34 -0000	1.24
+++ reboot.8	29 Jan 2008 12:50:23 -0000
@@ -39,17 +39,29 @@
 .Nd stopping and restarting the system
 .Sh SYNOPSIS
 .Nm halt
-.Op Fl lnpq
-.Op Fl k Ar kernel
-.Nm
-.Op Fl dlnpq
-.Op Fl k Ar kernel
+.Op Fl clnpq
+.Op Fl o Ar options
+.Op Fl b Ar kernel-name
+.Op Fl k Ar kernel-directory
+.Op Fl - Ar options ...
+.Nm
+.Op Fl cdlnpq
+.Op Fl o Ar options
+.Op Fl b Ar kernel-name
+.Op Fl k Ar kernel-directory
+.Op Fl - Ar options ...
 .Nm fasthalt
-.Op Fl lnpq
-.Op Fl k Ar kernel
+.Op Fl clnpq
+.Op Fl o Ar options
+.Op Fl b Ar kernel-name
+.Op Fl k Ar kernel-directory
+.Op Fl - Ar options ...
 .Nm fastboot
-.Op Fl dlnpq
-.Op Fl k Ar kernel
+.Op Fl cdlnpq
+.Op Fl o Ar options
+.Op Fl b Ar kernel-name
+.Op Fl k Ar kernel-directory
+.Op Fl - Ar options ...
 .Sh DESCRIPTION
 The
 .Nm halt
@@ -73,9 +85,20 @@
 supported only when rebooting, and it has no effect unless a dump
 device has previously been specified with
 .Xr dumpon 8 .
-.It Fl k Ar kernel
-Boot the specified
+.It Fl k Ar kernel-directory
+Boot from the specified
+.Ar kernel-directory
+on the next system boot.
+If the kernel boots successfully, the
+.Em default
+kernel will be booted on successive boots, this is a one-shot option.
+If the boot fails, the system will continue attempting to boot
 .Ar kernel
+until the boot process is interrupted and a valid kernel booted.
+This may change in the future.
+.It Fl b Ar kernel-name
+Boot the specified
+.Ar kernel-name
 on the next system boot.
 If the kernel boots successfully, the
 .Em default
@@ -84,6 +107,11 @@
 .Ar kernel
 until the boot process is interrupted and a valid kernel booted.
 This may change in the future.
+.It Fl c
+Reboot the system with the current kernel, obtained from kern.bootfile
+sysctl.
+.It Fl o
+This option allows the passing of kernel flags for the next boot.
 .It Fl l
 The halt or reboot is
 .Em not
@@ -129,6 +157,26 @@
 utility is used when the system needs to be halted or restarted, giving
 users advance warning of their impending doom and cleanly terminating
 specific programs.
+.Sh EXAMPLES
+.Pp
+Reboot the system:
+.Pp
+.Dl "reboot"
+.Pp
+Reboot the system into single user mode:
+.Pp
+.Dl "reboot -o -s"
+.Dl "reboot -- -s"
+.Pp
+Reboot the system into a GENERIC kernel:
+.Pp
+.Dl "reboot -k GENERIC"
+.Pp
+Reboot the system into a kernel with debugging symbols:
+.Pp
+.Dl "reboot -b kernel.debug"
+.Pp
+.Pp
 .Sh SEE ALSO
 .Xr wtmp 5 ,
 .Xr boot 8 ,
Index: reboot.c
===================================================================
RCS file: /home/ncvs/src/sbin/reboot/reboot.c,v
retrieving revision 1.26
diff -u -r1.26 reboot.c
--- reboot.c	2 Aug 2006 13:05:38 -0000	1.26
+++ reboot.c	29 Jan 2008 12:50:23 -0000
@@ -41,9 +41,12 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD: src/sbin/reboot/reboot.c,v 1.26 2006/08/02 13:05:38 bms Exp $");
 
+#include <sys/param.h>
+#include <sys/imgact.h>
 #include <sys/reboot.h>
-#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/sysctl.h>
+#include <sys/types.h>
 #include <signal.h>
 #include <err.h>
 #include <errno.h>
@@ -56,6 +59,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#define NEXTBOOT	"/boot/nextboot.conf"
+
 static void usage(void);
 static u_int get_pageins(void);
 
@@ -65,18 +70,28 @@
 main(int argc, char *argv[])
 {
 	const struct passwd *pw;
-	int ch, howto, i, fd, lflag, nflag, qflag, pflag, sverrno;
+	int ch, howto, i, cflag, lflag, nflag, qflag, pflag, sverrno;
 	u_int pageins;
-	const char *p, *user, *kernel = NULL;
+	const char *p, *user, *kernel = NULL, *bootfile = NULL;
+	char sysctl_bootfile[200];
+	char args[MAXSHELLCMDLEN];
 
 	if (strstr((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
 		dohalt = 1;
 		howto = RB_HALT;
 	} else
 		howto = 0;
-	lflag = nflag = qflag = 0;
-	while ((ch = getopt(argc, argv, "dk:lnpq")) != -1)
+	cflag = lflag = nflag = pflag = qflag = 0;
+	*args = '\0';
+
+	while ((ch = getopt(argc, argv, "b:cdk:lno:pq")) != -1)
 		switch(ch) {
+		case 'b':
+			bootfile = optarg;
+			break;
+		case 'c':
+			cflag = 1;
+			break;
 		case 'd':
 			howto |= RB_DUMP;
 			break;
@@ -90,6 +105,10 @@
 			nflag = 1;
 			howto |= RB_NOSYNC;
 			break;
+		case 'o':
+			if (*args != '\0') strcat(args, " ");
+			strcat(args, optarg);
+			break;
 		case 'p':
 			pflag = 1;
 			howto |= RB_POWEROFF;
@@ -104,6 +123,14 @@
 	argc -= optind;
 	argv += optind;
 
+	/* Concat all arguments after the -- on the command line */
+	while (argc > 0) {
+		if (*args != '\0') strcat(args, " ");
+		strcat(args, *argv);
+		argv++;
+		argc--;
+	}
+
 	if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT))
 		errx(1, "cannot dump (-d) when halting; must reboot instead");
 	if (geteuid()) {
@@ -111,21 +138,47 @@
 		err(1, NULL);
 	}
 
+	if (cflag) {
+		int max = sizeof(sysctl_bootfile) - 1;
+		char *c;
+		if (sysctlbyname("kern.bootfile",
+		    sysctl_bootfile, &max, NULL, 0) < 0) {
+			perror("sysctl: kern.bootfile");
+			errx(1, NULL);
+		}
+
+		/*
+		 * Split /boot/kernel/kernel.debug into kernel and kernel.debug
+		 */
+		c = strchr(sysctl_bootfile, '/') + 1;
+		c = strchr(c, '/') + 1;
+		kernel = c;
+		c = strchr(c, '/');
+		*c = '\0';
+		bootfile = c + 1;
+	}
+
 	if (qflag) {
 		reboot(howto);
 		err(1, NULL);
 	}
 
-	if (kernel != NULL) {
-		fd = open("/boot/nextboot.conf", O_WRONLY | O_CREAT | O_TRUNC,
-		    0444);
-		if (fd > -1) {
-			(void)write(fd, "nextboot_enable=\"YES\"\n", 22);
-			(void)write(fd, "kernel=\"", 8L);
-			(void)write(fd, kernel, strlen(kernel));
-			(void)write(fd, "\"\n", 2);
-			close(fd);
+	if (bootfile != NULL || kernel != NULL || *args != '\0') {
+		FILE *f;
+
+		if ((f = fopen(NEXTBOOT, "w")) == NULL) {
+			perror("fopen");
+			errx(1, NULL);
 		}
+		fprintf(f, "nextboot_enable=\"YES\"\n");
+		if (kernel != NULL)
+			fprintf(f, "kernel=\"%s\"\n", kernel);
+		if (bootfile != NULL)
+			fprintf(f, "bootfile=\"%s\"\n", bootfile);
+		if (*args != '\0')
+			fprintf(f, "kernel_options=\"%s\"\n", args);
+		fclose(f);
+		chmod(NEXTBOOT, 0444);
 	}
 
 	/* Log the reboot. */
@@ -219,7 +272,8 @@
 static void
 usage()
 {
-	(void)fprintf(stderr, "usage: %s [-%slnpq] [-k kernel]\n",
+	(void)fprintf(stderr,
+	    "usage: %s [-%slnpq] [-b bootfile] [-k kernel] [-o options]\n",
 	    getprogname(), dohalt ? "" : "d");
 	exit(1);
 }
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->edwin 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Tue Jan 29 13:01:14 UTC 2008 
Responsible-Changed-Why:  
Handle with mentor 

http://www.freebsd.org/cgi/query-pr.cgi?pr=120114 

From: Edwin Groothuis <edwin@mavetju.org>
To: FreeBSD Gnats Submit <freebsd-gnats-submit@freebsd.org>
Cc:  
Subject: bin/120114: [patch] sbin/reboot - add features available in Solaris
Date: Wed, 30 Jan 2008 09:03:52 +1100

 Updates after comments from users.
 
 Index: nextboot.8
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/nextboot.8,v
 retrieving revision 1.4
 diff -u -r1.4 nextboot.8
 --- nextboot.8	12 Dec 2002 17:25:56 -0000	1.4
 +++ nextboot.8	29 Jan 2008 22:03:11 -0000
 @@ -34,23 +34,29 @@
  .Nm
  .Op Fl f
  .Op Fl o Ar options
 -.Fl k Ar kernel
 +.Op Fl b Ar bootfile
 +.Op Fl k Ar kernel
  .Nm
  .Fl D
  .Sh DESCRIPTION
  The
  .Nm
 -utility allows specifying an alternate kernel and/or boot flags for the
 -next time the machine is booted.
 +utility allows specifying an alternate kernel, kernel bootfile and/or boot
 +flags for the next time the machine is booted.
  Once the
  .Xr loader 8
 -loads in the new kernel
 -information, it is deleted so in case the new kernel hangs the machine,
 -once it is rebooted, the machine will automatically revert to its previous
 -configuration.
 +loads in the new kernel information, it is disabled so in case the
 +new kernel hangs the machine, once it is rebooted, the machine will
 +automatically revert to its previous configuration.
  .Pp
  The options are as follows:
 -.Bl -tag -width ".Fl o Ar options"
 +.Bl -tag -width ".Fl b Ar bootfile"
 +.It Fl b Ar bootfile
 +This option specifies the kernel name, relative to
 +.Pa /boot/kernel
 +or whatever the
 +.Fl k
 +option sets the kernel directory to.
  .It Fl D
  Invoking
  .Nm
 @@ -90,7 +96,11 @@
  .Pp
  To enable into single user mode with the normal kernel:
  .Pp
 -.Dl "nextboot -o ""-s"" -k kernel"
 +.Dl "nextboot -o ""-s"""
 +.Pp
 +To boot a kernel with debugging symbols:
 +.Pp
 +.Dl "nextboot -b kernel.debug"
  .Pp
  To remove an existing nextboot configuration:
  .Pp
 Index: nextboot.sh
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/nextboot.sh,v
 retrieving revision 1.3
 diff -u -r1.3 nextboot.sh
 --- nextboot.sh	18 Jan 2006 04:48:45 -0000	1.3
 +++ nextboot.sh	29 Jan 2008 22:03:11 -0000
 @@ -10,12 +10,15 @@
  nextboot_file="/boot/nextboot.conf"
  
  display_usage() {
 -	echo "Usage: nextboot [-f] [-o options] -k kernel"
 +	echo "Usage: nextboot [-f] [-o options] [-b bootfile] -k kernel"
  	echo "       nextboot -D"
  }
  
 -while getopts "Dfk:o:" argument ; do
 +while getopts "b:Dfk:o:" argument ; do
  	case "${argument}" in
 +	b)
 +		bootfile="${OPTARG}"
 +		;;
  	D)
  		delete="YES"
  		;;
 @@ -40,9 +43,13 @@
  	exit 0
  fi
  
 -if [ "xxx${kernel}" = "xxx" ]; then
 -	display_usage
 -	exit 1
 +if [ -z "${bootfile}" ]; then
 +	bootfile=`sysctl -n kern.bootfile | sed -e 's,^.*/,,'`
 +fi
 +
 +if [ -z "${kernel}" ]; then
 +	kernel=`sysctl -n kern.bootfile | \
 +		sed -e 's,/boot/,,' | sed -e 's,/.*$,,`
  fi
  
  if [ ${force} = "NO" -a ! -d /boot/${kernel} ]; then
 @@ -50,8 +57,14 @@
  	exit 1
  fi
  
 +if [ ${force} = "NO" -a ! -f /boot/${kernel}/${bootfile} ]; then
 +	echo "Error: /boot/${kernel}/${bootfile} doesn't exist. Use -f to override."
 +	exit 1
 +fi
 +
  cat > ${nextboot_file} << EOF
  nextboot_enable="YES"
  kernel="${kernel}"
 +bootfile="${bootfile}"
  kernel_options="${kernel_options}"
  EOF
 Index: reboot.8
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/reboot.8,v
 retrieving revision 1.24
 diff -u -r1.24 reboot.8
 --- reboot.8	22 Nov 2006 13:12:34 -0000	1.24
 +++ reboot.8	29 Jan 2008 22:03:11 -0000
 @@ -39,17 +39,29 @@
  .Nd stopping and restarting the system
  .Sh SYNOPSIS
  .Nm halt
 -.Op Fl lnpq
 -.Op Fl k Ar kernel
 -.Nm
 -.Op Fl dlnpq
 -.Op Fl k Ar kernel
 +.Op Fl clnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
 +.Nm
 +.Op Fl cdlnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Nm fasthalt
 -.Op Fl lnpq
 -.Op Fl k Ar kernel
 +.Op Fl clnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Nm fastboot
 -.Op Fl dlnpq
 -.Op Fl k Ar kernel
 +.Op Fl cdlnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Sh DESCRIPTION
  The
  .Nm halt
 @@ -73,9 +85,20 @@
  supported only when rebooting, and it has no effect unless a dump
  device has previously been specified with
  .Xr dumpon 8 .
 -.It Fl k Ar kernel
 -Boot the specified
 +.It Fl k Ar kernel-directory
 +Boot from the specified
 +.Ar kernel-directory
 +on the next system boot.
 +If the kernel boots successfully, the
 +.Em default
 +kernel will be booted on successive boots, this is a one-shot option.
 +If the boot fails, the system will continue attempting to boot
  .Ar kernel
 +until the boot process is interrupted and a valid kernel booted.
 +This may change in the future.
 +.It Fl b Ar kernel-name
 +Boot the specified
 +.Ar kernel-name
  on the next system boot.
  If the kernel boots successfully, the
  .Em default
 @@ -84,6 +107,11 @@
  .Ar kernel
  until the boot process is interrupted and a valid kernel booted.
  This may change in the future.
 +.It Fl c
 +Reboot the system with the current kernel, obtained from kern.bootfile
 +sysctl.
 +.It Fl o
 +This option allows the passing of kernel flags for the next boot.
  .It Fl l
  The halt or reboot is
  .Em not
 @@ -129,6 +157,26 @@
  utility is used when the system needs to be halted or restarted, giving
  users advance warning of their impending doom and cleanly terminating
  specific programs.
 +.Sh EXAMPLES
 +.Pp
 +Reboot the system:
 +.Pp
 +.Dl "reboot"
 +.Pp
 +Reboot the system into single user mode:
 +.Pp
 +.Dl "reboot -o -s"
 +.Dl "reboot -- -s"
 +.Pp
 +Reboot the system into a GENERIC kernel:
 +.Pp
 +.Dl "reboot -k GENERIC"
 +.Pp
 +Reboot the system into a kernel with debugging symbols:
 +.Pp
 +.Dl "reboot -b kernel.debug"
 +.Pp
 +.Pp
  .Sh SEE ALSO
  .Xr wtmp 5 ,
  .Xr boot 8 ,
 Index: reboot.c
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/reboot.c,v
 retrieving revision 1.26
 diff -u -r1.26 reboot.c
 --- reboot.c	2 Aug 2006 13:05:38 -0000	1.26
 +++ reboot.c	29 Jan 2008 22:03:11 -0000
 @@ -41,9 +41,12 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD: src/sbin/reboot/reboot.c,v 1.26 2006/08/02 13:05:38 bms Exp $");
  
 +#include <sys/param.h>
 +#include <sys/imgact.h>
  #include <sys/reboot.h>
 -#include <sys/types.h>
 +#include <sys/stat.h>
  #include <sys/sysctl.h>
 +#include <sys/types.h>
  #include <signal.h>
  #include <err.h>
  #include <errno.h>
 @@ -56,6 +59,8 @@
  #include <string.h>
  #include <unistd.h>
  
 +#define NEXTBOOT	"/boot/nextboot.conf"
 +
  static void usage(void);
  static u_int get_pageins(void);
  
 @@ -65,18 +70,28 @@
  main(int argc, char *argv[])
  {
  	const struct passwd *pw;
 -	int ch, howto, i, fd, lflag, nflag, qflag, pflag, sverrno;
 +	int ch, howto, i, cflag, lflag, nflag, qflag, pflag, sverrno;
  	u_int pageins;
 -	const char *p, *user, *kernel = NULL;
 +	const char *p, *user, *kernel = NULL, *bootfile = NULL;
 +	char sysctl_bootfile[200];
 +	char args[ARG_MAX];
  
  	if (strstr((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
  		dohalt = 1;
  		howto = RB_HALT;
  	} else
  		howto = 0;
 -	lflag = nflag = qflag = 0;
 -	while ((ch = getopt(argc, argv, "dk:lnpq")) != -1)
 +	cflag = lflag = nflag = pflag = qflag = 0;
 +	*args = '\0';
 +
 +	while ((ch = getopt(argc, argv, "b:cdk:lno:pq")) != -1)
  		switch(ch) {
 +		case 'b':
 +			bootfile = optarg;
 +			break;
 +		case 'c':
 +			cflag = 1;
 +			break;
  		case 'd':
  			howto |= RB_DUMP;
  			break;
 @@ -90,6 +105,10 @@
  			nflag = 1;
  			howto |= RB_NOSYNC;
  			break;
 +		case 'o':
 +			if (*args != '\0') strlcat(args, " ", sizeof(args));
 +			strlcat(args, optarg, sizeof(args));
 +			break;
  		case 'p':
  			pflag = 1;
  			howto |= RB_POWEROFF;
 @@ -104,6 +123,14 @@
  	argc -= optind;
  	argv += optind;
  
 +	/* Concat all arguments after the -- on the command line */
 +	while (argc > 0) {
 +		if (*args != '\0') strlcat(args, " ", sizeof(args));
 +		strlcat(args, *argv, sizeof(args));
 +		argv++;
 +		argc--;
 +	}
 +
  	if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT))
  		errx(1, "cannot dump (-d) when halting; must reboot instead");
  	if (geteuid()) {
 @@ -111,21 +138,55 @@
  		err(1, NULL);
  	}
  
 +	if (cflag) {
 +		int max = sizeof(sysctl_bootfile) - 1;
 +		char *c;
 +		if (sysctlbyname("kern.bootfile",
 +		    sysctl_bootfile, &max, NULL, 0) < 0)
 +			errx(1, "sysctl: kern.bootfile");
 +
 +		/*
 +		 * Split /boot/kernel/kernel.debug into kernel and kernel.debug
 +		 * This can go wrong when the kernel is booted from outside
 +		 * /boot/, in that case kernel is keps clear but bootfile is
 +		 * pointing to the value returned by the sysctl.
 +		 */
 +		if (strncmp(sysctl_bootfile, "/boot/", 6) == 0) {
 +			c = strchr(sysctl_bootfile, '/') + 1;
 +			if (c != NULL)
 +				c = strchr(c, '/') + 1;
 +			if (c != NULL) {
 +				kernel = c;
 +				c = strchr(c, '/');
 +			}
 +			if (c != NULL) {
 +				*c = '\0';
 +				bootfile = c + 1;
 +			}
 +		} else
 +			bootfile = sysctl_bootfile;
 +	}
 +
  	if (qflag) {
  		reboot(howto);
  		err(1, NULL);
  	}
  
 -	if (kernel != NULL) {
 -		fd = open("/boot/nextboot.conf", O_WRONLY | O_CREAT | O_TRUNC,
 -		    0444);
 -		if (fd > -1) {
 -			(void)write(fd, "nextboot_enable=\"YES\"\n", 22);
 -			(void)write(fd, "kernel=\"", 8L);
 -			(void)write(fd, kernel, strlen(kernel));
 -			(void)write(fd, "\"\n", 2);
 -			close(fd);
 -		}
 +	if (bootfile != NULL || kernel != NULL || *args != '\0') {
 +		FILE *f;
 +
 +		if ((f = fopen(NEXTBOOT, "w")) == NULL)
 +			errx(1, "fopen");
 +
 +		fprintf(f, "nextboot_enable=\"YES\"\n");
 +		if (kernel != NULL)
 +			fprintf(f, "kernel=\"%s\"\n", kernel);
 +		if (bootfile != NULL)
 +			fprintf(f, "bootfile=\"%s\"\n", bootfile);
 +		if (*args != '\0')
 +			fprintf(f, "kernel_options=\"%s\"\n", args);
 +		fclose(f);
 +		chmod(NEXTBOOT, 0444);
  	}
  
  	/* Log the reboot. */
 @@ -219,7 +280,8 @@
  static void
  usage()
  {
 -	(void)fprintf(stderr, "usage: %s [-%slnpq] [-k kernel]\n",
 +	(void)fprintf(stderr,
 +	    "usage: %s [-%slnpq] [-b bootfile] [-k kernel] [-o options]\n",
  	    getprogname(), dohalt ? "" : "d");
  	exit(1);
  }
 
 -- 
 Edwin Groothuis      |            Personal website: http://www.mavetju.org
 edwin@mavetju.org    |              Weblog: http://www.mavetju.org/weblog/
 

From: Edwin Groothuis <edwin@mavetju.org>
To: FreeBSD Gnats Submit <freebsd-gnats-submit@freebsd.org>
Cc:  
Subject: Re: bin/120114: [patch] sbin/reboot - add features available in Solaris.
Date: Thu, 31 Jan 2008 15:58:47 +1100

 --sm4nu43k4a2Rpi4c
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Last patch
 
 -- 
 Edwin Groothuis      |            Personal website: http://www.mavetju.org
 edwin@mavetju.org    |              Weblog: http://www.mavetju.org/weblog/
 
 --sm4nu43k4a2Rpi4c
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename=a
 
 Index: nextboot.8
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/nextboot.8,v
 retrieving revision 1.4
 diff -u -r1.4 nextboot.8
 --- nextboot.8	12 Dec 2002 17:25:56 -0000	1.4
 +++ nextboot.8	31 Jan 2008 04:57:02 -0000
 @@ -32,25 +32,28 @@
  .Nd "specify an alternate kernel and boot flags for the next reboot"
  .Sh SYNOPSIS
  .Nm
 -.Op Fl f
 +.Op Fl fc
  .Op Fl o Ar options
 -.Fl k Ar kernel
 +.Op Fl b Ar bootfile
 +.Op Fl k Ar kernel
  .Nm
  .Fl D
  .Sh DESCRIPTION
  The
  .Nm
 -utility allows specifying an alternate kernel and/or boot flags for the
 -next time the machine is booted.
 +utility allows specifying an alternate kernel, kernel bootfile and/or boot
 +flags for the next time the machine is booted.
  Once the
  .Xr loader 8
 -loads in the new kernel
 -information, it is deleted so in case the new kernel hangs the machine,
 -once it is rebooted, the machine will automatically revert to its previous
 -configuration.
 +loads in the new kernel information, it is disabled so in case the
 +new kernel hangs the machine, once it is rebooted, the machine will
 +automatically revert to its previous configuration.
  .Pp
  The options are as follows:
 -.Bl -tag -width ".Fl o Ar options"
 +.Bl -tag -width ".Fl b Ar bootfile"
 +.It Fl c
 +Picks the kernel directory and bootfile from the kern.bootfile
 +sysctl variable.
  .It Fl D
  Invoking
  .Nm
 @@ -68,6 +71,12 @@
  This option specifies a kernel directory relative to
  .Pa /boot
  to load the kernel and any modules from.
 +.It Fl b Ar bootfile
 +This option specifies the kernel name, relative to
 +.Pa /boot/kernel
 +or whatever the
 +.Fl k
 +option sets the kernel directory to.
  .It Fl o Ar options
  This option
  allows the passing of kernel flags for the next boot.
 @@ -90,7 +99,11 @@
  .Pp
  To enable into single user mode with the normal kernel:
  .Pp
 -.Dl "nextboot -o ""-s"" -k kernel"
 +.Dl "nextboot -o ""-s"""
 +.Pp
 +To boot a kernel with debugging symbols:
 +.Pp
 +.Dl "nextboot -b kernel.debug"
  .Pp
  To remove an existing nextboot configuration:
  .Pp
 Index: nextboot.sh
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/nextboot.sh,v
 retrieving revision 1.3
 diff -u -r1.3 nextboot.sh
 --- nextboot.sh	18 Jan 2006 04:48:45 -0000	1.3
 +++ nextboot.sh	31 Jan 2008 04:57:02 -0000
 @@ -8,14 +8,21 @@
  delete="NO"
  force="NO"
  nextboot_file="/boot/nextboot.conf"
 +continue="NO"
  
  display_usage() {
 -	echo "Usage: nextboot [-f] [-o options] -k kernel"
 +	echo "Usage: nextboot [-cf] [-o options] [-b bootfile] [-k kernel]"
  	echo "       nextboot -D"
  }
  
 -while getopts "Dfk:o:" argument ; do
 +while getopts "b:cDfk:o:" argument ; do
  	case "${argument}" in
 +	b)
 +		bootfile="${OPTARG}"
 +		;;
 +	c)
 +		continue="YES"
 +		;;
  	D)
  		delete="YES"
  		;;
 @@ -40,18 +47,29 @@
  	exit 0
  fi
  
 -if [ "xxx${kernel}" = "xxx" ]; then
 -	display_usage
 +if [ "${continue}" = "YES" ]; then
 +	kernel=`sysctl -n kern.bootfile | \
 +		sed -e 's,/boot/,,' | sed -e 's,/.*$,,`
 +	bootfile=`sysctl -n kern.bootfile | sed -e 's,^.*/,,'`
 +fi
 +
 +if [ ${force} = "NO" -a ! -d /boot/${kernel:-kernel} ]; then
 +	echo "Error: /boot/${kernel:-kernel} doesn't exist. Use -f to override."
  	exit 1
  fi
  
 -if [ ${force} = "NO" -a ! -d /boot/${kernel} ]; then
 -	echo "Error: /boot/${kernel} doesn't exist. Use -f to override."
 +if [ ${force} = "NO" -a ! -f /boot/${kernel:-kernel}/${bootfile:-kernel} ]; then
 +	echo "Error: /boot/${kernel:-kernel}/${bootfile:-kernel} doesn't exist. Use -f to override."
  	exit 1
  fi
  
 -cat > ${nextboot_file} << EOF
 -nextboot_enable="YES"
 -kernel="${kernel}"
 -kernel_options="${kernel_options}"
 -EOF
 +echo "nextboot_enable=\"YES\"" > ${nextboot_file}
 +if [ ! -z "${kernel}" ]; then
 +	echo "kernel=\"${kernel}\"" >> ${nextboot_file}
 +fi
 +if [ ! -z "${bootfile}" ]; then
 +	echo "bootfile=\"${bootfile}\"" >> ${nextboot_file}
 +fi
 +if [ ! -z "${kernel_options}" ]; then
 +	echo "kernel_options=\"${kernel_options}\"" >> ${nextboot_file}
 +fi
 Index: reboot.8
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/reboot.8,v
 retrieving revision 1.24
 diff -u -r1.24 reboot.8
 --- reboot.8	22 Nov 2006 13:12:34 -0000	1.24
 +++ reboot.8	31 Jan 2008 04:57:03 -0000
 @@ -39,17 +39,29 @@
  .Nd stopping and restarting the system
  .Sh SYNOPSIS
  .Nm halt
 -.Op Fl lnpq
 -.Op Fl k Ar kernel
 -.Nm
 -.Op Fl dlnpq
 -.Op Fl k Ar kernel
 +.Op Fl clnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
 +.Nm
 +.Op Fl cdlnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Nm fasthalt
 -.Op Fl lnpq
 -.Op Fl k Ar kernel
 +.Op Fl clnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Nm fastboot
 -.Op Fl dlnpq
 -.Op Fl k Ar kernel
 +.Op Fl cdlnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Sh DESCRIPTION
  The
  .Nm halt
 @@ -73,9 +85,20 @@
  supported only when rebooting, and it has no effect unless a dump
  device has previously been specified with
  .Xr dumpon 8 .
 -.It Fl k Ar kernel
 -Boot the specified
 +.It Fl k Ar kernel-directory
 +Boot from the specified
 +.Ar kernel-directory
 +on the next system boot.
 +If the kernel boots successfully, the
 +.Em default
 +kernel will be booted on successive boots, this is a one-shot option.
 +If the boot fails, the system will continue attempting to boot
  .Ar kernel
 +until the boot process is interrupted and a valid kernel booted.
 +This may change in the future.
 +.It Fl b Ar kernel-name
 +Boot the specified
 +.Ar kernel-name
  on the next system boot.
  If the kernel boots successfully, the
  .Em default
 @@ -84,6 +107,11 @@
  .Ar kernel
  until the boot process is interrupted and a valid kernel booted.
  This may change in the future.
 +.It Fl c
 +Reboot the system with the current kernel, obtained from kern.bootfile
 +sysctl.
 +.It Fl o
 +This option allows the passing of kernel flags for the next boot.
  .It Fl l
  The halt or reboot is
  .Em not
 @@ -129,6 +157,26 @@
  utility is used when the system needs to be halted or restarted, giving
  users advance warning of their impending doom and cleanly terminating
  specific programs.
 +.Sh EXAMPLES
 +.Pp
 +Reboot the system:
 +.Pp
 +.Dl "reboot"
 +.Pp
 +Reboot the system into single user mode:
 +.Pp
 +.Dl "reboot -o -s"
 +.Dl "reboot -- -s"
 +.Pp
 +Reboot the system into a GENERIC kernel:
 +.Pp
 +.Dl "reboot -k GENERIC"
 +.Pp
 +Reboot the system into a kernel with debugging symbols:
 +.Pp
 +.Dl "reboot -b kernel.debug"
 +.Pp
 +.Pp
  .Sh SEE ALSO
  .Xr wtmp 5 ,
  .Xr boot 8 ,
 Index: reboot.c
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/reboot.c,v
 retrieving revision 1.26
 diff -u -r1.26 reboot.c
 --- reboot.c	2 Aug 2006 13:05:38 -0000	1.26
 +++ reboot.c	31 Jan 2008 04:57:03 -0000
 @@ -41,9 +41,12 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD: src/sbin/reboot/reboot.c,v 1.26 2006/08/02 13:05:38 bms Exp $");
  
 +#include <sys/param.h>
 +#include <sys/imgact.h>
  #include <sys/reboot.h>
 -#include <sys/types.h>
 +#include <sys/stat.h>
  #include <sys/sysctl.h>
 +#include <sys/types.h>
  #include <signal.h>
  #include <err.h>
  #include <errno.h>
 @@ -56,6 +59,8 @@
  #include <string.h>
  #include <unistd.h>
  
 +#define NEXTBOOT	"/boot/nextboot.conf"
 +
  static void usage(void);
  static u_int get_pageins(void);
  
 @@ -65,18 +70,28 @@
  main(int argc, char *argv[])
  {
  	const struct passwd *pw;
 -	int ch, howto, i, fd, lflag, nflag, qflag, pflag, sverrno;
 +	int ch, howto, i, cflag, lflag, nflag, qflag, pflag, sverrno;
  	u_int pageins;
 -	const char *p, *user, *kernel = NULL;
 +	const char *p, *user, *kernel = NULL, *bootfile = NULL;
 +	char sysctl_bootfile[200];
 +	char args[ARG_MAX];
  
  	if (strstr((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
  		dohalt = 1;
  		howto = RB_HALT;
  	} else
  		howto = 0;
 -	lflag = nflag = qflag = 0;
 -	while ((ch = getopt(argc, argv, "dk:lnpq")) != -1)
 +	cflag = lflag = nflag = pflag = qflag = 0;
 +	*args = '\0';
 +
 +	while ((ch = getopt(argc, argv, "b:cdk:lno:pq")) != -1)
  		switch(ch) {
 +		case 'b':
 +			bootfile = optarg;
 +			break;
 +		case 'c':
 +			cflag = 1;
 +			break;
  		case 'd':
  			howto |= RB_DUMP;
  			break;
 @@ -90,6 +105,10 @@
  			nflag = 1;
  			howto |= RB_NOSYNC;
  			break;
 +		case 'o':
 +			if (*args != '\0') strlcat(args, " ", sizeof(args));
 +			strlcat(args, optarg, sizeof(args));
 +			break;
  		case 'p':
  			pflag = 1;
  			howto |= RB_POWEROFF;
 @@ -104,6 +123,14 @@
  	argc -= optind;
  	argv += optind;
  
 +	/* Concat all arguments after the -- on the command line */
 +	while (argc > 0) {
 +		if (*args != '\0') strlcat(args, " ", sizeof(args));
 +		strlcat(args, *argv, sizeof(args));
 +		argv++;
 +		argc--;
 +	}
 +
  	if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT))
  		errx(1, "cannot dump (-d) when halting; must reboot instead");
  	if (geteuid()) {
 @@ -111,21 +138,55 @@
  		err(1, NULL);
  	}
  
 +	if (cflag) {
 +		int max = sizeof(sysctl_bootfile) - 1;
 +		char *c;
 +		if (sysctlbyname("kern.bootfile",
 +		    sysctl_bootfile, &max, NULL, 0) < 0)
 +			errx(1, "sysctl: kern.bootfile");
 +
 +		/*
 +		 * Split /boot/kernel/kernel.debug into kernel and kernel.debug
 +		 * This can go wrong when the kernel is booted from outside
 +		 * /boot/, in that case kernel is keps clear but bootfile is
 +		 * pointing to the value returned by the sysctl.
 +		 */
 +		if (strncmp(sysctl_bootfile, "/boot/", 6) == 0) {
 +			c = strchr(sysctl_bootfile, '/') + 1;
 +			if (c != NULL)
 +				c = strchr(c, '/') + 1;
 +			if (c != NULL) {
 +				kernel = c;
 +				c = strchr(c, '/');
 +			}
 +			if (c != NULL) {
 +				*c = '\0';
 +				bootfile = c + 1;
 +			}
 +		} else
 +			bootfile = sysctl_bootfile;
 +	}
 +
  	if (qflag) {
  		reboot(howto);
  		err(1, NULL);
  	}
  
 -	if (kernel != NULL) {
 -		fd = open("/boot/nextboot.conf", O_WRONLY | O_CREAT | O_TRUNC,
 -		    0444);
 -		if (fd > -1) {
 -			(void)write(fd, "nextboot_enable=\"YES\"\n", 22);
 -			(void)write(fd, "kernel=\"", 8L);
 -			(void)write(fd, kernel, strlen(kernel));
 -			(void)write(fd, "\"\n", 2);
 -			close(fd);
 -		}
 +	if (bootfile != NULL || kernel != NULL || *args != '\0') {
 +		FILE *f;
 +
 +		if ((f = fopen(NEXTBOOT, "w")) == NULL)
 +			errx(1, "fopen");
 +
 +		fprintf(f, "nextboot_enable=\"YES\"\n");
 +		if (kernel != NULL)
 +			fprintf(f, "kernel=\"%s\"\n", kernel);
 +		if (bootfile != NULL)
 +			fprintf(f, "bootfile=\"%s\"\n", bootfile);
 +		if (*args != '\0')
 +			fprintf(f, "kernel_options=\"%s\"\n", args);
 +		fclose(f);
 +		chmod(NEXTBOOT, 0444);
  	}
  
  	/* Log the reboot. */
 @@ -219,7 +280,8 @@
  static void
  usage()
  {
 -	(void)fprintf(stderr, "usage: %s [-%slnpq] [-k kernel]\n",
 +	(void)fprintf(stderr,
 +	    "usage: %s [-%slnpq] [-b bootfile] [-k kernel] [-o options]\n",
  	    getprogname(), dohalt ? "" : "d");
  	exit(1);
  }
 
 --sm4nu43k4a2Rpi4c--

From: Edwin Groothuis <edwin@mavetju.org>
To: FreeBSD Gnats Submit <freebsd-gnats-submit@freebsd.org>
Cc:  
Subject: Re: bin/120114: [patch] sbin/reboot - add features available in Solaris.
Date: Sat, 9 Feb 2008 21:58:46 +1100

 --bp/iNruPH9dso1Pn
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 New patches
 
 -- 
 Edwin Groothuis      |            Personal website: http://www.mavetju.org
 edwin@mavetju.org    |              Weblog: http://www.mavetju.org/weblog/
 
 --bp/iNruPH9dso1Pn
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename=a
 
 ? boot_i386.8.gz
 ? nextboot.8.gz
 ? reboot
 ? reboot.8.gz
 Index: nextboot.8
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/nextboot.8,v
 retrieving revision 1.4
 diff -u -r1.4 nextboot.8
 --- nextboot.8	12 Dec 2002 17:25:56 -0000	1.4
 +++ nextboot.8	9 Feb 2008 10:48:53 -0000
 @@ -32,25 +32,28 @@
  .Nd "specify an alternate kernel and boot flags for the next reboot"
  .Sh SYNOPSIS
  .Nm
 -.Op Fl f
 +.Op Fl fc
  .Op Fl o Ar options
 -.Fl k Ar kernel
 +.Op Fl b Ar bootfile
 +.Op Fl k Ar kernel
  .Nm
  .Fl D
  .Sh DESCRIPTION
  The
  .Nm
 -utility allows specifying an alternate kernel and/or boot flags for the
 -next time the machine is booted.
 +utility allows specifying an alternate kernel, kernel bootfile and/or boot
 +flags for the next time the machine is booted.
  Once the
  .Xr loader 8
 -loads in the new kernel
 -information, it is deleted so in case the new kernel hangs the machine,
 -once it is rebooted, the machine will automatically revert to its previous
 -configuration.
 +loads in the new kernel information, it is disabled so in case the
 +new kernel hangs the machine, once it is rebooted, the machine will
 +automatically revert to its previous configuration.
  .Pp
  The options are as follows:
 -.Bl -tag -width ".Fl o Ar options"
 +.Bl -tag -width ".Fl b Ar bootfile"
 +.It Fl c
 +Picks the kernel directory and bootfile from the kern.bootfile
 +sysctl variable.
  .It Fl D
  Invoking
  .Nm
 @@ -68,6 +71,12 @@
  This option specifies a kernel directory relative to
  .Pa /boot
  to load the kernel and any modules from.
 +.It Fl b Ar bootfile
 +This option specifies the kernel name, relative to
 +.Pa /boot/kernel
 +or whatever the
 +.Fl k
 +option sets the kernel directory to.
  .It Fl o Ar options
  This option
  allows the passing of kernel flags for the next boot.
 @@ -90,7 +99,11 @@
  .Pp
  To enable into single user mode with the normal kernel:
  .Pp
 -.Dl "nextboot -o ""-s"" -k kernel"
 +.Dl "nextboot -o ""-s"""
 +.Pp
 +To boot a kernel with debugging symbols:
 +.Pp
 +.Dl "nextboot -b kernel.debug"
  .Pp
  To remove an existing nextboot configuration:
  .Pp
 Index: nextboot.sh
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/nextboot.sh,v
 retrieving revision 1.3
 diff -u -r1.3 nextboot.sh
 --- nextboot.sh	18 Jan 2006 04:48:45 -0000	1.3
 +++ nextboot.sh	9 Feb 2008 10:48:53 -0000
 @@ -8,14 +8,21 @@
  delete="NO"
  force="NO"
  nextboot_file="/boot/nextboot.conf"
 +continue="NO"
  
  display_usage() {
 -	echo "Usage: nextboot [-f] [-o options] -k kernel"
 +	echo "Usage: nextboot [-cf] [-o options] [-b bootfile] [-k kernel]"
  	echo "       nextboot -D"
  }
  
 -while getopts "Dfk:o:" argument ; do
 +while getopts "b:cDfk:o:" argument ; do
  	case "${argument}" in
 +	b)
 +		bootfile="${OPTARG}"
 +		;;
 +	c)
 +		continue="YES"
 +		;;
  	D)
  		delete="YES"
  		;;
 @@ -40,18 +47,30 @@
  	exit 0
  fi
  
 -if [ "xxx${kernel}" = "xxx" ]; then
 -	display_usage
 +if [ "${continue}" = "YES" ]; then
 +	sysctl=`sysctl -n kern.bootfile`
 +	kernel=`dirname $sysctl`
 +	kernel=`basename ${kernel}`
 +	bootfile=`basename $sysctl`
 +fi
 +
 +if [ ${force} = "NO" -a ! -d /boot/${kernel:-kernel} ]; then
 +	echo "Error: /boot/${kernel:-kernel} doesn't exist. Use -f to override."
  	exit 1
  fi
  
 -if [ ${force} = "NO" -a ! -d /boot/${kernel} ]; then
 -	echo "Error: /boot/${kernel} doesn't exist. Use -f to override."
 +if [ ${force} = "NO" -a ! -f /boot/${kernel:-kernel}/${bootfile:-kernel} ]; then
 +	echo "Error: /boot/${kernel:-kernel}/${bootfile:-kernel} doesn't exist. Use -f to override."
  	exit 1
  fi
  
 -cat > ${nextboot_file} << EOF
 -nextboot_enable="YES"
 -kernel="${kernel}"
 -kernel_options="${kernel_options}"
 -EOF
 +echo "nextboot_enable=\"YES\"" > ${nextboot_file}
 +if [ ! -z "${kernel}" ]; then
 +	echo "kernel=\"${kernel}\"" >> ${nextboot_file}
 +fi
 +if [ ! -z "${bootfile}" ]; then
 +	echo "bootfile=\"${bootfile}\"" >> ${nextboot_file}
 +fi
 +if [ ! -z "${kernel_options}" ]; then
 +	echo "kernel_options=\"${kernel_options}\"" >> ${nextboot_file}
 +fi
 Index: reboot.8
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/reboot.8,v
 retrieving revision 1.24
 diff -u -r1.24 reboot.8
 --- reboot.8	22 Nov 2006 13:12:34 -0000	1.24
 +++ reboot.8	9 Feb 2008 10:48:53 -0000
 @@ -39,17 +39,29 @@
  .Nd stopping and restarting the system
  .Sh SYNOPSIS
  .Nm halt
 -.Op Fl lnpq
 -.Op Fl k Ar kernel
 -.Nm
 -.Op Fl dlnpq
 -.Op Fl k Ar kernel
 +.Op Fl clnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
 +.Nm
 +.Op Fl cdlnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Nm fasthalt
 -.Op Fl lnpq
 -.Op Fl k Ar kernel
 +.Op Fl clnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Nm fastboot
 -.Op Fl dlnpq
 -.Op Fl k Ar kernel
 +.Op Fl cdlnpq
 +.Op Fl o Ar options
 +.Op Fl b Ar kernel-name
 +.Op Fl k Ar kernel-directory
 +.Op Fl - Ar options ...
  .Sh DESCRIPTION
  The
  .Nm halt
 @@ -73,9 +85,20 @@
  supported only when rebooting, and it has no effect unless a dump
  device has previously been specified with
  .Xr dumpon 8 .
 -.It Fl k Ar kernel
 -Boot the specified
 +.It Fl k Ar kernel-directory
 +Boot from the specified
 +.Ar kernel-directory
 +on the next system boot.
 +If the kernel boots successfully, the
 +.Em default
 +kernel will be booted on successive boots, this is a one-shot option.
 +If the boot fails, the system will continue attempting to boot
  .Ar kernel
 +until the boot process is interrupted and a valid kernel booted.
 +This may change in the future.
 +.It Fl b Ar kernel-name
 +Boot the specified
 +.Ar kernel-name
  on the next system boot.
  If the kernel boots successfully, the
  .Em default
 @@ -84,6 +107,11 @@
  .Ar kernel
  until the boot process is interrupted and a valid kernel booted.
  This may change in the future.
 +.It Fl c
 +Reboot the system with the current kernel, obtained from kern.bootfile
 +sysctl.
 +.It Fl o
 +This option allows the passing of kernel flags for the next boot.
  .It Fl l
  The halt or reboot is
  .Em not
 @@ -129,6 +157,26 @@
  utility is used when the system needs to be halted or restarted, giving
  users advance warning of their impending doom and cleanly terminating
  specific programs.
 +.Sh EXAMPLES
 +.Pp
 +Reboot the system:
 +.Pp
 +.Dl "reboot"
 +.Pp
 +Reboot the system into single user mode:
 +.Pp
 +.Dl "reboot -o -s"
 +.Dl "reboot -- -s"
 +.Pp
 +Reboot the system into a GENERIC kernel:
 +.Pp
 +.Dl "reboot -k GENERIC"
 +.Pp
 +Reboot the system into a kernel with debugging symbols:
 +.Pp
 +.Dl "reboot -b kernel.debug"
 +.Pp
 +.Pp
  .Sh SEE ALSO
  .Xr wtmp 5 ,
  .Xr boot 8 ,
 Index: reboot.c
 ===================================================================
 RCS file: /home/ncvs/src/sbin/reboot/reboot.c,v
 retrieving revision 1.26
 diff -u -r1.26 reboot.c
 --- reboot.c	2 Aug 2006 13:05:38 -0000	1.26
 +++ reboot.c	9 Feb 2008 10:48:53 -0000
 @@ -41,13 +41,17 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD: src/sbin/reboot/reboot.c,v 1.26 2006/08/02 13:05:38 bms Exp $");
  
 +#include <sys/param.h>
 +#include <sys/imgact.h>
  #include <sys/reboot.h>
 -#include <sys/types.h>
 +#include <sys/stat.h>
  #include <sys/sysctl.h>
 +#include <sys/types.h>
  #include <signal.h>
  #include <err.h>
  #include <errno.h>
  #include <fcntl.h>
 +#include <libgen.h>
  #include <libutil.h>
  #include <pwd.h>
  #include <syslog.h>
 @@ -56,6 +60,8 @@
  #include <string.h>
  #include <unistd.h>
  
 +#define NEXTBOOT	"/boot/nextboot.conf"
 +
  static void usage(void);
  static u_int get_pageins(void);
  
 @@ -65,18 +71,28 @@
  main(int argc, char *argv[])
  {
  	const struct passwd *pw;
 -	int ch, howto, i, fd, lflag, nflag, qflag, pflag, sverrno;
 +	int ch, howto, i, cflag, lflag, nflag, qflag, pflag, sverrno;
  	u_int pageins;
 -	const char *p, *user, *kernel = NULL;
 +	const char *p, *user, *kernel = NULL, *bootfile = NULL;
 +	char sysctl_bootfile[200];
 +	char args[ARG_MAX];
  
  	if (strstr((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
  		dohalt = 1;
  		howto = RB_HALT;
  	} else
  		howto = 0;
 -	lflag = nflag = qflag = 0;
 -	while ((ch = getopt(argc, argv, "dk:lnpq")) != -1)
 +	cflag = lflag = nflag = pflag = qflag = 0;
 +	*args = '\0';
 +
 +	while ((ch = getopt(argc, argv, "b:cdk:lno:pq")) != -1)
  		switch(ch) {
 +		case 'b':
 +			bootfile = optarg;
 +			break;
 +		case 'c':
 +			cflag = 1;
 +			break;
  		case 'd':
  			howto |= RB_DUMP;
  			break;
 @@ -90,6 +106,11 @@
  			nflag = 1;
  			howto |= RB_NOSYNC;
  			break;
 +		case 'o':
 +			if (*args != '\0')
 +				strlcat(args, " ", sizeof(args));
 +			strlcat(args, optarg, sizeof(args));
 +			break;
  		case 'p':
  			pflag = 1;
  			howto |= RB_POWEROFF;
 @@ -104,6 +125,15 @@
  	argc -= optind;
  	argv += optind;
  
 +	/* Concat all arguments after the -- on the command line */
 +	while (argc > 0) {
 +		if (*args != '\0')
 +			strlcat(args, " ", sizeof(args));
 +		strlcat(args, *argv, sizeof(args));
 +		argv++;
 +		argc--;
 +	}
 +
  	if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT))
  		errx(1, "cannot dump (-d) when halting; must reboot instead");
  	if (geteuid()) {
 @@ -111,21 +141,52 @@
  		err(1, NULL);
  	}
  
 +	if (cflag) {
 +		int max = sizeof(sysctl_bootfile) - 1;
 +		char *c;
 +		if (sysctlbyname("kern.bootfile", sysctl_bootfile, &max, NULL,
 +		    0) < 0)
 +			errx(1, "sysctl: kern.bootfile");
 +
 +		/*
 +		 * Split /boot/kernel/kernel.debug into kernel and kernel.debug
 +		 * This can go wrong when the kernel is booted from outside
 +		 * /boot/, in that case kernel is keeps clear but bootfile is
 +		 * pointing to the value returned by the sysctl.
 +		 */
 +		if (strncmp(sysctl_bootfile, "/boot/", 6) == 0) {
 +			c = basename(sysctl_bootfile);
 +			if (c != NULL)
 +				bootfile = strdup(c);
 +			c = dirname(sysctl_bootfile);
 +			if (c != NULL)
 +				c = basename(c);
 +			if (c != NULL)
 +				kernel = strdup(c);
 +		} else
 +			bootfile = sysctl_bootfile;
 +	}
 +
  	if (qflag) {
  		reboot(howto);
  		err(1, NULL);
  	}
  
 -	if (kernel != NULL) {
 -		fd = open("/boot/nextboot.conf", O_WRONLY | O_CREAT | O_TRUNC,
 -		    0444);
 -		if (fd > -1) {
 -			(void)write(fd, "nextboot_enable=\"YES\"\n", 22);
 -			(void)write(fd, "kernel=\"", 8L);
 -			(void)write(fd, kernel, strlen(kernel));
 -			(void)write(fd, "\"\n", 2);
 -			close(fd);
 -		}
 +	if (bootfile != NULL || kernel != NULL || *args != '\0') {
 +		FILE *f;
 +
 +		if ((f = fopen(NEXTBOOT, "w")) == NULL)
 +			errx(1, "fopen");
 +
 +		fprintf(f, "nextboot_enable=\"YES\"\n");
 +		if (kernel != NULL)
 +			fprintf(f, "kernel=\"%s\"\n", kernel);
 +		if (bootfile != NULL)
 +			fprintf(f, "bootfile=\"%s\"\n", bootfile);
 +		if (*args != '\0')
 +			fprintf(f, "kernel_options=\"%s\"\n", args);
 +		fclose(f);
 +		chmod(NEXTBOOT, 0444);
  	}
  
  	/* Log the reboot. */
 @@ -219,7 +280,9 @@
  static void
  usage()
  {
 -	(void)fprintf(stderr, "usage: %s [-%slnpq] [-k kernel]\n",
 +
 +	(void)fprintf(stderr,
 +	    "usage: %s [-%slnpq] [-b bootfile] [-k kernel] [-o options]\n",
  	    getprogname(), dohalt ? "" : "d");
  	exit(1);
  }
 
 --bp/iNruPH9dso1Pn--
Responsible-Changed-From-To: edwin->freebsd-bugs 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Thu Feb 14 09:25:13 UTC 2008 
Responsible-Changed-Why:  
Let somebody else worry about it. (See followup email) 

http://www.freebsd.org/cgi/query-pr.cgi?pr=120114 

Adding to audit trail from misfiled PR ports/120637:

Date: Thu, 14 Feb 2008 20:25:32 +1100
From: Edwin Groothuis <edwin@mavetju.org>

 ----- Forwarded message from Greg 'groggy' Lehey <grog@lemis.com> -----
 
 Date: Thu, 14 Feb 2008 11:04:33 +1030
 From: Greg 'groggy' Lehey <grog@lemis.com>
 To: Edwin Groothuis <edwin@mavetju.org>
 Subject: bin/120114: [patch] sbin/reboot - add features available in Solaris.
 
 On Saturday,  9 February 2008 at 21:51:32 +1100, Edwin Groothuis wrote:
 >
 > Here you go, courtesy of callum who did have the patience to explain
 > the same problem he had with the initial interpretation of what you
 > said.
 
 basename(3) is clear.  Sorry if you misunderstood, but the numbers are
 important.
 
 > Index: nextboot.8
 > ===================================================================
 > RCS file: /home/ncvs/src/sbin/reboot/nextboot.8,v
 > retrieving revision 1.4
 > diff -u -r1.4 nextboot.8
 > --- nextboot.8	12 Dec 2002 17:25:56 -0000	1.4
 > +++ nextboot.8	9 Feb 2008 10:48:53 -0000
 > @@ -32,25 +32,28 @@
 >  .Nd "specify an alternate kernel and boot flags for the next reboot"
 >  .Sh SYNOPSIS
 >  .Nm
 > -.Op Fl f
 > +.Op Fl fc
 >  .Op Fl o Ar options
 > -.Fl k Ar kernel
 > +.Op Fl b Ar bootfile
 > +.Op Fl k Ar kernel
 >  .Nm
 >  .Fl D
 >  .Sh DESCRIPTION
 >  The
 >  .Nm
 > -utility allows specifying an alternate kernel and/or boot flags for the
 > -next time the machine is booted.
 > +utility allows specifying an alternate kernel, kernel bootfile and/or boot
 > +flags for the next time the machine is booted.
 
 and/or is ugly.  How about "or"?
 
 >  Once the
 >  .Xr loader 8
 > -loads in the new kernel
 > -information, it is deleted so in case the new kernel hangs the machine,
 > -once it is rebooted, the machine will automatically revert to its previous
 > -configuration.
 > +loads in the new kernel information, it is disabled so in case the
 > +new kernel hangs the machine, once it is rebooted, the machine will
 > +automatically revert to its previous configuration.
 
 I don't understand this text.  What do you mean by "disabled"?  Not
 the same as "deleted"?  Looking at nextboot.conf, it appears to be the
 value of the nextboot_enable variable in nextboot.conf.  But you need
 to say that.  You also need to say how to reenable it.
 
 Also, it's not clear from the text whether this disables the
 information or the loader.  How about s/it/the information/?
 
 >  .Pp
 >  The options are as follows:
 > -.Bl -tag -width ".Fl o Ar options"
 > +.Bl -tag -width ".Fl b Ar bootfile"
 > +.It Fl c
 > +Picks the kernel directory and bootfile from the kern.bootfile
 > +sysctl variable.
 
 Pick or picks, not Picks.  I'd go for Pick because it matches the
 other options.
 
 You should also revise the BUGS section.  It's obviously written from
 the viewpoint of the unnamed author (though Gordon seems to have
 written the code too), and it suggests that all the code is in
 loader(8), which is just plain wrong.  I'd remove the first paragraph
 and significantly revise the second.
 
 This man page is also very confused about what it means by "kernel".
 After looking at it, it's clear that it refers to a kernel directory.
 It should say so.
 
 > Index: nextboot.sh
 > ===================================================================
 > RCS file: /home/ncvs/src/sbin/reboot/nextboot.sh,v
 > retrieving revision 1.3
 > diff -u -r1.3 nextboot.sh
 > --- nextboot.sh	18 Jan 2006 04:48:45 -0000	1.3
 > +++ nextboot.sh	9 Feb 2008 10:48:53 -0000
 > @@ -8,14 +8,21 @@
 >  delete="NO"
 >  force="NO"
 >  nextboot_file="/boot/nextboot.conf"
 > +continue="NO"
 >
 >  display_usage() {
 > -	echo "Usage: nextboot [-f] [-o options] -k kernel"
 > +	echo "Usage: nextboot [-cf] [-o options] [-b bootfile] [-k kernel]"
 >  	echo "       nextboot -D"
 >  }
 >
 > -while getopts "Dfk:o:" argument ; do
 > +while getopts "b:cDfk:o:" argument ; do
 >  	case "${argument}" in
 > +	b)
 > +		bootfile="${OPTARG}"
 > +		;;
 > +	c)
 > +		continue="YES"
 > +		;;
 
 Why continue?  Firstly it's a reserved word, and secondly it doesn't
 describe the action of picking the info well.  Maybe "current"?
 
 > Index: reboot.8
 > ===================================================================
 > RCS file: /home/ncvs/src/sbin/reboot/reboot.8,v
 > retrieving revision 1.24
 > diff -u -r1.24 reboot.8
 > --- reboot.8	22 Nov 2006 13:12:34 -0000	1.24
 > +++ reboot.8	9 Feb 2008 10:48:53 -0000
 > @@ -73,9 +85,20 @@
 >  supported only when rebooting, and it has no effect unless a dump
 >  device has previously been specified with
 >  .Xr dumpon 8 .
 > -.It Fl k Ar kernel
 > -Boot the specified
 > +.It Fl k Ar kernel-directory
 > +Boot from the specified
 > +.Ar kernel-directory
 > +on the next system boot.
 > +If the kernel boots successfully, the
 > +.Em default
 > +kernel will be booted on successive boots, this is a one-shot option.
 > +If the boot fails, the system will continue attempting to boot
 >  .Ar kernel
 > +until the boot process is interrupted and a valid kernel booted.
 > +This may change in the future.
 > +.It Fl b Ar kernel-name
 > +Boot the specified
 > +.Ar kernel-name
 >  on the next system boot.
 
 This is messy.  I suppose we need to keep the -k option for backward
 compatibility, but it should be possible to do things like:
 
   reboot -b kernel.debug
 
 to reboot from ${current_kernel_dir}/kernel.debug, and
 
   reboot -b GENERIC/kernel
 
 to reboot from ${current_kernel_dir}/kernel.debug, and
 
   reboot -b GENERIC/
 
 to reboot from boot/GENERIC/kernel (replacing the -k option), and
 
   reboot -b /boot/kernel/kernel.debug
 
 to be completely explicit.  This last one might be convenient for
 scripts.  I'd suggest allowing either -b or -k, not both.  This seems
 to match the comments in sys/boot/forth/support.4th:
 
    \ Try to load a kernel; the kernel name is taken from one of
    \ the following lists, as ordered:
    \
    \   1. The "bootfile" environment variable
    \   2. The "kernel" environment variable
    \
    \ Flags are passed, if provided.
    \
    \ The kernel will be loaded from a directory computed from the
    \ path given. Two directories will be tried in the following order:
    \
    \   1. /boot/path
    \   2. path
    \
 
 > +.It Fl o
 > +This option allows the passing of kernel flags for the next boot.
 
 How?  Which flags?  I see this was in nextboot too, but I didn't
 notice it there.  You need more description here.
 
 > +Reboot the system into single user mode:
 > +.Pp
 > +.Dl "reboot -o -s"
 > +.Dl "reboot -- -s"
 
 Why are there two different ways of doing this?  You should also
 either describe the -- construct under DESCRIPTION, or, better, remove
 it (unless there's some difference I haven't understood).
 
 > Index: reboot.c
 > ===================================================================
 > RCS file: /home/ncvs/src/sbin/reboot/reboot.c,v
 > retrieving revision 1.26
 > diff -u -r1.26 reboot.c
 > --- reboot.c	2 Aug 2006 13:05:38 -0000	1.26
 > +++ reboot.c	9 Feb 2008 10:48:53 -0000
 > +	if (cflag) {
 > +		int max = sizeof(sysctl_bootfile) - 1;
 > +		char *c;
 > +		if (sysctlbyname("kern.bootfile", sysctl_bootfile, &max, NULL,
 > +		    0) < 0)
 > +			errx(1, "sysctl: kern.bootfile");
 > +
 > +		/*
 > +		 * Split /boot/kernel/kernel.debug into kernel and kernel.debug
 > +		 * This can go wrong when the kernel is booted from outside
 > +		 * /boot/, in that case kernel is keeps clear but bootfile is
 > +		 * pointing to the value returned by the sysctl.
 > +		 */
 > +		if (strncmp(sysctl_bootfile, "/boot/", 6) == 0) {
 > +			c = basename(sysctl_bootfile);
 > +			if (c != NULL)
 > +				bootfile = strdup(c);
 > +			c = dirname(sysctl_bootfile);
 > +			if (c != NULL)
 > +				c = basename(c);
 > +			if (c != NULL)
 > +				kernel = strdup(c);
 > +		} else
 > +			bootfile = sysctl_bootfile;
 > +	}
 
 This is still wrong.  As you say, it can go wrong if it's not in
 /boot, which apparently loader(8) supports.  But what if it's set to,
 say, "kernel/kernel"?  That can happen:
 
   # sysctl kern.bootfile
   kern.bootfile: kernel/kernel
 
 What happens if you write kernel/kernel as bootfile to nextboot.conf?
 
 So, still work to be done.
 
 Another ugliness in reboot(8) is that it has a -p option.  What for?
 Some time that should be disabled.
 
 Also, one thing missing from both nextboot and reboot is a -P option
 to specify selecting a different boot partition.  On my systems, for
 example, I have two boot partitions.  When I upgrade, I switch to the
 "other" partition, so I have to manually change it for reboot.  Your
 current changes don't address this problem, and it should be possible
 to do.  You don't have to implement this now, but it's worth thinking
 about.
 
 Greg
 --
 Finger grog@Freebsd.org for PGP public key.
 See complete headers for address and phone numbers.
 
 
 
 ----- End forwarded message -----
 
>Unformatted:
