bacaea57cdf37466d3239ce33f4b6cb075ac7af9
[navit-package] / navit / support / wordexp / wordexp.c
1
2 #include <config.h>
3
4 #include <sys/types.h>
5 #include <assert.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include "wordexp.h"
12 #include "glob.h"
13
14
15 static int
16 is_valid_variable_char(char c, int pos)
17 {
18         if ( (pos && c >= '0' && c <= '9') ||
19               c == '_' ||
20              (c >= 'a' && c <= 'z') ||
21              (c >= 'A' && c <= 'Z'))
22                 return 1;
23         return 0;
24 }
25
26 /*
27  * @brief replace all names of $NAME ${NAME}
28  * with the corresponding environment variable 
29  * @ param in: the string to be checked
30  * @ return the expanded string or a copy of the existing string
31  * must be free() by the calling function 
32 */
33 static char *
34 expand_variables(const char *in)
35 {
36         char *var,*pos,*ret=strdup(in);
37         char *val,*str;
38         pos=ret;
39         while ((var=strchr(pos, '$'))) {
40                 char *name,*begin=var+1;
41                 int npos=0,bpos=0,slen,elen;
42                 *var='\0';
43                 if (var[1] == '{') {
44                         begin++;
45                         while (begin[npos]) {
46                                 bpos=npos;
47                                 if (begin[npos++] == '}') 
48                                         break;
49                         }
50                 } else {
51                         while (is_valid_variable_char(begin[npos],npos)) 
52                                 npos++; 
53                         bpos=npos;
54                 }
55                 name=strdup(begin);
56                 name[bpos]='\0';                
57                 val=getenv(name);
58                 free(name);
59                 if (! val)
60                         val="";
61                 slen=strlen(ret)+strlen(val);
62                 elen=strlen(begin+npos);
63                 str=malloc(slen+elen+1);
64                 strcpy(str,ret);
65                 strcat(str,val);
66                 strcat(str,begin+npos);
67                 free(ret);
68                 ret=str;
69                 pos=ret+slen;
70         }
71         return ret;
72 }
73
74 /*
75  * @brief minimal realization of wordexp according to IEEE standard
76  * shall perform word expansion as described in the Shell
77  * expansion of ´$NAME´ or ´${NAME}´
78  * expansion of ´*´ and ´?´
79  * @param words: pointer to a string containing one or more words to be expanded
80  * but here only one word supported
81  */
82 int 
83 wordexp(const char *words, wordexp_t *we, int flags)
84 {       
85         int     i;
86         int     error;  
87         char   *words_expanded;
88 #ifdef HAVE_API_WIN32_BASE
89         glob_t  pglob;
90 #endif
91
92         assert(we != NULL);
93         assert(words != NULL);
94  
95         /* expansion of ´$NAME´ or ´${NAME}´ */
96         words_expanded=expand_variables(words);
97
98 #ifdef HAVE_API_WIN32_BASE
99         /* expansion of ´*´, ´?´ */
100         error=glob(words_expanded, 0, NULL, &pglob);
101         if (!error)
102         {
103                 /* copy the content of struct of glob into struct of wordexp */
104                 we->we_wordc = pglob.gl_pathc;
105                 we->we_offs = pglob.gl_offs;
106                 we->we_wordv = malloc(we->we_wordc * sizeof(char*));
107                 for (i=0; i<we->we_wordc; i++)
108                 {
109                         we->we_wordv[i] = strdup(pglob.gl_pathv[i]);
110                 }               
111                 globfree(&pglob);
112                 free(words_expanded);
113         }
114         else
115         {
116 #endif
117                 we->we_wordc = 1;               
118                 we->we_wordv = malloc(sizeof(char*));   
119                 we->we_wordv[0] = words_expanded;
120 #ifdef HAVE_API_WIN32_BASE
121         }
122 #endif
123
124
125         return error;   
126 }
127
128
129 void wordfree(wordexp_t *we)
130 {
131         int i;
132
133         for (i=0; i < we->we_wordc; i++)
134         {
135                 free (we->we_wordv[i]);
136         }
137         
138         free (we->we_wordv);
139         we->we_wordc = 0;
140 }