/* loadconf.c - load and query configuration files
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif				/* HAVE_CONFIG_H */
#include <stdio.h>
#include <string.h>
#include "mstring.h"
#include "ldb.h"
#include "bbs.h"


int cf_lookup_key(bbs_cf_t *, char *);
char *cf_lookup_str(bbs_cf_t *, char *);
long cf_lookup_int(bbs_cf_t *, char *);
int cf_lookup_bool(bbs_cf_t *, char *);

bbs_cf_t *cf__opt_g = 0;		 /* global configuration */
bbs_cf_t *cf__opt_l = 0;		 /* local configuration */


/* Return the value of "key".
 */
char *cf_str(char *key)
{
	if (cf__opt_l) {		    /* look in local config first */
		if (cf_lookup_key(cf__opt_l, key) >= 0) {
			return (cf_lookup_str(cf__opt_l, key));
		}
	}
	return (cf_lookup_str(cf__opt_g, key));
}


/* Return the value of "key".
 */
long cf_int(char *key)
{
	if (cf__opt_l) {		    /* look in local config first */
		if (cf_lookup_key(cf__opt_l, key) >= 0) {
			return (cf_lookup_int(cf__opt_l, key));
		}
	}
	return (cf_lookup_int(cf__opt_g, key));
}


/* Return the value of "key".
 */
int cf_bool(char *key)
{
	if (cf__opt_l) {		    /* look in local config first */
		if (cf_lookup_key(cf__opt_l, key) >= 0) {
			return (cf_lookup_bool(cf__opt_l, key));
		}
	}
	return (cf_lookup_bool(cf__opt_g, key));
}


/* Expand filenames which contain special characters.
 */
void cf__expand(bbs_cf_t * spec)
{
	char buf[1024];
	char *a;
	int n;
	int i;

	for (i = 0; spec[i].key_name; i++) {
		if (spec[i].key_type != CF_FILENAME)
			continue;
		if (!strcmp(spec[i].key_name, "root"))
			continue;

		strncpy(buf, spec[i].strval, sizeof(buf) - 1);
		buf[sizeof(buf) - 1] = 0;

		n = 0;
		do {
			n += strcspn(buf + n, "~$%");
			if (n < 0)
				n = strlen(buf);
			if (buf[n] == 0)
				continue;
			switch (buf[n]) {
			case '~':
				a = home_dir;
				break;
			case '$':
				a = cf_str("root");
				break;
			case '%':
				a = current_user;
				break;
			default:
				a = 0;
			}
			if (a) {
				mstrdelete(buf, n, 1);
				mstrinsert(buf, a, &n, sizeof(buf) - 1);
			}
		} while (n < strlen(buf));

		if (buf[0] == '/') {
			spec[i].strval = strdup(ldb_filename(buf));
		} else {
			spec[i].strval = strdup(buf);
		}
	}
}


/* Load the global configuration file, searching various directories to find
 * it. Returns nonzero on error.
 */
int cf_global(void)
{
	FILE *fptr;
	int i;
	char *search[] = {
		CF_PREFIX "/etc/bbsrc",
		CF_PREFIX "/etc/bbs.cf",
		"/etc/bbs.cf",
		"/etc/bbsrc",
		"/usr/etc/bbs.cf",
		"/usr/etc/bbsrc",
		"/usr/local/etc/bbs.cf",
		"/usr/local/etc/bbsrc",
		0
	};
	static bbs_cf_t options[] = {
		{"root", CF_FILENAME, "/bbs", 0},	/* BBS root dir */
		{"main", CF_FILENAME, "$/main.mn", 0},	/* main menu */
		{"special", CF_FILENAME, "$/sys/esc.mn", 0},	/* get-anywhere menu */
		{"options", CF_FILENAME, "$/sys/opts.mn", 0},	/* options menu */
		{"xwarn", CF_FILENAME, "$/sys/xwarn.ro", 0},	/* X-rated warning */
		{"udb", CF_FILENAME, "$/sys/udb/%", 0},	/* user's UDB file */
		{"ldb", CF_FILENAME, "$/sys/ldb/%", 0},	/* user's LDB file */
		{"edit", CF_FILENAME, "~/.bbstmp", 0},	/* user's edit file */
		{"u2u", CF_FILENAME, "$/sys/u2u", 0},	/* u2u directory */
		{"u2uomax", CF_INTEGER, 0, 100},	/* max size on logout */
		{"u2uimax", CF_INTEGER, 0, 1000},	/* max size logged in */
		{"u2uomin", CF_INTEGER, 0, 50},	/* trunc to on logout */
		{"u2uimin", CF_INTEGER, 0, 600},	/* trunc to logged in */
		{"u2ulog", CF_FILENAME, "$/sys/log/u2u.log", 0},	/* log of all u2us */
		{"u2ulgsz", CF_INTEGER, 0, 4000},	/* max u2u log size */
		{"friends", CF_FILENAME, "$/sys/friends/%", 0},	/* friends list */
		{"sysop", CF_STRING, "root ivarch", 0},	/* BBS sysops */
		{"logdir", CF_FILENAME, "$/sys/log", 0},	/* system log dir */
		{"addlog", CF_FILENAME, "add.log", 0},	/* log of [A]dd */
		{"dellog", CF_FILENAME, "del.log", 0},	/* log of [.][D]el */
		{"editlog", CF_FILENAME, "edit.log", 0},	/* log of [.][A] */
		{"runlog", CF_FILENAME, "run.log", 0},	/* log of X/S run */
		{"maillog", CF_FILENAME, "mail.log", 0},	/* log of [M]ail */
		{"bbslog", CF_FILENAME, "client.log", 0},	/* log of clients */
		{"logsize", CF_INTEGER, 0, 100},	/* max log size, K */
		{"usrlist", CF_FILENAME, "$/listdirs", 0},	/* user list dirs */
		{"listdir", CF_FILENAME, "$/sys/list", 0},	/* special list dir */
		{"paths", CF_FILENAME, "$/sys/paths", 0},	/* allowed cmds */
		{"extlim", CF_INTEGER, 0, 20},	/* max externals */
		{"idleext", CF_INTEGER, 0, 1800},	/* max idle time */
		{"idleint", CF_INTEGER, 0, 10800},	/* max idle time */
		{"nolog", CF_FILENAME, "", 0},	/* nolog prefix */
		{"status", CF_FILENAME, "$/sys/status", 0},	/* client status dir */
		{0, 0, 0, 0}
	};

	cf__opt_g = options;

	for (i = 0; search[i]; i++) {
		fptr = fopen(search[i], "r");
		if (!fptr)
			continue;
		fclose(fptr);
		if (cf_load(search[i], cf__opt_g))
			return (1);
		cf__expand(cf__opt_g);
		return (0);
	}

	fprintf(stderr, "Cannot find global configuration file.\n\r");
	return (1);
}


/* Load the per-user configuration file, returning nonzero on error.
 *
 * Since there is nothing yet to put into a per-user configuration file,
 * this function currently does nothing.
 */
int cf_local(void)
{
	return (0);
}

/* EOF */
