home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume06 / setenv < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  7.1 KB

  1. From decwrl!ucbvax!tut.cis.ohio-state.edu!mailrus!ames!amdahl!uunet!allbery Fri Mar 24 22:24:47 PST 1989
  2. Article 821 of comp.sources.misc:
  3. Path: decwrl!ucbvax!tut.cis.ohio-state.edu!mailrus!ames!amdahl!uunet!allbery
  4. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Newsgroups: comp.sources.misc
  6. Subject: v06i056: setenv.c - a sorted environment package
  7. Message-ID: <8902222357.aa04304@solo9.cs.vu.nl>
  8. Date: 8 Mar 89 01:19:54 GMT
  9. Sender: allbery@uunet.UU.NET
  10. Reply-To: Maarten Litmaath <maart@cs.vu.nl>
  11. Lines: 338
  12. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  13.  
  14. Posting-number: Volume 6, Issue 56
  15. Submitted-by: Maarten Litmaath <maart@cs.vu.nl>
  16. Archive-name: setenv
  17.  
  18. setenv() is better than putenv() in 3 ways:
  19.  
  20.     1) the call is setenv(var, value), which is both easier and more
  21.        natural than putenv(string)
  22.        compare
  23.         setenv("HOME", home);
  24.        with
  25.         strcpy(buf, "HOME=");
  26.         strcat(buf, home);
  27.         putenv(buf);
  28.  
  29.     2) it isn't an error to invoke setenv() with a local (automatic)
  30.        variable, because setenv() uses a malloc() + copy scheme (it needn't
  31.        be blistering fast, you know)
  32.  
  33.     3) it keeps the environment sorted, both for its own purposes and as a
  34.        service to the user
  35.  
  36. Regards & thanks for your attention,
  37.                     Maarten Litmaath @ VU Amsterdam:
  38.                     maart@cs.vu.nl, mcvax!botter!maart
  39.  
  40. : This is a shar archive.  Extract with sh, not csh.
  41. : This archive ends with exit, so do not worry about trailing junk.
  42. : --------------------------- cut here --------------------------
  43. PATH=/bin:/usr/bin:/usr/ucb
  44. echo Extracting 'setenv.c'
  45. sed 's/^X//' > 'setenv.c' << '+ END-OF-FILE ''setenv.c'
  46. Xstatic    char    id[] = "@(#)setenv.c 2.1 89/02/22 Maarten Litmaath";
  47. X
  48. X/*
  49. X * setenv.c
  50. X *
  51. X * Sorted environment package.
  52. X *
  53. X * char *setenv(char *var, char *value);
  54. X * Returns a pointer to the new "var=value" string if `value' has been
  55. X * assigned to `var', (char *) NULL if the number of environment variables
  56. X * exceeds MAX_ENV, or `var' is a NULL pointer or a malloc error occurred.
  57. X * If `value' is a NULL pointer, the empty string is assigned to `var'.
  58. X *
  59. X * int unsetenv(char *var);
  60. X * If `var' is the NULL pointer, the complete environment is unset.
  61. X * Returns -1 if the initial number of environment variables exceeds MAX_ENV
  62. X * or a malloc error occurred, else 0.
  63. X *
  64. X * int _envc;
  65. X * The current number of environment variables.
  66. X */
  67. X
  68. X#include    "setenv.h"
  69. X#include    <stdio.h>
  70. X
  71. Xstatic    char    *envbuf[MAX_ENV] = { 0 };
  72. Xstatic    int    initialized = 0, initenv(), envsearch();
  73. Xint    _envc = 0;
  74. Xextern    void    free();
  75. X
  76. X
  77. Xchar    *setenv(var, value)
  78. Xchar    *var, *value;
  79. X{
  80. X    extern    char    *malloc();
  81. X    char    **env, *buf;
  82. X    int    n;
  83. X
  84. X
  85. X    if (!initialized && initenv() == -1)
  86. X        return NULL;
  87. X
  88. X    if (!var)
  89. X        return NULL;
  90. X
  91. X    if (!value)
  92. X        value = "";
  93. X
  94. X    n = strlen(var);
  95. X
  96. X    if (!(buf = malloc(n + strlen(value) + 2)))
  97. X        return NULL;
  98. X
  99. X    (void) sprintf(buf, "%s=%s", var, value);
  100. X
  101. X    if (envsearch(var, n, &env) == 0) {
  102. X        free(*env);            /* unsetenv old value */
  103. X        *env = buf;            /* setenv new value */
  104. X    } else
  105. X        if (_envc == MAX_ENV)
  106. X            return NULL;
  107. X    else
  108. X        if (env == envbuf + _envc++) {
  109. X            *env++ = buf;
  110. X            *env = 0;
  111. X        }
  112. X    else {                    /* *env > var */
  113. X        register char    **p, **q;
  114. X
  115. X
  116. X        p = envbuf + _envc;
  117. X        q = p++;
  118. X        while (q > env)
  119. X            *--p = *--q;        /* shift down */
  120. X        *env = buf;            /* insert new var */
  121. X    }
  122. X
  123. X    return buf;
  124. X}
  125. X
  126. X
  127. Xint    unsetenv(var)
  128. Xchar    *var;
  129. X{
  130. X    register char    **p, **q;
  131. X    char    **env;
  132. X
  133. X
  134. X    if (!var)
  135. X        if (!initialized) {
  136. X            environ = envbuf;
  137. X            return 0;
  138. X        } else {
  139. X            for (p = envbuf; *p; )
  140. X                free(*p++);
  141. X            *envbuf = 0;
  142. X            _envc = 0;
  143. X            return 0;
  144. X        }
  145. X
  146. X    if (!initialized && initenv() == -1)
  147. X        return -1;
  148. X
  149. X    if (envsearch(var, strlen(var), &env) == 1)
  150. X        return 0;
  151. X
  152. X    free(*env);            /* unsetenv var */
  153. X
  154. X    p = env++;
  155. X    q = env;
  156. X    while (*p++ = *q++)        /* shift up rest of environment */
  157. X        ;
  158. X    --_envc;
  159. X
  160. X    return 0;
  161. X}
  162. X
  163. X
  164. X/*
  165. X * int initenv();
  166. X * Copy environment to private area, sort the copy, set environ to copy,
  167. X * initialize _envc.
  168. X * Return -1 if the environment exceeds MAX_ENV or a malloc error occurred,
  169. X * else 0.
  170. X */
  171. X
  172. Xstatic    int    initenv()
  173. X{
  174. X    register char    **p = environ, **env = envbuf;
  175. X    extern    char    *malloc(), *strcpy();
  176. X    extern    void    qsort();
  177. X    static    int    error = 0;
  178. X    int    istrcmp();
  179. X
  180. X
  181. X    if (error == -1)
  182. X        return -1;
  183. X
  184. X    if (p)
  185. X        while (*p && p < environ + MAX_ENV)
  186. X            if (!(*env = malloc(strlen(*p) + 1)))
  187. X                return error = -1;
  188. X            else
  189. X                (void) strcpy(*env++, *p++);
  190. X
  191. X    if (p >= environ + MAX_ENV)
  192. X        return error = -1;
  193. X
  194. X    *env = 0;
  195. X    _envc = env - envbuf;
  196. X    qsort((char *) envbuf, _envc, sizeof *envbuf, istrcmp);
  197. X    environ = envbuf;
  198. X    initialized = 1;
  199. X    return 0;
  200. X}
  201. X
  202. X
  203. X/*
  204. X * int envsearch(char *var, int n, char ***pos);
  205. X * Binarily search environment for `var', whose length is `n'.
  206. X * If it is present, `*pos' is set to the address of `var' in the environment
  207. X * and 0 is returned, else `*pos' is set to the address of the first variable
  208. X * lexicographically greater than `var', or to the end of the environment,
  209. X * and 1 is returned.
  210. X */
  211. X
  212. Xstatic    int    envsearch(var, n, pos)
  213. Xregister char    *var;
  214. Xregister int    n;
  215. Xchar    ***pos;
  216. X{
  217. X    register char    **env, **first = envbuf, **last = envbuf + _envc;
  218. X    register int    m;
  219. X    extern    int    strncmp();
  220. X
  221. X
  222. X    while (first < last) {
  223. X        env = first + ((last - first) >> 1);
  224. X        if ((m = strncmp(*env, var, n)) < 0) {
  225. X            first = env + 1;
  226. X            continue;
  227. X        }
  228. X        if (m > 0) {
  229. X            last = env;
  230. X            continue;
  231. X        }
  232. X        if ((m = (*env)[n] - '=') == 0) {
  233. X            *pos = env;
  234. X            return 0;
  235. X        }
  236. X        if (m < 0) {
  237. X            first = env + 1;
  238. X            continue;
  239. X        }
  240. X        last = env;
  241. X    }
  242. X
  243. X    *pos = last;
  244. X    return 1;
  245. X}
  246. X
  247. X
  248. Xstatic    int    istrcmp(p, q)            /* indirect strcmp */
  249. Xchar    **p, **q;
  250. X{
  251. X    register char    *s1 = *p, *s2 = *q;
  252. X
  253. X    while (*s1 == *s2++)
  254. X        if (!*s1++)
  255. X            return 0;
  256. X    return *s1 - *--s2;
  257. X}
  258. X
  259. X
  260. X#ifdef    STANDALONE
  261. X
  262. Xmain(argc)
  263. Xint    argc;
  264. X{
  265. X    void    set(), unset(), printenv();
  266. X
  267. X
  268. X    printenv();
  269. X
  270. X    if (argc > 1)
  271. X        unset((char *) 0);
  272. X
  273. X    unset("SHELL");
  274. X    unset("PATH");
  275. X    set("SHELL", "/foo/bar/baz");
  276. X    set("FOO", "BAR");
  277. X    unset("FOOO");
  278. X    unset("FO");
  279. X    unset((char *) 0);
  280. X    set("ZORK", (char *) 0);
  281. X    set("TMP", "/tmp");
  282. X}
  283. X
  284. X
  285. Xvoid    set(p, q)
  286. Xchar    *p, *q;
  287. X{
  288. X    void    printenv();
  289. X
  290. X
  291. X    printf("%s -> %s\n\n", p ? p : "(null)", (q = setenv(p, q)) ? q : "?");
  292. X    printenv();
  293. X}
  294. X
  295. X
  296. Xvoid    unset(p)
  297. Xchar    *p;
  298. X{
  299. X    void    printenv();
  300. X
  301. X
  302. X    printf("%s: %d\n\n", p ? p : "(null)", unsetenv(p));
  303. X    printenv();
  304. X}
  305. X
  306. X
  307. Xvoid    printenv()
  308. X{
  309. X    register char    **env;
  310. X
  311. X
  312. X    for (env = environ; *env; ++env)
  313. X        printf("%s\n", *env);
  314. X    printf("\n_envc=%d\n\n", _envc);
  315. X}
  316. X
  317. X#endif    STANDALONE
  318. + END-OF-FILE setenv.c
  319. chmod 'u=rw,g=r,o=r' 'setenv.c'
  320. set `wc -c 'setenv.c'`
  321. count=$1
  322. case $count in
  323. 4740)    :;;
  324. *)    echo 'Bad character count in ''setenv.c' >&2
  325.         echo 'Count should be 4740' >&2
  326. esac
  327. echo Extracting 'setenv.h'
  328. sed 's/^X//' > 'setenv.h' << '+ END-OF-FILE ''setenv.h'
  329. X/*
  330. X * setenv.h
  331. X */
  332. X
  333. X#ifndef    SETENV_H
  334. X#define        SETENV_H
  335. X
  336. X#define        MAX_ENV        256
  337. X
  338. Xextern    char    **environ, *setenv();
  339. Xextern    int    unsetenv(), _envc;
  340. X
  341. X#endif    !SETENV_H
  342. + END-OF-FILE setenv.h
  343. chmod 'u=rw,g=r,o=r' 'setenv.h'
  344. set `wc -c 'setenv.h'`
  345. count=$1
  346. case $count in
  347. 161)    :;;
  348. *)    echo 'Bad character count in ''setenv.h' >&2
  349.         echo 'Count should be 161' >&2
  350. esac
  351. exit 0
  352.  
  353.  
  354.