/*
 * Libraries and headers for PDC release 3.3 (C) 1989 Lionel Hummel.
 * PDC Software Distribution (C) 1989 Lionel Hummel and Paul Petersen.
 * PDC I/O Library (C) 1987 by J.A. Lydiatt.
 *
 * This code is freely redistributable upon the conditions that this
 * notice remains intact and that modified versions of this file not
 * be included as part of the PDC Software Distribution without the
 * express consent of the copyright holders.  No warrantee of any
 * kind is provided with this code.  For further information, contact:
 *
 *  PDC Software Distribution    Internet:                     BIX:
 *  P.O. Box 4006             or hummel@cs.uiuc.edu            lhummel
 *  Urbana, IL  61801-8801       petersen@uicsrd.csrd.uiuc.edu
 */

/* Environment.c - Functions to aid in dealing with environment variables
 *
 *      getenv(v)       Returns the string value of environment variable v
 *      setenv(v, s)    Sets environment variable v to string s
 *	unsetenv(v)	Removes environment variable v
 *      putenv(s)       s is in form "variable=value", calls setenv()
 *      ParseEnv(s)     Places the next parsed entry in String or NULL if
 *                      no more.  String is set to s if s is non-NULL.
 */

/* Misc. notes on environment variables:
 * To embed a space in a file name, precede it with the escape delimiter
 * (usually a backslash).
 */

/* modified - ryb */

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>

#define MAX_ENV_LENGTH (1024)

#define ARG_DELIM       ';'
#define ESC_DELIM       '\\'
#define QUOTE_CHAR      '"'

static char *String = NULL;
static char *currChar = NULL;

char *
getenv (const char *v)
{
  int env_file;
  int size = 0;
  char *tmp_buf, *value; /* Used for environment filename and input buffer */
  char *return_buf;
  char *ptr;

  value = tmp_buf = (char *) malloc (MAX_ENV_LENGTH);
  if (!tmp_buf)
    exit (ENOMEM);

  sprintf (value, "ENV:%s", v);

  if ((env_file = open (value, O_RDONLY)) != -1)
    {
      size = read (env_file, value, MAX_ENV_LENGTH);
      close (env_file);
    }
  else
    return NULL;

  value[size] = '\0';

  ptr = return_buf = (char *) malloc (size + 1);
  if (return_buf)
    while (*ptr++ = *value++) ;
  else
    exit (ENOMEM);

  free (tmp_buf);

  return return_buf;
}


int
setenv (const char *v, const char *s, int replace)
{
  int env_file;
  int mode;
  char *tmp_buf;

  tmp_buf = (char *) malloc (MAX_ENV_LENGTH);
  if (!tmp_buf)
    return -1;

  sprintf (tmp_buf, "ENV:%s", v);

  mode = O_EXCL | O_WRONLY;
  if (replace)
    mode = O_CREAT | O_WRONLY;

  env_file = open (tmp_buf, mode);
  if (env_file != -1)
    {
      write (env_file, s, strlen (s));
      close (env_file);
    }

  free (tmp_buf);

  if (env_file == -1 && errno != EEXIST)
    return -1;

  return 0;
}


void
unsetenv (const char *v)
{
  char *tmp_buf;

  tmp_buf = (char *) malloc (MAX_ENV_LENGTH);
  if (!tmp_buf)
    return;
  sprintf (tmp_buf, "ENV:%s", v);
  remove (tmp_buf);
  free (tmp_buf);
}


int
putenv (const char *s)
{
  char *variable;
  char *value;
  int status = -1;

  variable = strdup (s);
  if (variable)
    {
      value = strchr (s, '=');
      if (value != NULL)
	{
	  *value++ = '\0';
	  status = setenv (variable, value, 1);
	}
      free (variable);
    }
  return status;
}


char *
ParseEnv (char *s)
{
  char *ptr;
  int in_quote = 0;

  if (s != NULL)
    {
      if (String != NULL)
	free (String);
      currChar = String = strdup (s);
    }

  s = ptr = currChar;

  if (*currChar == '\0')
    return (NULL);

  while ((*currChar != '\0') && (*currChar != ARG_DELIM))
    {
      if (*currChar == ESC_DELIM)
	switch (*(currChar + 1))
	  {
	  case QUOTE_CHAR:
	  case ESC_DELIM:
	  case ARG_DELIM:
	    *ptr++ = *++currChar;
	    currChar++;
	    break;
	  default:
	    *ptr++ = *currChar++;
	    break;
	  }
      else if (isspace (*currChar) && !in_quote)
	currChar++;
      else if (*currChar == QUOTE_CHAR)
	{
	  in_quote = !in_quote;
	  currChar++;
	}
      else
	*ptr++ = *currChar++;
    }

  if (*currChar == ARG_DELIM)
    currChar++;

  *ptr = '\0';

  return s;
}
