/*
 * Written by Alexei V. Galatenko <agalat@castle.nmd.msu.ru>
 * and Andrey V. Savochkin <saw@msu.ru>
 */

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

#define NUM_POSIX	6

extern char **environ;

const char *posix_env[] = {
    "LANG",
    "LC_COLLATE",
    "LC_CTYPE",
    "LC_MONETARY",
    "LC_NUMERIC",
    "TZ",
};

void free_env (char **env)
{
    int i;
    for (i = 0; env [i] != NULL; i++)
	free (env [i]);
    free (env);
}

int make_environment(int keep_env, const char *home, char ***env)
{
    int i, j;
    char *tmpe;

    if (keep_env)
    {
	/* calculate the number of environment variables */
	if (environ == NULL) 
	    return 1;
    
	for (i = 0; environ[i] != NULL; i++);
	/* allocate the memory for remembering enironment */
	*env = (char **) calloc (i + 1, sizeof (char *));
	if (*env == NULL)
	    return 1;
        /* preserve the original environment */
	for (i = 0; environ[i] != NULL; i++) 
	{
	    (*env)[i] = malloc(strlen(environ[i]) + 1);
	    if ((*env)[i] == NULL) 
	    {
		free_env (*env);
		return 1;
	    }
	    strcpy((*env)[i], environ[i]);
	}
	(*env)[i] = NULL;
    }
    else
    {
	/* allocate the memory for remembering enironment */
	*env = (char **) calloc (NUM_POSIX + 3, sizeof (char *));
	if (*env == NULL)
            return 1;

	/* Adding terminal description */
	tmpe = getenv("TERM");
	if (tmpe == NULL) 
            tmpe = "dumb";
	(*env)[0] = malloc(strlen(tmpe) + sizeof ("TERM="));
        if ((*env)[0] == NULL)
        {
            free_env (*env);
            return 1;
        }
	sprintf ((*env)[0], "TERM=%s", tmpe);

	/* Adding home directory */
        (*env)[1] = malloc(strlen(home) + sizeof ("HOME="));
        if ((*env)[1] == NULL)
        {
            free_env (*env);
            return 1;
        }
        sprintf ((*env)[1], "HOME=%s", home);

	/* filling POSIX environment */
	for (i = 2, j = 0; j < NUM_POSIX; j++) 
	{
	    tmpe = getenv(posix_env[j]);
            if (tmpe == NULL)
                continue;
	    (*env)[i] = malloc(strlen (posix_env[j]) + sizeof "=" +
                               strlen (tmpe));
	    if ((*env)[i] == NULL) 
	    {
		free_env (*env);
		return 1;	
	    }
	    sprintf ((*env)[i], "%s=%s", posix_env[j], tmpe);
            i++;
	}

	(*env)[i] = NULL;
    }
    return 0;
}
