#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <utmp.h>
#include "myc_tmp.h"
#include "myc_str.h"
#include "myc_fortran.h"

#define ENAM_LEN 128
#define EVAL_LEN 1024

int lnblnk_(const char *str, int len);
#ifdef __alpha
  int setenv(char *p1, char *p2, int ow);
#endif

typedef struct _EnvList { struct _EnvList *next; char *name; char *value; } EnvList;
static EnvList *envlist;
static char tmpfil[128];
static char senv_id[16];
static char *empty="";
static int loaded=0;
static int dirty=0;

EnvList *sys_findenv(char *name) {
  EnvList *p;
  for (p=envlist; p!=NULL; p=p->next) {
    if (0==strcmp(name, p->name)) {
      return p;
    }
  }
  return NULL;
}

int F_FUN(sys_loadenv)(void) {
  FILE *fil;
  char buf[ENAM_LEN+EVAL_LEN+10];
  char old[EVAL_LEN], userid[32];
  char *nam, *val, *pold, *u, *ret, *v;
  int l;
  EnvList *p;
  
  if (!loaded) {
    loaded=-1; /* assume failure */
    /* u=cuserid(userid); */
    u=getenv("USER");
    if (u==NULL) {
      strcpy(userid, "Anonymous");
    } else {
      strncpy(userid, u, sizeof(userid));
    }
    val=getenv("senv_id");
    if (val==NULL) {
      sprintf(senv_id, "%d", getppid());
    } else {
      strcpy(senv_id, val);
    }
    sprintf(tmpfil, "/tmp/.senv_%s.%s", userid, senv_id);
    fil=fopen(tmpfil, "r");
    if (fil==NULL) {
      loaded=1;
      return 1;
    }
    while (1) {

      ret=fgets(buf, sizeof(buf), fil);
      if (!ret || buf[0]=='#') break;
      l=strlen(buf);
      if (l<10 || buf[l-1]!='\n') return -1;
      buf[l-1]='\0';
      buf[6]='\0';
      if (0!=strcmp(buf, "setenv")) return -1;
      nam=buf+7;
      val=strchr(nam, ' ');
      if (val==NULL) return -1;
      *val='\0'; val++;
      if (*val=='"') {
	if (buf[l-2]!='"') return -1;
	buf[l-2]='\0';
	val++;
      }
      
      ret=fgets(old, sizeof(old), fil);
      if (!ret) break;
      l=strlen(old);
      if (l==0 || old[0]!='#' || old[l-1]!='\n') return -1;
      old[l-1]='\0';
      pold=old+1;

      v=getenv(nam);
      if (v==NULL) v=empty;
      if (0==strcmp(v,pold)) { /* take value from file only if env. variable not changed in the meantime */
        p = malloc(sizeof(*p)); if (p == NULL) goto senv;
        if (NULL==(p->name = strdup(nam))) goto senv;
        if (NULL==(p->value = strdup(v))) goto senv;
        p->next = envlist;
        envlist=p;
	senv:
	setenv(nam, val, 1);
      }
    }
    if (0>fclose(fil)) return -1;
    loaded=1;
  }
  return loaded;
}

int F_FUN(sys_setenv)(char *enam, char *eval, int snam, int sval) {
  int lnam, lval;
  char *v, nam[ENAM_LEN], val[EVAL_LEN];
  EnvList *p=NULL;
  
  lnam = lnblnk_(enam,snam);
  if (lnam>=sizeof(nam)) lnam=sizeof(nam)-1;
  strncpy(nam,enam,lnam); nam[lnam] = '\0';

  lval = lnblnk_(eval,sval);
  if (lval>=sizeof(val)) lval=sizeof(val)-1;
  strncpy(val,eval,lval); val[lval] = '\0';

  if (loaded>0) {
    v=getenv(nam);
    if (v == NULL) v=empty;
    if (!dirty) {
      dirty = 0 != strcmp(val,v);
    }
    p=sys_findenv(nam);
    if (p==NULL) {  
      p = malloc(sizeof(*p)); if (p == NULL) goto senv;
      if (NULL==(p->name = strdup(nam))) goto senv;
      if (NULL==(p->value = strdup(v))) goto senv;
      p->next = envlist;
      envlist=p;
    }
  }
  senv:
  return setenv(nam, val, 1);
}

int F_FUN(sys_saveenv)(void) {
  FILE *fil;
  char *v;
  EnvList *p;
  
  if (F_FUN(sys_loadenv)()<0 || !dirty) return loaded;
  
  fil=fopen(tmpfil, "w");
  if (fil==NULL) return -1;

  for (p=envlist; p!=NULL; p=p->next) {
    v=getenv(p->name);
    if (0!=strcmp(v, p->value)) {
      if (0>fputs("setenv ", fil)) return -1;
      if (0>fputs(p->name, fil)) return -1;
      if (0>fputs(" \"", fil)) return -1;
      if (0>fputs(v, fil)) return -1;
      if (0>fputs("\"\n#", fil)) return -1;
      if (0>fputs(p->value, fil)) return -1;
      if (0>fputs("\n", fil)) return -1;
    }
  }
  if (0>fputs("#\nif ($$ == ", fil)) return -1;
  if (0>fputs(senv_id, fil)) return -1;
  if (0>fputs(") then\n /bin/rm ", fil)) return -1;
  if (0>fputs(tmpfil, fil)) return -1;
/*
  if (0>fputs("\n echo \"#\" > ", fil)) return -1;
  if (0>fputs(tmpfil, fil)) return -1;
*/
  if (0>fputs("\nendif\n", fil)) return -1;
  if (0>fclose(fil)) return -1;
  dirty=0;
  return 0;
}
