12966d28cSSean Farley /*-
23522c38bSSean Farley * Copyright (c) 2007-2008 Sean C. Farley <scf@FreeBSD.org>
32966d28cSSean Farley * All rights reserved.
42966d28cSSean Farley *
52966d28cSSean Farley * Redistribution and use in source and binary forms, with or without
62966d28cSSean Farley * modification, are permitted provided that the following conditions
72966d28cSSean Farley * are met:
82966d28cSSean Farley * 1. Redistributions of source code must retain the above copyright
92966d28cSSean Farley * notice, this list of conditions and the following disclaimer,
102966d28cSSean Farley * without modification, immediately at the beginning of the file.
112966d28cSSean Farley * 2. Redistributions in binary form must reproduce the above copyright
122966d28cSSean Farley * notice, this list of conditions and the following disclaimer in the
132966d28cSSean Farley * documentation and/or other materials provided with the distribution.
142966d28cSSean Farley *
152966d28cSSean Farley * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
162966d28cSSean Farley * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
172966d28cSSean Farley * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
182966d28cSSean Farley * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
192966d28cSSean Farley * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
202966d28cSSean Farley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
212966d28cSSean Farley * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
222966d28cSSean Farley * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
232966d28cSSean Farley * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
242966d28cSSean Farley * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252966d28cSSean Farley */
262966d28cSSean Farley #include <errno.h>
272966d28cSSean Farley #include <libgen.h>
282966d28cSSean Farley #include <stdbool.h>
292966d28cSSean Farley #include <stdio.h>
302966d28cSSean Farley #include <stdlib.h>
312966d28cSSean Farley #include <string.h>
322966d28cSSean Farley #include <unistd.h>
332966d28cSSean Farley
342966d28cSSean Farley
352966d28cSSean Farley #include <sys/cdefs.h>
362966d28cSSean Farley extern char **environ;
372966d28cSSean Farley
382966d28cSSean Farley
39143d18caSSean Farley /*
40143d18caSSean Farley * Print entire environ array.
41143d18caSSean Farley */
422966d28cSSean Farley static void
dump_environ(void)432966d28cSSean Farley dump_environ(void)
442966d28cSSean Farley {
452966d28cSSean Farley char **environPtr;
462966d28cSSean Farley
47143d18caSSean Farley for (environPtr = environ; *environPtr != NULL; environPtr++)
482966d28cSSean Farley printf("%s\n", *environPtr);
492966d28cSSean Farley
502966d28cSSean Farley return;
512966d28cSSean Farley }
522966d28cSSean Farley
532966d28cSSean Farley
54143d18caSSean Farley /*
55143d18caSSean Farley * Print usage.
56143d18caSSean Farley */
572966d28cSSean Farley static void
usage(const char * program)582966d28cSSean Farley usage(const char *program)
592966d28cSSean Farley {
6020f492f0SBrian Feldman fprintf(stderr, "Usage: %s [-DGUchrt] [-c 1|2|3|4] [-bgu name] "
613522c38bSSean Farley "[-p name=value]\n"
623522c38bSSean Farley "\t[(-S|-s name) value overwrite]\n\n"
632966d28cSSean Farley "Options:\n"
642966d28cSSean Farley " -D\t\t\t\tDump environ\n"
652966d28cSSean Farley " -G name\t\t\tgetenv(NULL)\n"
662966d28cSSean Farley " -S value overwrite\t\tsetenv(NULL, value, overwrite)\n"
672966d28cSSean Farley " -U\t\t\t\tunsetenv(NULL)\n"
6820f492f0SBrian Feldman " -b name\t\t\tblank the 'name=$name' entry, corrupting it\n"
693522c38bSSean Farley " -c 1|2|3|4\t\t\tClear environ variable using method:\n"
703522c38bSSean Farley "\t\t\t\t1 - set environ to NULL pointer\n"
713522c38bSSean Farley "\t\t\t\t2 - set environ[0] to NULL pointer\n"
723522c38bSSean Farley "\t\t\t\t3 - set environ to calloc()'d NULL-terminated array\n"
733522c38bSSean Farley "\t\t\t\t4 - set environ to static NULL-terminated array\n"
742966d28cSSean Farley " -g name\t\t\tgetenv(name)\n"
752966d28cSSean Farley " -h\t\t\t\tHelp\n"
762966d28cSSean Farley " -p name=value\t\t\tputenv(name=value)\n"
779bab2367SSean Farley " -r\t\t\t\treplace environ with { \"FOO=bar\", NULL }\n"
782966d28cSSean Farley " -s name value overwrite\tsetenv(name, value, overwrite)\n"
792966d28cSSean Farley " -t\t\t\t\tOutput is suitable for testing (no newlines)\n"
802966d28cSSean Farley " -u name\t\t\tunsetenv(name)\n",
812966d28cSSean Farley basename(program));
822966d28cSSean Farley
832966d28cSSean Farley return;
842966d28cSSean Farley }
852966d28cSSean Farley
862966d28cSSean Farley
87143d18caSSean Farley /*
88143d18caSSean Farley * Print the return value of a call along with errno upon error else zero.
89143d18caSSean Farley * Also, use the eol string based upon whether running in test mode or not.
90143d18caSSean Farley */
91143d18caSSean Farley static void
print_rtrn_errno(int rtrnVal,const char * eol)92143d18caSSean Farley print_rtrn_errno(int rtrnVal, const char *eol)
93143d18caSSean Farley {
94143d18caSSean Farley printf("%d %d%s", rtrnVal, rtrnVal != 0 ? errno : 0, eol);
95143d18caSSean Farley
96143d18caSSean Farley return;
97143d18caSSean Farley }
98143d18caSSean Farley
9920f492f0SBrian Feldman static void
blank_env(const char * var)10020f492f0SBrian Feldman blank_env(const char *var)
10120f492f0SBrian Feldman {
10220f492f0SBrian Feldman char **newenviron;
10320f492f0SBrian Feldman int n, varlen;
10420f492f0SBrian Feldman
10520f492f0SBrian Feldman if (environ == NULL)
10620f492f0SBrian Feldman return;
10720f492f0SBrian Feldman
10820f492f0SBrian Feldman for (n = 0; environ[n] != NULL; n++)
10920f492f0SBrian Feldman ;
11020f492f0SBrian Feldman newenviron = malloc(sizeof(char *) * (n + 1));
11120f492f0SBrian Feldman varlen = strlen(var);
11220f492f0SBrian Feldman for (; n >= 0; n--) {
11320f492f0SBrian Feldman newenviron[n] = environ[n];
11420f492f0SBrian Feldman if (newenviron[n] != NULL &&
11520f492f0SBrian Feldman strncmp(newenviron[n], var, varlen) == 0 &&
11620f492f0SBrian Feldman newenviron[n][varlen] == '=')
11720f492f0SBrian Feldman newenviron[n] += strlen(newenviron[n]);
11820f492f0SBrian Feldman }
11920f492f0SBrian Feldman environ = newenviron;
12020f492f0SBrian Feldman }
121143d18caSSean Farley
1222966d28cSSean Farley int
main(int argc,char ** argv)1232966d28cSSean Farley main(int argc, char **argv)
1242966d28cSSean Farley {
1252966d28cSSean Farley char arg;
1262966d28cSSean Farley const char *eol = "\n";
1272966d28cSSean Farley const char *value;
1283522c38bSSean Farley static char *emptyEnv[] = { NULL };
1293522c38bSSean Farley static char *staticEnv[] = { "FOO=bar", NULL };
1302966d28cSSean Farley
1312966d28cSSean Farley if (argc == 1) {
1322966d28cSSean Farley usage(argv[0]);
1332966d28cSSean Farley exit(EXIT_FAILURE);
1342966d28cSSean Farley }
1352966d28cSSean Farley
136143d18caSSean Farley /* The entire program is basically executed from this loop. */
13720f492f0SBrian Feldman while ((arg = getopt(argc, argv, "DGS:Ub:c:g:hp:rs:tu:")) != -1) {
1382966d28cSSean Farley switch (arg) {
13920f492f0SBrian Feldman case 'b':
14020f492f0SBrian Feldman blank_env(optarg);
14120f492f0SBrian Feldman break;
14220f492f0SBrian Feldman
1433522c38bSSean Farley case 'c':
1443522c38bSSean Farley switch (atoi(optarg)) {
1453522c38bSSean Farley case 1:
1469bab2367SSean Farley environ = NULL;
1472966d28cSSean Farley break;
1482966d28cSSean Farley
1493522c38bSSean Farley case 2:
1503522c38bSSean Farley environ[0] = NULL;
1513522c38bSSean Farley break;
1523522c38bSSean Farley
1533522c38bSSean Farley case 3:
1549bab2367SSean Farley environ = calloc(1, sizeof(*environ));
1559bab2367SSean Farley break;
1569bab2367SSean Farley
1573522c38bSSean Farley case 4:
1583522c38bSSean Farley environ = emptyEnv;
1593522c38bSSean Farley break;
1603522c38bSSean Farley }
1613522c38bSSean Farley break;
1623522c38bSSean Farley
1639bab2367SSean Farley case 'D':
1649bab2367SSean Farley dump_environ();
1652966d28cSSean Farley break;
1662966d28cSSean Farley
1672966d28cSSean Farley case 'G':
1682966d28cSSean Farley case 'g':
169143d18caSSean Farley value = getenv(arg == 'g' ? optarg : NULL);
1708cfaf5a9SSean Farley printf("%s%s", value == NULL ? "*NULL*" : value, eol);
1712966d28cSSean Farley break;
1722966d28cSSean Farley
1732966d28cSSean Farley case 'p':
174143d18caSSean Farley print_rtrn_errno(putenv(optarg), eol);
1752966d28cSSean Farley break;
1762966d28cSSean Farley
1779bab2367SSean Farley case 'r':
1789bab2367SSean Farley environ = staticEnv;
1799bab2367SSean Farley break;
1809bab2367SSean Farley
1812966d28cSSean Farley case 'S':
182143d18caSSean Farley print_rtrn_errno(setenv(NULL, optarg,
183143d18caSSean Farley atoi(argv[optind])), eol);
1842966d28cSSean Farley optind += 1;
1852966d28cSSean Farley break;
1862966d28cSSean Farley
1872966d28cSSean Farley case 's':
188143d18caSSean Farley print_rtrn_errno(setenv(optarg, argv[optind],
189143d18caSSean Farley atoi(argv[optind + 1])), eol);
1902966d28cSSean Farley optind += 2;
1912966d28cSSean Farley break;
1922966d28cSSean Farley
1932966d28cSSean Farley case 't':
1942966d28cSSean Farley eol = " ";
1952966d28cSSean Farley break;
1962966d28cSSean Farley
1972966d28cSSean Farley case 'U':
1982966d28cSSean Farley case 'u':
19986168e15SSean Farley print_rtrn_errno(unsetenv(arg == 'u' ? optarg : NULL),
20086168e15SSean Farley eol);
2012966d28cSSean Farley break;
2022966d28cSSean Farley
2032966d28cSSean Farley case 'h':
2042966d28cSSean Farley default:
2052966d28cSSean Farley usage(argv[0]);
2062966d28cSSean Farley exit(EXIT_FAILURE);
2072966d28cSSean Farley }
2082966d28cSSean Farley }
2092966d28cSSean Farley
210143d18caSSean Farley /* Output a closing newline in test mode. */
2112966d28cSSean Farley if (eol[0] == ' ')
2122966d28cSSean Farley printf("\n");
2132966d28cSSean Farley
2142966d28cSSean Farley return (EXIT_SUCCESS);
2152966d28cSSean Farley }
216