/[ascend]/trunk/base/generic/utilities/ascEnvVar.c
ViewVC logotype

Contents of /trunk/base/generic/utilities/ascEnvVar.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 586 - (show annotations) (download) (as text)
Thu May 11 00:47:54 2006 UTC (14 years, 6 months ago) by johnpye
File MIME type: text/x-csrc
File size: 12533 byte(s)
Working on improving handling of paths.
1 /*
2 * Ascend Environment Variable Imitation
3 * by Ben Allan
4 * Created: 6/3/97
5 * Version: $Revision: 1.5 $
6 * Version control file: $RCSfile: ascEnvVar.c,v $
7 * Date last modified: $Date: 1997/07/18 12:04:07 $
8 * Last modified by: $Author: mthomas $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1997 Benjamin Andrew Allan
13 *
14 * The Ascend Language Interpreter is free software; you can redistribute
15 * it and/or modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * The Ascend Language Interpreter is distributed in hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with the program; if not, write to the Free Software Foundation,
26 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
27 * COPYING.
28 *
29 * This file exists because win32, among others, can't keep their
30 * POSIX compliance up. In particular, getting and setting
31 * environment vars is exceedingly unreliable.
32 * This file implements a general way to store and fetch multiple
33 * paths.
34 */
35
36 #include <ctype.h>
37 #include "ascConfig.h"
38 #include "ascPanic.h"
39 #include "ascMalloc.h"
40 #include "ascEnvVar.h"
41 #include <general/list.h>
42
43 #ifndef lint
44 static CONST char ascEnvVarid[] = "$Id: ascEnvVar.c,v 1.5 1997/07/18 12:04:07 mthomas Exp $";
45 #endif /* RCS ID keyword */
46
47
48 #ifdef __WIN32__
49 #define SLASH '\\'
50 #define PATHDIV ';'
51 #else /* ! __WIN32__ */
52 #define SLASH '/'
53 #define PATHDIV ':'
54 #endif
55
56 /*
57 * structure we have for each envvar.
58 * each contains a list with pointers to strings.
59 */
60 struct asc_env_t {
61 char *name;
62 struct gl_list_t *data;
63 };
64
65 /*
66 * This list is a list of pointer to struct asc_env_t's
67 * that constitute the environment.
68 */
69
70 static
71 struct gl_list_t *g_env_list = NULL;
72
73 /*
74 * ev = CreateEnvVar(envvar_name_we_own);
75 * Returns NULL, or the asc_env_t requested.
76 * The requested has an empty gl_list.
77 * The name sent is the user's responsibility if we
78 * return NULL, OTHERWISE it is henceforth ours.
79 * We do not append the requested to the global list; that is the
80 * caller's job.
81 */
82 static
83 struct asc_env_t *CreateEnvVar(char *keepname)
84 {
85 struct asc_env_t *ev;
86 ev = (struct asc_env_t *)ascmalloc(sizeof(struct asc_env_t));
87 if (ev == NULL) {
88 return NULL;
89 }
90 ev->data = gl_create(4);
91 ev->name = keepname;
92 return ev;
93 }
94
95 /*
96 * clear out a env variable data blob.
97 */
98 static
99 void DestroyEnvVar(struct asc_env_t *ev)
100 {
101 if (ev==NULL) {
102 return;
103 }
104 ascfree(ev->name);
105 gl_free_and_destroy(ev->data);
106 ascfree(ev);
107 }
108
109 /*
110 * compare two env variable data blobs by name.
111 */
112 static
113 int CmpEV(struct asc_env_t *ev1, struct asc_env_t *ev2)
114 {
115 if (ev1==ev2) {
116 return 0;
117 }
118 if (ev1==NULL || ev1->name == NULL) {
119 return 1;
120 }
121 if (ev2==NULL || ev2->name == NULL) {
122 return -1;
123 }
124 return strcmp(ev1->name,ev2->name);
125 }
126
127 /*
128 * returns the envvar with the name specified.
129 */
130 static
131 struct asc_env_t *FindEnvVar(char *name)
132 {
133 unsigned long pos;
134 struct asc_env_t dummy;
135
136 dummy.name = name;
137 pos = gl_search(g_env_list,&dummy,(CmpFunc)CmpEV);
138 if (pos==0) {
139 //FPRINTF(ASCERR,"ENV VAR '%s' NOT FOUND\n",name);
140 return NULL;
141 }
142 return (struct asc_env_t *)gl_fetch(g_env_list,pos);
143 }
144
145 /*
146 * add a var to the global sorted list.
147 */
148 static
149 void AppendEnvVar(struct gl_list_t *env, struct asc_env_t *ev)
150 {
151 gl_insert_sorted(env,ev,(CmpFunc)CmpEV);
152 }
153
154 /*
155 * removes and destroys a var in the environment, if it exists.
156 */
157 static
158 void DeleteEnvVar(char *name)
159 {
160 unsigned long pos;
161 struct asc_env_t *ev;
162 struct asc_env_t dummy;
163
164 dummy.name = name;
165
166 if (name == NULL || g_env_list == NULL) {
167 return;
168 }
169 pos = gl_search(g_env_list,&dummy,(CmpFunc)CmpEV);
170 ev = (struct asc_env_t *)gl_fetch(g_env_list,pos);
171 gl_delete(g_env_list,pos,0);
172 DestroyEnvVar(ev);
173 }
174
175 int Asc_InitEnvironment(unsigned long len)
176 {
177 if (g_env_list != NULL) {
178 return 1;
179 }
180 g_env_list = gl_create(len);
181 if (g_env_list == NULL) {
182 return 1;
183 }
184 return 0;
185 }
186
187
188 void Asc_DestroyEnvironment(void)
189 {
190 if (g_env_list == NULL) {
191 return;
192 }
193 gl_iterate(g_env_list,(void (*)(VOIDPTR))DestroyEnvVar);
194 gl_destroy(g_env_list);
195 g_env_list = NULL;
196 }
197
198
199 int Asc_SetPathList(CONST char *envvar, CONST char *pathstring)
200 {
201 char g_path_var[MAX_ENV_VAR_LENGTH];
202 unsigned int c, length, spcseen=0;
203 struct asc_env_t *ev;
204 char *keepname;
205 CONST char *path;
206 char *putenvstring;
207
208 if ((g_env_list == NULL) ||
209 (envvar == NULL) ||
210 (strlen(envvar) == 0) ||
211 (pathstring == NULL) ||
212 (strlen(pathstring) == 0) ||
213 (strlen(envvar) >= MAX_ENV_VAR_LENGTH)) {
214 return 1;
215 }
216 /*
217 * transform envvar into a string w/out lead/trail blanks and copy.
218 */
219 putenvstring = g_path_var;
220 snprintf(putenvstring, MAX_ENV_VAR_LENGTH, "%s", envvar);
221 /* trim leading whitespace */
222 while (isspace(putenvstring[0])) {
223 putenvstring++;
224 }
225 for (c = 0; putenvstring[c] !='\0'; c++) {
226 if (isspace(putenvstring[c])) {
227 spcseen++;
228 }
229 }
230 /* backup to before last trailing space */
231 while (isspace(putenvstring[c-1])) {
232 c--;
233 spcseen--;
234 }
235 /* check for no spaces in keepname */
236 if (spcseen) {
237 return 1;
238 }
239 keepname = (char *)ascmalloc(c+1);
240 if (keepname == NULL) {
241 return 1;
242 }
243 strncpy(keepname, putenvstring, c);
244 keepname[c] = '\0';
245 /* delete the old variable if it was already assigned */
246 ev = FindEnvVar(keepname);
247 if (ev!=NULL) {
248 DeleteEnvVar(keepname);
249 }
250 ev = CreateEnvVar(keepname);
251 if (ev == NULL) {
252 ascfree(keepname);
253 return 1;
254 }
255 AppendEnvVar(g_env_list, ev);
256
257 /*
258 * copy/split the pathstring
259 */
260 path = pathstring;
261
262 /* strip any leading whitespace */
263 while( isspace( *path ) ) {
264 path++;
265 }
266 while( *path != '\0' ) {
267 length = 0;
268 /* copy the directory from path to the g_path_var */
269 while(( *path != PATHDIV ) &&
270 ( *path != '\0' ) &&
271 ( length < (MAX_ENV_VAR_LENGTH - 1) )) {
272 g_path_var[length++] = *(path++);
273 }
274 /* if we didn't run out of room, strip trailing whitespace */
275 if (( length > 0) && ( length < (MAX_ENV_VAR_LENGTH - 1) )) {
276 while (isspace(g_path_var[length-1])) {
277 length--;
278 }
279 }
280 /* otherwise advance to the next substring in path */
281 else {
282 while(( *path != PATHDIV ) && ( *path != '\0' )) {
283 path++;
284 }
285 }
286 /* append the value if not empty */
287 if ( length > 0 ) {
288 g_path_var[length++] = '\0';
289 if ( Asc_AppendPath(keepname,g_path_var) != 0 ) {
290 return 1;
291 }
292 }
293 /* advance path past any whitespace & delimiters */
294 while( isspace(*path) || ( *path == PATHDIV ) ) path++;
295 }
296 return 0;
297 }
298
299
300 int Asc_PutEnv(CONST char *envstring)
301 {
302 char g_path_var[MAX_ENV_VAR_LENGTH];
303 unsigned int c, length, spcseen=0, rhs;
304 struct asc_env_t *ev;
305 char *keepname, *path, *putenvstring;
306
307 if ((g_env_list == NULL) ||
308 (envstring == NULL) ||
309 (strlen(envstring) == 0) ||
310 (strlen(envstring) >= MAX_ENV_VAR_LENGTH)) {
311 return 1;
312 }
313
314 putenvstring = g_path_var;
315 snprintf(putenvstring, MAX_ENV_VAR_LENGTH, "%s", envstring);
316 /* trim leading whitespace */
317 while (isspace(putenvstring[0])) {
318 putenvstring++;
319 }
320 /* locate '=' or EOS, counting whitespace along the way */
321 for (c = 0; putenvstring[c] !='\0' && putenvstring[c] != '='; c++) {
322 if (isspace(putenvstring[c])) {
323 spcseen++;
324 }
325 }
326 /* check for empty rhs */
327 if (putenvstring[c] == '\0') {
328 return 1;
329 }
330 rhs = c;
331 /* backup space before = */
332 while (isspace(putenvstring[c-1])) {
333 c--;
334 spcseen--;
335 }
336 /* check for no spaces in keepname */
337 if (spcseen) {
338 return 1;
339 }
340 keepname = (char *)ascmalloc(c+1);
341 if (keepname == NULL) {
342 return 1;
343 }
344 strncpy(keepname,putenvstring,c);
345 keepname[c] = '\0';
346 /* delete the old variable if it was already assigned */
347 ev = FindEnvVar(keepname);
348 if (ev!=NULL) {
349 DeleteEnvVar(keepname);
350 }
351 ev = CreateEnvVar(keepname);
352 if (ev == NULL) {
353 ascfree(keepname);
354 return 1;
355 }
356
357 AppendEnvVar(g_env_list,ev);
358 path = putenvstring + rhs + 1; /* got past the '=' */
359
360 while( isspace( *path ) ) {
361 path++;
362 }
363 while( *path != '\0' ) {
364 length = 0;
365 /* copy the directory from path to the g_path_var */
366 while(( *path != PATHDIV ) && ( *path != '\0' )) {
367 g_path_var[length++] = *(path++);
368 }
369 while (( length > 0 ) && isspace(g_path_var[length-1])) {
370 length--;
371 }
372 if ( length > 0) {
373 g_path_var[length++] = '\0';
374 if (Asc_AppendPath(keepname,g_path_var)!=0) {
375 return 1;
376 }
377 }
378 while( isspace(*path) || ( *path == PATHDIV ) ) path++;
379 }
380 return 0;
381 }
382
383
384 int Asc_ImportPathList(CONST char *envvar)
385 {
386 char *rhs;
387
388 if (( g_env_list == NULL ) ||
389 ( envvar == NULL ) ||
390 ( strlen(envvar) == 0 )) {
391 return 1;
392 }
393 rhs = getenv(envvar);
394 if (( rhs == NULL ) || ( strlen(rhs) == '\0' )) {
395 return 1;
396 }
397 return Asc_SetPathList(envvar, rhs);
398 }
399
400
401 int Asc_AppendPath(char *envvar, char *newelement)
402 {
403 struct asc_env_t *ev;
404 char *keepname, *keepval;
405
406 if ((g_env_list == NULL) ||
407 (envvar == NULL) ||
408 (newelement == NULL) ||
409 (strlen(envvar) == 0) ||
410 (strlen(newelement) == 0)) {
411 return 1;
412 }
413 ev = FindEnvVar(envvar);
414 if (ev == NULL) {
415 keepname = ascstrdup(envvar);
416 if (keepname == NULL) {
417 return 1;
418 }
419 ev = CreateEnvVar(keepname);
420 if (ev == NULL) {
421 ascfree(keepname);
422 return 1;
423 }
424 AppendEnvVar(g_env_list, ev);
425 }
426 keepval = ascstrdup(newelement);
427
428 if (keepval == NULL) {
429 return 1;
430 }
431 gl_append_ptr(ev->data, keepval);
432 return 0;
433 }
434
435
436 char **Asc_GetPathList(char *envvar, int *argc)
437 {
438 struct asc_env_t *ev;
439 char **argv;
440 char *tmppos, *val;
441 unsigned long len, c, slen;
442
443 if ( argc == NULL ) {
444 return NULL;
445 }
446 if (( g_env_list == NULL ) ||
447 ( envvar == NULL )) {
448 FPRINTF(ASCERR,"G_ENV_LIST IS NULL LOOKING FOR %s\n",envvar);
449 *argc = -1;
450 return NULL;
451 }
452 if ( strlen(envvar) == 0 ) {
453 *argc = 0;
454 return NULL;
455 }
456 ev = FindEnvVar(envvar);
457 if (ev==NULL ) {
458 FPRINTF(ASCERR,"UNABLE TO FINDENVVAR %s\n",envvar);
459
460 *argc = 0;
461 return NULL;
462 }
463 len = gl_length(ev->data);
464 slen = (len+1)*sizeof(char *); /* space for argv pointers */
465 for (c = 1; c <= len; c++) {
466 /* space for the values */
467 slen += (strlen((char *)gl_fetch(ev->data,(unsigned long)c)) +1 );
468 }
469 argv = (char **)ascmalloc(slen);
470 if ( argv == NULL ) {
471 *argc = -1;
472 return NULL;
473 }
474 tmppos = (char *)argv;
475 tmppos += (len+1)*sizeof(char *);
476 for (c = 1 ; c <= len ; c++) {
477 val = (char *)gl_fetch(ev->data,(unsigned long)c);
478 argv[c-1] = tmppos;
479 while ( *val != '\0' ) {
480 *tmppos++ = *val++;
481 }
482 *tmppos++ = *val; /* include trailing '\0' */
483 }
484 argv[len] = NULL;
485 *argc = (int)len;
486 return argv;
487 }
488
489
490 char *Asc_GetEnv(const char *envvar)
491 {
492 struct asc_env_t *ev;
493 char *result, *val, *tmppos;
494 unsigned long slen, c, llen;
495
496 if ((g_env_list == NULL) ||
497 (envvar == NULL) ||
498 (strlen(envvar) == 0)) {
499 return NULL;
500 }
501 ev = FindEnvVar(envvar);
502 if (ev==NULL ) {
503 return NULL;
504 }
505 slen = 0;
506 llen = gl_length(ev->data);
507 for (c = 1; c <= llen; c++) {
508 slen += (strlen((char *)gl_fetch(ev->data,(unsigned long)c)) +1 );
509 }
510 result = (char *)ascmalloc(slen+1);
511 if (result == NULL) {
512 return NULL;
513 }
514 tmppos = result;
515 for (c = 1; c <= llen; c++) {
516 val = (char *)gl_fetch(ev->data,(unsigned long)c);
517 while (*val != '\0') {
518 *tmppos++ = *val++;
519 }
520 *tmppos++ = PATHDIV; /* include delimiter */
521 }
522 result[slen-1] = '\0'; /* overwrite final trailing delimiter */
523 return result;
524 }
525
526
527 char **Asc_EnvNames(int *argc)
528 {
529 char **argv;
530 unsigned long c, len;
531
532 if (g_env_list == NULL) {
533 *argc = -1;
534 return NULL;
535 }
536 len = gl_length(g_env_list);
537 *argc = (int)len;
538 argv = (char **)ascmalloc((*argc + 1)*sizeof(char *));
539 if (argv==NULL) {
540 *argc = -1;
541 return NULL;
542 }
543 for (c = 1; c <= len; c++) {
544 argv[c-1] = ((struct asc_env_t *)gl_fetch(g_env_list,c))->name;
545 }
546 argv[len] = NULL;
547 return argv;
548 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22