xref: /aosp_15_r20/external/toybox/toys/posix/env.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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