[comp.lang.c] replacement for putenv

rogol@marob.MASA.COM (Fred Buck) (02/11/89)

In article <164@bds-ny.UUCP> jduro@bds-ny.UUCP (Jacques Durosier) writes:

>Setting: UniPlus SysV release 5.0 
>Problem: lack of putenv() 
>
>The function putenv() which is included in Release 5.2 and above is 
>not part of libc.a on the above system.
>
>Apparently, there is a PD replacement, which I have not been able
>to locate.

Whether this one, which I wrote for another system lacking putenv(), is
the PD replacement to which you refer, I dunno, although others besides
me use it.  (Coding style crunched a bit to excuse posting [even short]
source to a non-source newsgroup):

/* putenv( string ) -- place a string into the current process' environment
 * ================
 *   char *string;
 *
 *          Returns: (-1) on error, otherwise 0
 *
 * Putenv() places 'string' into the environment of the current
 * process.  'String' should be a null-terminated string of the
 * form "name=value".  If the environment already contains such a
 * string, 'string' is substituted for it; otherwise, 'string' is
 * added to the environment as a new variable.
 * 
 * If the existing environment lacks sufficient space to hold
 * 'string', putenv() attempts to allocate more space via
 * malloc().
 * 
 * Putenv() will fail and return a value of (-1) if 'string' is
 * not in the form "name=value" or if additional necessary space
 * cannot be allocated for the new environment.
 */

putenv(string)
char *string;
{
    extern char **environ;
    extern char *strchr(), *malloc();
    extern char **calloc();        	/* a lie for 'lint' */

    register int i;
    int namelen, numvars;
    char *cptr, **newenv;

    if (string==0) return(-1);
    namelen = (int)(strchr(string,'=') - string) + 1;
    if (namelen<2) return(-1);
    /* see if this variable is already in environment */
    i = (-1);
    while (environ[++i]) {
        if (strncmp(string,environ[i],namelen)==0) {  /* It's there */
                /* if we can just patch it, do so and return */
            if (strlen(string)<=strlen(environ[i])) {
                strcpy(environ[i],string); return(0);
            }
            else break;
        }
    }
        /* OK, allocate a spot for 'string' and copy it there */
    cptr = malloc(strlen(string)+1);
    if (cptr==0) return(-1);          /* can't malloc */
    strcpy(cptr,string);
        /* no env at all; or else var exists but's too small to hold 'string' */
    if (i==0 || environ[i]) {  
        environ[i] = cptr; return(0);     /* ok, done */
    }
        /* "name" ain't there, or no space for it; so rebuild env. array */
    numvars = i;
    newenv = calloc(numvars+2,sizeof(char *));
    if (newenv==0) return(-1);        /* can't calloc */
    for (i=0;i<numvars;++i)
        newenv[i] = environ[i];
    newenv[i] = cptr;
    newenv[++i] = 0;
    environ = newenv;
    return(0);
}