[klibc] [PATCH v2 3/4] kinit: Add run_scripts()
Mike Waychison
mikew at google.com
Tue Aug 2 15:47:00 PDT 2011
This patch implements support for executing files present in drop
directories. This is implemented by a new function called run_scripts,
which takes the name of the base drop-directory to search for scripts.
It is implemented by simply doing a single-depth search for files
present in the directory using scandir(). It then will synchronously
execute each file in order. Failure to execute anything that looks like
a file is treated as a fatal error, which should be easy to catch as
these directories are essentially configuration directories and failure
to execute should be immediately visible to developers.
Execution is implemented as a simple fork/exec, passing all the command
line flags in as the arguments to the executed script/binary.
Signed-off-by: Mike Waychison <mikew at google.com>
---
usr/kinit/Kbuild | 2 -
usr/kinit/kinit.h | 2 +
usr/kinit/run_scripts.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+), 1 deletions(-)
create mode 100644 usr/kinit/run_scripts.c
diff --git a/usr/kinit/Kbuild b/usr/kinit/Kbuild
index ff1d449..b743b87 100644
--- a/usr/kinit/Kbuild
+++ b/usr/kinit/Kbuild
@@ -8,7 +8,7 @@ lib-y := name_to_dev.o devname.o getarg.o
kinit-y := lib.a
kinit-y += kinit.o do_mounts.o ramdisk_load.o initrd.o
-kinit-y += getintfile.o readfile.o xpio.o
+kinit-y += getintfile.o readfile.o xpio.o run_scripts.o
kinit-y += do_mounts_md.o do_mounts_mtd.o nfsroot.o
kinit-y += ipconfig/
diff --git a/usr/kinit/kinit.h b/usr/kinit/kinit.h
index c2e67b7..808deee 100644
--- a/usr/kinit/kinit.h
+++ b/usr/kinit/kinit.h
@@ -65,4 +65,6 @@ static inline void dump_args(int argc, char *argv[])
}
#endif
+void run_scripts(const char *basepath, int cmdc, char **cmdv);
+
#endif /* KINIT_H */
diff --git a/usr/kinit/run_scripts.c b/usr/kinit/run_scripts.c
new file mode 100644
index 0000000..4609b39
--- /dev/null
+++ b/usr/kinit/run_scripts.c
@@ -0,0 +1,110 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "kinit.h"
+
+static int is_file(const struct dirent *dirent)
+{
+ return (dirent->d_type == DT_REG);
+}
+
+static void run_script(const char *basepath, const char *filename,
+ int cmdc, char **cmdv)
+{
+ char *fullpath;
+ char **args;
+ pid_t pid;
+ int status;
+ int ret;
+ int i;
+
+ /* Figure out fullpath */
+ fullpath = malloc(strlen(basepath) + strlen(filename) + 2);
+ if (!fullpath) {
+ fprintf(stderr, "Ran out of memory!\n");
+ exit(1);
+ }
+ sprintf(fullpath, "%s/%s", basepath, filename);
+
+ /* Prepare args for call */
+ args = malloc(sizeof(*args) * (cmdc + 2)); /* NULL + ARGV[0} */
+ if (!args) {
+ fprintf(stderr, "Ran out of memory!\n");
+ free(fullpath);
+ exit(1);
+ }
+ args[0] = fullpath;
+ for (i = 0; i < cmdc; i++)
+ args[i + 1] = cmdv[i];
+ args[cmdc + 1] = NULL;
+
+ /* Run the child */
+ pid = fork();
+ if (pid == -1) {
+ fprintf(stderr, "Failed to fork in run_scripts(%s)\n",
+ basepath);
+ exit(1);
+ }
+ if (pid == 0) {
+ /* Child */
+ execv(fullpath, args);
+ fprintf(stderr, "Failed to exec %s: %s\n", fullpath,
+ strerror(errno));
+ exit(1);
+ }
+
+ /* Parent */
+ while (1) {
+ ret = waitpid(pid, &status, 0);
+ if (ret == pid)
+ break;
+ if (ret == -1 && errno == EINTR)
+ continue;
+ fprintf(stderr, "failed to wait on child: ret=%d errno=%d\n",
+ ret, errno);
+ exit(1);
+ }
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != 0)
+ fprintf(stderr, "%s exited with status: %d\n",
+ fullpath, WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ fprintf(stderr, "%s terminated by signal %d\n",
+ fullpath, WTERMSIG(status));
+ } else {
+ fprintf(stderr, "Failed to understand status code 0x%x\n",
+ status);
+ }
+
+ free(args);
+ free(fullpath);
+}
+
+void run_scripts(const char *basepath, int cmdc, char **cmdv)
+{
+ struct dirent **namelist;
+ int i;
+ int count;
+
+ count = scandir(basepath, &namelist, is_file, alphasort);
+ if (count < 0) {
+ if (errno == ENOENT)
+ return;
+ fprintf(stderr, "WARNING: could not run_scripts(%s): %s\n",
+ basepath, strerror(errno));
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ run_script(basepath, namelist[i]->d_name, cmdc, cmdv);
+ free(namelist[i]);
+ }
+ free(namelist);
+}
More information about the klibc
mailing list