xref: /freebsd/tools/regression/environ/envctl.c (revision 20f492f0ebaac48ba6f70c67e93e6b01578bc3e6)
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 __FBSDID("$FreeBSD$");
372966d28cSSean Farley 
382966d28cSSean Farley 
392966d28cSSean Farley extern char **environ;
402966d28cSSean Farley 
412966d28cSSean Farley 
42143d18caSSean Farley /*
43143d18caSSean Farley  * Print entire environ array.
44143d18caSSean Farley  */
452966d28cSSean Farley static void
462966d28cSSean Farley dump_environ(void)
472966d28cSSean Farley {
482966d28cSSean Farley 	char **environPtr;
492966d28cSSean Farley 
50143d18caSSean Farley 	for (environPtr = environ; *environPtr != NULL; environPtr++)
512966d28cSSean Farley 		printf("%s\n", *environPtr);
522966d28cSSean Farley 
532966d28cSSean Farley 	return;
542966d28cSSean Farley }
552966d28cSSean Farley 
562966d28cSSean Farley 
57143d18caSSean Farley /*
58143d18caSSean Farley  * Print usage.
59143d18caSSean Farley  */
602966d28cSSean Farley static void
612966d28cSSean Farley usage(const char *program)
622966d28cSSean Farley {
6320f492f0SBrian Feldman 	fprintf(stderr, "Usage:  %s [-DGUchrt] [-c 1|2|3|4] [-bgu name] "
643522c38bSSean Farley 	    "[-p name=value]\n"
653522c38bSSean Farley 	    "\t[(-S|-s name) value overwrite]\n\n"
662966d28cSSean Farley 	    "Options:\n"
672966d28cSSean Farley 	    "  -D\t\t\t\tDump environ\n"
682966d28cSSean Farley 	    "  -G name\t\t\tgetenv(NULL)\n"
692966d28cSSean Farley 	    "  -S value overwrite\t\tsetenv(NULL, value, overwrite)\n"
702966d28cSSean Farley 	    "  -U\t\t\t\tunsetenv(NULL)\n"
7120f492f0SBrian Feldman 	    "  -b name\t\t\tblank the 'name=$name' entry, corrupting it\n"
723522c38bSSean Farley 	    "  -c 1|2|3|4\t\t\tClear environ variable using method:\n"
733522c38bSSean Farley 	    "\t\t\t\t1 - set environ to NULL pointer\n"
743522c38bSSean Farley 	    "\t\t\t\t2 - set environ[0] to NULL pointer\n"
753522c38bSSean Farley 	    "\t\t\t\t3 - set environ to calloc()'d NULL-terminated array\n"
763522c38bSSean Farley 	    "\t\t\t\t4 - set environ to static NULL-terminated array\n"
772966d28cSSean Farley 	    "  -g name\t\t\tgetenv(name)\n"
782966d28cSSean Farley 	    "  -h\t\t\t\tHelp\n"
792966d28cSSean Farley 	    "  -p name=value\t\t\tputenv(name=value)\n"
809bab2367SSean Farley 	    "  -r\t\t\t\treplace environ with { \"FOO=bar\", NULL }\n"
812966d28cSSean Farley 	    "  -s name value overwrite\tsetenv(name, value, overwrite)\n"
822966d28cSSean Farley 	    "  -t\t\t\t\tOutput is suitable for testing (no newlines)\n"
832966d28cSSean Farley 	    "  -u name\t\t\tunsetenv(name)\n",
842966d28cSSean Farley 	    basename(program));
852966d28cSSean Farley 
862966d28cSSean Farley 	return;
872966d28cSSean Farley }
882966d28cSSean Farley 
892966d28cSSean Farley 
90143d18caSSean Farley /*
91143d18caSSean Farley  * Print the return value of a call along with errno upon error else zero.
92143d18caSSean Farley  * Also, use the eol string based upon whether running in test mode or not.
93143d18caSSean Farley  */
94143d18caSSean Farley static void
95143d18caSSean Farley print_rtrn_errno(int rtrnVal, const char *eol)
96143d18caSSean Farley {
97143d18caSSean Farley 	printf("%d %d%s", rtrnVal, rtrnVal != 0 ? errno : 0, eol);
98143d18caSSean Farley 
99143d18caSSean Farley 	return;
100143d18caSSean Farley }
101143d18caSSean Farley 
10220f492f0SBrian Feldman static void
10320f492f0SBrian Feldman blank_env(const char *var)
10420f492f0SBrian Feldman {
10520f492f0SBrian Feldman 	char **newenviron;
10620f492f0SBrian Feldman 	int n, varlen;
10720f492f0SBrian Feldman 
10820f492f0SBrian Feldman 	if (environ == NULL)
10920f492f0SBrian Feldman 		return;
11020f492f0SBrian Feldman 
11120f492f0SBrian Feldman 	for (n = 0; environ[n] != NULL; n++)
11220f492f0SBrian Feldman 		;
11320f492f0SBrian Feldman 	newenviron = malloc(sizeof(char *) * (n + 1));
11420f492f0SBrian Feldman 	varlen = strlen(var);
11520f492f0SBrian Feldman 	for (; n >= 0; n--) {
11620f492f0SBrian Feldman 		newenviron[n] = environ[n];
11720f492f0SBrian Feldman 		if (newenviron[n] != NULL &&
11820f492f0SBrian Feldman 		    strncmp(newenviron[n], var, varlen) == 0 &&
11920f492f0SBrian Feldman 		    newenviron[n][varlen] == '=')
12020f492f0SBrian Feldman 			newenviron[n] += strlen(newenviron[n]);
12120f492f0SBrian Feldman 	}
12220f492f0SBrian Feldman 	environ = newenviron;
12320f492f0SBrian Feldman }
124143d18caSSean Farley 
1252966d28cSSean Farley int
1262966d28cSSean Farley main(int argc, char **argv)
1272966d28cSSean Farley {
1282966d28cSSean Farley 	char arg;
1292966d28cSSean Farley 	const char *eol = "\n";
1302966d28cSSean Farley 	const char *value;
1313522c38bSSean Farley 	static char *emptyEnv[] = { NULL };
1323522c38bSSean Farley 	static char *staticEnv[] = { "FOO=bar", NULL };
1332966d28cSSean Farley 
1342966d28cSSean Farley 	if (argc == 1) {
1352966d28cSSean Farley 		usage(argv[0]);
1362966d28cSSean Farley 		exit(EXIT_FAILURE);
1372966d28cSSean Farley 	}
1382966d28cSSean Farley 
139143d18caSSean Farley 	/* The entire program is basically executed from this loop. */
14020f492f0SBrian Feldman 	while ((arg = getopt(argc, argv, "DGS:Ub:c:g:hp:rs:tu:")) != -1) {
1412966d28cSSean Farley 		switch (arg) {
14220f492f0SBrian Feldman 		case 'b':
14320f492f0SBrian Feldman 			blank_env(optarg);
14420f492f0SBrian Feldman 			break;
14520f492f0SBrian Feldman 
1463522c38bSSean Farley 		case 'c':
1473522c38bSSean Farley 			switch (atoi(optarg)) {
1483522c38bSSean Farley 			case 1:
1499bab2367SSean Farley 				environ = NULL;
1502966d28cSSean Farley 				break;
1512966d28cSSean Farley 
1523522c38bSSean Farley 			case 2:
1533522c38bSSean Farley 				environ[0] = NULL;
1543522c38bSSean Farley 				break;
1553522c38bSSean Farley 
1563522c38bSSean Farley 			case 3:
1579bab2367SSean Farley 				environ = calloc(1, sizeof(*environ));
1589bab2367SSean Farley 				break;
1599bab2367SSean Farley 
1603522c38bSSean Farley 			case 4:
1613522c38bSSean Farley 				environ = emptyEnv;
1623522c38bSSean Farley 				break;
1633522c38bSSean Farley 			}
1643522c38bSSean Farley 			break;
1653522c38bSSean Farley 
1669bab2367SSean Farley 		case 'D':
1679bab2367SSean Farley 			dump_environ();
1682966d28cSSean Farley 			break;
1692966d28cSSean Farley 
1702966d28cSSean Farley 		case 'G':
1712966d28cSSean Farley 		case 'g':
172143d18caSSean Farley 			value = getenv(arg == 'g' ? optarg : NULL);
1738cfaf5a9SSean Farley 			printf("%s%s", value == NULL ? "*NULL*" : value, eol);
1742966d28cSSean Farley 			break;
1752966d28cSSean Farley 
1762966d28cSSean Farley 		case 'p':
177143d18caSSean Farley 			print_rtrn_errno(putenv(optarg), eol);
1782966d28cSSean Farley 			break;
1792966d28cSSean Farley 
1809bab2367SSean Farley 		case 'r':
1819bab2367SSean Farley 			environ = staticEnv;
1829bab2367SSean Farley 			break;
1839bab2367SSean Farley 
1842966d28cSSean Farley 		case 'S':
185143d18caSSean Farley 			print_rtrn_errno(setenv(NULL, optarg,
186143d18caSSean Farley 			    atoi(argv[optind])), eol);
1872966d28cSSean Farley 			optind += 1;
1882966d28cSSean Farley 			break;
1892966d28cSSean Farley 
1902966d28cSSean Farley 		case 's':
191143d18caSSean Farley 			print_rtrn_errno(setenv(optarg, argv[optind],
192143d18caSSean Farley 			    atoi(argv[optind + 1])), eol);
1932966d28cSSean Farley 			optind += 2;
1942966d28cSSean Farley 			break;
1952966d28cSSean Farley 
1962966d28cSSean Farley 		case 't':
1972966d28cSSean Farley 			eol = " ";
1982966d28cSSean Farley 			break;
1992966d28cSSean Farley 
2002966d28cSSean Farley 		case 'U':
2012966d28cSSean Farley 		case 'u':
20286168e15SSean Farley 			print_rtrn_errno(unsetenv(arg == 'u' ? optarg : NULL),
20386168e15SSean Farley 			    eol);
2042966d28cSSean Farley 			break;
2052966d28cSSean Farley 
2062966d28cSSean Farley 		case 'h':
2072966d28cSSean Farley 		default:
2082966d28cSSean Farley 			usage(argv[0]);
2092966d28cSSean Farley 			exit(EXIT_FAILURE);
2102966d28cSSean Farley 		}
2112966d28cSSean Farley 	}
2122966d28cSSean Farley 
213143d18caSSean Farley 	/* Output a closing newline in test mode. */
2142966d28cSSean Farley 	if (eol[0] == ' ')
2152966d28cSSean Farley 		printf("\n");
2162966d28cSSean Farley 
2172966d28cSSean Farley 	return (EXIT_SUCCESS);
2182966d28cSSean Farley }
219