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