/*
 *	Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
 *	This will be free software, but only when it is finished.
 */

/*LINTLIBRARY*/

/*
 *  The routines in this file will gulp in a configuration file in
 *  the syntax of printenv output, and allow access to the values read
 *  through an analogue of getenv().
 */

#include "mailer.h"
#include <ctype.h>
#include <sys/stat.h>
#include "mail.h"

static char *zenviron = NULL;
static int zenvlen = 0;

extern char *strerror();
extern int errno;
extern char *progname;

int
readzenv(file)
	char *file;
{
	int fd;
	struct stat stbuf;

	if ((fd = open(file, 0)) < 0) {
		fprintf(stderr, "%s: open: %s: %s\n",
			progname, file, strerror(errno));
		return 0;
	}
	if (fstat(fd, &stbuf) < 0) {
		fprintf(stderr, "%s: fstat: %s: %s\n",
			progname, file, strerror(errno));
		close(fd);
		return 0;
	}
	if ((zenviron = (char*)malloc((u_int) stbuf.st_size)) == NULL) {
		fprintf(stderr,
			"%s: malloc(size of %s): %d: out of memory\n",
			progname, file, stbuf.st_size);
		close(fd);
		return 0;
	}
	zenvlen = stbuf.st_size;
	if (read(fd, zenviron, stbuf.st_size) != stbuf.st_size) {
		fprintf(stderr, "%s: read: %s: %s\n",
			progname, file, strerror(errno));
		free(zenviron);
		zenviron = NULL;
		zenvlen = 0;
		close(fd);
		return 0;
	}
	close(fd);
	return 1;
}

#define BOL	1

char *
getzenv(variable)
	char *variable;
{
	register int len, state;
	register char *cp;
	int varlen;
	char *save;

	if (variable == NULL || (varlen = strlen(variable)) == 0)
		return NULL;
	if ((len = zenvlen) <= 0) {
		if (!readzenv(ZMAILER_ENV_FILE) || (len = zenvlen) <= 0)
			return NULL;
	}
	for (state = BOL, cp = zenviron; len > 0; --len, ++cp) {
		if (*cp == '\n' || *cp == '\0') {
			state = BOL;
			continue;
		}
		if (state != BOL)
			continue;
		state = !BOL;
		if (varlen < len && *variable == *cp
		    && strncmp(variable, cp, varlen) == 0
		    && *(cp+varlen) == '=')
			break;
	}
	if (len > 0) {
		for (cp += varlen+1; isascii(*cp) && isspace(*cp); ++cp)
			if (*cp == '\n') {
				*cp = '\0';
				return cp;	/* empty value */
			}
		/*
		 * We want to return cp, but also make sure the string is
		 * properly terminated.
		 */
		for (save = cp; *cp != '\0'; ++cp)
			if (*cp == '\n') {
				*cp = '\0';
				break;
			}
		return save;
	}
	return NULL;
}
