1*59814Shibler /* env.c - manipulate environment and execute a program 2*59814Shibler in that environment 3*59814Shibler Mly 861126 4*59814Shibler 5*59814Shibler Copyright (C) 1986 Free Software Foundation, Inc. 6*59814Shibler 7*59814Shibler This program is free software; you can redistribute it and/or modify 8*59814Shibler it under the terms of the GNU General Public License as published by 9*59814Shibler the Free Software Foundation; either version 1, or (at your option) 10*59814Shibler any later version. 11*59814Shibler 12*59814Shibler This program is distributed in the hope that it will be useful, 13*59814Shibler but WITHOUT ANY WARRANTY; without even the implied warranty of 14*59814Shibler MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*59814Shibler GNU General Public License for more details. 16*59814Shibler 17*59814Shibler You should have received a copy of the GNU General Public License 18*59814Shibler along with this program; if not, write to the Free Software 19*59814Shibler Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*59814Shibler 21*59814Shibler In other words, you are welcome to use, share and improve this program. 22*59814Shibler You are forbidden to forbid anyone else to use, share and improve 23*59814Shibler what you give them. Help stamp out software-hoarding! */ 24*59814Shibler 25*59814Shibler /* 26*59814Shibler 27*59814Shibler If first argument is "-", then a new environment is constructed 28*59814Shibler from scratch; otherwise the environment is inherited from the parent 29*59814Shibler process, except as modified by other options. 30*59814Shibler 31*59814Shibler So, "env - foo" will invoke the "foo" program in a null environment, 32*59814Shibler whereas "env foo" would invoke "foo" in the same environment as that 33*59814Shibler passed to "env" itself. 34*59814Shibler 35*59814Shibler Subsequent arguments are interpreted as follows: 36*59814Shibler 37*59814Shibler * "variable=value" (ie an arg containing a "=" character) 38*59814Shibler means to set the specified environment variable to that value. 39*59814Shibler `value' may be of zero length ("variable="). Note that setting 40*59814Shibler a variable to a zero-length value is different from unsetting it. 41*59814Shibler 42*59814Shibler * "-u variable" or "-unset variable" 43*59814Shibler means to unset that variable 44*59814Shibler If that variable isn't set, does nothing. 45*59814Shibler 46*59814Shibler * "-s variable value" or "-set variable value" 47*59814Shibler same as "variable=value" 48*59814Shibler 49*59814Shibler * "-" or "--" 50*59814Shibler are used to indicate that the following argument is the program 51*59814Shibler to invoke. This is only necessary when the program's name 52*59814Shibler begins with "-" or contains a "=" 53*59814Shibler 54*59814Shibler * anything else 55*59814Shibler The first remaining argument specifies a program to invoke 56*59814Shibler (it is searched for according to the specification of the PATH 57*59814Shibler environment variable) and any arguments following that are 58*59814Shibler passed as arguments to that program 59*59814Shibler 60*59814Shibler If no program-name is specified following the environment 61*59814Shibler specifications the the resulting environment is printed 62*59814Shibler (The is like specifying a program-name of "printenv") 63*59814Shibler 64*59814Shibler Examples: 65*59814Shibler If the environment passed to "env" is 66*59814Shibler { USER=rms EDITOR=emacs PATH=.:/gnubin:/hacks } 67*59814Shibler 68*59814Shibler * "env DISPLAY=gnu:0 nemacs" 69*59814Shibler calls "nemacs" in the envionment 70*59814Shibler { EDITOR=emacs USER=rms DISPLAY=gnu } 71*59814Shibler 72*59814Shibler * "env - USER=foo /hacks/hack bar baz" 73*59814Shibler will call the "hack" program on arguments "bar" and "baz" 74*59814Shibler in an environment in which the only variable is "USER" 75*59814Shibler Note that the "-" option will clear out the PATH variable, 76*59814Shibler so one should be careful to specify in which directory 77*59814Shibler to find the program to call 78*59814Shibler 79*59814Shibler * "env -u EDITOR USER=foo PATH=/energy -- e=mc2 bar baz" 80*59814Shibler The program "/energy/e=mc2" is called with environment 81*59814Shibler { USER=foo PATH=/energy } 82*59814Shibler 83*59814Shibler */ 84*59814Shibler 85*59814Shibler #ifdef EMACS 86*59814Shibler #define NO_SHORTNAMES 87*59814Shibler #include "../src/config.h" 88*59814Shibler #endif /* EMACS */ 89*59814Shibler 90*59814Shibler #include <stdio.h> 91*59814Shibler 92*59814Shibler extern int execvp (); 93*59814Shibler extern char *index (); 94*59814Shibler 95*59814Shibler char *xmalloc (), *xrealloc (); 96*59814Shibler char *concat (); 97*59814Shibler 98*59814Shibler extern char **environ; 99*59814Shibler 100*59814Shibler char **nenv; 101*59814Shibler int nenv_size; 102*59814Shibler 103*59814Shibler char *progname; 104*59814Shibler void setenv (); 105*59814Shibler void fatal (); 106*59814Shibler 107*59814Shibler main (argc, argv, envp) 108*59814Shibler register int argc; 109*59814Shibler register char **argv; 110*59814Shibler char **envp; 111*59814Shibler { 112*59814Shibler register char *tem; 113*59814Shibler 114*59814Shibler progname = argv[0]; 115*59814Shibler argc--; 116*59814Shibler argv++; 117*59814Shibler 118*59814Shibler nenv_size = 100; 119*59814Shibler nenv = (char **) xmalloc (nenv_size * sizeof (char *)); 120*59814Shibler *nenv = (char *) 0; 121*59814Shibler 122*59814Shibler /* "-" flag means to not inherit parent's environment */ 123*59814Shibler if (argc && !strcmp (*argv, "-")) 124*59814Shibler { 125*59814Shibler argc--; 126*59814Shibler argv++; 127*59814Shibler } 128*59814Shibler else 129*59814Shibler /* Else pass on existing env vars. */ 130*59814Shibler for (; *envp; envp++) 131*59814Shibler { 132*59814Shibler tem = index (*envp, '='); 133*59814Shibler if (tem) 134*59814Shibler { 135*59814Shibler *tem = '\000'; 136*59814Shibler setenv (*envp, tem + 1); 137*59814Shibler } 138*59814Shibler } 139*59814Shibler 140*59814Shibler while (argc > 0) 141*59814Shibler { 142*59814Shibler tem = index (*argv, '='); 143*59814Shibler if (tem) 144*59814Shibler /* If arg contains a "=" it specifies to set a variable */ 145*59814Shibler { 146*59814Shibler *tem = '\000'; 147*59814Shibler setenv (*argv, tem + 1); 148*59814Shibler argc--; argv++; 149*59814Shibler continue; 150*59814Shibler } 151*59814Shibler 152*59814Shibler if (**argv != '-') 153*59814Shibler /* Remaining args are program name and args to pass it */ 154*59814Shibler break; 155*59814Shibler 156*59814Shibler if (argc < 2) 157*59814Shibler fatal ("No argument following \"%s\" switch", *argv); 158*59814Shibler if (!strcmp (*argv, "-u") || 159*59814Shibler !strcmp (*argv, "-unset")) 160*59814Shibler /* Unset a variable */ 161*59814Shibler { 162*59814Shibler argc--; argv++; 163*59814Shibler setenv (*argv, 0); 164*59814Shibler argc--; argv++; 165*59814Shibler } 166*59814Shibler else if (!strcmp (*argv, "-s") || 167*59814Shibler !strcmp (*argv, "-set")) 168*59814Shibler /* Set a variable */ 169*59814Shibler { 170*59814Shibler argc--; argv++; 171*59814Shibler tem = *argv; 172*59814Shibler if (argc < 2) 173*59814Shibler fatal ("No value specified for variable \"%s\"", 174*59814Shibler tem); 175*59814Shibler argc--; argv++; 176*59814Shibler setenv (tem, *argv); 177*59814Shibler argc--; argv++; 178*59814Shibler } 179*59814Shibler else if (!strcmp (*argv, "-") || !strcmp (*argv, "--")) 180*59814Shibler { 181*59814Shibler argc--; argv++; 182*59814Shibler break; 183*59814Shibler } 184*59814Shibler else 185*59814Shibler { 186*59814Shibler fatal ("unknown switch \"%s\"", *argv); 187*59814Shibler } 188*59814Shibler } 189*59814Shibler 190*59814Shibler /* If no program specified print the environment and exit */ 191*59814Shibler if (argc <= 0) 192*59814Shibler { 193*59814Shibler while (*nenv) 194*59814Shibler printf ("%s\n", *nenv++); 195*59814Shibler exit (0); 196*59814Shibler } 197*59814Shibler else 198*59814Shibler { 199*59814Shibler extern int errno, sys_nerr; 200*59814Shibler extern char *sys_errlist[]; 201*59814Shibler 202*59814Shibler environ = nenv; 203*59814Shibler (void) execvp (*argv, argv); 204*59814Shibler 205*59814Shibler fprintf (stderr, "%s: Cannot execute \"%s\"", 206*59814Shibler progname, *argv); 207*59814Shibler if (errno < sys_nerr) 208*59814Shibler fprintf (stderr, ": %s\n" , sys_errlist[errno]); 209*59814Shibler else 210*59814Shibler putc ('\n', stderr); 211*59814Shibler exit (errno != 0 ? errno : 1); 212*59814Shibler } 213*59814Shibler } 214*59814Shibler 215*59814Shibler void 216*59814Shibler setenv (var, val) 217*59814Shibler register char *var, *val; 218*59814Shibler { 219*59814Shibler register char **e; 220*59814Shibler int len = strlen (var); 221*59814Shibler 222*59814Shibler { 223*59814Shibler register char *tem = index (var, '='); 224*59814Shibler if (tem) 225*59814Shibler fatal ("Environment variable names may not contain \"=\": %s", 226*59814Shibler var); 227*59814Shibler else if (*var == '\000') 228*59814Shibler fatal ("Zero-length environment variable name specified."); 229*59814Shibler } 230*59814Shibler 231*59814Shibler for (e = nenv; *e; e++) 232*59814Shibler if (!strncmp (var, *e, len) && 233*59814Shibler (*e)[len] == '=') 234*59814Shibler { 235*59814Shibler if (val) 236*59814Shibler goto set; 237*59814Shibler else 238*59814Shibler do { *e = *(e + 1); } while (*e++); 239*59814Shibler return; 240*59814Shibler } 241*59814Shibler 242*59814Shibler if (!val) 243*59814Shibler return; /* Nothing to unset */ 244*59814Shibler 245*59814Shibler len = e - nenv; 246*59814Shibler if (len + 1 >= nenv_size) 247*59814Shibler { 248*59814Shibler nenv_size += 100; 249*59814Shibler nenv = (char **) xrealloc (nenv, nenv_size * sizeof (char *)); 250*59814Shibler e = nenv + len; 251*59814Shibler } 252*59814Shibler 253*59814Shibler set: 254*59814Shibler val = concat (var, "=", val); 255*59814Shibler if (*e) 256*59814Shibler free (*e); 257*59814Shibler else 258*59814Shibler *(e + 1) = (char *) 0; 259*59814Shibler *e = val; 260*59814Shibler return; 261*59814Shibler } 262*59814Shibler 263*59814Shibler void 264*59814Shibler fatal (msg, arg1, arg2) 265*59814Shibler char *msg, *arg1, *arg2; 266*59814Shibler { 267*59814Shibler fprintf (stderr, "%s: ", progname); 268*59814Shibler fprintf (stderr, msg, arg1, arg2); 269*59814Shibler putc ('\n', stderr); 270*59814Shibler exit (1); 271*59814Shibler } 272*59814Shibler 273*59814Shibler 274*59814Shibler extern char *malloc (), *realloc (); 275*59814Shibler 276*59814Shibler void 277*59814Shibler memory_fatal () 278*59814Shibler { 279*59814Shibler fatal ("Out of memory"); 280*59814Shibler } 281*59814Shibler 282*59814Shibler char * 283*59814Shibler xmalloc (size) 284*59814Shibler int size; 285*59814Shibler { 286*59814Shibler register char *value; 287*59814Shibler value = (char *) malloc (size); 288*59814Shibler if (!value) memory_fatal (); 289*59814Shibler return (value); 290*59814Shibler } 291*59814Shibler 292*59814Shibler char * 293*59814Shibler xrealloc (ptr, size) 294*59814Shibler char *ptr; 295*59814Shibler int size; 296*59814Shibler { 297*59814Shibler register char *value; 298*59814Shibler value = (char *) realloc (ptr, size); 299*59814Shibler if (!value) memory_fatal (); 300*59814Shibler return (value); 301*59814Shibler } 302*59814Shibler 303*59814Shibler /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */ 304*59814Shibler 305*59814Shibler char * 306*59814Shibler concat (s1, s2, s3) 307*59814Shibler char *s1, *s2, *s3; 308*59814Shibler { 309*59814Shibler int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); 310*59814Shibler char *result = (char *) xmalloc (len1 + len2 + len3 + 1); 311*59814Shibler 312*59814Shibler strcpy (result, s1); 313*59814Shibler strcpy (result + len1, s2); 314*59814Shibler strcpy (result + len1 + len2, s3); 315*59814Shibler *(result + len1 + len2 + len3) = 0; 316*59814Shibler 317*59814Shibler return result; 318*59814Shibler } 319*59814Shibler 320*59814Shibler 321*59814Shibler /* 322*59814Shibler * Local variables: 323*59814Shibler * compile-command: "cc -g -o env env.c" 324*59814Shibler * end: 325*59814Shibler */ 326