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