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