1*cf5a6c84SAndroid Build Coastguard Worker /* env.c - Set the environment for command invocation.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2012 Tryn Mirell <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * http://opengroup.org/onlinepubs/9699919799/utilities/env.html
6*cf5a6c84SAndroid Build Coastguard Worker *
7*cf5a6c84SAndroid Build Coastguard Worker * Note: env bypasses shell builtins, so don't xexec().
8*cf5a6c84SAndroid Build Coastguard Worker *
9*cf5a6c84SAndroid Build Coastguard Worker * Deviations from posix: "-" argument and -0
10*cf5a6c84SAndroid Build Coastguard Worker
11*cf5a6c84SAndroid Build Coastguard Worker USE_ENV(NEWTOY(env, "^e:i0u*", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
12*cf5a6c84SAndroid Build Coastguard Worker
13*cf5a6c84SAndroid Build Coastguard Worker config ENV
14*cf5a6c84SAndroid Build Coastguard Worker bool "env"
15*cf5a6c84SAndroid Build Coastguard Worker default y
16*cf5a6c84SAndroid Build Coastguard Worker help
17*cf5a6c84SAndroid Build Coastguard Worker usage: env [-0i] [-e FILE] [-u NAME] [NAME=VALUE...] [COMMAND...]
18*cf5a6c84SAndroid Build Coastguard Worker
19*cf5a6c84SAndroid Build Coastguard Worker Set the environment for command invocation, or list environment variables.
20*cf5a6c84SAndroid Build Coastguard Worker
21*cf5a6c84SAndroid Build Coastguard Worker -e Execute FILE instead of argv[0] in COMMAND list
22*cf5a6c84SAndroid Build Coastguard Worker -i Clear existing environment
23*cf5a6c84SAndroid Build Coastguard Worker -u NAME Remove NAME from the environment
24*cf5a6c84SAndroid Build Coastguard Worker -0 Use null instead of newline in output
25*cf5a6c84SAndroid Build Coastguard Worker */
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker #define FOR_env
28*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
29*cf5a6c84SAndroid Build Coastguard Worker
GLOBALS(struct arg_list * u;char * e;)30*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
31*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *u;
32*cf5a6c84SAndroid Build Coastguard Worker char *e;
33*cf5a6c84SAndroid Build Coastguard Worker )
34*cf5a6c84SAndroid Build Coastguard Worker
35*cf5a6c84SAndroid Build Coastguard Worker void env_main(void)
36*cf5a6c84SAndroid Build Coastguard Worker {
37*cf5a6c84SAndroid Build Coastguard Worker char **ev = toys.optargs, **ee = 0, **set QUIET, *path = getenv("PATH");
38*cf5a6c84SAndroid Build Coastguard Worker struct string_list *sl = 0;
39*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *u;
40*cf5a6c84SAndroid Build Coastguard Worker
41*cf5a6c84SAndroid Build Coastguard Worker // If first nonoption argument is "-" treat it as -i
42*cf5a6c84SAndroid Build Coastguard Worker if (*ev && **ev == '-' && !(*ev)[1]) {
43*cf5a6c84SAndroid Build Coastguard Worker toys.optflags |= FLAG_i;
44*cf5a6c84SAndroid Build Coastguard Worker ev++;
45*cf5a6c84SAndroid Build Coastguard Worker }
46*cf5a6c84SAndroid Build Coastguard Worker
47*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(i)) ee = set = xzalloc(sizeof(void *)*(toys.optc+1));
48*cf5a6c84SAndroid Build Coastguard Worker else for (u = TT.u; u; u = u->next) xunsetenv(u->arg);
49*cf5a6c84SAndroid Build Coastguard Worker
50*cf5a6c84SAndroid Build Coastguard Worker for (; *ev; ev++) {
51*cf5a6c84SAndroid Build Coastguard Worker if (strchr(*ev, '=')) {
52*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(i)) *set++ = *ev;
53*cf5a6c84SAndroid Build Coastguard Worker else xsetenv(xstrdup(*ev), 0);
54*cf5a6c84SAndroid Build Coastguard Worker if (!strncmp(*ev, "PATH=", 5)) path=(*ev)+5;
55*cf5a6c84SAndroid Build Coastguard Worker } else {
56*cf5a6c84SAndroid Build Coastguard Worker char *ex = TT.e ? : *ev;
57*cf5a6c84SAndroid Build Coastguard Worker
58*cf5a6c84SAndroid Build Coastguard Worker // unfortunately, posix has no exec combining p and e, so do p ourselves
59*cf5a6c84SAndroid Build Coastguard Worker if (!strchr(ex, '/') && path) {
60*cf5a6c84SAndroid Build Coastguard Worker errno = ENOENT;
61*cf5a6c84SAndroid Build Coastguard Worker for (sl = find_in_path(path, ex); sl; sl = sl->next)
62*cf5a6c84SAndroid Build Coastguard Worker execve(sl->str, ev, ee ? : environ);
63*cf5a6c84SAndroid Build Coastguard Worker } else execve(ex, ev, ee ? : environ);
64*cf5a6c84SAndroid Build Coastguard Worker perror_msg("exec %s", ex);
65*cf5a6c84SAndroid Build Coastguard Worker _exit(126+(errno == ENOENT));
66*cf5a6c84SAndroid Build Coastguard Worker }
67*cf5a6c84SAndroid Build Coastguard Worker }
68*cf5a6c84SAndroid Build Coastguard Worker
69*cf5a6c84SAndroid Build Coastguard Worker for (ev = ee ? : environ; *ev; ev++) xprintf("%s%c", *ev, '\n'*!FLAG(0));
70*cf5a6c84SAndroid Build Coastguard Worker }
71