/* udb.c - handle user database file
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif				/* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
#include "mstring.h"
#include "lock.h"
#include "bbs.h"

time_t udb__last_mtime = 0;
extern int bbs__external;


/* Load the current user's database file and set any appropriate environment
 * variables from it and from the global configuration file.
 */
void udb_load(void)
{
	struct passwd *z;
	struct stat sb;
	char buf[1024];
	FILE *fptr;
	char *a;
	int fd;

	fd = open(cf_str("udb"), O_RDWR);
	if (fd >= 0) {

		my_flock(cf_str("udb"), fd, LOCK_EX);

		fptr = fopen(cf_str("udb"), "r");

		while ((fptr) && (!ferror(fptr)) && (!feof(fptr))) {
			buf[0] = 0;
			fgets(buf, sizeof(buf) - 1, fptr);
			a = strchr(buf, '\n');
			if (a)
				a[0] = 0;
			a = strchr(buf, '=');
			if (a) {
				*a = 0;
				a++;
				setenv(buf, a, 1);
			}
		}

		if (fptr)
			fclose(fptr);
		my_flock(cf_str("udb"), fd, LOCK_UN);
		close(fd);
	}

	if (!stat(cf_str("udb"), &sb))
		udb__last_mtime = sb.st_mtime;

	if (!getenv("MVIEW_NAMELINE")) {    /* set default nameline */
		z = getpwuid(getuid());
		if (z) {
			strncpy(buf, (z->pw_gecos) ? z->pw_gecos : "",
				sizeof(buf) - 4);
			buf[sizeof(buf) - 4] = 0;
			a = strchr(buf, ',');
			if (a)
				a[0] = 0;
			setenv("MVIEW_NAMELINE", buf, 1);
		}
	}

	if (!getenv("BBS_EMAIL")) {	    /* set default email addr */
		sprintf(buf, "%s@localhost", current_user);
		setenv("BBS_EMAIL", buf, 1);
	}

	if (!getenv("BBS_LOGINS"))
		setenv("BBS_LOGINS", "0", 1);	/* logins */

	if (!bbs__external)
		setenv("MVIEW_EDIT_TMP", cf_str("edit"), 1);

	if (!getenv("BBS_MESSAGES")) {	    /* dflt new message action */
		setenv("BBS_MESSAGES", "read", 1);
	}

	if (getenv("BBS_COLOUR")) {	    /* if colour option, use it */
		if (!strcmp(getenv("BBS_COLOUR"), "0")) {
			mstrtoansi_colours(0);
		} else {
			mstrtoansi_colours(1);
		}
	}

	if (bbs_is_sysop(current_user)) {   /* set sysop privs etc */
		setenv("BBS_PRIVS", "DA", 1);
		setenv("BBS_BANS", "", 1);
		setenv("BBS_LEVEL", "0", 1);
	}

	if (!strcmp(current_user, "guest")) {	/* set guest privs, bans etc */
		setenv("BBS_PRIVS", "", 1);
		setenv("BBS_BANS", "NM2E", 1);
		setenv("BBS_LEVEL", "99", 1);
		setenv("MVIEW_NAMELINE", "Guest User", 1);
	}
}


/* Return the environment variable "var", or "" if it is unset.
 */
char *udb_env(char *var)
{
	char *val;
	val = getenv(var);
	return (val ? val : "");
}


/* Save the current user's database file, updating from the environment.
 *
 * If the UDB file has changed since it was last read, it is re-read instead
 * of saving.
 */
void udb_save(void)
{
	struct stat sb;
	FILE *fptr;
	int fd;

	if (!stat(cf_str("udb"), &sb)) {
		if (sb.st_mtime > udb__last_mtime) {
			udb_load();
			return;
		}
	}

	remove(cf_str("udb"));

	fd = open(cf_str("udb"), O_WRONLY | O_APPEND | O_CREAT,
		  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
	if (fd < 0)
		return;

	fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);

	lseek(fd, 0, SEEK_SET);
	my_flock(cf_str("udb"), fd, LOCK_EX);

	fptr = fopen(cf_str("udb"), "w");

	if (fptr) {
		fprintf(fptr, "BBS_PRIVS=%s\n", udb_env("BBS_PRIVS"));
		fprintf(fptr, "BBS_BANS=%s\n", udb_env("BBS_BANS"));
		fprintf(fptr, "BBS_LEVEL=%s\n", udb_env("BBS_LEVEL"));
		fprintf(fptr, "BBS_EMAIL=%s\n", udb_env("BBS_EMAIL"));
		fprintf(fptr, "MVIEW_NAMELINE=%s\n",
			udb_env("MVIEW_NAMELINE"));
		fprintf(fptr, "BBS_XWARN=%s\n", udb_env("BBS_XWARN"));
		fprintf(fptr, "BBS_USERS_ON_TIME=%s\n",
			udb_env("BBS_USERS_ON_TIME"));
		fprintf(fptr, "EDITOR_OPTIONS=%s\n",
			udb_env("EDITOR_OPTIONS"));
		fprintf(fptr, "BBS_SPACE_EXIT=%s\n",
			udb_env("BBS_SPACE_EXIT"));
		fprintf(fptr, "BBS_MESSAGES=%s\n",
			udb_env("BBS_MESSAGES"));
		fprintf(fptr, "BBS_COLOUR=%s\n", udb_env("BBS_COLOUR"));
		fprintf(fptr, "BBS_LOGINS=%s\n", udb_env("BBS_LOGINS"));
		fprintf(fptr, "BBS_LOGOUT=%s\n", udb_env("BBS_LOGOUT"));
		fprintf(fptr, "BBS_PASS=%s\n", udb_env("BBS_PASS"));
		fclose(fptr);
	}

	my_flock(cf_str("udb"), fd, LOCK_UN);
	close(fd);

	if (!stat(cf_str("udb"), &sb))
		udb__last_mtime = sb.st_mtime;
}

/* EOF */
