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

Contents of /trunk/ascend/utilities/ascEnvVar.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2525 - (show annotations) (download) (as text)
Thu Jan 19 22:01:31 2012 UTC (12 years, 4 months ago) by jpye
File MIME type: text/x-csrc
File size: 12527 byte(s)
Couple more minor tests for ascEnvVar for leading whitespace etc.
Formatting changes.
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 <ascend/general/platform.h>
38 #include <ascend/general/panic.h>
39 #include <ascend/general/ascMalloc.h>
40 #include "ascEnvVar.h"
41 #include <ascend/general/list.h>
42
43 #ifdef __WIN32__
44 #define SLASH '\\'
45 #define PATHDIV ';'
46 #else /* ! __WIN32__ */
47 #define SLASH '/'
48 #define PATHDIV ':'
49 #endif
50
51 /*
52 * structure we have for each envvar.
53 * each contains a list with pointers to strings.
54 */
55 struct asc_env_t {
56 const char *name;
57 struct gl_list_t *data;
58 };
59
60 /*
61 * This list is a list of pointer to struct asc_env_t's
62 * that constitute the environment.
63 */
64
65 static
66 struct gl_list_t *g_env_list = NULL;
67
68 /*
69 * ev = CreateEnvVar(envvar_name_we_own);
70 * Returns NULL, or the asc_env_t requested.
71 * The requested has an empty gl_list.
72 * The name sent is the user's responsibility if we
73 * return NULL, OTHERWISE it is henceforth ours.
74 * We do not append the requested to the global list; that is the
75 * caller's job.
76 */
77 static
78 struct asc_env_t *CreateEnvVar(char *keepname)
79 {
80 struct asc_env_t *ev;
81 ev = ASC_NEW(struct asc_env_t);
82 if (ev == NULL) {
83 return NULL;
84 }
85 ev->data = gl_create(4);
86 ev->name = keepname;
87 return ev;
88 }
89
90 /*
91 * clear out a env variable data blob.
92 */
93 static
94 void DestroyEnvVar(struct asc_env_t *ev)
95 {
96 if (ev==NULL) {
97 return;
98 }
99 ascfree((char *)ev->name);
100 gl_free_and_destroy(ev->data);
101 ascfree(ev);
102 }
103
104 /*
105 * compare two env variable data blobs by name.
106 */
107
108 CmpFunc CmpEv;
109
110 static
111 int CmpEV(struct asc_env_t *ev1, struct asc_env_t *ev2)
112 {
113 if (ev1==ev2) {
114 return 0;
115 }
116 if (ev1==NULL || ev1->name == NULL) {
117 return 1;
118 }
119 if (ev2==NULL || ev2->name == NULL) {
120 return -1;
121 }
122 return strcmp(ev1->name,ev2->name);
123 }
124
125 /*
126 * returns the envvar with the name specified.
127 */
128 static
129 struct asc_env_t *FindEnvVar(const char *name)
130 {
131 unsigned long pos;
132 struct asc_env_t dummy;
133
134 dummy.name = name;
135 pos = gl_search(g_env_list,&dummy,(CmpFunc)CmpEV);
136 if (pos==0) {
137 #if 0
138 FPRINTF(ASCERR,"ENV VAR '%s' NOT FOUND\n",name);
139 #endif
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 = ASC_NEW_ARRAY(char,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
317 /* trim leading whitespace */
318 while(isspace(putenvstring[0])) {
319 putenvstring++;
320 }
321
322 /* locate '=' or EOS, counting whitespace along the way */
323 for(c = 0; putenvstring[c] !='\0' && putenvstring[c] != '='; c++){
324 if(isspace(putenvstring[c])){
325 spcseen++;
326 }
327 }
328
329 /* check for empty rhs */
330 if(putenvstring[c] == '\0'){
331 return 1;
332 }
333 rhs = c;
334
335 if(c == 0){
336 /* '=' is at start of string */
337 return 1;
338 }
339
340 /* backup space before = */
341 while(isspace(putenvstring[c-1])){
342 c--;
343 spcseen--;
344 }
345 /* check for no spaces in keepname */
346 if(spcseen){
347 return 1;
348 }
349 keepname = ASC_NEW_ARRAY(char,c+1);
350 if(keepname == NULL){
351 return 1;
352 }
353 strncpy(keepname,putenvstring,c);
354 keepname[c] = '\0';
355 /* delete the old variable if it was already assigned */
356 ev = FindEnvVar(keepname);
357 if(ev!=NULL){
358 DeleteEnvVar(keepname);
359 }
360 ev = CreateEnvVar(keepname);
361
362 if(ev == NULL){
363 ascfree(keepname);
364 return 1;
365 }
366
367 AppendEnvVar(g_env_list,ev);
368 path = putenvstring + rhs + 1; /* got past the '=' */
369
370 while(isspace(*path)){
371 path++;
372 }
373 while(*path != '\0'){
374 length = 0;
375 /* copy the directory from path to the g_path_var */
376 while((*path != PATHDIV) && (*path != '\0')){
377 g_path_var[length++] = *(path++);
378 }
379 while((length > 0) && isspace(g_path_var[length-1])){
380 length--;
381 }
382 if(length > 0){
383 g_path_var[length++] = '\0';
384 if(Asc_AppendPath(keepname,g_path_var)!=0) {
385 return 1;
386 }
387 }
388 while(isspace(*path) || ( *path == PATHDIV))path++;
389 }
390 return 0;
391 }
392
393
394 int Asc_ImportPathList(CONST char *envvar)
395 {
396 char *rhs;
397
398 if (( g_env_list == NULL ) ||
399 ( envvar == NULL ) ||
400 ( strlen(envvar) == 0 )) {
401 return 1;
402 }
403 rhs = getenv(envvar);
404 if (( rhs == NULL ) || ( strlen(rhs) == 0 )) {
405 return 1;
406 }
407 return Asc_SetPathList(envvar, rhs);
408 }
409
410
411 int Asc_AppendPath(char *envvar, char *newelement)
412 {
413 struct asc_env_t *ev;
414 char *keepname, *keepval;
415
416 if ((g_env_list == NULL) ||
417 (envvar == NULL) ||
418 (newelement == NULL) ||
419 (strlen(envvar) == 0) ||
420 (strlen(newelement) == 0)) {
421 return 1;
422 }
423 ev = FindEnvVar(envvar);
424 if (ev == NULL) {
425 keepname = ASC_STRDUP(envvar);
426 if (keepname == NULL) {
427 return 1;
428 }
429 ev = CreateEnvVar(keepname);
430 if (ev == NULL) {
431 ascfree(keepname);
432 return 1;
433 }
434 AppendEnvVar(g_env_list, ev);
435 }
436 keepval = ASC_STRDUP(newelement);
437
438 if (keepval == NULL) {
439 return 1;
440 }
441 gl_append_ptr(ev->data, keepval);
442 return 0;
443 }
444
445 const char **Asc_GetPathList(const char *envvar, int *argc){
446 struct asc_env_t *ev;
447 CONST char **argv;
448 char *tmppos, *val;
449 unsigned long len, c, slen;
450
451 if ( argc == NULL ) {
452 return NULL;
453 }
454 if (( g_env_list == NULL ) ||
455 ( envvar == NULL )) {
456 //FPRINTF(ASCERR,"G_ENV_LIST IS NULL LOOKING FOR %s\n",envvar);
457 *argc = -1;
458 return NULL;
459 }
460 if ( strlen(envvar) == 0 ) {
461 *argc = 0;
462 return NULL;
463 }
464 ev = FindEnvVar(envvar);
465 if (ev==NULL ) {
466 //FPRINTF(ASCERR,"UNABLE TO FINDENVVAR %s\n",envvar);
467
468 *argc = 0;
469 return NULL;
470 }
471 len = gl_length(ev->data);
472 slen = (len+1)*sizeof(char *); /* space for argv pointers */
473 for (c = 1; c <= len; c++) {
474 /* space for the values */
475 slen += (strlen((char *)gl_fetch(ev->data,(unsigned long)c)) +1 );
476 }
477 argv = ASC_NEW_ARRAY(CONST char *,slen);
478 if ( argv == NULL ) {
479 *argc = -1;
480 return NULL;
481 }
482 tmppos = (char *)argv;
483 tmppos += (len+1)*sizeof(char *);
484 for (c = 1 ; c <= len ; c++) {
485 val = (char *)gl_fetch(ev->data,(unsigned long)c);
486 argv[c-1] = tmppos;
487 while ( *val != '\0' ) {
488 *tmppos++ = *val++;
489 }
490 *tmppos++ = *val; /* include trailing '\0' */
491 }
492 argv[len] = NULL;
493 *argc = (int)len;
494 return argv;
495 }
496
497
498 char *Asc_GetEnv(const char *envvar)
499 {
500 struct asc_env_t *ev;
501 char *result, *val, *tmppos;
502 unsigned long slen, c, llen;
503
504 if ((g_env_list == NULL) ||
505 (envvar == NULL) ||
506 (strlen(envvar) == 0)) {
507 return NULL;
508 }
509 ev = FindEnvVar(envvar);
510 if (ev==NULL ) {
511 return NULL;
512 }
513 slen = 0;
514 llen = gl_length(ev->data);
515 for (c = 1; c <= llen; c++) {
516 slen += (strlen((char *)gl_fetch(ev->data,(unsigned long)c)) +1 );
517 }
518 result = ASC_NEW_ARRAY(char,slen+1);
519 if (result == NULL) {
520 return NULL;
521 }
522 tmppos = result;
523 for (c = 1; c <= llen; c++) {
524 val = (char *)gl_fetch(ev->data,(unsigned long)c);
525 while (*val != '\0') {
526 *tmppos++ = *val++;
527 }
528 *tmppos++ = PATHDIV; /* include delimiter */
529 }
530 result[slen-1] = '\0'; /* overwrite final trailing delimiter */
531 return result;
532 }
533
534
535 const char **Asc_EnvNames(int *argc)
536 {
537 const char **argv;
538 unsigned long c, len;
539
540 if (g_env_list == NULL) {
541 *argc = -1;
542 return NULL;
543 }
544 len = gl_length(g_env_list);
545 *argc = (int)len;
546 argv = ASC_NEW_ARRAY(CONST char *,*argc + 1);
547 if (argv==NULL) {
548 *argc = -1;
549 return NULL;
550 }
551 for (c = 1; c <= len; c++) {
552 argv[c-1] = ((struct asc_env_t *)gl_fetch(g_env_list,c))->name;
553 }
554 argv[len] = NULL;
555 return argv;
556 }

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