[klibc] [PATCH] RFC: Running initscripts from kinit

Mike Waychison mikew at google.com
Wed Apr 28 13:39:04 PDT 2010


For our platforms, we'd like to embed several different userland scripts /
programs that are executed before we have mounted the root filesystem as part
of the initramfs payload.

Specifically, I'd like to have multiple scripts executed before do_mounts(), so
I coded up this simple do_initscripts function that executes all executables
found in /etc/init.d in alphabetically sorted order.

I realize now that this could be all simplified to blindly calling:

system("/etc/rc.sysinit");

or similar though and leaving the drop directory handling to it (which is
easier done in shell anyway).

What are other folks' thoughts on the matter?  Would anyone object to calling
system() as part of the kinit process?

Signed-off-by: Mike Waychison <mikew at google.com>
---
 usr/kinit/kinit.c |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/usr/kinit/kinit.c b/usr/kinit/kinit.c
index 7c33718..88d1b28 100644
--- a/usr/kinit/kinit.c
+++ b/usr/kinit/kinit.c
@@ -1,5 +1,6 @@
 #include <sys/mount.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -9,12 +10,15 @@
 #include <limits.h>
 #include <ctype.h>
 #include <termios.h>
+#include <dirent.h>
 
 #include "kinit.h"
 #include "ipconfig.h"
 #include "run-init.h"
 #include "resume.h"
 
+#define INITD "/etc/init.d"
+
 const char *progname = "kinit";
 int mnt_procfs;
 int mnt_sysfs;
@@ -189,6 +193,70 @@ static const char *find_init(const char *root, const char *user)
 	return path;
 }
 
+static int sort_compare(const void *a, const void *b)
+{
+	return strcmp(a, b);
+}
+
+/* Go through and run all scripts found in /etc/init.d */
+static void do_runscripts()
+{
+	DIR *dir;
+	struct dirent *dirent;
+	char **names = NULL;
+	unsigned used_count = 0;
+	unsigned total_count = 0;
+	char buf[256 + strlen(INITD) + 1];
+	int i;
+
+	dir = opendir(INITD);
+	if (!dir)
+		return;
+
+	while (1) {
+		dirent = readdir(dir);
+		if (dirent == NULL && errno != 0) {
+			perror("Failed to read initscript directory");
+			goto out;
+		} else if (dirent == NULL)
+			break;
+		if (!strcmp(dirent->d_name, ".")
+		 || !strcmp(dirent->d_name, ".."))
+			continue;
+		sprintf(buf, "%s/%s", INITD, dirent->d_name);
+		if (access(buf, X_OK))
+			continue;
+		if (used_count == total_count) {
+			total_count += 10;
+			names = realloc(names, total_count * sizeof(char *));
+			if (!names) {
+				fprintf(stderr, "Failed to reallocate\n");
+				goto out;
+			}
+		}
+		names[used_count] = strdup(dirent->d_name);
+		if (names[used_count] == NULL) {
+			fprintf(stderr, "Failed to strdup\n");
+			goto out;
+		}
+		used_count++;
+	}
+
+	/* Sort the files */
+	qsort(names, used_count, sizeof(char *), sort_compare);
+
+	/* Execute each script */
+	for (i = 0; i < used_count; i++) {
+		sprintf(buf, "%s/%s", INITD, names[i]);
+		system(buf);
+	}
+out:
+	for (i = 0; i < used_count; i++)
+		free(names[i]);
+	free(names);
+	closedir(dir);
+}
+
 /* This is the argc and argv we pass to init */
 const char *init_path;
 int init_argc;
@@ -288,6 +356,8 @@ int main(int argc, char *argv[])
 	check_path("/root");
 	do_mounts(cmdc, cmdv);
 
+	do_runscripts();
+
 	if (mnt_procfs) {
 		umount2("/proc", 0);
 		mnt_procfs = 0;
-- 
1.7.0.1



More information about the klibc mailing list