/* 	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		10 July 87
 *
 *	$Id: genv.dyna,v 1.1 90/01/16 10:30:22 crash Exp Locker: crash $
 */

#ifndef lint
static char RCSid[] = "$Id: genv.dyna,v 1.1 90/01/16 10:30:22 crash Exp Locker: crash $";
#endif /* !lint */
 
#include <stdio.h>
#include "genv.h"

/* Environment variables are in file "PROFILE" */
#define PROFILE ":usr/lib/uucp/profile"

#define SAME	0
#define MAXLINE 255

#define DMAILBOX	"mailbox"
#define	DNAME		"noname"
#define	DDOMAIN		"pc.uucp"
#define	DMAILDIR	":usr/spool/mail"
#define DHOME		":usr/noname"
#define	DCONFDIR	":usr/lib/uucp"
#define	DSPOOLDIR	":usr/spool/uucp"
#define DLOGDIR		":usr/spool/uucp"
#define DPUBDIR		":usr/spool/uucppublic"
#define DNEWSSDIR	":usr/spool/rnews"
#define DTEMPDIR	"RAM:T"
#define	DMAILSERVICE	"host"
#define	DNODENAME	"noname"
#define	DDEVICE		"CON:"
#define	DSPEED		"1200"

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

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

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

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

static int getone( f )
FILE *f;
{
	static char line[256];		/* [FJE] Added "static" */
	static int pos = -1;
	static int len = 0;

	if ( ++pos > len || line[pos] == '\0' )  {
		if ( fgets( line, 255, f ) == NULL )
			return EOF;
		pos = -1;
		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						the end-of-file character
	 *	OTHER   a character		anything else
	 *
	 *	Comments begin with # and are delimited by an end of line
	 */

	static int lastchar = 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 '#' terminated by EOL character */
	if ( c == '#' )
		while ( c != '\n' && c != EOF )
			c = getone( f );
	if ( c == EOF )							/* End of file? */
		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;
}

/*--------------------------------------------------------------*/
/*	xmalloc: Just alloc with die on allocation failure	*/
/*--------------------------------------------------------------*/
static char *xmalloc( size )
unsigned int size;
{
	char *malloc();
	register char *p;

	if ( (p = malloc( size )) != NULL )
	   return p;

	fprintf( stderr, "Genv.c: Can't allocated %u bytes\n", size );
	exit( NULL );
}

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

typedef struct environment {
	struct environment *next;
	char *name;
	char *value;
} ENV;

static ENV *envList = NULL;

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

	envframe        = (ENV *) xmalloc( sizeof( ENV ));
	envframe->name  = xmalloc( strlen(var)+1 );
	envframe->value = xmalloc( strlen(value)+1 );
	envframe->next  = envList;
	envList		    = envframe;
	
	strcpy( envframe->name, var );
	strcpy( envframe->value, value);
}

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

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

	for ( list = envList; list != (ENV *)NULL; list = list->next )
		if ( strcmp( var, list->name ) == SAME )
			return list->value;

	return NULL;
}

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

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

	if ( (f = fopen( PROFILE, "r" )) == NULL ) {
		fprintf( stderr, "Can't open profile file \"%s\"\n", PROFILE );
		exit( NULL );
	}
	/*
	 *	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 );
			exit( NULL );
		}
		if ( (symval = getsym( f, value )) != DELIM ) {
			fprintf( stderr, "Missing '=' in environment file\n" );
			exit( NULL );
		}
		if ( (symval = getsym( f, value )) != ID && symval != STR ) {
			fprintf( stderr, "missing value in environment file\n");
			exit( NULL );
		}
		setenv( name, value );
	}
	fclose( f );
}

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

void exitenv()
{
	register ENV *p, *q;	

	for ( p = envList; p != NULL; p = q ) {
		free( p->name );
		free( p->value);
		q = p->next;
		free( p );
	}
	envList = NULL;
}

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;
	}
#if 0
	fprintf( stderr, "genv: %s \"%s\"\n", envname, *thename );
#endif
}

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

	/* get environment var's */
	genv( &name,		NAME,			DNAME );
	genv( &mailbox,		MAILBOX,		DMAILBOX );
	genv( &home,		HOME,			DHOME );
	genv( &domain,		DOMAIN,			DDOMAIN );
	genv( &maildir,		MAILDIR,		DMAILDIR );
	genv( &confdir,		CONFDIR,		DCONFDIR );
	genv( &spooldir,	SPOOLDIR,		DSPOOLDIR );
	genv( &logdir,		LOGDIR,			DLOGDIR );
	genv( &pubdir,		PUBDIR,			DPUBDIR );
	genv( &mailserv,	MAILSERVICE,	DMAILSERVICE );
	genv( &nodename,	NODENAME,		DNODENAME );
	genv( &device,		DEVICE,			DDEVICE );
	genv( &speed,		SPEED,			DSPEED );
	genv( &tempdir,		TEMPDIR,		DTEMPDIR );
}
 
#if 0		/* Needs to be updated via mkfilename() in genv.c */

void mkfilename( filename, dirname, name )
char *filename;
char *dirname;
char *name;
{
	sprintf( filename, FILENAME, dirname, name );	
	fprintf( stderr, "New filename %s\n", filename );
}
#endif

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

	loadenv();
	for ( p = envList; p != NULL; p = p->next )
		fprintf( stderr, "Name=\"%s\" value=\"%s\"\n", p->name, p->value );
}
#endif
