/[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 956 - (show annotations) (download) (as text)
Sat Dec 9 15:38:05 2006 UTC (17 years ago) by johnpye
File MIME type: text/x-csrc
File size: 12581 byte(s)
Removed references to 'ASC_BIG_BUGMAIL' and 'ASC_MILD_BUGMAIL'
Disabled stream redirection functions (they were making testing difficult)
Re-wrote the main test-runner to permit specific tests to be run from the commandline (ongoing)
Disabled readln tests that required stream redirection.
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 const 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 = ASC_NEW(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((char *)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
113 CmpFunc CmpEv;
114
115 static
116 int CmpEV(struct asc_env_t *ev1, struct asc_env_t *ev2)
117 {
118 if (ev1==ev2) {
119 return 0;
120 }
121 if (ev1==NULL || ev1->name == NULL) {
122 return 1;
123 }
124 if (ev2==NULL || ev2->name == NULL) {
125 return -1;
126 }
127 return strcmp(ev1->name,ev2->name);
128 }
129
130 /*
131 * returns the envvar with the name specified.
132 */
133 static
134 struct asc_env_t *FindEnvVar(const char *name)
135 {
136 unsigned long pos;
137 struct asc_env_t dummy;
138
139 dummy.name = name;
140 pos = gl_search(g_env_list,&dummy,(CmpFunc)CmpEV);
141 if (pos==0) {
142 #if 0
143 FPRINTF(ASCERR,"ENV VAR '%s' NOT FOUND\n",name);
144 #endif
145 return NULL;
146 }
147 return (struct asc_env_t *)gl_fetch(g_env_list,pos);
148 }
149
150 /*
151 * add a var to the global sorted list.
152 */
153 static
154 void AppendEnvVar(struct gl_list_t *env, struct asc_env_t *ev)
155 {
156 gl_insert_sorted(env,ev,(CmpFunc)CmpEV);
157 }
158
159 /*
160 * removes and destroys a var in the environment, if it exists.
161 */
162 static
163 void DeleteEnvVar(char *name)
164 {
165 unsigned long pos;
166 struct asc_env_t *ev;
167 struct asc_env_t dummy;
168
169 dummy.name = name;
170
171 if (name == NULL || g_env_list == NULL) {
172 return;
173 }
174 pos = gl_search(g_env_list,&dummy,(CmpFunc)CmpEV);
175 ev = (struct asc_env_t *)gl_fetch(g_env_list,pos);
176 gl_delete(g_env_list,pos,0);
177 DestroyEnvVar(ev);
178 }
179
180 int Asc_InitEnvironment(unsigned long len)
181 {
182 if (g_env_list != NULL) {
183 return 1;
184 }
185 g_env_list = gl_create(len);
186 if (g_env_list == NULL) {
187 return 1;
188 }
189 return 0;
190 }
191
192
193 void Asc_DestroyEnvironment(void)
194 {
195 if (g_env_list == NULL) {
196 return;
197 }
198 gl_iterate(g_env_list,(void (*)(VOIDPTR))DestroyEnvVar);
199 gl_destroy(g_env_list);
200 g_env_list = NULL;
201 }
202
203
204 int Asc_SetPathList(CONST char *envvar, CONST char *pathstring)
205 {
206 char g_path_var[MAX_ENV_VAR_LENGTH];
207 unsigned int c, length, spcseen=0;
208 struct asc_env_t *ev;
209 char *keepname;
210 CONST char *path;
211 char *putenvstring;
212
213 if ((g_env_list == NULL) ||
214 (envvar == NULL) ||
215 (strlen(envvar) == 0) ||
216 (pathstring == NULL) ||
217 (strlen(pathstring) == 0) ||
218 (strlen(envvar) >= MAX_ENV_VAR_LENGTH)) {
219 return 1;
220 }
221 /*
222 * transform envvar into a string w/out lead/trail blanks and copy.
223 */
224 putenvstring = g_path_var;
225 snprintf(putenvstring, MAX_ENV_VAR_LENGTH, "%s", envvar);
226 /* trim leading whitespace */
227 while (isspace(putenvstring[0])) {
228 putenvstring++;
229 }
230 for (c = 0; putenvstring[c] !='\0'; c++) {
231 if (isspace(putenvstring[c])) {
232 spcseen++;
233 }
234 }
235 /* backup to before last trailing space */
236 while (isspace(putenvstring[c-1])) {
237 c--;
238 spcseen--;
239 }
240 /* check for no spaces in keepname */
241 if (spcseen) {
242 return 1;
243 }
244 keepname = ASC_NEW_ARRAY(char,c+1);
245 if (keepname == NULL) {
246 return 1;
247 }
248 strncpy(keepname, putenvstring, c);
249 keepname[c] = '\0';
250 /* delete the old variable if it was already assigned */
251 ev = FindEnvVar(keepname);
252 if (ev!=NULL) {
253 DeleteEnvVar(keepname);
254 }
255 ev = CreateEnvVar(keepname);
256 if (ev == NULL) {
257 ascfree(keepname);
258 return 1;
259 }
260 AppendEnvVar(g_env_list, ev);
261
262 /*
263 * copy/split the pathstring
264 */
265 path = pathstring;
266
267 /* strip any leading whitespace */
268 while( isspace( *path ) ) {
269 path++;
270 }
271 while( *path != '\0' ) {
272 length = 0;
273 /* copy the directory from path to the g_path_var */
274 while(( *path != PATHDIV ) &&
275 ( *path != '\0' ) &&
276 ( length < (MAX_ENV_VAR_LENGTH - 1) )) {
277 g_path_var[length++] = *(path++);
278 }
279 /* if we didn't run out of room, strip trailing whitespace */
280 if (( length > 0) && ( length < (MAX_ENV_VAR_LENGTH - 1) )) {
281 while (isspace(g_path_var[length-1])) {
282 length--;
283 }
284 }
285 /* otherwise advance to the next substring in path */
286 else {
287 while(( *path != PATHDIV ) && ( *path != '\0' )) {
288 path++;
289 }
290 }
291 /* append the value if not empty */
292 if ( length > 0 ) {
293 g_path_var[length++] = '\0';
294 if ( Asc_AppendPath(keepname,g_path_var) != 0 ) {
295 return 1;
296 }
297 }
298 /* advance path past any whitespace & delimiters */
299 while( isspace(*path) || ( *path == PATHDIV ) ) path++;
300 }
301 return 0;
302 }
303
304
305 int Asc_PutEnv(CONST char *envstring)
306 {
307 char g_path_var[MAX_ENV_VAR_LENGTH];
308 unsigned int c, length, spcseen=0, rhs;
309 struct asc_env_t *ev;
310 char *keepname, *path, *putenvstring;
311
312 if ((g_env_list == NULL) ||
313 (envstring == NULL) ||
314 (strlen(envstring) == 0) ||
315 (strlen(envstring) >= MAX_ENV_VAR_LENGTH)) {
316 return 1;
317 }
318
319 putenvstring = g_path_var;
320 snprintf(putenvstring, MAX_ENV_VAR_LENGTH, "%s", envstring);
321 /* trim leading whitespace */
322 while (isspace(putenvstring[0])) {
323 putenvstring++;
324 }
325 /* locate '=' or EOS, counting whitespace along the way */
326 for (c = 0; putenvstring[c] !='\0' && putenvstring[c] != '='; c++) {
327 if (isspace(putenvstring[c])) {
328 spcseen++;
329 }
330 }
331 /* check for empty rhs */
332 if (putenvstring[c] == '\0') {
333 return 1;
334 }
335 rhs = c;
336 /* backup space before = */
337 while (isspace(putenvstring[c-1])) {
338 c--;
339 spcseen--;
340 }
341 /* check for no spaces in keepname */
342 if (spcseen) {
343 return 1;
344 }
345 keepname = ASC_NEW_ARRAY(char,c+1);
346 if (keepname == NULL) {
347 return 1;
348 }
349 strncpy(keepname,putenvstring,c);
350 keepname[c] = '\0';
351 /* delete the old variable if it was already assigned */
352 ev = FindEnvVar(keepname);
353 if (ev!=NULL) {
354 DeleteEnvVar(keepname);
355 }
356 ev = CreateEnvVar(keepname);
357 if (ev == NULL) {
358 ascfree(keepname);
359 return 1;
360 }
361
362 AppendEnvVar(g_env_list,ev);
363 path = putenvstring + rhs + 1; /* got past the '=' */
364
365 while( isspace( *path ) ) {
366 path++;
367 }
368 while( *path != '\0' ) {
369 length = 0;
370 /* copy the directory from path to the g_path_var */
371 while(( *path != PATHDIV ) && ( *path != '\0' )) {
372 g_path_var[length++] = *(path++);
373 }
374 while (( length > 0 ) && isspace(g_path_var[length-1])) {
375 length--;
376 }
377 if ( length > 0) {
378 g_path_var[length++] = '\0';
379 if (Asc_AppendPath(keepname,g_path_var)!=0) {
380 return 1;
381 }
382 }
383 while( isspace(*path) || ( *path == PATHDIV ) ) path++;
384 }
385 return 0;
386 }
387
388
389 int Asc_ImportPathList(CONST char *envvar)
390 {
391 char *rhs;
392
393 if (( g_env_list == NULL ) ||
394 ( envvar == NULL ) ||
395 ( strlen(envvar) == 0 )) {
396 return 1;
397 }
398 rhs = getenv(envvar);
399 if (( rhs == NULL ) || ( strlen(rhs) == 0 )) {
400 return 1;
401 }
402 return Asc_SetPathList(envvar, rhs);
403 }
404
405
406 int Asc_AppendPath(char *envvar, char *newelement)
407 {
408 struct asc_env_t *ev;
409 char *keepname, *keepval;
410
411 if ((g_env_list == NULL) ||
412 (envvar == NULL) ||
413 (newelement == NULL) ||
414 (strlen(envvar) == 0) ||
415 (strlen(newelement) == 0)) {
416 return 1;
417 }
418 ev = FindEnvVar(envvar);
419 if (ev == NULL) {
420 keepname = ascstrdup(envvar);
421 if (keepname == NULL) {
422 return 1;
423 }
424 ev = CreateEnvVar(keepname);
425 if (ev == NULL) {
426 ascfree(keepname);
427 return 1;
428 }
429 AppendEnvVar(g_env_list, ev);
430 }
431 keepval = ascstrdup(newelement);
432
433 if (keepval == NULL) {
434 return 1;
435 }
436 gl_append_ptr(ev->data, keepval);
437 return 0;
438 }
439
440
441 CONST char **Asc_GetPathList(CONST char *envvar, int *argc)
442 {
443 struct asc_env_t *ev;
444 CONST char **argv;
445 char *tmppos, *val;
446 unsigned long len, c, slen;
447
448 if ( argc == NULL ) {
449 return NULL;
450 }
451 if (( g_env_list == NULL ) ||
452 ( envvar == NULL )) {
453 FPRINTF(ASCERR,"G_ENV_LIST IS NULL LOOKING FOR %s\n",envvar);
454 *argc = -1;
455 return NULL;
456 }
457 if ( strlen(envvar) == 0 ) {
458 *argc = 0;
459 return NULL;
460 }
461 ev = FindEnvVar(envvar);
462 if (ev==NULL ) {
463 FPRINTF(ASCERR,"UNABLE TO FINDENVVAR %s\n",envvar);
464
465 *argc = 0;
466 return NULL;
467 }
468 len = gl_length(ev->data);
469 slen = (len+1)*sizeof(char *); /* space for argv pointers */
470 for (c = 1; c <= len; c++) {
471 /* space for the values */
472 slen += (strlen((char *)gl_fetch(ev->data,(unsigned long)c)) +1 );
473 }
474 argv = ASC_NEW_ARRAY(CONST char *,slen);
475 if ( argv == NULL ) {
476 *argc = -1;
477 return NULL;
478 }
479 tmppos = (char *)argv;
480 tmppos += (len+1)*sizeof(char *);
481 for (c = 1 ; c <= len ; c++) {
482 val = (char *)gl_fetch(ev->data,(unsigned long)c);
483 argv[c-1] = tmppos;
484 while ( *val != '\0' ) {
485 *tmppos++ = *val++;
486 }
487 *tmppos++ = *val; /* include trailing '\0' */
488 }
489 argv[len] = NULL;
490 *argc = (int)len;
491 return argv;
492 }
493
494
495 char *Asc_GetEnv(const char *envvar)
496 {
497 struct asc_env_t *ev;
498 char *result, *val, *tmppos;
499 unsigned long slen, c, llen;
500
501 if ((g_env_list == NULL) ||
502 (envvar == NULL) ||
503 (strlen(envvar) == 0)) {
504 return NULL;
505 }
506 ev = FindEnvVar(envvar);
507 if (ev==NULL ) {
508 return NULL;
509 }
510 slen = 0;
511 llen = gl_length(ev->data);
512 for (c = 1; c <= llen; c++) {
513 slen += (strlen((char *)gl_fetch(ev->data,(unsigned long)c)) +1 );
514 }
515 result = ASC_NEW_ARRAY(char,slen+1);
516 if (result == NULL) {
517 return NULL;
518 }
519 tmppos = result;
520 for (c = 1; c <= llen; c++) {
521 val = (char *)gl_fetch(ev->data,(unsigned long)c);
522 while (*val != '\0') {
523 *tmppos++ = *val++;
524 }
525 *tmppos++ = PATHDIV; /* include delimiter */
526 }
527 result[slen-1] = '\0'; /* overwrite final trailing delimiter */
528 return result;
529 }
530
531
532 const char **Asc_EnvNames(int *argc)
533 {
534 const char **argv;
535 unsigned long c, len;
536
537 if (g_env_list == NULL) {
538 *argc = -1;
539 return NULL;
540 }
541 len = gl_length(g_env_list);
542 *argc = (int)len;
543 argv = ASC_NEW_ARRAY(CONST char *,*argc + 1);
544 if (argv==NULL) {
545 *argc = -1;
546 return NULL;
547 }
548 for (c = 1; c <= len; c++) {
549 argv[c-1] = ((struct asc_env_t *)gl_fetch(g_env_list,c))->name;
550 }
551 argv[len] = NULL;
552 return argv;
553 }

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