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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 589 - (hide annotations) (download) (as text)
Thu May 11 03:10:43 2006 UTC (18 years, 1 month ago) by johnpye
File MIME type: text/x-csrc
File size: 12536 byte(s)
Fixing some malloc bugs.
1 aw0a 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 johnpye 399 #include "ascConfig.h"
38     #include "ascPanic.h"
39     #include "ascMalloc.h"
40     #include "ascEnvVar.h"
41     #include <general/list.h>
42 aw0a 1
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 johnpye 341
70 aw0a 1 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 jds 103 ascfree(ev->name);
105 aw0a 1 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 johnpye 589 struct asc_env_t *FindEnvVar(const char *name)
132 aw0a 1 {
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 johnpye 62 //FPRINTF(ASCERR,"ENV VAR '%s' NOT FOUND\n",name);
140 aw0a 1 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 jds 59 int Asc_InitEnvironment(unsigned long len)
176 aw0a 1 {
177 jds 59 if (g_env_list != NULL) {
178 aw0a 1 return 1;
179     }
180 jds 59 g_env_list = gl_create(len);
181     if (g_env_list == NULL) {
182 aw0a 1 return 1;
183     }
184     return 0;
185     }
186    
187 jds 59
188 aw0a 1 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 jds 59
199 aw0a 1 int Asc_SetPathList(CONST char *envvar, CONST char *pathstring)
200     {
201 jds 59 char g_path_var[MAX_ENV_VAR_LENGTH];
202     unsigned int c, length, spcseen=0;
203 aw0a 1 struct asc_env_t *ev;
204     char *keepname;
205     CONST char *path;
206     char *putenvstring;
207    
208 jds 59 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 aw0a 1 return 1;
215     }
216     /*
217 jds 59 * transform envvar into a string w/out lead/trail blanks and copy.
218 aw0a 1 */
219     putenvstring = g_path_var;
220 jds 59 snprintf(putenvstring, MAX_ENV_VAR_LENGTH, "%s", envvar);
221 aw0a 1 /* 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 jds 59 /* backup to before last trailing space */
231 aw0a 1 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 jds 59 strncpy(keepname, putenvstring, c);
244 aw0a 1 keepname[c] = '\0';
245 jds 59 /* delete the old variable if it was already assigned */
246 aw0a 1 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 jds 59 AppendEnvVar(g_env_list, ev);
256    
257     /*
258 johnpye 341 * copy/split the pathstring
259 jds 59 */
260 aw0a 1 path = pathstring;
261    
262 jds 59 /* strip any leading whitespace */
263 aw0a 1 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 jds 59 while(( *path != PATHDIV ) &&
270     ( *path != '\0' ) &&
271     ( length < (MAX_ENV_VAR_LENGTH - 1) )) {
272 aw0a 1 g_path_var[length++] = *(path++);
273     }
274 jds 59 /* 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 aw0a 1 }
280 jds 59 /* otherwise advance to the next substring in path */
281     else {
282     while(( *path != PATHDIV ) && ( *path != '\0' )) {
283     path++;
284     }
285 aw0a 1 }
286 jds 59 /* 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 aw0a 1 while( isspace(*path) || ( *path == PATHDIV ) ) path++;
295     }
296     return 0;
297     }
298    
299 jds 59
300 johnpye 341 int Asc_PutEnv(CONST char *envstring)
301 aw0a 1 {
302 jds 59 char g_path_var[MAX_ENV_VAR_LENGTH];
303     unsigned int c, length, spcseen=0, rhs;
304 aw0a 1 struct asc_env_t *ev;
305     char *keepname, *path, *putenvstring;
306    
307 jds 59 if ((g_env_list == NULL) ||
308     (envstring == NULL) ||
309     (strlen(envstring) == 0) ||
310     (strlen(envstring) >= MAX_ENV_VAR_LENGTH)) {
311 aw0a 1 return 1;
312     }
313 jds 59
314 aw0a 1 putenvstring = g_path_var;
315 jds 59 snprintf(putenvstring, MAX_ENV_VAR_LENGTH, "%s", envstring);
316 aw0a 1 /* trim leading whitespace */
317     while (isspace(putenvstring[0])) {
318     putenvstring++;
319     }
320 jds 59 /* locate '=' or EOS, counting whitespace along the way */
321 aw0a 1 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 jds 59 /* delete the old variable if it was already assigned */
347 aw0a 1 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 jds 103
357 aw0a 1 AppendEnvVar(g_env_list,ev);
358 jds 59 path = putenvstring + rhs + 1; /* got past the '=' */
359 aw0a 1
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 jds 59 while (( length > 0 ) && isspace(g_path_var[length-1])) {
370 aw0a 1 length--;
371     }
372 jds 59 if ( length > 0) {
373     g_path_var[length++] = '\0';
374     if (Asc_AppendPath(keepname,g_path_var)!=0) {
375     return 1;
376     }
377 aw0a 1 }
378     while( isspace(*path) || ( *path == PATHDIV ) ) path++;
379     }
380     return 0;
381     }
382    
383 jds 59
384 aw0a 1 int Asc_ImportPathList(CONST char *envvar)
385     {
386 jds 59 char *rhs;
387    
388     if (( g_env_list == NULL ) ||
389     ( envvar == NULL ) ||
390     ( strlen(envvar) == 0 )) {
391 aw0a 1 return 1;
392     }
393     rhs = getenv(envvar);
394 johnpye 589 if (( rhs == NULL ) || ( strlen(rhs) == 0 )) {
395 aw0a 1 return 1;
396     }
397 jds 59 return Asc_SetPathList(envvar, rhs);
398 aw0a 1 }
399    
400 jds 59
401 aw0a 1 int Asc_AppendPath(char *envvar, char *newelement)
402     {
403     struct asc_env_t *ev;
404     char *keepname, *keepval;
405 jds 59
406     if ((g_env_list == NULL) ||
407     (envvar == NULL) ||
408     (newelement == NULL) ||
409     (strlen(envvar) == 0) ||
410     (strlen(newelement) == 0)) {
411 aw0a 1 return 1;
412     }
413     ev = FindEnvVar(envvar);
414     if (ev == NULL) {
415 jds 103 keepname = ascstrdup(envvar);
416 aw0a 1 if (keepname == NULL) {
417     return 1;
418     }
419     ev = CreateEnvVar(keepname);
420     if (ev == NULL) {
421     ascfree(keepname);
422     return 1;
423     }
424 jds 59 AppendEnvVar(g_env_list, ev);
425 aw0a 1 }
426 jds 103 keepval = ascstrdup(newelement);
427 jds 59
428 aw0a 1 if (keepval == NULL) {
429     return 1;
430     }
431 jds 59 gl_append_ptr(ev->data, keepval);
432 aw0a 1 return 0;
433     }
434    
435 jds 59
436 aw0a 1 char **Asc_GetPathList(char *envvar, int *argc)
437     {
438     struct asc_env_t *ev;
439     char **argv;
440     char *tmppos, *val;
441 jds 59 unsigned long len, c, slen;
442 aw0a 1
443 jds 59 if ( argc == NULL ) {
444     return NULL;
445     }
446     if (( g_env_list == NULL ) ||
447     ( envvar == NULL )) {
448 johnpye 62 FPRINTF(ASCERR,"G_ENV_LIST IS NULL LOOKING FOR %s\n",envvar);
449 aw0a 1 *argc = -1;
450     return NULL;
451     }
452 jds 59 if ( strlen(envvar) == 0 ) {
453 aw0a 1 *argc = 0;
454     return NULL;
455     }
456     ev = FindEnvVar(envvar);
457     if (ev==NULL ) {
458 johnpye 62 FPRINTF(ASCERR,"UNABLE TO FINDENVVAR %s\n",envvar);
459    
460 aw0a 1 *argc = 0;
461     return NULL;
462     }
463 jds 59 len = gl_length(ev->data);
464     slen = (len+1)*sizeof(char *); /* space for argv pointers */
465 aw0a 1 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 jds 59 if ( argv == NULL ) {
471 aw0a 1 *argc = -1;
472     return NULL;
473     }
474     tmppos = (char *)argv;
475     tmppos += (len+1)*sizeof(char *);
476 jds 59 for (c = 1 ; c <= len ; c++) {
477 aw0a 1 val = (char *)gl_fetch(ev->data,(unsigned long)c);
478     argv[c-1] = tmppos;
479 jds 59 while ( *val != '\0' ) {
480     *tmppos++ = *val++;
481     }
482     *tmppos++ = *val; /* include trailing '\0' */
483 aw0a 1 }
484     argv[len] = NULL;
485     *argc = (int)len;
486     return argv;
487     }
488    
489 jds 59
490 johnpye 586 char *Asc_GetEnv(const char *envvar)
491 aw0a 1 {
492     struct asc_env_t *ev;
493     char *result, *val, *tmppos;
494 jds 59 unsigned long slen, c, llen;
495    
496     if ((g_env_list == NULL) ||
497     (envvar == NULL) ||
498     (strlen(envvar) == 0)) {
499 aw0a 1 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 jds 59 while (*val != '\0') {
518     *tmppos++ = *val++;
519     }
520     *tmppos++ = PATHDIV; /* include delimiter */
521 aw0a 1 }
522 jds 59 result[slen-1] = '\0'; /* overwrite final trailing delimiter */
523 aw0a 1 return result;
524     }
525    
526 jds 59
527 aw0a 1 char **Asc_EnvNames(int *argc)
528     {
529     char **argv;
530     unsigned long c, len;
531 jds 59
532 aw0a 1 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