/*
**	defaults.c
**
**	Routines to access runtime defaults file in [uu]getty.
**	This is to allow program features to be configured
**	without the need to recompile.
*/

/*
**	Modification History:
**
**	10-Sep-02, CSJ: Release 2.1.0  - lots of fixes.
**	10-Jun-02, CSJ: Release 2.0.8 - lots of fixes, new maintainer.
**	21-Feb-97, SN:  Add baud rates higher than 38400, and remove baud
**			rates lower than 2400 (2.0.7.j)
**	25-Apr-96, JC:  Modify so that failure to open the "tty" after 3
**			attempts will terminate the program (2.0.7.i).
**	Unknown	   MB:  Fix segmentation fault when ttytype is not specified
**			on the command line (2.0.7.h).
**	Unknown	   ZT:  Several minor fixes, including bundling needed
**			sources (2.0.7g).
**	Unknown	   AW:	Modify so that utmp is updated correctly (2.0.7f).
**
**	AW: Alan Went (alan@ezlink.com)
**	CSJ: Christine S. Jamison (getty-info@nwmagic.net)
**	JC: Jeff Chua (jchua@fedex.com)
**	MB: Mike Blatchley (Mike_Blatchley@maxtor.com)
**	SN: Sho Nakagama (bbs.fdu.edu)
**	ZT: Zoltan Hidvegi (hzoli@cs.elte.hu)
**
**
**	Copyright 1989,1990 by Paul Sutcliffe Jr.
**	Portions copyright 2000,2002 by Christine Jamison.
**
**	Permission is hereby granted to copy, reproduce, redistribute,
**	or otherwise use this software as long as: there is no monetary
**	profit gained specifically from the use or reproduction of this
**	software; it is not sold, rented, traded or otherwise marketed;
**	and this copyright notice is included prominently in any copy
**	made.
**
**	The authors make no claims as to the fitness or correctness of
**	this software for any use whatsoever, and it is provided as is. 
**	Any use of this software is at the user's own risk.
*/

#include "getty.h"
#include "defaults.h"
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>


/*
**	defbuild() - create in-core list of defaults
**
**	Returns (DEF**)NULL if no defaults file found or an error occurs.
*/

DEF **defbuild(filename)
char *filename;
{
	register int i;
	register DEF *dp;
	register DEF *next;
	FILE *fp;
	char *fname, defname[MAXLINE+1], buf[MAXLINE+1];
	static DEF *deflist[MAXDEF+1];		/* in-core list */
	struct stat st;
	extern int errno;

	debug(D_DEF, "defbuild(%s) called",
			((filename == NULLPTR) ? "NULL" : filename));

	/* look to see if there's a DEFAULTS/MyName.Device file
	 */
	(void) sprintf(buf, "%s", DEFAULTS);
	(void) strcat(buf, ".%s");
	(void) sprintf(defname, buf, MyName, Device);
	debug(D_DEF, "looking for %s", defname);
	if ((stat(defname, &st) == FAIL) && errno == ENOENT) {	/* Nope */
		debug(D_DEF, "stat failed, no file");
		(void) sprintf(defname, DEFAULTS, MyName);
	}

	fname = (filename != NULLPTR) ? filename : defname;

	/* if fname doesn't begin with a '/', assume it's a
	 * filename to be made "DEFAULTS/fname"
	 */
	if (*fname != '/') {
		(void) sprintf(defname, DEFAULTS, fname);
		fname = defname;
	}

	debug(D_DEF, "fname = (%s)", fname);

	if ((fp = defopen(fname)) == (FILE *) NULL) {
		debug(D_DEF, "defopen() failed");
		return((DEF **) NULL);		/* couldn't open file */
	}

	for (i=0; i < MAXDEF; i++) {
		if ((dp = defread(fp)) == (DEF *) NULL)
			break;
		if ((next = (DEF *) malloc((unsigned) sizeof(DEF))) ==
		    (DEF *) NULL) {
			logerr("malloc() failed: defaults list truncated");
			break;
		}
		next->name = dp->name;
		next->value = dp->value;
		deflist[i] = next;
		debug(D_DEF, "deflist[%d]: name=(%s), value=(%s)",
				i, deflist[i]->name, deflist[i]->value);
	}
	deflist[i] = (DEF *) NULL;	/* terminate list */
	(void) defclose(fp);
	debug(D_DEF, "defbuild() successful");
	return(deflist);
}


/*
**	defvalue() - locate the value in "deflist" that matches "name"
**
**	Returns (char*)NULL if no match is made.
*/

char *defvalue(deflist, name)
register DEF **deflist;
register char *name;
{
	debug(D_DEF, "defvalue(%s) called", name);

	if (deflist != (DEF **) NULL)
		for (; *deflist != (DEF *) NULL; deflist++)
			if (strequal(name, (*deflist)->name)) {
				debug(D_DEF, "defvalue returns (%s)",
						(*deflist)->value);
				return((*deflist)->value);  /* normal exit */
			}

	debug(D_DEF, "defvalue returns NULL");
	return(NULLPTR);
}


/*
**	defopen() - open the defaults file
**
**	Returns (FILE*)NULL if file not found or an error occurs.
*/

FILE *defopen(filename)
register char *filename;
{
	if (filename != NULLPTR)
		return(fopen(filename, "r"));

	return((FILE *) NULL);
}


/*
**	defread() - read a line from the defaults file
**
**	Returns (DEF*)NULL if an error occurs.
*/

DEF *defread(fp)
register FILE *fp;
{
	register char *p, *p2;
	char buf[MAXLINE+1];	/* buffer large enough for 1 line */
	static DEF def;

readArec:
	do {
		if (fgets(buf, sizeof(buf), fp) == NULLPTR)
			return((DEF *) NULL);	/* no more lines */

	} while ((buf[0] == '#') || (buf[0] == '\n'));
	  /* SMR - ignore comment lines */

	buf[strlen(buf)-1] = '\0';		/* rm trailing \n */

	/* lines should be in the form "NAME=value" */
	if ((p = index(buf, '=')) == NULLPTR) {
		logerr("bad defaults line: %s", buf);
		goto readArec;
	}
	*p++ = '\0';		/* split into two fields, name and value    */
	while (*p && isspace(*p))
	   p++;			/* Jump past space before value.            */
	
	p2 = p + strlen(p) - 1;
	while (isspace(*p2))
	   *p2-- = '\0';	/* Remove spaces from end of value.         */
	def.value = strdup(p);
	p = buf;
	while (*p == ' ')
	   p++;			/* Jump past spaces before variable name.   */
	p2 = p + strlen(p) - 1;
	while (isspace(*p2))
	   *p2-- = '\0';	/* Remove spaces from end of variable name. */
	def.name = strdup(p);

	return(&def);
}


/*
**	defclose() - closes the defaults file
**
**	Returns EOF if an error occurs.
*/

int defclose(fp)
register FILE *fp;
{
	return(fclose(fp));
}

