root/src/env.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. env_init
  2. env_free
  3. env_copy
  4. env_set
  5. env_set_from_environ
  6. load_env
  7. env_get
  8. env_update_home

   1 /* Copyright 1988,1990,1993,1994 by Paul Vixie
   2  * All rights reserved
   3  */
   4 
   5 /*
   6  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
   7  * Copyright (c) 1997,2000 by Internet Software Consortium, Inc.
   8  *
   9  * Permission to use, copy, modify, and distribute this software for any
  10  * purpose with or without fee is hereby granted, provided that the above
  11  * copyright notice and this permission notice appear in all copies.
  12  *
  13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
  14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  15  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
  16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  20  */
  21 
  22 #include "config.h"
  23 
  24 #include <ctype.h>
  25 #include <errno.h>
  26 #include <stdlib.h>
  27 #include <string.h>
  28 #include <sys/types.h>
  29 #include <unistd.h>
  30 
  31 #include "globals.h"
  32 #include "funcs.h"
  33 
  34 #if defined(BSD)
  35 extern char **environ;
  36 #endif
  37 
  38 char **env_init(void) {
     /* [previous][next][first][last][top][bottom][index][help]  */
  39         char **p = (char **) malloc(sizeof (char *));
  40 
  41         if (p != NULL)
  42                 p[0] = NULL;
  43         return (p);
  44 }
  45 
  46 void env_free(char **envp) {
     /* [previous][next][first][last][top][bottom][index][help]  */
  47         char **p;
  48 
  49         for (p = envp; *p != NULL; p++)
  50                 free(*p);
  51         free(envp);
  52 }
  53 
  54 char **env_copy(char **envp) {
     /* [previous][next][first][last][top][bottom][index][help]  */
  55         int save_errno;
  56         size_t 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                 for (i = 0; i < count; i++)
  64                         if ((p[i] = strdup(envp[i])) == NULL) {
  65                                 save_errno = errno;
  66                                 while (i-- > 0)
  67                                         free(p[i]);
  68                                 free(p);
  69                                 errno = save_errno;
  70                                 return (NULL);
  71                         }
  72                 p[count] = NULL;
  73         }
  74         return (p);
  75 }
  76 
  77 char **env_set(char **envp, const char *envstr) {
     /* [previous][next][first][last][top][bottom][index][help]  */
  78         size_t count, found;
  79         char **p, *envtmp;
  80 
  81         /*
  82          * count the number of elements, including the null pointer;
  83          * also set 'found' to -1 or index of entry if already in here.
  84          */
  85         found = (size_t)-1;
  86         for (count = 0; envp[count] != NULL; count++) {
  87                 if (!strcmp_until(envp[count], envstr, '='))
  88                         found = count;
  89         }
  90         count++;        /* for the NULL */
  91 
  92         if (found != (size_t)-1) {
  93                 /*
  94                  * it exists already, so just free the existing setting,
  95                  * save our new one there, and return the existing array.
  96                  */
  97                 if ((envtmp = strdup(envstr)) == NULL)
  98                         return (NULL);
  99                 free(envp[found]);
 100                 envp[found] = envtmp;
 101                 return (envp);
 102         }
 103 
 104         /*
 105          * it doesn't exist yet, so resize the array, move null pointer over
 106          * one, save our string over the old null pointer, and return resized
 107          * array.
 108          */
 109         if ((envtmp = strdup(envstr)) == NULL)
 110                 return (NULL);
 111         p = (char **) realloc((void *) envp,
 112                 (count + 1) * sizeof (char *));
 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 int env_set_from_environ(char ***envpp) {
     /* [previous][next][first][last][top][bottom][index][help]  */
 123         static const char *names[] = {
 124                 "LANG",
 125                 "LC_CTYPE",
 126                 "LC_NUMERIC",
 127                 "LC_TIME",
 128                 "LC_COLLATE",
 129                 "LC_MONETARY",
 130                 "LC_MESSAGES",
 131                 "LC_PAPER",
 132                 "LC_NAME",
 133                 "LC_ADDRESS",
 134                 "LC_TELEPHONE",
 135                 "LC_MEASUREMENT",
 136                 "LC_IDENTIFICATION",
 137                 "LC_ALL",
 138                 "LANGUAGE",
 139                 "RANDOM_DELAY",
 140                 NULL
 141         };
 142         const char **name;
 143         char **procenv;
 144 
 145         for (procenv = environ; *procenv != NULL; ++procenv) {
 146                 for (name = names; *name != NULL; ++name) {
 147                         size_t namelen;
 148 
 149                         namelen = strlen(*name);
 150                         if (strncmp(*name, *procenv, namelen) == 0 
 151                             && (*procenv)[namelen] == '=') {
 152                                 char **tmpenv;
 153 
 154                                 tmpenv = env_set(*envpp, *procenv);
 155                                 if (tmpenv == NULL)
 156                                         return FALSE;
 157                                 *envpp = tmpenv;
 158                         }
 159                 }
 160         }
 161         return TRUE;
 162 }
 163 
 164 /* The following states are used by load_env(), traversed in order: */
 165 enum env_state {
 166         NAMEI,  /* First char of NAME, may be quote */
 167         NAME,   /* Subsequent chars of NAME */
 168         EQ1,    /* After end of name, looking for '=' sign */
 169         EQ2,    /* After '=', skipping whitespace */
 170         VALUEI, /* First char of VALUE, may be quote */
 171         VALUE,  /* Subsequent chars of VALUE */
 172         FINI,   /* All done, skipping trailing whitespace */
 173         ERROR,  /* Error */
 174 };
 175 
 176 /* return       ERR = end of file
 177  *              FALSE = not an env setting (file was repositioned)
 178  *              TRUE = was an env setting
 179  */
 180 int load_env(char *envstr, FILE * f) {
     /* [previous][next][first][last][top][bottom][index][help]  */
 181         long filepos;
 182         int fileline;
 183         enum env_state state;
 184         char name[MAX_ENVSTR], val[MAX_ENVSTR];
 185         char quotechar, *c, *str;
 186 
 187         filepos = ftell(f);
 188         fileline = LineNumber;
 189         skip_comments(f);
 190         if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n"))
 191                 return (ERR);
 192 
 193         Debug(DPARS, ("load_env, read <%s>\n", envstr));
 194 
 195         memset(name, 0, sizeof name);
 196         memset(val, 0, sizeof val);
 197 
 198         str = name;
 199         state = NAMEI;
 200         quotechar = '\0';
 201         c = envstr;
 202         while (state != ERROR && *c) {
 203                 switch (state) {
 204                 case NAMEI:
 205                 case VALUEI:
 206                         if (*c == '\'' || *c == '"')
 207                                 quotechar = *c++;
 208                         state++;
 209                         /* FALLTHROUGH */
 210                 case NAME:
 211                 case VALUE:
 212                         if (quotechar) {
 213                                 if (*c == quotechar) {
 214                                         state++;
 215                                         c++;
 216                                         break;
 217                                 }
 218                                 if (state == NAME && *c == '=') {
 219                                         state = ERROR;
 220                                         break;
 221                                 }
 222                         }
 223                         else {
 224                                 if (state == NAME) {
 225                                         if (isspace((unsigned char) *c)) {
 226                                                 c++;
 227                                                 state++;
 228                                                 break;
 229                                         }
 230                                         if (*c == '=') {
 231                                                 state++;
 232                                                 break;
 233                                         }
 234                                 }
 235                         }
 236                         *str++ = *c++;
 237                         break;
 238 
 239                 case EQ1:
 240                         if (*c == '=') {
 241                                 state++;
 242                                 str = val;
 243                                 quotechar = '\0';
 244                         }
 245                         else {
 246                                 if (!isspace((unsigned char) *c))
 247                                         state = ERROR;
 248                         }
 249                         c++;
 250                         break;
 251 
 252                 case EQ2:
 253                 case FINI:
 254                         if (isspace((unsigned char) *c))
 255                                 c++;
 256                         else
 257                                 state++;
 258                         break;
 259 
 260                 default:
 261                         abort();
 262                 }
 263         }
 264         if (state != FINI && state != EQ2 && !(state == VALUE && !quotechar)) {
 265                 Debug(DPARS, ("load_env, not an env var, state = %d\n", state));
 266                         if (fseek(f, filepos, 0)) {
 267                 return ERR;
 268            }
 269                 Set_LineNum(fileline);
 270                 return (FALSE);
 271         }
 272         if (state == VALUE) {
 273                 /* End of unquoted value: trim trailing whitespace */
 274                 c = val + strlen(val);
 275                 while (c > val && isspace((unsigned char) c[-1]))
 276                         *(--c) = '\0';
 277         }
 278 
 279         /* 2 fields from parser; looks like an env setting */
 280 
 281         /*
 282          * This can't overflow because get_string() limited the size of the
 283          * name and val fields.  Still, it doesn't hurt to be careful...
 284          */
 285         if (!glue_strings(envstr, MAX_ENVSTR, name, val, '='))
 286                 return (FALSE);
 287         Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val, envstr));
 288                 return (TRUE);
 289 }
 290 
 291 char *env_get(const char *name, char **envp) {
     /* [previous][next][first][last][top][bottom][index][help]  */
 292         size_t len = strlen(name);
 293         char *p, *q;
 294 
 295         while ((p = *envp++) != NULL) {
 296                 if (!(q = strchr(p, '=')))
 297                         continue;
 298                 if ((q - p) == len && !strncmp(p, name, len))
 299                         return (q + 1);
 300         }
 301         return (NULL);
 302 }
 303 
 304 char **env_update_home(char **envp, const char *dir) {
     /* [previous][next][first][last][top][bottom][index][help]  */
 305         char envstr[MAX_ENVSTR];
 306 
 307         if (dir == NULL || *dir == '\0' || env_get("HOME", envp)) {
 308                 return envp;
 309         }
 310 
 311         if (glue_strings(envstr, sizeof envstr, "HOME", dir, '=')) {
 312                 envp = env_set(envp, envstr);
 313         }                       
 314         else
 315                 log_it("CRON", getpid(), "ERROR", "can't set HOME", 0);
 316 
 317         return envp;
 318 }

/* [previous][next][first][last][top][bottom][index][help]  */