new tool
[hband-tools.git] / compiled-tools / loadenv.c
blob359807a28887558e7c1ef0ce79dcb8dd80668276
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <err.h>
6 #include <string.h>
7 #include <tool/libarray.h>
9 static char* helptext =
10 "Usage: loadenv [-0c] <FILE> <COMMAND> [<ARG> [...]]\n"
11 "See loadenv(1).\n"
15 struct dedupdata {
16 size_t envnamelen;
17 char * env;
18 Array** envarray;
21 array_loop_control
22 remove_duplicate(array_index_t index, char* item, struct dedupdata * dedupdata)
24 if(strchr(item, '=')-item == dedupdata->envnamelen && strncmp(item, dedupdata->env, dedupdata->envnamelen) == 0)
26 array_delete(dedupdata->envarray, index, 1);
27 return ARRAY_LOOP_STOP;
29 return ARRAY_LOOP_CONTINUE;
32 #ifdef DEBUG
33 array_loop_control
34 pprint(array_index_t index, char * item, void * x)
36 warnx("index %d item %s", index, item);
37 return ARRAY_LOOP_CONTINUE;
39 #endif
41 int main(int argc, char** argv, char** current_env)
43 FILE * envfile;
44 Array* envarray;
45 unsigned char argidx;
46 unsigned char delimiter;
47 char * env;
48 size_t envsize;
49 size_t envnamelen;
50 ssize_t read_status;
51 char * envval;
52 struct dedupdata dedupdata;
53 unsigned char copy_current_environment;
54 unsigned int it;
56 delimiter = '\n';
57 copy_current_environment = 0;
58 argidx = 1;
60 while(argidx < argc)
62 if(strcmp(argv[argidx], "-0")==0)
64 delimiter = '\0';
66 else if(strcmp(argv[argidx], "-c")==0)
68 copy_current_environment = 1;
70 else if(strcmp(argv[argidx], "--help")==0)
72 printf("%s", helptext);
73 exit(0);
75 else if(argv[argidx][0] == '-')
77 errx(-2, "unknown option: %s", argv[argidx]);
79 else {
80 break;
82 argidx++;
85 if(argidx+1 < argc)
87 if(envfile = fopen(argv[argidx], "r"))
89 array_init(&envarray, 2);
91 /* copy current environment */
92 if(copy_current_environment)
94 for(it = 0; current_env[it] != NULL; it++)
96 array_append(&envarray, current_env[it]);
100 /* read up environments from file */
101 while(1)
103 env = NULL;
104 envsize = 0;
105 read_status = getdelim(&env, &envsize, delimiter, envfile);
106 if(read_status == -1) break;
107 if(!env) goto read_next_env;
109 // chomp
110 envsize = strlen(env);
111 if(envsize == 0) goto read_next_env;
112 if(env[envsize-1] == delimiter) env[envsize-1] = '\0';
113 envsize = strlen(env);
115 // ignore empty
116 if(envsize == 0) goto read_next_env;
118 // ignore comments
119 if(delimiter == '\n' && env[0] == '#') goto read_next_env;
121 // locate value
122 envval = strchr(env, '=');
124 if(envval == NULL)
126 // remove the named environment variable if it's a name only without '=' equal sign in it.
127 dedupdata.envnamelen = envsize;
128 dedupdata.env = env;
129 dedupdata.envarray = &envarray;
130 array_foreach(&envarray, 0, (array_loop_control(*)(array_index_t, char*, void*))remove_duplicate, &dedupdata);
132 else
134 envval++; // envval point past to the '=' equal sign
136 #ifdef DEBUG
137 array_foreach(&envarray, 0, pprint, NULL);
138 #endif
140 // deduplicate
141 dedupdata.envnamelen = envval - env - 1;
142 dedupdata.env = env;
143 dedupdata.envarray = &envarray;
144 array_foreach(&envarray, 0, (array_loop_control(*)(array_index_t, char*, void*))remove_duplicate, &dedupdata);
146 // add to the env list
147 array_append(&envarray, env);
150 read_next_env:
151 if(env) free(env);
154 array_append(&envarray, NULL);
156 else
158 perror("fopen");
159 goto fail;
162 #ifdef DEBUG
163 array_foreach(&envarray, 0, pprint, NULL);
164 #endif
166 execvpe(argv[argidx+1], &argv[argidx+1], array_getarray(&envarray));
167 goto fail;
169 else
171 fprintf(stderr, "%s", helptext);
172 exit(-2);
175 fail:
176 return errno == 0 ? -1 : errno;