Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Dec 1994 15:15:11 +0100 (MET)
From:      roberto@blaise.ibp.fr (Ollivier ROBERT)
To:        hackers@freebsd.org (Hackers' list FreeBSD)
Subject:   /etc/rc.shutdown (First shot)
Message-ID:  <9412221415.AA02591@blaise.ibp.fr>

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

I've tried to implement a /etc/rc.shutdown mechanism into init. Can someone
review the following patch and find any errors I could have made ? I cannot
test it at the moment...

Don't worry it is not a full blown /etc/rc0.d :-)

===================================================================
RCS file: /build/master/freebsd/init/init.8,v
retrieving revision 1.2
diff -u -r1.2 init.8
--- 1.2	1994/08/27 21:32:01
+++ init.8	1994/12/22 14:02:33
@@ -238,6 +238,15 @@
 This is useful for shutting the machine down cleanly from inside the kernel
 or from X when the machines appears to be hung.
 .Pp
+When shuting down the machine,
+.Nm init
+will try to run the
+.Pa /etc/rc.shutdown
+script. This script can be used to cleanly terminate specific programs such
+as
+.Nm innd
+(the InterNetNews server).
+.Pp
 The role of
 .Nm init
 is so critical that if it dies, the system will reboot itself
@@ -277,6 +286,8 @@
 The terminal initialization information file.
 .It Pa /etc/rc
 System startup commands.
+.It Pa /etc/rc.shutdown
+System shutdown commands.
 .El
 .Sh SEE ALSO
 .Xr login 1 ,
===================================================================
RCS file: /build/master/freebsd/init/init.c,v
retrieving revision 1.5
diff -u -r1.5 init.c
--- 1.5	1994/10/14 17:15:40
+++ init.c	1994/12/22 14:03:23
@@ -98,6 +98,7 @@
 void emergency __P((char *, ...));
 void disaster __P((int));
 void badsys __P((int));
+int  runshutdown __P((void));
 
 /*
  * We really need a recursive typedef...
@@ -1349,6 +1350,7 @@
 death()
 {
 	register session_t *sp;
+    register int rcdown;
 	register int i;
 	pid_t pid;
 	static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
@@ -1356,6 +1358,11 @@
 	for (sp = sessions; sp; sp = sp->se_next)
 		sp->se_flags |= SE_SHUTDOWN;
 
+    /* Try to run the rc.shutdown script */
+    rcdown = runshutdown();
+    if (rcdown)
+        stall("Could not run %s, check this please.", _PATH_RUNDOWN);
+    
 	/* NB: should send a message to the session logger to avoid blocking. */
 	logwtmp("~", "shutdown", "");
 
@@ -1377,4 +1384,90 @@
 	warning("some processes would not die; ps axl advised");
 
 	return (state_func_t) single_user;
+}
+
+/*
+ * Run the system shutdown script.
+ *
+ * Exit codes:      XXX I should document more
+ * 0        good.
+ * 1        fatal error
+ * 2        some error
+ */
+int
+runshutdown()
+{
+	pid_t pid, wpid;
+	int status;
+	char *argv[3];
+	struct sigaction sa;
+
+	if ((pid = fork()) == 0) {
+		sigemptyset(&sa.sa_mask);
+		sa.sa_flags = 0;
+		sa.sa_handler = SIG_IGN;
+		(void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
+		(void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
+
+		setctty(_PATH_CONSOLE);
+
+		argv[0] = "sh";
+		argv[1] = _PATH_RUNDOWN;
+		argv[2] = 0;
+
+		sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
+
+		execv(_PATH_BSHELL, argv);
+		stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNDOWN);
+		_exit(1);	/* force single user mode */
+	}
+
+	if (pid == -1) {
+		emergency("can't fork for %s on %s: %m",
+			_PATH_BSHELL, _PATH_RUNDOWN);
+		while (waitpid(-1, (int *) 0, WNOHANG) > 0)
+			continue;
+		sleep(STALL_TIMEOUT);
+		return 1;
+	}
+
+	/*
+	 * Copied from single_user().  This is a bit paranoid.
+	 */
+	do {
+		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
+			collect_child(wpid);
+		if (wpid == -1) {
+			if (errno == EINTR)
+				continue;
+			warning("wait for %s on %s failed: %m; going to single user mode",
+				_PATH_BSHELL, _PATH_RUNDOWN);
+			return 2;
+		}
+		if (wpid == pid && WIFSTOPPED(status)) {
+			warning("init: %s on %s stopped, restarting\n",
+				_PATH_BSHELL, _PATH_RUNDOWN);
+			kill(pid, SIGCONT);
+			wpid = -1;
+		}
+	} while (wpid != pid);
+
+	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
+	    requested_transition == catatonia) {
+		/* /etc/rc executed /sbin/reboot; wait for the end quietly */
+		sigset_t s;
+
+		sigfillset(&s);
+		for (;;)
+			sigsuspend(&s);
+	}
+
+	if (!WIFEXITED(status)) {
+		warning("%s on %s terminated abnormally, going to single user mode",
+			_PATH_BSHELL, _PATH_RUNDOWN);
+		return 1;
+	}
+
+	if (WEXITSTATUS(status))
+		return 2;
 }
===================================================================
RCS file: /build/master/freebsd/init/pathnames.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 pathnames.h
--- 1.1.1.1	1994/05/26 06:34:19
+++ pathnames.h	1994/12/22 13:37:45
@@ -40,3 +40,4 @@
 
 #define	_PATH_SLOGGER	"/sbin/session_logger"
 #define	_PATH_RUNCOM	"/etc/rc"
+#define _PATH_RUNDOWN   "/etc/rc.shutdown"

-- 
Ollivier ROBERT   -=- FreeBSD: the daemon is FREE! -=-   roberto@freebsd.org
      FreeBSD keltia 2.1.0-Development #0: Sun Dec 11 20:52:22  1994
          roberto@keltia:/usr/src/sys/compile/KELTIA i386 ctm#221



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