From e19206c2bfbd24ae9eceb5fbba9324fdcb3a544f Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Mon, 26 Jul 1999 23:15:57 +0000 Subject: [PATCH] Fiddling with environment variables. Organization: Straylight/Edgeware From: mdw --- env.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ env.h | 131 +++++++++++++++++++++++++++++++++ man/env.3 | 86 ++++++++++++++++++++++ 3 files changed, 433 insertions(+) create mode 100644 env.c create mode 100644 env.h create mode 100644 man/env.3 diff --git a/env.c b/env.c new file mode 100644 index 0000000..4a4fbe5 --- /dev/null +++ b/env.c @@ -0,0 +1,216 @@ +/* -*-c-*- + * + * $Id: env.c,v 1.1 1999/07/26 23:15:57 mdw Exp $ + * + * Fiddling with environment variables + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the mLib utilities library. + * + * mLib is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * mLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with mLib; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: env.c,v $ + * Revision 1.1 1999/07/26 23:15:57 mdw + * Fiddling with environment variables. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "alloc.h" +#include "sym.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct var { + sym_base _base; + char *v; +} var; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @env_get@ --- * + * + * Arguments: @sym_table *t@ = pointer to a symbol table + * @const char *name@ = pointer to variable name to look up + * + * Returns: Pointer to corresponding value string, or null. + * + * Use: Looks up an environment variable in the table and returns its + * value. If the variable can't be found, a null pointer is + * returned. + */ + +char *env_get(sym_table *t, const char *name) +{ + var *e = sym_find(t, name, -1, 0, 0); + return (e ? e->v : 0); +} + +/* --- @env_put@ --- * + * + * Arguments: @sym_table *t@ = pointer to a symbol table + * @const char *name@ = pointer to variable name to set + * @const char *value@ = pointer to value string to assign + * + * Returns: --- + * + * Use: Assigns a value to a variable. If the @name@ contains an + * equals character, then it's assumed to be of the form + * `VAR=VALUE' and @value@ argument is ignored. Otherwise, if + * @value@ is null, the variable is deleted. Finally, the + * normal case: @name@ is a plain name, and @value@ is a normal + * string causes the variable to be assigned the value in the + * way you'd expect. + */ + +void env_put(sym_table *t, const char *name, const char *value) +{ + char *q = 0; + + /* --- Sort out the mess with `NAME=VALUE' forms --- */ + + { + size_t eq = strcspn(name, "="); + if (name[eq] == '=') { + q = xmalloc(eq + 1); + memcpy(q, name, eq); + q[eq] = 0; + value = name + eq + 1; + name = q; + } + } + + /* --- Read the current value --- */ + + if (!value) { + var *v; + if ((v = sym_find(t, name, -1, 0, 0)) != 0) { + free(v->v); + sym_remove(t, v); + } + } else { + unsigned found; + var *v = sym_find(t, name, -1, sizeof(*v), &found); + if (found) + free(v->v); + v->v = xstrdup(value); + } + + /* --- Tidying --- */ + + if (q) + free(q); +} + +/* --- @env_import@ --- * + * + * Arguments: @sym_table *t@ = pointer to a symbol table + * @char **env@ = pointer to an environment list + * + * Returns: --- + * + * Use: Inserts all of the environment variables listed into a symbol + * table for rapid access. Equivalent to a lot of calls to + * @env_put@. + */ + +void env_import(sym_table *t, char **env) +{ + while (*env) { + env_put(t, *env, 0); + env++; + } +} + +/* --- @env_export@ --- * + * + * Arguments: @sym_table *t@ = pointer to a symbol table + * + * Returns: A big environment list. + * + * Use: Extracts an environment table from a symbol table + * representation of an environment. The table and all of the + * strings are in one big block allocated from the heap. + */ + +char **env_export(sym_table *t) +{ + size_t n = 1; + size_t sz = 0; + sym_iter i; + var *v; + char **env; + char *p, **pp; + + /* --- Work out sizes for everything --- */ + + for (sym_mkiter(&i, t); (v = sym_next(&i)) != 0; ) { + n++; + sz += strlen(SYM_NAME(v)) + strlen(v->v) + 2; + } + + /* --- Allocate the big chunk of memory --- */ + + env = pp = xmalloc(n * sizeof(char *) + sz); + p = (char *)(env + n); + + /* --- Dump the output in the big chunk of memory --- */ + + for (sym_mkiter(&i, t); (v = sym_next(&i)) != 0; ) { + const char *name = SYM_NAME(v); + size_t nlen = strlen(name), vlen = strlen(v->v); + *pp++ = p; + memcpy(p, name, nlen); p += nlen; + *p++ = '='; + memcpy(p, v->v, vlen); p += vlen; + *p++ = 0; + } + *pp++ = 0; + return (env); +} + +/* --- @env_destroy@ --- * + * + * Arguments: @sym_table *t@ = pointer to symbol table + * + * Returns: --- + * + * Use: Destroys all the variables in the symbol table. + */ + +void env_destroy(sym_table *t) +{ + sym_iter i; + var *v; + + for (sym_mkiter(&i, t); (v = sym_next(&i)) != 0; ) + free(v->v); + sym_destroy(t); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/env.h b/env.h new file mode 100644 index 0000000..efe4052 --- /dev/null +++ b/env.h @@ -0,0 +1,131 @@ +/* -*-c-*- + * + * $Id: env.h,v 1.1 1999/07/26 23:15:57 mdw Exp $ + * + * Fiddling with environment variables + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the mLib utilities library. + * + * mLib is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * mLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with mLib; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: env.h,v $ + * Revision 1.1 1999/07/26 23:15:57 mdw + * Fiddling with environment variables. + * + */ + +#ifndef ENV_H +#define ENV_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef SYM_H +# include "sym.h" +#endif + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @env_get@ --- * + * + * Arguments: @sym_table *t@ = pointer to a symbol table + * @const char *name@ = pointer to variable name to look up + * + * Returns: Pointer to corresponding value string, or null. + * + * Use: Looks up an environment variable in the table and returns its + * value. If the variable can't be found, a null pointer is + * returned. + */ + +extern char *env_get(sym_table */*t*/, const char */*name*/); + +/* --- @env_put@ --- * + * + * Arguments: @sym_table *t@ = pointer to a symbol table + * @const char *name@ = pointer to variable name to set + * @const char *value@ = pointer to value string to assign + * + * Returns: --- + * + * Use: Assigns a value to a variable. If the @name@ contains an + * equals character, then it's assumed to be of the form + * `VAR=VALUE' and @value@ argument is ignored. Otherwise, if + * @value@ is null, the variable is deleted. Finally, the + * normal case: @name@ is a plain name, and @value@ is a normal + * string causes the variable to be assigned the value in the + * way you'd expect. + */ + +extern void env_put(sym_table */*t*/, + const char */*name*/, const char */*value*/); + +/* --- @env_import@ --- * + * + * Arguments: @sym_table *t@ = pointer to a symbol table + * @char **env@ = pointer to an environment list + * + * Returns: --- + * + * Use: Inserts all of the environment variables listed into a symbol + * table for rapid access. Equivalent to a lot of calls to + * @env_put@. + */ + +extern void env_import(sym_table */*t*/, char **/*env*/); + +/* --- @env_export@ --- * + * + * Arguments: @sym_table *t@ = pointer to a symbol table + * + * Returns: A big environment list. + * + * Use: Extracts an environment table from a symbol table + * representation of an environment. The table and all of the + * strings are in one big block allocated from the heap. + */ + +extern char **env_export(sym_table */*t*/); + +/* --- @env_destroy@ --- * + * + * Arguments: @sym_table *t@ = pointer to symbol table + * + * Returns: --- + * + * Use: Destroys all the variables in the symbol table. + */ + +extern void env_destroy(sym_table */*t*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/man/env.3 b/man/env.3 new file mode 100644 index 0000000..7894d7c --- /dev/null +++ b/man/env.3 @@ -0,0 +1,86 @@ +.\" -*-nroff-*- +.TH env 3 "26 July 1999" mLib +.SH "NAME" +env \- efficient fiddline with environment variables +.\" @env_get +.\" @env_put +.\" @env_import +.\" @env_export +.\" @env_destroy +.SH "SYNOPSIS" +.nf +.B "#include " + +.BI "char *env_get(sym_table *" t ", const char *" name ); +.BI "void env_put(sym_table * " t , +.BI " const char *" name ", const char *" value ); +.BI "void env_import(sym_table *" t ", char **" env ); +.BI "char **env_export(sym_table *" t ); +.fi +.SH "DESCRIPTION" +The functions in the +.B "" +header manipulate environment variables stored in a hash table. +.PP +The function +.B env_import +reads a standard Unix environment array and stores the variables in the +symbol table. (A standard Unix environment array is an array of +pointers to strings of the form +.IB name = value +terminated by a null pointer. This format is used for the global +.B environ +variable, and by the +.BR execve (2) +function.) The symbol table must have already been created (see +.BR sym_create (3)). +.PP +The function +.B env_export +creates a Unix environment array from a symbol table. The environment +array is one big block of memory allocated using +.BR malloc (3); +hence, one call to +.BR free (3) +releases all the memory used for the pointer array and the strings. +.PP +The +.B env_get +function looks up a variable in an environment symbol table. The +returned result is the variable's value if it exists, or a null pointer +if not. +.PP +The +.B env_put +function sets or deletes environment variables. If the +.I name +argument contains an +.RB ` = ' +character, it is assumed to be of the form +.IB n = v\fR; +the +.I value argument is ignored, and the variable +.I n +is assigned the value +.IR v . +Otherwise, if +.I value +is not a null pointer, the variable +.I name +is assigned the value +.I value . +Finally, if +.I value +is null, the variable +.I name +is deleted. +.PP +The +.B env_destroy +function frees all the memory used by an environment symbol table. The +table itself is destroyed too. +.SH "SEE ALSO" +.BR sym (3), +.BR mLib (3). +.SH "AUTHOR" +Mark Wooding, -- [mdw]