1 /* Copyright 1988,1990,1993,1994 by Paul Vixie
2 * All rights reserved
3 */
4
5 /*
6 * Copyright (c) 1997 by Internet Software Consortium
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
13 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
14 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
15 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
18 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
19 * SOFTWARE.
20 */
21
22 #if !defined(lint) && !defined(LINT)
23 static const char rcsid[] = "$Id: env.c,v 1.3 1998/08/14 00:32:39 vixie Exp $";
24 #endif
25
26
27 #include "cron.h"
28
29
30 char **
env_init(void)31 env_init(void)
32 {
33 char **p = (char **) malloc(sizeof(char **));
34
35 if (p)
36 p[0] = NULL;
37 return (p);
38 }
39
40
41 void
env_free(char ** envp)42 env_free(char **envp)
43 {
44 char **p;
45
46 if ((p = envp))
47 for (; *p; p++)
48 free(*p);
49 free(envp);
50 }
51
52
53 char **
env_copy(char ** envp)54 env_copy(char **envp)
55 {
56 int count, i;
57 char **p;
58
59 for (count = 0; envp[count] != NULL; count++)
60 ;
61 p = (char **) malloc((count+1) * sizeof(char *)); /* 1 for the NULL */
62 if (p == NULL) {
63 errno = ENOMEM;
64 return NULL;
65 }
66 for (i = 0; i < count; i++)
67 if ((p[i] = strdup(envp[i])) == NULL) {
68 while (--i >= 0)
69 (void) free(p[i]);
70 free(p);
71 errno = ENOMEM;
72 return NULL;
73 }
74 p[count] = NULL;
75 return (p);
76 }
77
78
79 char **
env_set(char ** envp,char * envstr)80 env_set(char **envp, char *envstr)
81 {
82 int count, found;
83 char **p;
84 char *q;
85
86 /*
87 * count the number of elements, including the null pointer;
88 * also set 'found' to -1 or index of entry if already in here.
89 */
90 found = -1;
91 for (count = 0; envp[count] != NULL; count++) {
92 if (!strcmp_until(envp[count], envstr, '='))
93 found = count;
94 }
95 count++; /* for the NULL */
96
97 if (found != -1) {
98 /*
99 * it exists already, so just free the existing setting,
100 * save our new one there, and return the existing array.
101 */
102 q = envp[found];
103 if ((envp[found] = strdup(envstr)) == NULL) {
104 envp[found] = q;
105 /* XXX env_free(envp); */
106 errno = ENOMEM;
107 return NULL;
108 }
109 free(q);
110 return (envp);
111 }
112
113 /*
114 * it doesn't exist yet, so resize the array, move null pointer over
115 * one, save our string over the old null pointer, and return resized
116 * array.
117 */
118 p = (char **) realloc((void *) envp,
119 (unsigned) ((count+1) * sizeof(char *)));
120 if (p == NULL) {
121 /* XXX env_free(envp); */
122 errno = ENOMEM;
123 return NULL;
124 }
125 p[count] = p[count-1];
126 if ((p[count-1] = strdup(envstr)) == NULL) {
127 env_free(p);
128 errno = ENOMEM;
129 return NULL;
130 }
131 return (p);
132 }
133
134
135 /* return ERR = end of file
136 * FALSE = not an env setting (file was repositioned)
137 * TRUE = was an env setting
138 */
139 int
load_env(char * envstr,FILE * f)140 load_env(char *envstr, FILE *f)
141 {
142 long filepos;
143 int fileline;
144 char name[MAX_ENVSTR], val[MAX_ENVSTR];
145 char quotechar, *c, *str;
146 int state;
147
148 /* The following states are traversed in order: */
149 #define NAMEI 0 /* First char of NAME, may be quote */
150 #define NAME 1 /* Subsequent chars of NAME */
151 #define EQ1 2 /* After end of name, looking for '=' sign */
152 #define EQ2 3 /* After '=', skipping whitespace */
153 #define VALUEI 4 /* First char of VALUE, may be quote */
154 #define VALUE 5 /* Subsequent chars of VALUE */
155 #define FINI 6 /* All done, skipping trailing whitespace */
156 #define ERROR 7 /* Error */
157
158 filepos = ftell(f);
159 fileline = LineNumber;
160 skip_comments(f);
161 if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n"))
162 return (ERR);
163
164 Debug(DPARS, ("load_env, read <%s>\n", envstr));
165
166 bzero (name, sizeof name);
167 bzero (val, sizeof val);
168 str = name;
169 state = NAMEI;
170 quotechar = '\0';
171 c = envstr;
172 while (state != ERROR && *c) {
173 switch (state) {
174 case NAMEI:
175 case VALUEI:
176 if (*c == '\'' || *c == '"')
177 quotechar = *c++;
178 ++state;
179 /* FALLTHROUGH */
180 case NAME:
181 case VALUE:
182 if (quotechar) {
183 if (*c == quotechar) {
184 state++;
185 c++;
186 break;
187 }
188 if (state == NAME && *c == '=') {
189 state = ERROR;
190 break;
191 }
192 } else {
193 if (state == NAME) {
194 if (isspace (*c)) {
195 c++;
196 state++;
197 break;
198 }
199 if (*c == '=') {
200 state++;
201 break;
202 }
203 }
204 }
205 *str++ = *c++;
206 break;
207
208 case EQ1:
209 if (*c == '=') {
210 state++;
211 str = val;
212 quotechar = '\0';
213 } else {
214 if (!isspace (*c))
215 state = ERROR;
216 }
217 c++;
218 break;
219 case EQ2:
220 case FINI:
221 if (isspace (*c))
222 c++;
223 else
224 state++;
225 break;
226 }
227 }
228 if (state != FINI && !(state == VALUE && !quotechar)) {
229 Debug(DPARS, ("load_env, parse error, state = %d\n", state))
230 fseek(f, filepos, 0);
231 Set_LineNum(fileline);
232 return (FALSE);
233 }
234 if (state == VALUE) {
235 /* End of unquoted value: trim trailing whitespace */
236 c = val + strlen (val);
237 while (c > val && isspace (*(c - 1)))
238 *(--c) = '\0';
239 }
240
241 /* 2 fields from parser; looks like an env setting */
242
243 if (snprintf(envstr, MAX_ENVSTR, "%s=%s", name, val) >= MAX_ENVSTR)
244 return (FALSE);
245 Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val, envstr))
246 return (TRUE);
247 }
248
249
250 char *
env_get(char * name,char ** envp)251 env_get(char *name, char **envp)
252 {
253 int len = strlen(name);
254 char *p, *q;
255
256 while ((p = *envp++) != NULL) {
257 if (!(q = strchr(p, '=')))
258 continue;
259 if ((q - p) == len && !strncmp(p, name, len))
260 return (q+1);
261 }
262 return (NULL);
263 }
264