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