/* check.c - functions dealing with new message checking
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include "viewfile.h"
#include "terminal.h"
#include "lock.h"
#include "hook.h"
#include "u2u.h"
#include "bbs.h"
#include "ldb.h"

#ifndef O_SYNC				    /* FreeBSD kludge */
#ifdef O_FSYNC
#define O_SYNC O_FSYNC
#endif
#endif				/* O_SYNC */


time_t u2u__last_checked = 0;
static int u2u__first_check = 1;

extern int rf_viewing_messages;

int log_truncate(int, int, long, long, int);


/* Initialise the message handling functions by making sure this user's
 * messages file exists and setting the "last checked" time to either now or
 * 0 (never) depending on whether the messages file has changed since it was
 * last read.
 *
 * Does nothing if the current user is "guest".
 */
void u2u_init(void)
{
	struct stat sb;
	char buf[1024];
	struct LDB l;
	int fd;

	if (!strcmp(current_user, "guest"))
		return;

	sprintf(buf, "%s/%s", cf_str("u2u"), current_user);

	fd = open(buf, O_CREAT | O_EXCL | O_RDWR);	/* create new U2U file */
	if (fd >= 0) {
		fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
		close(fd);
		stat(buf, &sb);
		ldb_read(cf_str("ldb"), buf, &l);	/* make an LDB entry */
		l.last_accessed = sb.st_mtime + 1;
		l.at_end = 1;
		ldb_write(cf_str("ldb"), &l);
	}

	stat(buf, &sb);

	u2u__last_checked = sb.st_mtime + 1;

	ldb_read(cf_str("ldb"), buf, &l);

	if (l.last_accessed == 0)
		u2u__last_checked = 0;

	if (l.last_accessed >= sb.st_mtime) {
		if (!l.at_end)
			u2u__last_checked = 0;
	} else
		u2u__last_checked = 0;

	u2u__first_check = 1;
}


/* Check for new messages if the environment variable BBS_MESSAGES is not
 * "ignore" and drop the user into the message viewer if new messages have
 * arrived, BBS_MESSAGES is "read", and "msgview" is non-zero.
 *
 * If new messages have arrived then the messages file is truncated.
 *
 * Does nothing if the current user is "guest".
 */
void u2u_check(int msgview)
{
	char action[1024];
	char keypath[64];
	struct stat sb;
	char buf[1024];
	struct LDB l;
	int allow_beep;
	char *ptr;
	char *e;
	int fd;

	allow_beep = (u2u__first_check) ? 0 : 1;
	u2u__first_check = 0;

	if (!strcmp(current_user, "guest"))
		return;

	e = getenv("BBS_MESSAGES");
	if (!e)
		e = "read";

	sprintf(buf, "%s/%s.ign", cf_str("u2u"), current_user);

	if (!strcmp(e, "ignore")) {
		fd = open(buf, O_CREAT | O_WRONLY);
		fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
		close(fd);
	} else
		remove(buf);

	if ((time(0) <= u2u__last_checked) && (!allow_beep))
		return;

	sprintf(buf, "%s/%s", cf_str("u2u"), current_user);
	stat(buf, &sb);

	if (sb.st_mtime < u2u__last_checked)
		return;

	fd = open(buf, O_CREAT | O_SYNC | O_RDWR);
	my_flock(buf, fd, LOCK_EX);
	log_truncate(fd, -1, cf_int("u2uimax") * 1024,	/* truncate messages */
		     cf_int("u2uimin") * 1024, 1);
	my_flock(buf, fd, LOCK_UN);
	close(fd);
	u2u__last_checked = time(0) + 1;

	if (!strcmp(e, "ignore"))
		return;			    /* ignore new messages */

	if (isatty(0) && allow_beep)
		t_abswrite("\a");	    /* beep */

	if (!strcmp(e, "beep"))
		return;

	if (!msgview) {			    /* can't view, beep again */
		if (isatty(0) && allow_beep)
			t_abswrite("\a");
		return;
	}

	ldb_read(cf_str("ldb"), buf, &l);
	strcpy(l.realname, buf);

	action[0] = 0;
	bbs_hook(HOOK_GET_ACTION, &ptr, 0);
	if (ptr)
		strncpy(action, ptr, sizeof(action) - 1);
	ptr = 0;
	keypath[0] = 0;
	bbs_hook(HOOK_GET_KEYPATH, &ptr, 0);
	if (ptr)
		strncpy(keypath, ptr, sizeof(keypath) - 1);

	bbs_hook(HOOK_SET_ACTION, "Reading ",
		 "Messages [\035BESC\035b][\035BR\035b]");
	bbs_hook(HOOK_SET_KEYPATH, "", 0);

	rf_viewing_messages = 1;
	do_read_file(&l, "Messages [\035BESC\035b][\035BR\035b]",
		     MENU_STATUS_DELETE | MENU_STATUS_BARLOG, 0);
	rf_viewing_messages = 0;

	bbs_hook(HOOK_SET_ACTION, 0, action);
	bbs_hook(HOOK_SET_KEYPATH, keypath, 0);

	ldb_write(cf_str("ldb"), &l);

	u2u__last_checked = time(0) + 1;

	rf_redraw = 1;
}

/* EOF */
