/* 		genv.c
 
 
 
		copyright (C) 1987 Jeff Lydiatt
 
		Copying and use of this program are controlled by the terms of the
		Free Software Foundations GNU Emacs General Public License.
 
 
		version		0.1		09 July 87

   Maintenance Notes: 
     01 Oct 87 - static line[] in getone() reported by Peter da Silva fixed. 
 
*/
 
#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 DNEWSDIR	":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>

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,		"",
	"",		"",
  };	
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;
char	*newsdir = NULL;

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

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

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

   c = line[pos];
   return c;
   
}

/*--------------------------------------------------------------*/
/*	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; /* 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 )		/* 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;

}
	

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

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

	for ( p = &profile[0];
	      *(p->name) != '\0';
	      ++p ) 
	  {
	     if ( strcmp( p->name, var ) == SAME )
		{

	  	   strcpy( p->name, var );
		   strcpy( p->value, value);
		   break;
		}
	   }
}

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

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

	for ( p = &profile[0];
	      *(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];

   /* fprintf( stderr, "Opening profile\n"); /**/
   if ( (f = fopen( PROFILE, "r" )) == NULL )
     {
	fprintf( stderr, "Can't open profile file \"%s\"\n",
	PROFILE );
	exit( 12 );
     }

    /* 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( 12 );
	  }

	if ( (symval = getsym( f, value )) != DELIM )
	  {
	     fprintf( stderr, "Missing '=' in environment file\n" );
	     exit( 12 );
	  }

	if ( (symval = getsym( f, value )) != ID && symval != STR )
	  {
	     fprintf( stderr, "missing value in environment file\n");
	     exit( 12 );
	  }

	setenv( name, value );
      }
    fclose( f );

}

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

void exitenv()
{
}

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;
	     setenv( envname, dflt );
		
	  }
	/* fprintf( stderr, "genv: %s \"%s\"\n", envname, *thename ); /**/
}

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 );
	genv( &newsdir, NEWSDIR2, DNEWSDIR );
}
 
void mkfilename( filename, dirname, name )
char * filename;
char * dirname;
char * name;
{
	sprintf( filename, FILENAME, dirname, name );	
	/* fprintf( stderr, "New filename %s\n", filename );  /**/	
}


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

	loadenv();

	for ( p = &profile[0];
	      *(p->name) != '\0';
	      ++p)

	    fprintf( stderr, "name=\"%s\", value=\"%s\"\n",
		     p->name, p->value);
} 

#endif


