home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / pty4 / part04 / env.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-18  |  4.0 KB  |  191 lines

  1. /* env.c, env.h: environ library
  2. Daniel J. Bernstein, brnstnd@nyu.edu.
  3. Depends on ralloc.h.
  4. Requires strlen, strncmp, environ.
  5. 8/3/91: Fixed off-by-one [sigh] in env_put2().
  6. 7/24/91: Added env_put2(). Recoded in terms of ralloc macros.
  7. 7/18/91: Cleanups. env 1.1, public domain.
  8. 7/10/91: Was ralloc()ing too little; didn't init env right. Tnx CW/EW/HB.
  9. 6/29/91: Added env_unsetlen(), made env_add use it so string can be const.
  10. 6/28/91: Baseline. env 1.0, public domain.
  11. No known patent problems.
  12.  
  13. Thanks to Christian Wettergren <d88-cwe@pdc.kth.se>, Erik Wallin
  14. <d87-ewa@pdc.kth.se>, and Harald Barth <d88-hba@tds.kth.se> for bug
  15. fixes.
  16.  
  17. This was originally meant as a portable version of putenv(). It expanded
  18. to include unsetenv() and getenv(). Note that the routines always
  19. maintain environ properly, so execvp() and friends will pick up the new
  20. variables. I recommend that programs which do a lot of environment
  21. manipulation work with strings and keep their own hash table, then use
  22. these routines to manipulate environ before an execvp().
  23.  
  24. env_init() does optional initialization. It returns 0 on success, -1 on
  25. failure. Note that env_init(), env_put(), and env_unset() may all change
  26. environ.
  27.  
  28. env_put("FOO=BAR") adds FOO=BAR to the environment, destroying any
  29. previous value of FOO. It returns 0 on success, -1 on failure. Note that
  30. previous versions of env.c required env_put's argument to be writable;
  31. this problem has been removed.
  32.  
  33. env_put2("FOO","BAR") is just like env_put("FOO=BAR"), except of course
  34. that in the second case the new environment variable refers to the
  35. string passed to env_put, while in the first case it refers to
  36. internally malloc()ed memory.
  37.  
  38. env_unset("FOO") unsets any variable FOO. It returns 0 on success, -1 on
  39. failure. It will always succeed if env_init() has previously succeeded.
  40.  
  41. env_get("FOO") returns the value of the first variable FOO, or 0 if
  42. there is no such variable.
  43.  
  44. env_pick() returns any FOO=BAR in the environment, or 0 if the
  45. environment is empty. This can be used to implement the BSD printenv
  46. call, or to clear the environment.
  47. */
  48.  
  49. #include "env.h"
  50. #include "ralloc.h"
  51.  
  52. static int init = 0;
  53. static int numenv;
  54. static int allocenv;
  55.  
  56. extern char *env_get(s)
  57. char *s;
  58. {
  59.  int i;
  60.  int slen;
  61.  char *envi;
  62.  
  63.  slen = strlen(s);
  64.  for (i = 0;envi = environ[i];++i)
  65.    if ((!strncmp(s,envi,slen)) && (envi[slen] == '='))
  66.      return envi + slen + 1;
  67.  return 0;
  68. }
  69.  
  70. extern char *env_pick()
  71. {
  72.  return environ[0]; /* environ[numenv-1] would make (pick-unset)^n easier */
  73. }
  74.  
  75. static void env_unsetlen(s,slen)
  76. char *s;
  77. int slen;
  78. {
  79.  int i;
  80.  for (i = 0;i < numenv;++i)
  81.    if ((!strncmp(s,environ[i],slen)) && (environ[i][slen] == '='))
  82.     {
  83.      if (i < --numenv)
  84.        environ[i] = environ[numenv];
  85.      environ[numenv] = 0;
  86.     }
  87. }
  88.  
  89. extern int env_unset(s)
  90. char *s;
  91. {
  92.  if (!init)
  93.    if (env_init())
  94.      return -1;
  95.  env_unsetlen(s,strlen(s));
  96.  return 0;
  97. }
  98.  
  99. static int env_realloc()
  100. {
  101.  char **envp;
  102.  
  103.  allocenv = numenv + 30;
  104.  envp = environ;
  105.  environ = RALLOC(char *,allocenv + 1);
  106.  if (!environ)
  107.   {
  108.    environ = envp;
  109.    allocenv = numenv;
  110.    return -1;
  111.   }
  112.  numenv = 0;
  113.  while (*envp)
  114.   {
  115.    environ[numenv] = *envp;
  116.    ++numenv;
  117.    ++envp;
  118.   }
  119.  environ[numenv] = 0;
  120.  RFREE(envp - numenv);
  121.  return 0;
  122. }
  123.  
  124. static int env_add(s)
  125. char *s;
  126. {
  127.  char *t;
  128.  for (t = s;*t;++t)
  129.    if (*t == '=')
  130.     {
  131.      env_unsetlen(s,t - s);
  132.      break;
  133.     }
  134.  if (numenv == allocenv)
  135.    if (env_realloc())
  136.      return -1;
  137.  environ[numenv] = s;
  138.  ++numenv;
  139.  environ[numenv] = 0;
  140.  return 0;
  141. }
  142.  
  143. int env_init()
  144. {
  145.  char **envp;
  146.  
  147.  numenv = 0;
  148.  allocenv = 0;
  149.  envp = environ;
  150.  environ = RALLOC(char *,1);
  151.  if (!environ)
  152.   {
  153.    environ = envp;
  154.    return -1;
  155.   }
  156.  environ[0] = 0;
  157.  init = 1;
  158.  while (*envp)
  159.   {
  160.    if (env_add(*envp))
  161.      return -1;
  162.    ++envp;
  163.   }
  164.  return 0;
  165. }
  166.  
  167. int env_put(s)
  168. char *s;
  169. {
  170.  if (!init)
  171.    if (env_init())
  172.      return -1;
  173.  return env_add(s);
  174. }
  175.  
  176. int env_put2(s,t)
  177. char *s;
  178. char *t;
  179. {
  180.  char *u;
  181.  int slen;
  182.  slen = strlen(s);
  183.  u = ralloc(slen + strlen(t) + 2);
  184.  if (!u)
  185.    return -1;
  186.  strcpy(u,s);
  187.  u[slen] = '=';
  188.  strcpy(u + slen + 1,t);
  189.  return env_put(u);
  190. }
  191.