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