From ec10a5eeb4ad9b8f681b5b8217885f788c2e2354 Mon Sep 17 00:00:00 2001 From: Morris Jette <jette@schedmd.com> Date: Wed, 18 Jan 2012 14:20:31 -0800 Subject: [PATCH] Modify sbatch to read env vars from open file --- doc/man/man1/sbatch.1 | 18 ++++++---- src/common/env.c | 81 +++++++++++++++++++++++++------------------ src/sbatch/opt.c | 4 +-- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/doc/man/man1/sbatch.1 b/doc/man/man1/sbatch.1 index 44aa023829d..61dbfa723b1 100644 --- a/doc/man/man1/sbatch.1 +++ b/doc/man/man1/sbatch.1 @@ -376,13 +376,17 @@ option will implicitly be set to load other environment variables based upon the user's configuration on the cluster which executes the job. .TP -\fB\-\-export\-file\fR=<\filename\fR> -Export environment variables defined in <\filename\fR> to the job's -execution environment. The file contains one or more environemnt -variable definitions of the form NAME=VALUE spearated by a null -character to allow the use of special characters in environment -definitions. The \fB\-\-get\-user\-env\fR option will be ignored if -\-\-export\-file is defined. +\fB\-\-export\-file\fR=<\fIfilename\fR | \fIpipe_fd\fR> +If a number between 3 and OPEN_MAX is specified as the argument to +this option, a pipe's read file descriptor will be assumed (STDIN and +STDOUT are not supported as valid arguments). Otherwise a filename is +assumed. Export environment variables defined in <\fIfilename\fR> or +read from <\fIpipe_fd\fR> to the job's execution environment. The +content is one or more environment variable definitions of the form +NAME=value, each separated by a null character. This allows the use +of special characters in environment definitions. The +\fB\-\-get\-user\-env\fR option will be ignored if \-\-export\-file is +defined. .TP \fB\-F\fR, \fB\-\-nodefile\fR=<\fInode file\fR> diff --git a/src/common/env.c b/src/common/env.c index fec09c98845..529f1af4950 100644 --- a/src/common/env.c +++ b/src/common/env.c @@ -1580,13 +1580,13 @@ static int _bracket_cnt(char *value) return count; } -/* - * Load user environment from a specified file. - * - * This will read in a user specified file, that is invoked - * via the --export-file option in sbatch. This file must - * have NULL separated line. The NULL character is to allow - * special characters in the environment definitons. +/* + * Load user environment from a specified file or pipe. + * + * This will read in a user specified file or pipe, that is invoked + * via the --export-file option in sbatch. The NAME=value entries must + * be NULL separated to support special characters in the environment + * definitions. * * (Note: This is being added to a minor release. For the * next major release, it might be a consideration to merge @@ -1596,44 +1596,59 @@ static int _bracket_cnt(char *value) char **env_array_from_file(const char *fname) { char *buf = NULL, *ptr = NULL, *eptr = NULL; - char *line, *value; + char *line, *value, *p; char **env = NULL; char name[256]; - struct stat buffer; - ssize_t n; + int buf_size = BUFSIZ, buf_left; + int file_size = 0, tmp_size; int separator = '\0'; - int file_size = 0; int fd; - fd = open(fname,O_RDONLY ); - if (fd == -1) { - error("Could not open user environment file at %s", - fname); - return NULL; - } + /* + * If file name is a numeric value, then it is assumed to be a pipe. + */ + fd = (int)strtol(fname, &p, 10); + if ((*p != '\0') || (fd < 3) || (fd > sysconf(_SC_OPEN_MAX)) || + (fcntl(fd, F_GETFL) < 0)) { + fd = open(fname, O_RDONLY); + if (fd == -1) { + error("Could not open user environment file %s", fname); + return NULL; + } + verbose("Getting environment variables from %s", fname); + } else + verbose("Getting environment variables from pipe %d", fd); /* - * Then read in the user's environment file data. + * Read in the user's environment data. */ - fstat(fd, &buffer); - file_size = buffer.st_size; - buf = xmalloc(file_size); - if ((n = fd_read_n(fd, buf, file_size)) < 0) { - error("Could not read of environment file at %s", fname); - close (fd); - xfree(buf); - return NULL; + buf = ptr = xmalloc(buf_size); + buf_left = buf_size; + while ((tmp_size = read(fd, ptr, buf_left))) { + if (tmp_size < 0) { + if (errno == EINTR) + continue; + error("read(environment_file): %m"); + break; + } + buf_left -= tmp_size; + file_size += tmp_size; + if (buf_left == 0) { + buf_size += BUFSIZ; + xrealloc(buf, buf_size); + } + ptr = buf + file_size; + buf_left = buf_size - file_size; } close(fd); /* - * Parse the buffer into indivudal environment variable names + * Parse the buffer into individual environment variable names * and build the environment. */ - verbose("Getting file of environment variables at %s", fname); - env = env_array_create(); - line = xmalloc(ENV_BUFSIZE); - value = xmalloc(ENV_BUFSIZE); + env = env_array_create(); + line = xmalloc(ENV_BUFSIZE); + value = xmalloc(ENV_BUFSIZE); ptr = buf; while (ptr) { memset(line, 0, ENV_BUFSIZE); @@ -1641,12 +1656,12 @@ char **env_array_from_file(const char *fname) if ((ptr == eptr) || (eptr == NULL)) break; strncpy(line, ptr,(eptr - ptr)); - ptr = eptr+1; + ptr = eptr + 1; if (_env_array_entry_splitter(line, name, sizeof(name), value, ENV_BUFSIZE) && (!_discard_env(name, value)) && (name[0] != ' ')) { - env_array_overwrite(&env, name, value); + env_array_overwrite(&env, name, value); } } xfree(buf); diff --git a/src/sbatch/opt.c b/src/sbatch/opt.c index 9e8153c3989..88aa8b03455 100644 --- a/src/sbatch/opt.c +++ b/src/sbatch/opt.c @@ -2803,7 +2803,7 @@ static void _usage(void) " [--network=type] [--mem-per-cpu=MB] [--qos=qos] [--gres=list]\n" " [--cpu_bind=...] [--mem_bind=...] [--reservation=name]\n" " [--switch=max-switches{@max-time-to-wait}]\n" -" [--export[=names]] [--export-file=file] executable [args...]\n"); +" [--export[=names]] [--export-file=file|pipe] executable [args...]\n"); } static void _help(void) @@ -2822,7 +2822,7 @@ static void _help(void) " -D, --workdir=directory set working directory for batch script\n" " -e, --error=err file for batch script's standard error\n" " --export[=names] specify environment variables to export\n" -" --export-file=file specify environment variables file to export\n" +" --export-file=file|pipe specify environment variables file or pipe to export\n" " --get-user-env load environment from local cluster\n" " --gid=group_id group ID to run job as (user root only)\n" " --gres=list required generic resources\n" -- GitLab