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