|
|
1.1 root 1: static char _version[]="env version 1.0";
2: /*
3: * env - execute a command in an environment
4: *
5: * usage: env [-] [VARIABLE=value ...] [command args]
6: *
7: * Executes "command" with "args", modifying the existing environment
8: * by doing the requested assignments. The "-" option means that the
9: * environment should be _replaced_ with the list assignements, otherwise
10: * the assignments are added to the environment.
11: * If "command" is ommitted, the resulting environment is printed.
12: */
13:
14: #include <stdio.h>
15: #include <string.h>
16: #include <errno.h>
17:
18: #define BIG_NUMBER 2048
19: #define TRUE (1==1)
20: #define FALSE (1==0)
21: #define VAR_SEPERATOR '=' /* Seperates an environment variable
22: from its value. */
23:
24: void parse_args();
25: int arglen();
26: char **argcpy();
27: char **envncat();
28: int is_assignment();
29:
30: /* Flags that tell us about our arguments */
31: int replace_env = FALSE;
32: int have_command = FALSE;
33:
34: int assignment_count; /* Number of assignments to add to environment. */
35: char *first_assignment_argument = NULL;
36:
37: int i; /* Generic index, used repeatedly */
38:
39: char **new_argv; /* Build new command line here. */
40: char **new_envp; /* Build the new environment here. */
41:
42:
43: void
44: main(argc, argv, envp)
45: int argc;
46: char *argv[];
47: char *envp[];
48: {
49: /* Parse arguments. */
50: parse_args(argc, argv);
51:
52: /* Build the new environment. */
53:
54: if (! replace_env) {
55: /* Make enough space for the disjoint union of the two sets of
56: * environment assignments. This is a guarenteed upper bound.
57: */
58: new_envp = (char **) malloc( sizeof(char *)
59: * (arglen(envp)
60: + assignment_count + 1)
61: );
62: argcpy(new_envp, envp);
63: } else {
64: /* Otherwise, we only need enough space for the new
65: * environment.
66: */
67: new_envp = (char **) malloc( sizeof(char *)
68: * (assignment_count + 1)
69: );
70: } /* if (! replace_env) */
71:
72:
73: envncat(new_envp, first_assignment_argument, assignment_count);
74:
75:
76: /* Do something--either a command or print the environment. */
77: if (have_command) {
78: execvep(new_argv[0], new_argv, new_envp);
79: perror(new_argv[0]);
80: exit(1);
81: } else {
82: char **pntr;
83:
84: for (pntr = new_envp; *pntr != NULL; ++pntr){
85: printf("%s\n", *pntr);
86: } /* for pntr in new_envp */
87:
88: } /* if have_command */
89:
90: exit(0);
91: }
92:
93:
94: void
95: parse_args(argc, argv)
96: int argc;
97: char *argv[];
98: {
99: int current_arg;
100:
101: if (argc > 1) {
102: current_arg = 1; /* Start looking at the first argument. */
103:
104: /* - option -- Replace the existing environment. */
105: if (strcmp(argv[current_arg], "-") == 0) {
106: replace_env = TRUE;
107: ++current_arg;
108: } /* if first argument is "-" */
109:
110: /* Count the number of arguments which are assignments. */
111: for (assignment_count = 0;
112: current_arg < argc;
113: current_arg++, assignment_count++) {
114:
115: if (! is_assignment(argv[current_arg])) {
116: break;
117: }
118:
119: if (first_assignment_argument == NULL) {
120: first_assignment_argument = &argv[current_arg];
121: }
122:
123: } /* for (Count the assignments on the command line. ) */
124:
125:
126: if ( current_arg < argc ) {
127: /* We broke out of the assignment couting loop
128: * early--this must be a command.
129: */
130: new_argv = &argv[current_arg];
131: have_command = TRUE;
132: } /* if ( current_arg <= argc ) */
133:
134: } /* if there are any args */
135:
136: } /* void parse_args() */
137:
138:
139:
140: /* Count the number of arguments in an argument vector.
141: * arg_vector MUST be NULL terminated!
142: */
143: int
144: arglen(arg_vector)
145: char **arg_vector;
146: {
147: int count;
148:
149: for (count = 0; arg_vector[count] != NULL; ++count) {
150: }
151:
152: return(count);
153: } /* arglen() */
154:
155:
156: /* Copy src argument vector to dest argument vector (pointer copy only).
157: */
158: char **
159: argcpy(dest, src)
160: char **dest, **src;
161: {
162: while (*src != NULL) {
163: *dest++ = *src++;
164: } /* while (walk two pointers down envp and new_envp) */
165: *dest = NULL;
166: return (dest);
167: } /* char **argcpy() */
168:
169:
170:
171:
172: /* Merge one environment onto another, overwriting duplicate
173: * variable names. Compare at most n patterns.
174: */
175: char **
176: envncat(dest, src, n)
177: char **dest, **src;
178: int n;
179: {
180: char **dest_walker;
181: char *sep_loc; /* Seperator ("=") location in assignment */
182: int i;
183: int name_size; /* Number of characters in a given variable name */
184:
185: for (i=0; *src != NULL && i < n; ++i, ++src) {
186:
187: /* Extract the variable name from the assignment *src. */
188: if ((sep_loc = strchr(*src, VAR_SEPERATOR)) == NULL) {
189: fprintf(stderr,
190: "Programming error: %s is not an assignment\n",
191: *src);
192: exit(1);
193: }
194: name_size = sep_loc - *src;
195:
196: /* Look for variable part of *src in dest.
197: * Point at end if not found.
198: */
199: for(dest_walker = dest; *dest_walker != NULL; ++dest_walker) {
200:
201: /* NB: the + 1 is so the "=" is compared too. */
202: if(strncmp(*dest_walker, *src, name_size + 1) == 0) {
203: /* We have found an exact match. */
204: break;
205: } /* if *dest_walker and *src are same variable */
206:
207: } /* for Walk down dest environment */
208:
209: /* Checkpoint - *dest_walker either matches *src or is NULL. */
210:
211: /* WARNING: possible memory leak--
212: * *dest_walker is always clobbered.
213: * Usually *dest_walker was copied from global
214: * envp, so it isn't really lost memory.
215: */
216: *dest_walker = *src;
217:
218: } /* for (i=0; *src != NULL && i < n; ++i, ++src) */
219:
220: return(dest);
221: } /* char ** envncat() */
222:
223: int
224: is_assignment(s)
225: char *s;
226: {
227: if ( strchr(s, VAR_SEPERATOR) != NULL ) {
228: return(TRUE);
229: } else {
230: return(FALSE);
231: }
232:
233: } /* int is_assignment() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.