sim: nrun: add --env-{set,unset,clear} command line options

Provide explicit control over the program's environment with the
basic set/unset/clear options.  These are a bit clunky to use,
but they're functional.

The env set operation is split out into a separate function as it'll
be used in the next commit.

With these in place, we can adjust the custom cris testsuite to use
the now standard options and not its one-off hack.
This commit is contained in:
Mike Frysinger 2021-11-16 02:54:44 -05:00
parent 85588c9ab9
commit 35818ade96
5 changed files with 107 additions and 10 deletions

View file

@ -62,6 +62,7 @@ main (int argc, char **argv)
{
const char *name;
char **prog_argv = NULL;
char **prog_envp = NULL;
struct bfd *prog_bfd;
enum sim_stop reason;
int sigrc = 0;
@ -99,6 +100,7 @@ main (int argc, char **argv)
/* Was there a program to run? */
prog_argv = STATE_PROG_ARGV (sd);
prog_envp = STATE_PROG_ENVP (sd) ? : environ;
prog_bfd = STATE_PROG_BFD (sd);
if (prog_argv == NULL || *prog_argv == NULL)
usage ();
@ -131,7 +133,7 @@ main (int argc, char **argv)
exit (1);
/* Prepare the program for execution. */
sim_create_inferior (sd, prog_bfd, prog_argv, environ);
sim_create_inferior (sd, prog_bfd, prog_argv, prog_envp);
/* To accommodate relative file paths, chdir to sysroot now. We
mustn't do this until BFD has opened the program, else we wouldn't

View file

@ -25,10 +25,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <unistd.h>
#include "libiberty.h"
#include "sim-options.h"
#include "sim-io.h"
#include "sim-assert.h"
#include "environ.h"
#include "version.h"
#include "hashtab.h"
@ -106,6 +108,9 @@ typedef enum {
OPTION_LOAD_VMA,
OPTION_SYSROOT,
OPTION_ARGV0,
OPTION_ENV_SET,
OPTION_ENV_UNSET,
OPTION_ENV_CLEAR,
} STANDARD_OPTIONS;
static const OPTION standard_options[] =
@ -184,9 +189,63 @@ static const OPTION standard_options[] =
'\0', "ARGV0", "Set argv[0] to the specified string",
standard_option_handler, NULL },
{ {"env-set", required_argument, NULL, OPTION_ENV_SET},
'\0', "VAR=VAL", "Set the variable in the program's environment",
standard_option_handler, NULL },
{ {"env-unset", required_argument, NULL, OPTION_ENV_UNSET},
'\0', "VAR", "Unset the variable in the program's environment",
standard_option_handler, NULL },
{ {"env-clear", no_argument, NULL, OPTION_ENV_CLEAR},
'\0', NULL, "Clear the program's environment",
standard_option_handler, NULL },
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
};
static SIM_RC
env_set (SIM_DESC sd, const char *arg)
{
int i, varlen;
char *eq;
char **envp;
if (STATE_PROG_ENVP (sd) == NULL)
STATE_PROG_ENVP (sd) = dupargv (environ);
eq = strchr (arg, '=');
if (eq == NULL)
{
sim_io_eprintf (sd, "invalid syntax when setting env var `%s'"
": missing value", arg);
return SIM_RC_FAIL;
}
/* Include the = in the comparison below. */
varlen = eq - arg + 1;
/* If we can find an existing variable, replace it. */
envp = STATE_PROG_ENVP (sd);
for (i = 0; envp[i]; ++i)
{
if (strncmp (envp[i], arg, varlen) == 0)
{
free (envp[i]);
envp[i] = xstrdup (arg);
break;
}
}
/* If we didn't find the var, add it. */
if (envp[i] == NULL)
{
envp = xrealloc (envp, (i + 2) * sizeof (char *));
envp[i] = xstrdup (arg);
envp[i + 1] = NULL;
STATE_PROG_ENVP (sd) = envp;
}
return SIM_RC_OK;
}
static SIM_RC
standard_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
char *arg, int is_command)
@ -430,6 +489,46 @@ standard_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
free (STATE_PROG_ARGV0 (sd));
STATE_PROG_ARGV0 (sd) = xstrdup (arg);
break;
case OPTION_ENV_SET:
return env_set (sd, arg);
case OPTION_ENV_UNSET:
{
int i, varlen;
char **envp;
if (STATE_PROG_ENVP (sd) == NULL)
STATE_PROG_ENVP (sd) = dupargv (environ);
varlen = strlen (arg);
/* If we can find an existing variable, replace it. */
envp = STATE_PROG_ENVP (sd);
for (i = 0; envp[i]; ++i)
{
char *env = envp[i];
if (strncmp (env, arg, varlen) == 0
&& (env[varlen] == '\0' || env[varlen] == '='))
{
free (envp[i]);
break;
}
}
/* If we clear the var, shift the array down. */
for (; envp[i]; ++i)
envp[i] = envp[i + 1];
break;
}
case OPTION_ENV_CLEAR:
freeargv (STATE_PROG_ENVP (sd));
STATE_PROG_ENVP (sd) = xmalloc (sizeof (char *));
STATE_PROG_ENVP (sd)[0] = NULL;
break;
}
return SIM_RC_OK;

View file

@ -101,7 +101,6 @@ foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
set opts(timeout) ""
set opts(mach) ""
set opts(xerror) "no"
set opts(simenv) ""
set opts(kfail) ""
set opts(xfail) ""
set opts(target) ""
@ -211,7 +210,7 @@ foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
}
set result [sim_run "$testname.x" "$opts(sim,$mach)" "$opts(progoptions)" \
"" "$opts(simenv)"]
"" ""]
set return_code [lindex $result 0]
set output [lindex $result 1]

View file

@ -1,6 +1,5 @@
/* Check that rare readlink calls don't cause the simulator to abort.
#notarget: cris*-*-elf
#simenv: env(-u\ PWD\ foo)=bar
FIXME: Need to unset PWD, but right now I won't bother tweaking the
generic parts of the testsuite machinery and instead abuse a flaw. */
#sim: --env-unset PWD
*/
#include "readlink2.c"

View file

@ -1,8 +1,6 @@
/* Check that rare readlink calls don't cause the simulator to abort.
#notarget: cris*-*-elf
#sim: --sysroot=@exedir@
#simenv: env(-u\ PWD\ foo)=bar
FIXME: Need to unset PWD, but right now I won't bother tweaking the
generic parts of the testsuite machinery and instead abuse a flaw. */
#sim: --sysroot=@exedir@ --env-unset PWD
*/
#define SYSROOTED 1
#include "readlink2.c"