12311Sjkh/* Copyright 1988,1990,1993,1994 by Paul Vixie 22311Sjkh * All rights reserved 32311Sjkh * 42311Sjkh * Distribute freely, except: don't remove my name from the source or 52311Sjkh * documentation (don't take credit for my work), mark your changes (don't 62311Sjkh * get me blamed for your possible bugs), don't alter or remove this 72311Sjkh * notice. May be sold if buildable source is provided to buyer. No 82311Sjkh * warrantee of any kind, express or implied, is included with this 92311Sjkh * software; use at your own risk, responsibility for damages (if any) to 102311Sjkh * anyone resulting from the use of this software rests entirely with the 112311Sjkh * user. 122311Sjkh * 132311Sjkh * Send bug reports, bug fixes, enhancements, requests, flames, etc., and 142311Sjkh * I'll try to keep a version up to date. I can be reached as follows: 152311Sjkh * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul 162311Sjkh */ 172311Sjkh 182311Sjkh#if !defined(lint) && !defined(LINT) 1929452Scharnierstatic const char rcsid[] = 2050479Speter "$FreeBSD$"; 212311Sjkh#endif 222311Sjkh 232311Sjkh 242311Sjkh#include "cron.h" 252311Sjkh 262311Sjkh 272311Sjkhchar ** 282311Sjkhenv_init() 292311Sjkh{ 3059785Sghelmer register char **p = (char **) malloc(sizeof(char *)); 312311Sjkh 3220573Spst if (p) 3320573Spst p[0] = NULL; 342311Sjkh return (p); 352311Sjkh} 362311Sjkh 372311Sjkh 382311Sjkhvoid 392311Sjkhenv_free(envp) 402311Sjkh char **envp; 412311Sjkh{ 422311Sjkh char **p; 432311Sjkh 4480030Sdavidn if ((p = envp)) 4580030Sdavidn for (; *p; p++) 462311Sjkh free(*p); 472311Sjkh free(envp); 482311Sjkh} 492311Sjkh 502311Sjkh 512311Sjkhchar ** 522311Sjkhenv_copy(envp) 532311Sjkh register char **envp; 542311Sjkh{ 552311Sjkh register int count, i; 562311Sjkh register char **p; 572311Sjkh 582311Sjkh for (count = 0; envp[count] != NULL; count++) 592311Sjkh ; 6059785Sghelmer p = (char **) malloc((count+1) * sizeof(char *)); /* 1 for the NULL */ 6120573Spst if (p == NULL) { 6220573Spst errno = ENOMEM; 6320573Spst return NULL; 6420573Spst } 652311Sjkh for (i = 0; i < count; i++) 6620573Spst if ((p[i] = strdup(envp[i])) == NULL) { 6720573Spst while (--i >= 0) 6820573Spst (void) free(p[i]); 6920573Spst free(p); 7020573Spst errno = ENOMEM; 7120573Spst return NULL; 7220573Spst } 732311Sjkh p[count] = NULL; 742311Sjkh return (p); 752311Sjkh} 762311Sjkh 772311Sjkh 782311Sjkhchar ** 792311Sjkhenv_set(envp, envstr) 802311Sjkh char **envp; 812311Sjkh char *envstr; 822311Sjkh{ 832311Sjkh register int count, found; 842311Sjkh register char **p; 8559727Sghelmer char *q; 862311Sjkh 872311Sjkh /* 882311Sjkh * count the number of elements, including the null pointer; 892311Sjkh * also set 'found' to -1 or index of entry if already in here. 902311Sjkh */ 912311Sjkh found = -1; 922311Sjkh for (count = 0; envp[count] != NULL; count++) { 932311Sjkh if (!strcmp_until(envp[count], envstr, '=')) 942311Sjkh found = count; 952311Sjkh } 962311Sjkh count++; /* for the NULL */ 972311Sjkh 982311Sjkh if (found != -1) { 992311Sjkh /* 1002311Sjkh * it exists already, so just free the existing setting, 1012311Sjkh * save our new one there, and return the existing array. 1022311Sjkh */ 10359727Sghelmer q = envp[found]; 10420573Spst if ((envp[found] = strdup(envstr)) == NULL) { 10559727Sghelmer envp[found] = q; 10659727Sghelmer /* XXX env_free(envp); */ 10720573Spst errno = ENOMEM; 10820573Spst return NULL; 10920573Spst } 11059727Sghelmer free(q); 1112311Sjkh return (envp); 1122311Sjkh } 1132311Sjkh 1142311Sjkh /* 1152311Sjkh * it doesn't exist yet, so resize the array, move null pointer over 1162311Sjkh * one, save our string over the old null pointer, and return resized 1172311Sjkh * array. 1182311Sjkh */ 1192311Sjkh p = (char **) realloc((void *) envp, 12059785Sghelmer (unsigned) ((count+1) * sizeof(char *))); 12120573Spst if (p == NULL) { 12259727Sghelmer /* XXX env_free(envp); */ 12320573Spst errno = ENOMEM; 12420573Spst return NULL; 12520573Spst } 1262311Sjkh p[count] = p[count-1]; 12720573Spst if ((p[count-1] = strdup(envstr)) == NULL) { 12859727Sghelmer env_free(p); 12920573Spst errno = ENOMEM; 13020573Spst return NULL; 13120573Spst } 1322311Sjkh return (p); 1332311Sjkh} 1342311Sjkh 1352311Sjkh 1362311Sjkh/* return ERR = end of file 1372311Sjkh * FALSE = not an env setting (file was repositioned) 1382311Sjkh * TRUE = was an env setting 1392311Sjkh */ 1402311Sjkhint 1412311Sjkhload_env(envstr, f) 1422311Sjkh char *envstr; 1432311Sjkh FILE *f; 1442311Sjkh{ 1452311Sjkh long filepos; 1462311Sjkh int fileline; 14720557Spst char name[MAX_ENVSTR], val[MAX_ENVSTR]; 14897165Sroberto char quotechar, *c, *str; 14997165Sroberto int state; 1502311Sjkh 15197165Sroberto /* The following states are traversed in order: */ 15297165Sroberto#define NAMEI 0 /* First char of NAME, may be quote */ 15397165Sroberto#define NAME 1 /* Subsequent chars of NAME */ 15497165Sroberto#define EQ1 2 /* After end of name, looking for '=' sign */ 15597165Sroberto#define EQ2 3 /* After '=', skipping whitespace */ 15697165Sroberto#define VALUEI 4 /* First char of VALUE, may be quote */ 15797165Sroberto#define VALUE 5 /* Subsequent chars of VALUE */ 15897165Sroberto#define FINI 6 /* All done, skipping trailing whitespace */ 15997165Sroberto#define ERROR 7 /* Error */ 16097165Sroberto 1612311Sjkh filepos = ftell(f); 1622311Sjkh fileline = LineNumber; 1632311Sjkh skip_comments(f); 1642311Sjkh if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n")) 1652311Sjkh return (ERR); 1662311Sjkh 16797165Sroberto Debug(DPARS, ("load_env, read <%s>\n", envstr)); 1682311Sjkh 16997165Sroberto bzero (name, sizeof name); 17097165Sroberto bzero (val, sizeof val); 17197165Sroberto str = name; 17297165Sroberto state = NAMEI; 17397165Sroberto quotechar = '\0'; 17497165Sroberto c = envstr; 17597165Sroberto while (state != ERROR && *c) { 17697165Sroberto switch (state) { 17797165Sroberto case NAMEI: 17897165Sroberto case VALUEI: 17997165Sroberto if (*c == '\'' || *c == '"') 18097165Sroberto quotechar = *c++; 18197165Sroberto ++state; 18297165Sroberto /* FALLTHROUGH */ 18397165Sroberto case NAME: 18497165Sroberto case VALUE: 18597165Sroberto if (quotechar) { 18697165Sroberto if (*c == quotechar) { 18797165Sroberto state++; 18897165Sroberto c++; 18997165Sroberto break; 19097165Sroberto } 19197165Sroberto if (state == NAME && *c == '=') { 19297165Sroberto state = ERROR; 19397165Sroberto break; 19497165Sroberto } 19597165Sroberto } else { 196110638Sthomas if (state == NAME) { 197110638Sthomas if (isspace (*c)) { 198110638Sthomas c++; 199110638Sthomas state++; 200110638Sthomas break; 201110638Sthomas } 202110638Sthomas if (*c == '=') { 203110638Sthomas state++; 204110638Sthomas break; 205110638Sthomas } 20697165Sroberto } 20797165Sroberto } 20897165Sroberto *str++ = *c++; 20997165Sroberto break; 21097165Sroberto 21197165Sroberto case EQ1: 21297165Sroberto if (*c == '=') { 21397165Sroberto state++; 21497165Sroberto str = val; 21597165Sroberto quotechar = '\0'; 21697165Sroberto } else { 21797165Sroberto if (!isspace (*c)) 21897165Sroberto state = ERROR; 21997165Sroberto } 22097165Sroberto c++; 22197165Sroberto break; 22297165Sroberto case EQ2: 22397165Sroberto case FINI: 22497165Sroberto if (isspace (*c)) 22597165Sroberto c++; 22697165Sroberto else 22797165Sroberto state++; 22897165Sroberto break; 22997165Sroberto } 23097165Sroberto } 23197165Sroberto if (state != FINI && !(state == VALUE && !quotechar)) { 23297165Sroberto Debug(DPARS, ("load_env, parse error, state = %d\n", state)) 2332311Sjkh fseek(f, filepos, 0); 2342311Sjkh Set_LineNum(fileline); 2352311Sjkh return (FALSE); 2362311Sjkh } 237110638Sthomas if (state == VALUE) { 238110638Sthomas /* End of unquoted value: trim trailing whitespace */ 239110638Sthomas c = val + strlen (val); 240110638Sthomas while (c > val && isspace (*(c - 1))) 241110638Sthomas *(--c) = '\0'; 242110638Sthomas } 2432311Sjkh 244110638Sthomas /* 2 fields from parser; looks like an env setting */ 2452311Sjkh 24620573Spst if (strlen(name) + 1 + strlen(val) >= MAX_ENVSTR-1) 24720573Spst return (FALSE); 2482311Sjkh (void) sprintf(envstr, "%s=%s", name, val); 2492311Sjkh Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val, envstr)) 2502311Sjkh return (TRUE); 2512311Sjkh} 2522311Sjkh 2532311Sjkh 2542311Sjkhchar * 2552311Sjkhenv_get(name, envp) 2562311Sjkh register char *name; 2572311Sjkh register char **envp; 2582311Sjkh{ 2592311Sjkh register int len = strlen(name); 2602311Sjkh register char *p, *q; 2612311Sjkh 26229452Scharnier while ((p = *envp++)) { 2632311Sjkh if (!(q = strchr(p, '='))) 2642311Sjkh continue; 2652311Sjkh if ((q - p) == len && !strncmp(p, name, len)) 2662311Sjkh return (q+1); 2672311Sjkh } 2682311Sjkh return (NULL); 2692311Sjkh} 270