
/*
 * SET.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 * Handles the variable lists for normal variables, aliases, and labels.
 */

#include "shell.h"
#define MAXLEVELS (3 + MAXSRC)

struct MASTER {
    struct MASTER *next;
    struct MASTER *last;
    char *name;
    char *text;
};

static struct MASTER *Mbase[MAXLEVELS];

char *
set_var(level, name, str)
short level;
register char *name, *str;
{
    register struct MASTER *base = Mbase[level];
    register struct MASTER *last;
    register short len;

    for (len = 0; isalphanum(name[len]); ++len);
    while (base != NULL) {
	if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) {
	    Free (base->text);
	    goto gotit;
	}
	last = base;
	base = base->next;
    }
    if (base == Mbase[level]) {
	base = Mbase[level] = (struct MASTER *)malloc(sizeof(struct MASTER));
	base->last = NULL;
    } else {
	base = (struct MASTER *)malloc (sizeof(struct MASTER));
	base->last = last;
	last->next = base;
    }
    base->name = malloc (len + 1);
    bmov (name, base->name, len);
    base->name[len] = 0;
    base->next = NULL;
gotit:
    base->text = malloc (strlen(str) + 1);
    strcpy (base->text, str);
    return (base->text);
}

char *
get_var (level, name)
short level;
register char *name;
{
    register struct MASTER *base = Mbase[level];
    register unsigned char *scr;
    register short len;
    static char *EnvBuf = NULL;
    char buf[128];
    long fh;

    for (scr = (UBYTE *)name; *scr && *scr != 0x80 && *scr != ' ' && *scr != ';' && *scr != '|'; ++scr);
    len = scr - name;

    while (base != NULL) {
	if (strlen(base->name) == len && strncmp (name, base->name, len) == 0)
	    return (base->text);
	base = base->next;
    }
    mountrequest(0);
    strcpy(buf, "ENV:");
    strncat(buf, name, len);
    buf[4+len] = 0;
    if (fh = Open(buf, 1005)) {
	long len = (Seek(fh, 0L, 1), Seek(fh, 0L, 0));
	if (len < 0)
	    len = 256;
	if (EnvBuf)
	    free(EnvBuf);
	if (EnvBuf = malloc(len+1)) {
	    Seek(fh, 0L, -1);
	    len = Read(fh, EnvBuf, len);
	    if (len < 0)
		len = 0;
	    EnvBuf[len] = 0;
	}
	Close(fh);
	mountrequest(1);
	return(EnvBuf);
    }
    mountrequest(1);
    return (NULL);
}


unset_level(level)
short level;
{
    register struct MASTER *base = Mbase[level];
    register struct MASTER *next;

    while (base) {
	next = base->next;
	Free (base->name);
	Free (base->text);
	Free (base);
	base = next;
    }
    Mbase[level] = NULL;
}


unset_var(level, name)
short level;
char *name;
{
    register struct MASTER *base = Mbase[level];
    register struct MASTER *last = NULL;
    register short len;

    for (len = 0; isalphanum(name[len]); ++len);
    while (base) {
	if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) {
	    if (base != Mbase[level])
		last->next = base->next;
	    else
		Mbase[level] = base->next;
	    if (base->next != NULL)
		base->next->last = last;
	    if (base == Mbase[level])
		Mbase[level] = base->next;
	    Free (base->name);
	    Free (base->text);
	    Free (base);
	    return (1);
	}
	last = base;
	base = base->next;
    }
    return (-1);
}


do_unset_var(garbage, level)
short level;
char *garbage;
{
    register short i;
    register char uu = 0;

    for (i = 1; i < ac; ++i) {
	unset_var (level, av[i]);
	if (*av[i] == '_')
	    uu = '_';
    }
    update_under(uu);
    return (0);
}


do_set_var(command, level)
short level;
char *command;
{
    register struct MASTER *base = Mbase[level];
    register char *str;

    if (ac == 1) {
	while (base) {
	    fhprintf (Cout, "%-10s ", base->name);
	    Oputs (base->text);
	    base = base->next;
	}
	return (0);
    }
    if (ac == 2) {
	str = get_var (level, av[1]);
	if (str) {
	    fhprintf (Cout, "%-10s ", av[1]);
	    Oputs(str);
	} else {
	    set_var (level, av[1], "");
	}
    }
    if (ac > 2)
	set_var (level, av[1], next_word (next_word (command)));
    update_under(*av[1]);
    return (0);
}

static
update_under(c)
{
    register char *str;
    if (c == '_') {
	S_histlen = (str = get_var(LEVEL_SET, V_HIST))   ? atoi(str) : 0;
	S_ignoreeof=(str = get_var(LEVEL_SET, V_IGNOREEOF)) ? 1 : 0;
	SDebug	  = (str = get_var(LEVEL_SET, V_DEBUG))  ? atoi(str) : 0;
	Verbose   = (get_var(LEVEL_SET, V_VERBOSE)) ? 1 : 0;
	if (S_histlen < 2)
	    S_histlen = 2;
    }
}



