Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 Jan 2008 23:51:08 +1100 (EST)
From:      Edwin Groothuis <edwin@mavetju.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/120114: [patch] sbin/reboot - add features available in Solaris.
Message-ID:  <20080129125108.822C3356@k7.mavetju>
Resent-Message-ID: <200801291300.m0TD05Oj045189@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         120114
>Category:       bin
>Synopsis:       [patch] sbin/reboot - 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:
>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:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080129125108.822C3356>