1 /*
2  * ENVIRON.C
3  *
4  * Written 1998 by Tobias Ernst and release to the Public Domain
5  *
6  * Environment variable (%MAILBOXDRIVE% -> E: and so on) expander.
7  */
8 
9 #include <string.h>
10 #include <ctype.h>
11 #include <stdlib.h>
12 #include "memextra.h"
13 
14 #undef isalnum
env_expand(char * line)15 char *env_expand(char *line)
16 { char *cpTemp;
17   char var[82]; char *cpvar, *cpsrc, *cpdest;
18   int isVar=0, l=0, invar=0;
19   size_t maxlen=2*strlen(line);
20 
21 start:
22   cpvar=var; cpsrc=line;
23   cpTemp=xmalloc(maxlen+1);
24   cpdest=cpTemp;
25 
26   while (*cpsrc)
27   { if (*cpsrc=='%')
28     {
29       if (isVar)
30       { *cpvar=0; isVar=0;
31 #ifndef UNIX
32         /* On all systems except unix, environment variables are stored in
33            uppercase alwys, but the user can access them via lowercase as
34            well. As getenv is case-sensitive, we uppercase the variable
35            name before passing it to getenv. */
36         for (cpvar=var;*cpvar;cpvar++)
37           *cpvar=toupper(*cpvar);
38 #endif
39         if (!strlen(var))
40         { *(cpdest++)='%'; if ((++l)>=maxlen) goto error; }
41         else
42             {
43           if ((cpvar=getenv(var))!=NULL)
44             for (;*cpvar;*(cpdest++)=*(cpvar++))
45               if ((++l)>=maxlen) goto error;
46             }
47         cpvar=var;
48       }
49       else
50       {
51         isVar=1; invar = 0;
52       }
53     }
54     else
55     {
56       if (isVar)
57       { int novar = 0;
58 
59         *(cpvar++) = (*cpsrc); invar++;
60         if (invar > 80)
61         {
62             novar = 1;
63         }
64         if ( ! ((*cpsrc >= 'A' && *cpsrc <= 'Z') ||
65                 (*cpsrc >= 'a' && *cpsrc <= 'z') ||
66                 (*cpsrc >= '0' && *cpsrc <= '9') ||
67                 (*cpsrc == '_')))
68         {
69             novar = 1;
70         }
71         if (novar)
72         { isVar=0; *cpvar=0;
73           *(cpdest++)='%';
74           if ((++l)>=maxlen) goto error;
75           for (cpvar=var;*cpvar;*(cpdest++)=*(cpvar++))
76             if ((++l)>=maxlen) goto error;
77           cpvar=var;
78         } else;
79       }
80       else
81       { *cpdest++=*cpsrc;
82         if ((++l)>=maxlen) goto error;
83       }
84     }
85 
86     cpsrc++;
87   }
88   if (isVar)
89   { isVar=0; *cpvar=0;
90     *(cpdest++)='%';
91     if ((++l)>=maxlen) goto error;
92     for (cpvar=var;*cpvar;*(cpdest++)=*(cpvar++))
93       if ((++l)>=maxlen) goto error;
94     cpvar=var;
95   }
96   *cpdest=0;
97 
98   return cpTemp;
99 
100 error: /* our estimate for the new buffer was too small */
101   xfree(cpTemp);
102   maxlen=maxlen+80;
103   goto start;
104 }
105 
106