/*
 *	genv.c
 *
 *	Copying and use of this program are controlled by the terms of the
 *	Free Software Foundations GNU Emacs General Public License.
 *
 *	Copyright (C) 1987 Jeff Lydiatt
 *	Version		0.1		09 July 87
 *
 *	$Id: genv.c,v 1.3 90/01/16 10:25:30 crash Exp Locker: crash $
 */

#ifndef lint
static char RCSid[] = "$Id: genv.c,v 1.3 90/01/16 10:25:30 crash Exp Locker: crash $";
#endif /* lint */

#include <stdio.h>
#include <ctype.h>
#include "genv.h"

/* Environment variables are in file "PROFILE" */
#define PROFILE		"Uupc:Config/profile"

#define SAME	0
#define MAXLINE 255

/*
 *	Hostname-type defines...
 */
#define DMAILBOX	"crash"
#define	DNAME		"ckctpa"			/* For UUPC comms */
#define	DDOMAIN		"ckctpa.uucp"
#define	DNODENAME	"ckctpa"			/* For the mailer */
#define	DMAILSERVICE "boake2"

/*
 *	Directory and file locations...
 */
#define DHOME		"Uupc:Mail"
#define	DMAILDIR	"Uupc:Mail"
#define	DCONFDIR	"Uupc:Config"
#define	DSPOOLDIR	"Uupc:Spool"
#define DLOGDIR		"Uupc:Config"
#define DPUBDIR		"Uupc:Spool"
#define DTEMPDIR	"Uupc:Spool"		/* Should be T: ?? */
#define DNEWSDIR	"News:"				/* See C-News docs */

/*
 *	Miscellaneous
 */
#define	DDEVICE		"SER:"
#define	DSPEED		"2400"
#define DPAGESIZE	"24"
#define DTIMEZONE	"+0500"


#define	TFILENAME	"tmpfile"
#define	FILENAME 	"%s/%s"

struct environment {
	char	name[16];
	char	value[64];
};
typedef struct environment ENV;

static ENV profile[] =  {
	MAILBOX, 		"",
	NAME, 			"",
	DOMAIN, 		"",
	MAILDIR, 		"",
	HOME, 			"",
	CONFDIR, 		"",
	SPOOLDIR, 		"",
	LOGDIR, 		"",
	PUBDIR, 		"",
	NEWSDIR2, 		"",
	TEMPDIR, 		"",
	MAILSERVICE, 	"",
	NODENAME, 		"",
	DEVICE, 		"",
	SPEED, 			"",
	PAGESIZE,		"",
	TIMEZONE,		"",
	"", 			"",
};


char	*name = NULL;
char	*nodename = NULL;
char	*home = NULL;
char	*domain = NULL;
char	*mailserv = NULL;
char	*mailbox = NULL;
char	*maildir = NULL;
char	*confdir = NULL;
char	*spooldir = NULL;
char	*logdir = NULL;
char	*pubdir = NULL;
char	*tempdir = NULL;
char	*newsdir = NULL;
char	*device = NULL;
char	*speed = NULL;
char	*timezone = NULL;
char	*pagesize = NULL;

/*--------------------------------------------------------------*/
/*	getone: get next character file f.  f already open			*/
/*--------------------------------------------------------------*/

static int getone(f)
FILE *f;
{
	char	c;
	static char line[256];
	static int	pos = 0;
	static int	len = 0;

	if ( ++pos > len || line[pos] == '\0' ) {
		if ( fgets( line, 255, f ) == NULL )
			return EOF;
		pos = 0;
		len = strlen( line );
	}
	return line[pos];
}


/*--------------------------------------------------------------*/
/*	getsym: get next symbol from file f.  f already open		*/
/*--------------------------------------------------------------*/

#define ID		1001
#define DELIM	1002
#define STR		1003
#define EOL		1004
#define OTHER	1005
#define UNKNOWN -1000

static int	getsym(f, sym)
FILE *f;
char *sym;
{
	/*
	 *	Simple non reentrant, non reuseable get next symbol from file f.
	 *
	 *	Valid symbols are:
     *		Type		Symbol Returned			Comment
	 *
	 *		ID			<identifier>			any valid c identifier.
     *	    DELIM		'='						an equal sign.
	 *		STR			a string				anything between "" or ''.
	 *		EOL			'\n'					a newline.
	 *		EOF			EOF						the end of file marker.
	 *		OTHER   	a character				anything else.
	 *
	 *	Comments begin with # and are delimited by an end of line.
	 */
	static int	lastchar = UNKNOWN; /* Unknown */
	int	c, delim;

	/* strip leading white space */

	if ( lastchar != UNKNOWN )
		c = lastchar;
	else
		c = getone( f );

	while (c == ' ' || c == '\t')
		c = getone(f);
	lastchar = UNKNOWN;

	/* Comments are '#' delimited by EOL character */

	if (c == '#')
		while (c != '\n' && c != EOF)
			c = getone(f);

	if (c == EOF) return EOF;

	if (c == '\n') {			/* End of Line? */
		strcpy(sym, "\n");
		return EOL;
	}
	if (c == '=') {				/* Delimiter '='? */
		strcpy(sym, "=");
		return DELIM;
	}
	if (c == '\"' || c == '\'') {	/* String ? */
		delim = c;
		while ((c = getone(f)) != delim && c != EOF && c != '\n')
			*sym++ = c;
		*sym = '\0';
		c = getone(f);
		return STR;
	}
	if (isalpha(c)) {			/* Identifier ? */
		*sym++ = c;
		while ((c = getone(f)) == '_' || isalnum(c))
			*sym++ = c;
		*sym = '\0';
		lastchar = c;
		return ID;
	}
	*sym++ = c;
	*sym = '\0';
	return OTHER;
}


/*--------------------------------------------------------------*/
/*	setenv: insert an environment variable into my list			*/
/*--------------------------------------------------------------*/

static void setenv(var, value)
register char *var;
char *value;
{
	register ENV *p;

	for (p = profile; *(p->name) != '\0'; ++p)
		if (strcmp(p->name, var) == SAME) {
/*			strcpy(p->name, var);		/* [FJE] Why do this?? */
			strcpy(p->value, value);
			return;
		}
}


/*--------------------------------------------------------------*/
/*	getenv: get pointer to value of environment variable		*/
/*--------------------------------------------------------------*/

static char	*getenv(var)
register char *var;
{
	register ENV *p;

	for (p = profile; *(p->name) != '\0'; ++p) {
		if (strcmp(p->name, var) == SAME) {
			if (*p->value != '\0')
				return p->value;
			else
				break;
		}
	}
	return NULL;
}


/*--------------------------------------------------------------*/
/*	readenv: read environment from a file. 						*/
/*--------------------------------------------------------------*/

static void readenv()
{
	FILE *f;
	int	symval;
	char name[MAXLINE+1], value[MAXLINE+1];

#ifdef FJE
	setmem(name, 0, sizeof(name));
	if (f = fopen("ENV:profile", "r")) {
		if (fread(name, sizeof(name)-1, 1, f) != 1) {
			strcpy(name, PROFILE);
			printf(stderr, "Can't read PROFILE variable: using default\n");
		}
		fclose(f);
	} else
		strcpy(name, PROFILE);
	if ((f = fopen(name, "r")) == NULL) {
		fprintf(stderr, "Can't open %s: using defaults\n", name);
		return;
	}
#else
	if ((f = fopen(PROFILE, "r")) == NULL) {
		fprintf(stderr, "Can't open %s: using defaults\n", PROFILE);
		exit( NULL );
	}
#endif /* !FJE */
	/*
	 *	File is layed out as follows:
	 *
	 *	<environment variable> '=' <ID> | <STRING> # comment....
     */

	while ((symval = getsym(f, name)) != EOF) {
		/* Skip over any comment lines */

		while (symval == EOL)
			symval = getsym(f, name);
		if (symval == EOF)
			break;

		if (symval != ID) {
			fprintf(stderr, "Bad environment variable name %s\n", name);
#ifdef FJE
			continue;
#else
			exit( NULL );
#endif /* !FJE */
		}
		if ((symval = getsym(f, value)) != DELIM) {
			fprintf(stderr, "Missing `=' in environment file\n");
#ifdef FJE
			continue;
#else
			exit( NULL );
#endif /* !FJE */
		}
		if ((symval = getsym(f, value)) != ID && symval != STR) {
			fprintf(stderr,
				"missing value for `%s' in environment file\n", name);
#ifdef FJE
			continue;
#else
			exit( NULL );
#endif /* !FJE */
		}
		setenv(name, value);
	}
	fclose(f);
}


/*--------------------------------------------------------------*/
/*	exitenv: free that memory when done!						*/
/*--------------------------------------------------------------*/

void exitenv()
{
	return;
}


static void genv(thename, envname, dflt)
char	**thename;
char	*envname;
char	*dflt;
{
	if ((*thename = getenv(envname)) == NULL) {
		fprintf(stderr, "genv: %s not found, using %s\n", envname, dflt);
		*thename = dflt;
	}
}


void loadenv()
{
	readenv();	/* read the profile from a file */

	/* get environment var's */
	genv( &name,		NAME,			DNAME );
	genv( &nodename,	NODENAME,		DNODENAME );
	genv( &domain,		DOMAIN,			DDOMAIN );
	genv( &mailserv,	MAILSERVICE,	DMAILSERVICE );
	genv( &home,		HOME,			DHOME );
	genv( &mailbox,		MAILBOX,		DMAILBOX );
	genv( &maildir,		MAILDIR,		DMAILDIR );
	genv( &confdir,		CONFDIR,		DCONFDIR );
	genv( &spooldir,	SPOOLDIR,		DSPOOLDIR );
	genv( &logdir,		LOGDIR,			DLOGDIR );
	genv( &pubdir,		PUBDIR,			DPUBDIR );
	genv( &tempdir,		TEMPDIR,		DTEMPDIR );
	genv( &newsdir,		NEWSDIR2,		DNEWSDIR );
	genv( &device,		DEVICE,			DDEVICE );
	genv( &speed,		SPEED,			DSPEED );
	genv( &pagesize,	PAGESIZE,		DPAGESIZE );
	genv( &timezone,	TIMEZONE,		DTIMEZONE );
}


void mkfilename(filename, dirname, name)
char	*filename, *name;
register char	*dirname;
{
#ifdef AMIGA
	/*
	 *	Make sure that a slash doesn't immediately follow
	 *	a colon, or that there aren't going to be two slashes
	 *	adjacent in the resulting filename...
	 */
	if (dirname[ strlen(dirname)-1 ] == ':' ||
		dirname[ strlen(dirname)-1 ] == '/')
			sprintf(filename, "%s%s", dirname, name);
	else
#endif /* AMIGA */
		sprintf(filename, FILENAME, dirname, name);
}


#ifdef TEST
main()
{
	register ENV *p;

	loadenv();
	for (p = profile; *(p->name); ++p)
		fprintf(stderr, "name=`%s', value=`%s'\n", p->name, p->value);
}
#endif /* TEST */
