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