/* key.c - deal with key presses
 */

#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include "viewfile.h"
#include "viewmenu.h"
#include "bbs.h"
#include "u2u.h"


extern time_t last_keypress;
extern time_t last_idle_update;
extern int menuview_exitup;
extern int menuview_abort;
extern char *logout_reason;

extern int hook_is_external(void);
void hook_set_proctitle(void);
void hook_get_keypath(char **);


/* Enter the special menu.
 */
void hook_special_menu(int c)
{
	char buf[64];
	char *ptr = 0;

	hook_get_keypath(&ptr);

	if (!ptr)
		ptr = "";

	strncpy(buf, ptr, sizeof(buf) - 4);
	strcat(buf, "^");

	read_menu(cf_str("special"), cf_str("ldb"), buf,
		  "Utilities", MENUFLAG_SUB | MENUFLAG_SPECIAL
		  | ((c < 0) ? MENUFLAG_READNOW : 0));

	if (!menuview_abort)
		rf_redraw = 1;
}


/* Deal with an unknown menu entry type being loaded (needed for special
 * menu).
 */
int hook_menu_type(menuentry_t * e, char *file)
{
	if (!file)
		return (0);
	if (!strcmp(file, cf_str("special")))
		return (1);
	if (!strcmp(file, cf_str("options")))
		return (1);
	return (0);
}


/* Deal with unknown key "*kptr" being pressed in the file viewer.
 */
void hook_key_file(rf_data_t data, int *kptr)
{
	if ((*kptr == 27) || (*kptr == -27))
		hook_special_menu(*kptr);
	else if ((*kptr == 'S') || (*kptr == 's'))
		u2u_file_send(data);
}


/* Deal with unknown key "*kptr" being pressed in the menu viewer.
 */
void hook_key_menu(menudata_t data, int *kptr)
{
	if ((*kptr == 27) || (*kptr == -27))
		hook_special_menu(*kptr);
}


/* Deal with key "*kptr" being pressed - update the idle time. If *ptr <= 0,
 * the last-keypress time is not changed. Regardless of whether the last
 * keypress time was changed, the process title (and "Users On" entry) is
 * changed at least every 10 seconds.
 *
 * If the idle time rises above the max idle time then "menuview_exitup" and
 * "menuview_abort" are set so that the user is logged out.
 *
 * If "cptr" is non-zero, it is taken as a pointer to the PID of the current
 * child process, and the current idle time is altered according to the last
 * modification time of the terminal. On idle-out, this PID is sent a TERM
 * signal, followed by a KILL signal one second later.
 */
void hook_key_pressed(pid_t * cptr, int *kptr)
{
	long maxidle;
	struct stat sb;
	char *a;
	time_t t;

	if (!kptr)
		return;

	t = time(0);

	if (*kptr > 0) {		    /* key pressed */
		last_keypress = t;
		last_idle_update = 0;
	} else if (cptr) {		    /* running a child process */
		a = ttyname(STDIN_FILENO);
		if (a) {
			stat(a, &sb);	    /* check tty mtime */
			if (sb.st_atime > last_keypress)
				last_keypress = sb.st_atime;
		}
	}

	if ((t - last_idle_update) >= 10)
		hook_set_proctitle();

	maxidle = cf_int(hook_is_external()? "idleext" : "idleint");

	if ((t - last_keypress) > maxidle) {	/* autologout */
		logout_reason =
		    "Idle time limit reached - you have been disconnected.";
		menuview_exitup = 1;
		menuview_abort = 1;
		if (cptr) {		    /* kill child processes */
			alarm(0);
			kill(*cptr, SIGTERM);
			sleep(1);
			kill(*cptr, SIGKILL);
		}
	}
}

/* EOF */
