/* File:	Config.c (Configuration)
 * Purpose:	Extract fields from UULIB:Config or the corresponding 
 *		environment variables.
 * Author:	Matthew Dillon
 * Created:	
 *
 *  (C) Copyright 1989-1990 by Matthew Dillon,	All Rights Reserved.
 *
 * Initials:
 *	BCW - Brett Wuth
 *		Phone: (403) 627-2460
 *		E-mail: support@castrov.cuc.ab.ca, support@castrov.UUCP
 *
 * HISTORY: $Log:	config.c,v $
 * Revision 1.5.1.2  94/08/07  21:32:34  wuth
 * .
 * 
 * Revision 1.6  94/07/26  23:07:54  wuth
 * .
 * 
 *	Add GetHostConfig().
 */

#include <assert.h>
#include <exec/types.h>
#include <exec/libraries.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"

Prototype char *FindLocalVariable (const char *);
Prototype char *FindConfig (const char *);
Prototype char *GetConfig (const char *, char *);
Prototype char *GetHostConfig (const char *Host, const char *Field, const char *Def);
Prototype const char *GetConfigDir (const char *);
Prototype char *GetConfigProgram (char *);
Prototype char *MakeConfigPath (const char *, const char *);
Prototype char *MakeConfigPathBuf (char *, const char *, const char *);
Prototype FILE *openlib (const char *);
Prototype FILE *openlib_write (const char *);

#define CTLZ	('z'&0x1F)

static char
	*ConfBuf = NULL;

typedef struct LVarNode {
	struct LVarNode *lv_Next;
	char *lv_Name;
	char lv_Buf [4];
} LVarNode;

char *
FindLocalVariable (const char *field)
{
	static LVarNode
		*LVBase = NULL;
	LVarNode
		*lvnode;

	for (lvnode = LVBase; lvnode; lvnode = lvnode->lv_Next) {
		if (stricmp ((char *) field, lvnode->lv_Name) == 0)
			return lvnode->lv_Buf;
	}

	if (SysBase->LibNode.lib_Version >= 37) {   /*	MUST be V37 or greater */
		char
			buf [2];

		if (GetVar ((UBYTE *) field, (UBYTE *) buf, sizeof (buf) - 1, 0) >= 0) {
			LVarNode
				*lvnode;
			long
				len = IoErr () + 1;

			lvnode = malloc (sizeof (LVarNode) + len + 1);
			if (lvnode) {
				lvnode->lv_Name = malloc (strlen (field) + 1);
				if (lvnode->lv_Name) {
					strcpy (lvnode->lv_Name, field);
					lvnode->lv_Next = LVBase;
					LVBase = lvnode;
					GetVar ((UBYTE *) field, (UBYTE *) lvnode->lv_Buf, len, 0);
					return lvnode->lv_Buf;
				}
			}
		}
	}

	return NULL;
}


char *
FindConfig (const char *field)
{
	char
	    *str;
	short
	    flen = strlen (field);

	/*
	 *  If under 2.0 or above, it may be a local environment variable
	 */

	if (str = FindLocalVariable (field))
		return str;

	/*
	 *  load config file if not already loaded
	 */

	if (ConfBuf == NULL) {
		FILE
			*fi;

		fi = fopen ("S:UUConfig", "r");
		if (fi == NULL)
			fi = fopen ("UULIB:Config", "r");
		if (fi) {
			long
				buflen;

			fseek (fi, 0L, 2);
			buflen = ftell (fi);
			fseek (fi, 0L, 0);
			if (buflen > 0 && (ConfBuf = malloc (buflen + 1))) {
				fread (ConfBuf, buflen, 1, fi);
				ConfBuf [buflen] = CTLZ;     /*  can't use \0 */
				for (str = ConfBuf; *str && *str != CTLZ; ++str) {
					char
						*bup;

					if (*str == '\n') {
						/*  make separate strs */
						*str = 0;
						/*  remove white space at end */
						for (bup = str - 1; bup >= ConfBuf && (*bup == ' ' || *bup == '\t'); --bup)
							*bup = 0;
					}
				}
			}
			else {
				ConfBuf = NULL;
			}

			fclose (fi);
		}
		else {
			fprintf (stderr, "Couldn't open S:UUConfig or UULIB:Config\n");
		}
	}

	if (ConfBuf == NULL)
		return NULL;

	/*
	 *  Search ConfBuf for Field<space/tab>
	 */

	for (str = ConfBuf; *str != CTLZ; str += strlen (str) + 1) {
		if (*str == 0 || *str == '#')
			continue;

		if (strnicmp (str, (char *) field, flen) == 0 && (str [flen] == ' ' || str [flen] == '\t')) {
			str += flen;
			while (*str == ' ' || *str == '\t')
				++str;
			return str;
		}
	}

	return NULL;
}

char *
GetConfig (const char *field, char *def)
{
	char
		*result = FindConfig (field);

	if (result == NULL)
		result = def;

	return result;
}

/*PUBLIC*/
char * /*value*/
GetHostConfig (const char *HostName, const char *Field, const char *def)
{
	char FieldNameHost[80];
	char * result;

	/* assume our temporary is big enough */
	assert(    sizeof (FieldNameHost) 
		>= strlen( HostName ) + strlen( Field ) + strlen( "Host--" )
		   + sizeof ('\0') );

	sprintf( FieldNameHost, "Host-%s-%s", HostName, Field );

	result = FindConfig( FieldNameHost );
	if (result == NULL)
	    result = FindConfig( Field );
	if (result == NULL)
	    result = def;

	return (result);
}


const char *
GetConfigDir (const char *field)
{
	const char
		*result = FindConfig (field);

	if (result == NULL)
		result = field + strlen (field) + 1;

	return result;
}

char *
GetConfigProgram (char *field)
{
	char
		*result = FindConfig (field);

	if (result == NULL)
		result = field;

	return result;
}

char *
MakeConfigPath (const char *field, const char *trailer)
{
	static char
		Buf [512];

	return MakeConfigPathBuf (Buf, field, trailer);
}

char *
MakeConfigPathBuf (char *buf, const char *field, const char *trailer)
{
	const char
		*result = GetConfigDir (field);
	short
		len = strlen (result) - 1;

	if (len > 0 && result [len] == '/' || result [len] == ':')
		sprintf (buf, "%s%s", result, trailer);
	else
		sprintf (buf, "%s/%s", result, trailer);

	return buf;
}

FILE *
openlib (const char *filename)
{
    return fopen (MakeConfigPath (UULIB, filename), "r");
}

FILE *
openlib_write (const char *filename)
{
    return fopen (MakeConfigPath (UULIB, filename), "w");
}

/*** EOF ***/
