[klibc] [PATCH v2 3/4] kinit: Add run_scripts()

maximilian attems max at stro.at
Wed Aug 3 11:20:48 PDT 2011


On Tue, 02 Aug 2011, Mike Waychison wrote:

> 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

not sure we want to add another `_' underscore cmd without real necessity.
afaik this is called run-parts, at least in Debian:

run-parts - run scripts or programs in a directory

also this would be really cool as standalone binary,
which I miss in belows incarnation.

thank you.
 
> 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 */

small nit, no need of arguments names.

> 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);
> +}
-- 
maks



More information about the klibc mailing list