1/* $NetBSD: env.c,v 1.3 2014/09/05 21:32:37 christos 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 26static 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.3 2014/09/05 21:32:37 christos Exp $"); 29#endif 30#endif 31 32#include "cron.h" 33 34char ** 35env_init(void) { 36 char **p = malloc(sizeof(char **)); 37 38 if (p != NULL) 39 p[0] = NULL; 40 return (p); 41} 42 43void 44env_free(char **envp) { 45 char **p; 46 47 for (p = envp; *p != NULL; p++) 48 free(*p); 49 free(envp); 50} 51 52char ** 53env_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 77char ** 78env_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: */ 123enum 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 */ 138int 139load_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 245char * 246env_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