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 ** 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 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 ** 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 ** 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 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 * 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