pike.git / src / builtin.cmod

version» Context lines:

pike.git/src/builtin.cmod:1:   /* -*- c -*-   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: builtin.cmod,v 1.221 2008/06/30 10:01:54 grubba Exp $ + || $Id: builtin.cmod,v 1.222 2008/07/08 12:27:05 grubba Exp $   */      #include "global.h"   #include "interpret.h"   #include "svalue.h"   #include "pike_macros.h"   #include "object.h"   #include "program.h"   #include "array.h"   #include "pike_error.h"
pike.git/src/builtin.cmod:1243:    while(count-- > 0) k=k->next;       /* Push result and return */    push_svalue(&k->ind);    push_svalue(&k->val);    f_aggregate(2);    stack_swap();    pop_stack();   }    + #if defined(HAVE_SETENV) && defined(HAVE_UNSETENV) + #define USE_SETENV + #else   /* Used to hold refs to the strings that we feed to putenv. Indexed on -  * variable names, values are the "name=value" strings. */ +  * variable names, values are the "name=value" strings. +  * +  * This is not needed when using {,un}setenv(), since they maintain +  * their own corresponding table. */   static struct mapping *env_allocs = NULL; -  + #endif      /* Works exactly like the getenv efun defined in the master, but only    * accesses the real environment. Everyone should use the caching    * version in the master instead. */   PIKEFUN string|mapping _getenv (void|string var)    rawtype tOr(tFunc(tStr, tString), tFunc(tVoid, tMap (tStr, tStr)));   {    /* FIXME: Perhaps add the amigaos4 stuff from pike_push_env here too. */       if (var) {
pike.git/src/builtin.cmod:1293:    int n;       /* Iterate the environment backwards below so that earlier    * variables will override later ones in case the same variable    * occur multiple times (which it shouldn't). That makes the    * result similar to what getenv(3) commonly returns (at least the    * one in gnu libc). */    for (n = 0; environ[n]; n++) {}       m = allocate_mapping (n); + #ifndef USE_SETENV    if (env_allocs)    new_env_allocs = allocate_mapping (m_sizeof (env_allocs)); -  + #endif /* !USE_SETENV */       while (--n >= 0) {    char *entry = environ[n], *eq = STRCHR (entry, '=');    if (eq) { /* gnu libc getenv ignores variables without '='. */    struct pike_string *var = make_shared_binary_string (entry, eq - entry);    struct pike_string *val = make_shared_string (eq + 1);    mapping_string_insert_string (m, var, val);    -  + #ifndef USE_SETENV    /* Populate new_env_allocs with the env_allocs entries that    * are still in use. */    if (env_allocs) {    struct svalue *ea_val = low_mapping_string_lookup (env_allocs, var);    if (ea_val && ea_val->u.string->str == entry)    mapping_string_insert (new_env_allocs, var, ea_val);    } -  + #endif /* !USE_SETENV */       free_string (var);    free_string (val);    }    }    -  + #ifndef USE_SETENV    if (env_allocs) {    free_mapping (env_allocs);    env_allocs = new_env_allocs;    } -  + #endif /* !USE_SETENV */       push_mapping (m);    }   }      /* Works exactly like the putenv efun defined in the master, but only    * updates the real environment. Everyone should use the version in    * the master instead so that the cache doesn't get stale. */   PIKEFUN void _putenv (string var, void|string val)   { -  + #ifndef USE_SETENV    struct pike_string *putenv_str, *env_alloc_var; -  + #endif       if (var->size_shift)    SIMPLE_ARG_TYPE_ERROR ("putenv", 1, "string(0..255)");    if (string_has_null (var) || STRCHR (var->str, '='))    SIMPLE_ARG_ERROR ("putenv", 1, "Variable name cannot contain '=' or NUL.");       if (val) { -  + #ifndef USE_SETENV    struct string_builder sb; -  + #endif       if (val->size_shift)    SIMPLE_ARG_TYPE_ERROR ("putenv", 2, "void|string(0..255)");    if (string_has_null (val))    SIMPLE_ARG_ERROR ("putenv", 2, "Variable value cannot contain NUL.");    -  + #ifdef USE_SETENV +  if (setenv(var->str, val->str, 1)) { +  if (errno == ENOMEM) +  SIMPLE_OUT_OF_MEMORY_ERROR ("putenv", 0); +  else +  Pike_error ("Error from setenv(3): %s\n", strerror (errno)); +  } + #else /* !USE_SETENV */    init_string_builder (&sb, 0);    string_builder_shared_strcat (&sb, var);    string_builder_putchar (&sb, '=');    string_builder_shared_strcat (&sb, val);    putenv_str = finish_string_builder (&sb);    push_string (putenv_str); /* Let mega_apply pop. */ -  + #endif /* USE_SETENV */    }    else { -  + #ifdef USE_SETENV +  /* Note: Some versions of glibc have a unsetenv(3) that returns void, +  * thus no checking of the return value here. +  */ +  unsetenv(var->str); + #else /* !USE_SETENV */   #ifdef PUTENV_ALWAYS_REQUIRES_EQUAL    /* Windows can never get things quite right.. :P */    struct string_builder sb;    init_string_builder (&sb, 0);    string_builder_shared_strcat (&sb, var);    string_builder_putchar (&sb, '=');    putenv_str = finish_string_builder (&sb);    push_string (putenv_str); /* Let mega_apply pop. */   #else    putenv_str = var;   #endif -  + #endif /* USE_SETENV */    }    -  + #ifndef USE_SETENV    if (putenv (putenv_str->str)) {    if (errno == ENOMEM)    SIMPLE_OUT_OF_MEMORY_ERROR ("putenv", 0);    else    Pike_error ("Error from putenv(3): %s\n", strerror (errno));    }      #ifdef __NT__    ref_push_string (var);    f_lower_case (1);
pike.git/src/builtin.cmod:1395:    if (val)    /* Must keep the string passed to putenv allocated (and we    * assume no other entities are naughty enough to modify it). */    mapping_string_insert_string (env_allocs, env_alloc_var, putenv_str);    else {    struct svalue key;    key.type = T_STRING;    key.u.string = env_alloc_var;    map_delete (env_allocs, &key);    } + #endif /* !USE_SETENV */   }      /*    * Backtrace handling.    */      /*! @module Pike    */      /*! @class BacktraceFrame
pike.git/src/builtin.cmod:3925:   void init_builtin(void)   {    init_pike_list_node_blocks();    INIT   }      void exit_builtin(void)   {    EXIT    free_all_pike_list_node_blocks(); + #ifndef USE_SETENV    if (env_allocs) free_mapping (env_allocs); -  + #endif   }