/*
	Schrodinger's Box Haven  code version -0.1 alpha
        Copyright (C) 1994, Gordon Chan

	You can do whatever ya want with this code as long as you leave this
        copyright & disclaimer intact.  You can hack it up all you want, etc...
        No guarantees.

	Send comments, flames, bug reports, etc ... to
		au233@freenet.carleton.ca  <---- (preferred address for now)
		gjc@achilles.net
		gchan@ccs.carleton.ca
*/


/* Here's the copyrights & disclaimers from the Opium Den and unixCB codes */

/* Opium Den */
/*
  val's haven code v -0.85

        Copyright (C) 1994 Joel Ward

        Warranty:
                Don't blame me for anything.

        You can do whatever the fuck you want with this code as long as you
don't remove this copyright/disclaimer notice.
*/

/* unixCB */
/*
  
  cbd.c
  
  "cbd.c" is the main code for the CB simulator.
  
  Copyright (c) 1992, Gary Grossman.  All rights reserved.
  Send comments and questions to: garyg@soda.berkeley.edu
  
  */

#include<stdio.h>
#include<sys/types.h>
#include<sys/time.h>
#include<errno.h>
#include<unistd.h>
#include<setjmp.h>

#include "linked_lists.h"
#include "main.h"
#include "chat.h"
#include "security.h"


long idletimeout = 3600, start_time;

fd_set master; /* master list of file descriptors */
int usercount = 0;  /* count of number of users */


main_loop (server_sock)
	int server_sock;
{
	char hostname[50];
	int remote_port, user_fd, nfd, numusers;
	struct user *u;
	fd_set readfds;

	static long lastcheck = 0;
	struct timeval temptime;
	struct timezone tempzone;

	nfd = getdtablesize ();

	signal_handler ();
	
	FD_ZERO(&master);
	FD_SET(server_sock, &master);
	(void) gettimeofday (&temptime, &tempzone);
	start_time = temptime.tv_sec;

	for (;;) {
/*
		FD_ZERO (&readfds);
		FD_SET (server_sock, &readfds);
		numusers = setup_userfds (&readfds);
*/
		memcpy(&readfds, &master, sizeof(fd_set));
		numusers = usercount;
#ifdef DEBUG
		sprintf (err, "		number of users %d\r\n", numusers);
		write_err (err);
#endif
		write_err ("BEFORE select\r\n");
		if (select (nfd, &readfds, (fd_set *)0, 
			    (fd_set *)0, (struct timeval *)0 ) == -1)  {
			if (errno == EINTR) 
				continue;
			else
				continue;
		}
		write_err ("AFTER select\r\n");

		for (u = firstuser; u; u = u->next) 
			if (FD_ISSET (u->desc, &readfds) )
				process_input (u); 


		/* check for idle users */
		(void) gettimeofday (&temptime, &tempzone);

		if ( (temptime.tv_sec - lastcheck) >=60 ) {
			check_idle ();
			lastcheck = temptime.tv_sec;
		}

		/* check for new users logging on */
		if (FD_ISSET (server_sock, &readfds) ) {
			if ((user_fd = new_connect (server_sock, hostname, &remote_port)) > 0) {
				if (numusers < MAXCONNECT) {
					add_user (user_fd, hostname, remote_port);
#ifdef DEBUG
					sprintf (err, "new user on slot %d\r\n", user_fd);
					write_err (err);
#endif
				} else {
					write_user (user_fd, ">> Sorry.  We're all full.  Try again later.\r\n");
					close (user_fd);
				}
			}
		}
	}
}


int setup_userfds (readfds)
	fd_set *readfds;
{
	struct user *user;
	int num;

	num = 0;
	
	for (user = firstuser; user; user = user->next) {
		FD_SET (user->desc, readfds);
		num++;
	}
	return num;
} 	


/* routine that checks for idlers and logs them off */

void check_idle ()
{
	struct user *u;
	struct timeval temptime;
	char temp[120];

	(void) gettimeofday (&temptime, (struct timezone *) 0);

	for (u = firstuser; u; u=u->next) 
		if ( ((temptime.tv_sec - u->idletime) >= idletimeout)
		  && (u->sec_level <= BABYCO) ) { 
			if (is_user (u, Fcomm_line) || is_user (u, Ftyping) )
				write_user (u->desc, "\r\n"); 
			sprintf (temp, ">> %s on line %d has idle timed out and left\r\n",
				u->name, u->desc);
			delete_user (u, ">> You have idled your time out!\r\n", 0, temp);
		}
}


void set_idletime(user, time)
  struct user *user;
  char *time;
{
  char tempbuffer[80];
  int idle = atoi(time);

  toggle_user(user, Fcomm_line);

  if (!*time) {
    sprintf(tempbuffer, ">> Current idletimeout is %d (%s).\r\n", idletimeout,
     convert_time(idletimeout));
    write_user(user->desc, tempbuffer);
  } else if (idle < 300) {
    write_user(user->desc, ">> Idletimeout has to be at least 300 (5m).\r\n");
    sprintf(tempbuffer, ">> Idletimeout is still %d (%s).\r\n", idletimeout,
     convert_time(idletimeout));
    write_user(user->desc, tempbuffer);
  } else if (idle > 86400) {
    idletimeout = 86400;  
    sprintf(tempbuffer, ">> Idletimeout has been set to 86400 (1d).\r\n");
    write_user(user->desc, tempbuffer);
  } else {
    idletimeout = idle;
    sprintf(tempbuffer, ">> Idletimeout has been set to %d (%s).\r\n",
     idle, convert_time(idle));
    write_user(user->desc, tempbuffer);
  }
  user->linecharmax = INPUTMAX;
}
