Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 4 Aug 2018 14:52:32 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r337321 - head/sbin/init
Message-ID:  <201808041452.w74EqWZB035652@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trasz
Date: Sat Aug  4 14:52:32 2018
New Revision: 337321
URL: https://svnweb.freebsd.org/changeset/base/337321

Log:
  Make it possible for init to execute any executable, not just sh(1)
  scripts. This means one should be able to eg rewrite their /etc/rc
  in Python.
  
  Reviewed by:	kib
  MFC after:	2 weeks
  Relnotes:	yes
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D16565

Modified:
  head/sbin/init/init.c

Modified: head/sbin/init/init.c
==============================================================================
--- head/sbin/init/init.c	Sat Aug  4 14:39:45 2018	(r337320)
+++ head/sbin/init/init.c	Sat Aug  4 14:52:32 2018	(r337321)
@@ -1057,7 +1057,7 @@ static state_func_t
 run_script(const char *script)
 {
 	pid_t pid, wpid;
-	int status;
+	int error, status;
 	char *argv[4];
 	const char *shell;
 	struct sigaction sa;
@@ -1086,6 +1086,21 @@ run_script(const char *script)
 #ifdef LOGIN_CAP
 		setprocresources(RESOURCE_RC);
 #endif
+
+		/*
+		 * Try to directly execute the script first.  If it
+		 * fails, try the old method of passing the script path
+		 * to sh(1).  Don't complain if it fails because of
+		 * the missing execute bit.
+		 */
+		error = access(script, X_OK);
+		if (error == 0) {
+			execv(script, argv + 1);
+			warning("can't exec %s: %m", script);
+		} else if (errno != EACCES) {
+			warning("can't access %s: %m", script);
+		}
+
 		execv(shell, argv);
 		stall("can't exec %s for %s: %m", shell, script);
 		_exit(1);	/* force single user mode */
@@ -1854,7 +1869,7 @@ static int
 runshutdown(void)
 {
 	pid_t pid, wpid;
-	int status;
+	int error, status;
 	int shutdowntimeout;
 	size_t len;
 	char *argv[4];
@@ -1897,6 +1912,21 @@ runshutdown(void)
 #ifdef LOGIN_CAP
 		setprocresources(RESOURCE_RC);
 #endif
+
+		/*
+		 * Try to directly execute the script first.  If it
+		 * fails, try the old method of passing the script path
+		 * to sh(1).  Don't complain if it fails because of
+		 * the missing execute bit.
+		 */
+		error = access(_path_rundown, X_OK);
+		if (error == 0) {
+			execv(_path_rundown, argv + 1);
+			warning("can't exec %s: %m", _path_rundown);
+		} else if (errno != EACCES) {
+			warning("can't access %s: %m", _path_rundown);
+		}
+
 		execv(shell, argv);
 		warning("can't exec %s for %s: %m", shell, _PATH_RUNDOWN);
 		_exit(1);	/* force single user mode */



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