Skip to content

Commit

Permalink
flux command: rework environment management
Browse files Browse the repository at this point in the history
subcommand search path:
   Environment use:    none
   Environment export: none
   Prototype:          <command-line>:<config-file>:<install-path>

module search path
   Environment use:    none
   Environment export: FLUX_MODULE_PATH
   Prototype:          <command-line>:<config-file>:<install-path>

Lua
   Environment use:    LUA_PATH, LUA_CPATH
   Environment export: LUA_PATH, LUA_CPATH
   Prototype:          <command-line>;<config-file>;<environment>;;;

broker path (executable path, not a search path):
   Environment use:    none
   Environment export: FLUX_CMBD_PATH
   Priority order:     1) command line, 2) config file, 3) install-path

The config file priority is
   1) command line, if provided
   2) $(selfdir)/../../flux.conf, if indicated by /proc/self/exe
   3) the default ~/.flux/config, if it exists.
  • Loading branch information
garlick committed Oct 2, 2014
1 parent d30a602 commit 6d40802
Show file tree
Hide file tree
Showing 2 changed files with 199 additions and 79 deletions.
3 changes: 2 additions & 1 deletion src/cmd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ bin_PROGRAMS = flux

flux_SOURCES = flux.c
flux_LDADD = \
$(top_builddir)/src/common/libflux/libflux.la \
$(top_builddir)/src/common/libutil/libutil.la \
$(LIBZMQ)
$(LIBZMQ) $(LIBCZMQ)

#
# Flux subcommands
Expand Down
275 changes: 197 additions & 78 deletions src/cmd/flux.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <stdbool.h>
#include <sys/param.h>
#include <glob.h>
#include <flux/core.h>

#include "src/common/libutil/log.h"
#include "src/common/libutil/xzmalloc.h"
Expand All @@ -42,16 +43,24 @@


void dump_environment (void);
void exec_subcommand (bool vopt, char *argv[]);
char *dir_self (void);
void exec_subcommand (const char *searchpath, bool vopt, char *argv[]);
char *intree_config (void);

#define OPTIONS "+T:tx:hM:B:v"
void setup_lua_env (zconfig_t *cf, const char *cpath_add, const char *path_add);
char *setup_exec_searchpath (zconfig_t *cf, const char *path_add);
void setup_module_env (zconfig_t *cf, const char *path_add);
void setup_cmbd_env (zconfig_t *cf, const char *path_override);

#define OPTIONS "+T:tx:hM:B:vc:L:C:"
static const struct option longopts[] = {
{"tmpdir", required_argument, 0, 'T'},
{"trace-apisocket", no_argument, 0, 't'},
{"exec-path", required_argument, 0, 'x'},
{"module-path", required_argument, 0, 'M'},
{"cmbd-path", required_argument, 0, 'B'},
{"lua-path", required_argument, 0, 'L'},
{"lua-cpath", required_argument, 0, 'C'},
{"config", required_argument, 0, 'c'},
{"verbose", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0},
Expand All @@ -61,12 +70,15 @@ static void usage (void)
{
fprintf (stderr,
"Usage: flux [OPTIONS] COMMAND ARGS\n"
" -x,--exec-path PATH set FLUX_EXEC_PATH\n"
" -M,--module-path PATH set FLUX_MODULE_PATH\n"
" -x,--exec-path PATH prepend PATH to command search path\n"
" -M,--module-path PATH prepend PATH to module search path\n"
" -L,--lua-path PATH prepend PATH to LUA_PATH\n"
" -C,--lua-cpath PATH prepend PATH to LUA_CPATH\n"
" -T,--tmpdir PATH set FLUX_TMPDIR\n"
" -t,--trace-apisock set FLUX_TRACE_APISOCK=1\n"
" -B,--cmbd-path set FLUX_CMBD_PATH\n"
" -v,--verbose show environment before executing command\n"
" -B,--cmbd-path override path to comms message broker\n"
" -c,--config-file set path to config file\n"
" -v,--verbose show FLUX_* environment and command search\n"
"\n"
"The flux-core commands are:\n"
" keygen Generate CURVE keypairs for session security\n"
Expand All @@ -87,34 +99,28 @@ static void usage (void)
);
}

int setup_lua_env (const char *exedir)
{
char *s;

/* XXX: For now Lua paths are set relative to path of the executable.
* Once we know where these things will be installed we can make these
* paths configurable on installation.
*/
s = getenv ("LUA_CPATH");
setenvf ("LUA_CPATH", 1, "%s/../bindings/lua/.libs/?.so;%s", exedir, s ? s : ";;");
s = getenv ("LUA_PATH");
setenvf ("LUA_PATH", 1, "%s/../bindings/lua/?.lua;%s", exedir, s ? s : ";;");
return (0);
}

int main (int argc, char *argv[])
{
int ch;
bool hopt = false;
bool vopt = false;
char *flux_exe_dir = dir_self ();
char *xopt = NULL;
char *Mopt = NULL;
char *Bopt = NULL;
char *Lopt = NULL;
char *Copt = NULL;
char *config_file = NULL;
zconfig_t *config;
char *searchpath;

log_init ("flux");

setup_lua_env (flux_exe_dir);

while ((ch = getopt_long (argc, argv, OPTIONS, longopts, NULL)) != -1) {
switch (ch) {
case 'c': /* --config FILE */
config_file = xstrdup (optarg);
break;
case 'T': /* --tmpdir PATH */
if (setenv ("FLUX_TMPDIR", optarg, 1) < 0)
err_exit ("setenv FLUX_TMPDIR=%s", optarg);
Expand All @@ -123,21 +129,24 @@ int main (int argc, char *argv[])
if (setenv ("FLUX_TRACE_APISOCK", "1", 1) < 0)
err_exit ("setenv FLUX_TRACE_APISOCK=1");
break;
case 'M': /* --module-path */
if (setenv ("FLUX_MODULE_PATH", optarg, 1) < 0)
err_exit ("setenv FLUX_MODULE_PATH=%s", optarg);
case 'M': /* --module-path PATH */
Mopt = optarg;
break;
case 'x': /* --exec-path */
if (setenv ("FLUX_EXEC_PATH", optarg, 1) < 0)
err_exit ("setenv FLUX_EXEC_PATH=%s", optarg);
case 'x': /* --exec-path PATH */
xopt = optarg;
break;
case 'B': /* --cmbd-path */
if (setenv ("FLUX_CMBD_PATH", optarg, 1) < 0)
err_exit ("setenv FLUX_CMBD_PATH=%s", optarg);
case 'B': /* --cmbd-path PATH */
Bopt = optarg;
break;
case 'v': /* --verbose */
vopt = true;
break;
case 'L': /* --lua-path PATH */
Lopt = optarg;
break;
case 'C': /* --lua-cpath PATH */
Copt = optarg;
break;
case 'h': /* --help */
hopt = true;
break;
Expand All @@ -149,35 +158,20 @@ int main (int argc, char *argv[])
argc -= optind;
argv += optind;

/* We are executing 'flux' from a path that is not the installed path.
* Presume we are in $top_builddir/src/cmd and set up environment
* accordingly.
*/
if (strcmp (flux_exe_dir, X_BINDIR) != 0) {
glob_t gl;
char *modpath;
if (setenv ("FLUX_EXEC_PATH", ".", 0) < 0)
err_exit ("setenv");
if (glob ("../modules/*/.libs", GLOB_ONLYDIR, NULL, &gl) == 0) {
modpath = argv_concat (gl.gl_pathc, gl.gl_pathv, ":");
globfree (&gl);
if (setenv ("FLUX_MODULE_PATH", modpath, 0) < 0)
err_exit ("setenv");
free (modpath);
}
if (setenv ("FLUX_CMBD_PATH", "../broker/cmbd", 0) < 0)
err_exit ("setenv");
} else {
if (setenv ("FLUX_EXEC_PATH", EXEC_PATH, 0) < 0)
err_exit ("setenv");
if (setenv ("FLUX_CMBD_PATH", CMBD_PATH, 0) < 0)
err_exit ("setenv");
}
if (!config_file)
config_file = intree_config ();
config = flux_config_load (config_file, false);

setup_lua_env (config, Lopt, Copt);
setup_module_env (config, Mopt);
setup_cmbd_env (config, Bopt);

searchpath = setup_exec_searchpath (config, xopt);

if (hopt) {
if (argc > 0) {
char *av[] = { argv[0], "--help", NULL };
exec_subcommand (vopt, av);
exec_subcommand (searchpath, vopt, av);
} else
usage ();
exit (0);
Expand All @@ -186,32 +180,22 @@ int main (int argc, char *argv[])
usage ();
exit (1);
}
if (vopt)
if (vopt) {
dump_environment ();
exec_subcommand (vopt, argv);
printf ("subcommand search path: %s", searchpath);
}
exec_subcommand (searchpath, vopt, argv);

free (flux_exe_dir);
zconfig_destroy (&config);
if (config_file)
free (config_file);

free (searchpath);
log_fini ();

return 0;
}

void dump_environment_one (const char *name)
{
char *s = getenv (name);
printf ("%20s=%s\n", name, s ? s : "<unset>");
}

void dump_environment (void)
{
dump_environment_one ("FLUX_EXEC_PATH");
dump_environment_one ("FLUX_MODULE_PATH");
dump_environment_one ("FLUX_CMBD_PATH");
dump_environment_one ("FLUX_TMPDIR");
dump_environment_one ("FLUX_TRACE_APISOCK");
}

/* Return directory containing this executable. Caller must free.
* (using non-portable /proc/self/exe support for now)
*/
Expand All @@ -227,6 +211,142 @@ char *dir_self (void)
return xstrdup (flux_exe_dir);
}

char *intree_config (void)
{
char *config_file = NULL;
char *selfdir = dir_self ();

if (strcmp (selfdir, X_BINDIR) != 0)
config_file = xasprintf ("%s/../../flux.conf", selfdir);
free (selfdir);
return config_file;
}

static void path_push (char **path, const char *add, const char *sep)
{
char *new = xasprintf ("%s%s%s", add, *path ? sep : "",
*path ? *path : "");
free (*path);
*path = new;
}

void setup_lua_env (zconfig_t *cf, const char *cpath_add, const char *path_add)
{
char *path = NULL, *cpath = NULL;;
zconfig_t *z;

path_push (&path, ";;", ";"); /* Lua replaces ;; with the default path */
path_push (&cpath, ";;", ";");

/* FIXME: push installed paths (needed if side-installed)
*/

if ((z = zconfig_locate (cf, "general/lua_path"))) {
char *val = zconfig_value (z);
if (val && strlen (val) > 0)
path_push (&path, val, ";");
}
if ((z = zconfig_locate (cf, "general/lua_cpath"))) {
char *val = zconfig_value (z);
if (val && strlen (val) > 0)
path_push (&cpath, val, ";");
}

if (path_add)
path_push (&path, path_add, ";");
if (cpath_add)
path_push (&cpath, cpath_add, ";");

if (setenv ("LUA_CPATH", cpath, 1) < 0)
err_exit ("%s", cpath);
if (setenv ("LUA_PATH", path, 1) < 0)
err_exit ("%s", path);

free (path);
free (cpath);
}

char *setup_exec_searchpath (zconfig_t *cf, const char *path_add)
{
char *path = NULL;
zconfig_t *z;

path_push (&path, EXEC_PATH, ":");

if ((z = zconfig_locate (cf, "general/exec_path"))) {
char *val = zconfig_value (z);
if (val && strlen (val) > 0)
path_push (&path, val, ":");
}

if (path_add)
path_push (&path, path_add, ":");

return path;
}

void setup_module_env (zconfig_t *cf, const char *path_add)
{
char *path = NULL;
zconfig_t *z;

path_push (&path, MODULE_PATH, ":");

if ((z = zconfig_locate (cf, "general/module_path"))) {
char *val = zconfig_value (z);
if (val && strlen (val) > 0)
path_push (&path, val, ":");
}

if (path_add)
path_push (&path, path_add, ":");

if (setenv ("FLUX_MODULE_PATH", path, 1) < 0)
err_exit ("%s", path);

free (path);
}

void setup_cmbd_env (zconfig_t *cf, const char *path_override)
{
const char *path = NULL;
zconfig_t *z;

if (path_override)
path = path_override;

if (!path) {
if ((z = zconfig_locate (cf, "general/cmbd_path"))) {
char *val = zconfig_value (z);
if (val && strlen (val) > 0)
path = val;
}
}

if (!path)
path = CMBD_PATH;

if (setenv ("FLUX_CMBD_PATH", path, 1) < 0)
err_exit ("%s", path);
}

void dump_environment_one (const char *name)
{
char *s = getenv (name);
printf ("%20s%s%s\n", name, s ? "=" : "",
s ? s : " is not set");
}

void dump_environment (void)
{
dump_environment_one ("FLUX_MODULE_PATH");
dump_environment_one ("FLUX_CMBD_PATH");
dump_environment_one ("FLUX_TMPDIR");
dump_environment_one ("FLUX_TRACE_APISOCK");
dump_environment_one ("LUA_PATH");
dump_environment_one ("LUA_CPATH");
}

void exec_subcommand_dir (bool vopt, const char *dir,char *argv[],
const char *prefix)
{
Expand All @@ -239,9 +359,8 @@ void exec_subcommand_dir (bool vopt, const char *dir,char *argv[],
free (path);
}

void exec_subcommand (bool vopt, char *argv[])
void exec_subcommand (const char *searchpath, bool vopt, char *argv[])
{
char *searchpath = getenv ("FLUX_EXEC_PATH"); // assert != NULL
char *cpy = xstrdup (searchpath);
char *dir, *saveptr = NULL, *a1 = cpy;

Expand Down

0 comments on commit 6d40802

Please sign in to comment.