/*
    slforum version 1.x - Simple chat room usable via telnet.
    Copyright (C) 2000-2005 Jeremy D. Monin, Dan Chin, Matt Lochansky
	(forum@shadowlands.org).
    Originally based on jdkchat v1.3, J.D.Koftinoff Software, Ltd. (GPL'd)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "world.h"
#include <dirent.h>  /* for opendir,closedir, DIR* */
#include <sys/resource.h>  /* for getrlimit */
#include "slforum.h"

/* in main(), check to see if we can write WTMPLOG;
 * if not, set to WTMPLOG_fallback .
 */
const char *wtmpfname;

static const char *transcript_logfname;
static FILE *log_file;


void manage_room( SLForumRoom *room )
{
	int num=0;
	fd_set rd,wr,ex;
	struct timeval t;
	
	t.tv_sec=2;
	t.tv_usec=0;
	
	FD_ZERO( &rd );
	FD_ZERO( &wr );
	FD_ZERO( &ex );
	
	room->Make_fdset( &rd, &wr, &ex );
	
	num=select( FD_SETSIZE, &rd, &wr, &ex, &t );
	
	if( num>0 )
	{
		room->ManageRoom( &rd, &wr, &ex );	
	}
	/*	else
	  sleep(1);   * if we don't hog cpu on freeze,
		      * this is why...
		      */

}

// so signal handler can find it
static SLForumRoom *pr;
static int gotTermSig = 0;

extern int in_lpcat;  /* jer added 981023.0320 */


/** signal handler for SIGALRM...
 *  as originally set up (sometime in july98), the signal is
 *  set when a guest tries to log in, and tripped 30 seconds
 *  later, to kick them off if they weren't invited in.
 *
 *  980805.2220: jer modded so this is called every WALLCLOCKMINUTES
 *  minutes... WallclockTick() checks to see the last
 *  announced time, and alarms and/or announces.
 * /// STATE STATE STATE it _isn't_ yet.. this was an idea I never
 * /// got around to implementing... (19990615.1600)
 *
 * 19990702.1900: This function re-calls itself every PING_INTERVAL_SEC
 *	to check whether idle users are still connected.
 */
_SIGHANDLER_(sig_LookForTimeouts) {
  if (gotTermSig) {
    exit(1);
  }
  if (pr != NULL) {
    pr->LookForTimers();	// timer, timeouts, hourly chime
  }
  in_lpcat = 0;  /* jer 981023.0320 */

  // reschedule it again to check again for disconnected users periodically.
  sked_alarm (PING_INTERVAL_SEC);
}


/** This schedules a SIGALRM; if one was scheduled sooner,
 *  it does it instead.  jer added 19990702.2015
 */
void sked_alarm (int seconds) {
  int lasttime = (int) alarm (seconds);
  if ((lasttime > 0) && (lasttime < seconds))
    alarm (lasttime);	// already had one scheduled sooner, do it instead
}



/** signal handler for SIGTERM...
 *  set up 980809.0900 for cleaner termination.
 *  980903.2200: SIGINT, SIGQUIT too
 */
_SIGHANDLER_(sig_CleanupAndTerm) {
  if (gotTermSig)
    exit(1);

  gotTermSig = 1;
  //  SLForumRoom *proom = pr;
  //  pr = NULL;

  alarm (2);  // in case delete(pr) hangs, use SIGALRM to exit
  in_lpcat = 0;  /* jer added 981023.0320 */
  {
    time_t tnow = time(NULL);
    pr->AnnounceTimestamp (tnow, 0, true);
  }
  pr->Announce ("Shadowlands Forum is exiting.");
  pr->room_cleanup();  /* jer added 19990522.0250 */
  if (log_file != NULL) {
    time_t tnow = time(NULL);
    fprintf (log_file, "\nRun ended at %s", ctime(&tnow));
  }
  exit(0);
}



/** signal handler for SIGHUP... closes, reopens transcript log, if any.
 *  set up 20000217.0430 for log rotate convenience.
 */
_SIGHANDLER_(sig_Reload) {

  time_t now;
  const char *nowstr;
  now = time (NULL);
  nowstr = ctime(&now);

  if (log_file != NULL) {
    fprintf (log_file, "---- Got SIGHUP, closing this logfile for log rotation ----\n");
    if (nowstr != NULL)
      fprintf (log_file, "(at %s)\n", nowstr);

    fclose(log_file);
  }

  if (transcript_logfname == NULL)
    return;
  
  // re-open it; code taken from main.
  // if you change it in one place,
  // change it in the other :)
  // [search for "this code is also now in sig_Reload"]
  log_file = slf_safe_fopen( "transcript log", transcript_logfname, "at" );
  if( log_file == NULL) {
    pr->Announce ("Error opening log file during SIGHUP reload");
  }


  fprintf (log_file, LOGIN_HELLO_MSG_TXT );
  if (nowstr == NULL)
    nowstr = "";
  fprintf (log_file, "\nContinuing run after SIGHUP at %s\n", nowstr);

  pr->SetLogFile(log_file);

}


// jer added 20001001 - SIGUSR1
_SIGHANDLER_(sig_DebugSlots) {
    pr->debug_PrintSlots();
}



#if defined(WIN32) || defined(_WIN32)
	/* no action required; not quite "signals" there */
#else

void setupSigHandler(int signum, _SIGHANDLER_T_ sigh) {

  struct sigaction sigac;
  sigac.sa_handler = sigh;
  sigemptyset(&sigac.sa_mask);
  sigac.sa_flags = 0;
#ifdef SIGHANDLE_POSIX
  sigac.sa_restorer = NULL;
#endif
  if (-1 == sigaction (signum, &sigac, NULL)) {
    fprintf (stderr, "While setting up handler for signal %d: ", signum);
    perror ("couldn't set up signal handler for login timeouts!");
    exit(1);
  }
}

#endif  /* defined(WIN32) || defined(_WIN32) */



extern "C"
{
// for logging from .c files.
// kinda a kludge but it works
// you'll recognize some of
// this code from logprintf...
// this func takes care of varargs
// and then calls the room logprintf
// (too bad we can't pass the varargs).
// It's c++ code, but linked with C
// linkage (no mangling) so the .c files
// can call it... all in the name of
// good debugging facilities :)
//
void Lprintf(const char *fmt, ...)
{
  // from vsprintf manpage example //
  char buf[256];
  va_list ap;
  va_start (ap, fmt);
  vsnprintf(buf, 255, fmt, ap);  buf[255] = '\0';
  va_end (ap);
  pr->logprintf("%s",buf);
}


}  /* end extern "C" */






void printUsageMessage(const char *argv0)
{
  fprintf(stderr, "\n");
  fprintf(stderr, "Usage: %s [portnumber] [-d dirname] [-ag groupnum] [+-aa] [+-ghm] [-bd dirname] [--nofork or logfilename]\n", argv0);
  fprintf(stderr, "\t-d specifies a home directory for SLForum files.\n");
  fprintf(stderr, "\t-ag specifies the group id of the admin group.\n");
  fprintf(stderr, "\t+aa turns on guest autoaccept, -aa turns it off.\n");
  fprintf(stderr, "\t+ghm prints a guest help message (how to log in as a guest)\n\t at the login prompt, -ghm does not.\n");
  fprintf(stderr, "\t-bd specifies a non-default banner directory.\n");
  fprintf(stderr, "\t--nofork leaves chat running in the foreground.\n");
  fprintf(stderr, "\tlogfilename logs all public chat to that file and forks to background.\n");
  fprintf(stderr, "\tDefault port is %d.\n", SLF_DEFAULT_PORT);
}


static int check_write_home_dir()
{
  if (slfhomedir == NULL)
    return 0;

  // does the dir exist?  if not, maybe we can make it
  {
    DIR *d = opendir(slfhomedir);
    if ((d == NULL) && (errno == ENOENT))
    {
      if (-1 == mkdir(slfhomedir, 0700))
	return 0;   // couldn't make it

      // else assume it's been made

    } else {
      if (d != NULL)
	closedir(d);
      else
	return 0;  // couldn't open it
    }
  }


  // now for user prefs dir within home dir
  {
    char ubuf[PATH_MAX];
    if (-1 == snprintf
	(ubuf, PATH_MAX-1, "%s%c%s", slfhomedir, PATH_SEP, SLFUSERDIR))
      {
	return 0;  // path to user prefs too long
      }

    DIR *d = opendir(ubuf);
    if ((d == NULL) && (errno == ENOENT))
    {
      if (-1 == mkdir(ubuf, 0700))
	return 0;  // couldn't make it
    } else {
      if (d != NULL)
	closedir(d);
      else
	return 0;  // couldn't open it
    }
  }

  // test write file

  char pat[PATH_MAX];  pat[PATH_MAX-1] = '\0';
  snprintf(pat, PATH_MAX-1, "%s%cwrite-test", slfhomedir, PATH_SEP);
  FILE *f = slf_safe_fopen("homedir write test file", pat, "w");
  if (f == NULL)
    return 0;

  fclose(f);
  if (0 == unlink(pat))
    return 1;

  fprintf(stderr, "couldn't unlink our test file %s, something's odd.\n", pat);
  return 0;
}



/** give it NULL for dirn to use default ones; dirn would be a path to a
 *  proposed banner dir given on the cmd line.
 */
static void try_set_bannersdir(const char *dirn, SLForumRoom *rrr)
{
  bool banset = false;

  if (dirn != NULL)
  {
    banset = (-1 != rrr->setBannersDir(dirn));
    if (! banset)
      fprintf(stderr, "Couldn't set banners dir to %s\n", dirn);
  }

  if ( (slfhomedir != NULL) && ! banset)
  {
    char bannpath[PATH_MAX];
    if (-1 == snprintf (bannpath, PATH_MAX-1,
			DFLT_BANNERSDIR  /* "%s%cbanners" */,
			slfhomedir, PATH_SEP))
    {
      fprintf(stderr, "Path to SLF Home Dir too long to find the banners\n");
    } else {
      banset = (-1 != rrr->setBannersDir(bannpath));
      if (! banset) {
	fprintf(stderr, "Couldn't set banners dir to %s\n", bannpath);
	perror("warning: couldn't set banners dir inside slf home dir");
      }
    }
  }

  if (! banset)
  {
    if (-1 == rrr->setBannersDir (DFLT_BANNERSDIR_fallback))
    {
      fprintf
	(stderr, "warning: couldn't set banners dir to %s either\n",
		   DFLT_BANNERSDIR_fallback );
      perror ("warning: couldn't set banners dir");
    } else {
      banset = true;
    }
  }

  if (banset)
    fprintf (stderr, "\tBanner directory: %s\n",rrr->getBannersDir());
}



static bool tryGetDirParam
  (const char *pname, const char*& setthis, char**argv, int argc, int &curarg)
{
  if (0 != strcasecmp(pname, argv[curarg]+1))
    return false;
  if ((argv[curarg][0] != '+') && (argv[curarg][0] != '-'))
    return false;

  ++curarg;
  if (argc <= curarg)
  {
    fprintf
      (stderr, "%s: Expected dir name after %c%s\n",
       argv[0], argv[curarg-1][0], pname);
    printUsageMessage(argv[0]);
    exit(1);
  }

  setthis = argv[curarg];
  if (setthis[0] == '-')
  {
    fprintf
      (stderr,
       "%ss: Expected dir name, not another flag, after %c%s\n",
       argv[0], argv[curarg-1][0], pname);
    printUsageMessage(argv[0]);
    exit(1);
  }
		 
  // check for and remove any trailing slash
  {
    size_t slen = strlen(setthis);
    if (setthis[slen-1] == PATH_SEP)  // has trailing slash
    {
      char *newc = (char *)malloc(sizeof(char) * slen);
      if (newc == NULL) {
	fprintf(stderr, "Out of memory already!\n");
	exit(1);
      }

      // copy everyting but the slash
      strncpy(newc, setthis, slen-1);
      newc[slen-1] = '\0';

      // and point our param at it
      // (was previous pointing into argv)
      setthis = newc;

      // the mem will be freed when we exit.
    }
  }

  // move on.
  ++curarg;
  return true;

}  // tryGetDirParam



static bool tryGetBoolParam
  (const char *pname, bool &setthis, char**argv, int argc, int &curarg)
{
  if (0!=strcasecmp(pname, argv[curarg]+1))
    return false;

  if (argv[curarg][0] == '+') {
    setthis = true;
    ++curarg;
    return true;
  } else if (argv[curarg][0] == '-') {
    setthis = false;
    ++curarg;
    return true;
  }

  return false;
}  // tryGetBoolParam



int main( int argc, char **argv )
{

	log_file=NULL;
	transcript_logfname = NULL;
	
	puts(LOGIN_HELLO_MSG_TXT);

	bool shouldfork = true;
	bool shouldAutoAccept = AUTO_ACCEPT_GUESTS;
	bool shouldPrintGuestHowtoMsg = GUEST_HOWTO_MESSAGE;

	int admgid = -1;

	// parse stuff

	int port = SLF_DEFAULT_PORT;	
	const char *askbandir = NULL;  // user-supplied banners dir

	int curarg = 1;

	while (argc>curarg)
	{

	  	// check for -h[elp] option.  This is admittedly not the most
		// optimal way of parsing cmdline args. ;)  But our cmdline
		// syntax is decidedly nonstandard.  Will Fix for 2.0.
	  if ((0==strcasecmp("-help",argv[curarg])) 
	      || (0==strcasecmp("-h", argv[curarg])))
	  {
	    printUsageMessage(argv[0]);
	    exit(0);
	  }

	  	// check for +-aa
	  if (tryGetBoolParam("aa", shouldAutoAccept, argv, argc, curarg))
	    continue;

		// check for +-ghm
	  if (tryGetBoolParam
	      ("ghm", shouldPrintGuestHowtoMsg, argv, argc, curarg))
	    continue;


	  	// check for -ag option. (admin group)
	  if (0==strcasecmp("ag",argv[curarg]+1))
	  {
	      if ((argv[curarg][0] == '+') || (argv[curarg][0] == '-'))
	      {
		  ++curarg;
		  if (argc <= curarg)
		  {
		      fprintf
			  (stderr, "%s: Expected gid after %cag\n",
			   argv[0], argv[curarg][0]);
		      printUsageMessage(argv[0]);
		      exit(1);
		  }
		  admgid = atoi(argv[curarg]);
		  ++curarg;
		  continue;
	      }
	  }


	  	// check for -d option. (slf home dir)
	  if (tryGetDirParam("d", slfhomedir, argv, argc, curarg))
	    continue;

	  	// check for -bd option. (banners dir)
	  if (tryGetDirParam("bd", askbandir, argv, argc, curarg))
	    continue;

	  	// check for -nofork or --nofork or portno or logfilename
	  if (*(argv[curarg]) != '-')
	  {

	    // try parse int
	    char *endc;
	    int tryport = (int) strtol (argv[curarg], &endc, 0);   
	    
	    if (*endc == '\0')
	    {
	      // valid number entered.

	      if (tryport < 2)
	      {
		fprintf
		    (stderr,
		     "%s: The port number must be at least 2; you tried %d.\n",
		     argv[0],
		     tryport );
		printUsageMessage (argv[0]);
		exit (1);
	      }
	      port = tryport;
	      ++curarg;
	      continue;
	    } else {
	      // not a number, assume it's a log filename

	      transcript_logfname = argv[curarg];
	      ++curarg;
	      continue;
	    }
	  } else {   // begins w/ '-'
	    if ((0==strcasecmp ("-nofork", argv[curarg]))
		|| (0==strcasecmp ("--nofork", argv[curarg])))
	    {
	      shouldfork = false;
	      ++curarg;
	      continue;
	    } else {
		// avoid creating logfiles w/ names like "-noork" or "-nofokr"
	      fprintf (stdout, "%s: unknown option '%s'\n", argv[0], argv[curarg]);
	      printUsageMessage(argv[0]);
	      return 1;
	    }
	  }
	}  // end while (parsing-cmdargs)


	// now that we think args are ok... do stuff.

	// say hi

	fprintf (stderr, "%s\n", LEGAL_HELLO_MSG_TXT);


	// check the home dir
	if (slfhomedir == NULL)
	  slfhomedir = SLFHOMEDIR;

	if (! check_write_home_dir())
	{
	  // change it, check again
	  char slfhd[PATH_MAX];  slfhd[0] = '\0';  slfhd[PATH_MAX-1] = '\0';
	  const char *home = getenv("HOME");
	  if (home != NULL)
	  {
	    snprintf(slfhd, PATH_MAX-1, 
		     SLFHOMEDIR_fallback /* "%s%c.slforum-%d" */,
		     home, PATH_SEP, port);
	    slfhomedir = slfhd;
	    
	    if (! check_write_home_dir())
	      slfhd[0] = '\0';
	  }

	  if (slfhd[0] == '\0')
	  {
	    // one more try...
	    snprintf(slfhd, PATH_MAX-1, 
		     SLFHOMEDIR_fallback /* "%s%c.slforum-%d" */,
		     SLFHOMEDIR_fullback /* "/tmp" */, PATH_SEP, port);
	    if (! check_write_home_dir())
	      slfhd[0] = '\0';
	  }

	  // if it's workable, copy it out of the temp var into perm storage
	  if (slfhd[0] != '\0')
	  {
	    size_t plen = strlen(slfhd);
	    char *slfhpath = (char *) malloc(sizeof(char)*(plen+1));
	    if (slfhpath == NULL)
	    {
	      fprintf(stderr, "out of memory already!\n");
	      exit(1);
	    }
	    strncpy(slfhpath, slfhd, plen);
	    slfhomedir = slfhpath;   // it's pointing to our malloc'd string,
				     // which will be free'd when we exit.
	  } else {
	    slfhomedir = NULL;
	  }
	}  // end home dir check

	// try opening the wtmp log

	/* make sure we can write to wtmp; 'borrow' the log_file var. */
	wtmpfname = WTMPLOG;
	log_file  = slf_safe_fopen ("wtmp file", wtmpfname, "a");
	if (log_file == NULL)
	{
	  perror ("opening wtmp-style logfile");
	  // try some alternatives...

	  if (slfhomedir == NULL)
	  {
	    fprintf(stderr, "%s: can't use wtmp file '%s', no -d defined so not logging logins\n", 
		   argv[0], wtmpfname);
	    wtmpfname = NULL;
	  } else {
	    char fallback[PATH_MAX];  fallback[PATH_MAX-1] = '\0';
	    snprintf(fallback, PATH_MAX-1,
		   WTMPLOG_fallback  /* "%s%cslforum-wtmp-%d" */,
		     slfhomedir, PATH_SEP, port);

	    fprintf (stderr, "%s: can't use wtmp file '%s': trying fallback %s\n",
		     argv[0], wtmpfname, fallback );
	    wtmpfname = fallback;
	    log_file = slf_safe_fopen ("backup wtmp file", wtmpfname, "a");
	    if (log_file == NULL)
	    {
	      perror ("opening wtmp-style logfile");
	      fprintf (stderr, "%s: can't use fallback wtmp file '%s': NOT LOGGING LOGINS.\n", argv[0], wtmpfname);

	      wtmpfname = NULL;	// changed this behavior 19990527.2045
	    //	    exit(1);	// Now just sets to NULL 'stead of exiting.
	    } else {
	      // k, this is a local var, so we need to copy it
	      size_t slen = strlen(wtmpfname)+1;
	      char *wtmplogf = (char*) malloc(sizeof(char) * slen);
	      if (wtmplogf == NULL)
	      {
		fprintf(stderr, "Out of memory already\n");
		exit(1);
	      }
	      strncpy(wtmplogf, wtmpfname, slen);
	      wtmpfname = wtmplogf;   // it'll be freed when program exits
	    }
	  }
	}  // end attempts to set log_file

	if (log_file != NULL) {
	  // we just needed to open it for testing purposes,
	  // to be sure we can write to it.  Close it for now.
	  // Below this point, log_file is used for the transcript log;
	  // we're done borrowing it for wtmp.
	  fclose (log_file);
	  log_file = NULL;
	}


	// try opening the transcript log

	if (transcript_logfname != NULL)
	{
	    // this code is also now in sig_Reload...
	    // if you change it in one place, change in the other :)
	    log_file = slf_safe_fopen
	      ( "transcript log", transcript_logfname, "at" );

	    if( log_file != NULL )
	    {
	      fprintf( stderr, "\nlogging to '%s'\n", transcript_logfname );
	    } else {
	      perror ("opening log file");
	      fprintf (stderr, "\n%s: Error opening log file '%s'\n",
		       argv[0], transcript_logfname );
	      exit (1);
	    }
	}


	if (! shouldfork)
	{
	  fprintf (stderr, "not forking... my pid is %ld\n", (long) getpid());
	}
	
	fprintf( stderr, "\n\tUsing port %d\n", port );
	fprintf( stderr, "\n\tSLForum Home Dir: %s\n",
		 (slfhomedir != NULL ? slfhomedir : "(none)" ));
#ifdef ALLOW_GUESTS
	fputs ( "\tGuests: ON\n", stderr);
	fprintf (stderr, "\tAutoAccept: %s\n",
		 shouldAutoAccept ? "ON" : "OFF");
	fprintf (stderr, "\tGuest How-To Message: %s\n",
		 shouldPrintGuestHowtoMsg ? "ON" : "OFF");
#else
	fputs ( "\tGuests: OFF\n", stderr);
#endif

#ifdef ALLOW_TOPICS
	fputs ( "\tTopics: ON\n", stderr);
#else
	fputs ( "\tTopics: OFF\n", stderr);
#endif	      


	srand ( (unsigned int) time(NULL));
	
	SLForumRoom r(port, log_file);
	if (!shouldfork)
	    r.setLogStdoutToo(true);
	
	r.setAutoAccept(shouldAutoAccept);
	r.setPrintGuestHowtoMsg(shouldPrintGuestHowtoMsg);
	if (admgid != -1)
	    r.setAdminGid((gid_t) admgid);
	else
	    admgid = (int) r.getAdminGid();
	fprintf (stderr, "\tAdmin gid: %d\n", admgid);

	// Do we have an admin userid? (see 20000714.2100 note)
	{
	    uid_t procuid = getuid();
	    if (procuid >= SLF_MIN_REAL_USERID)
		fprintf (stderr, "\tAdmin uid: %d\n", (int) procuid);
	}

	try_set_bannersdir(askbandir, &r);

	r.BindSocket();  // make ready to network :)

	pr = &r;  // used in sighandlers

	int f;
	if (shouldfork)
	  f=fork();
	else
	  f=0;  // simulate being child from fork, don't actually do it
	
	if( f==0 )
	{
	  // in child.

	  // tiptoe out of filesystems we don't need access to (980903.1230)
#ifdef DUMP_CORE
	  chdir ("/tmp");
#else
	  chdir ("/");
#endif

	  // set up signal handlers
#if defined(WIN32) || defined(_WIN32)
#else
	  setupSigHandler(SIGALRM, sig_LookForTimeouts); // 980703.2345
	  setupSigHandler(SIGTERM, sig_CleanupAndTerm);  // 980809.0900
	  setupSigHandler(SIGINT,  sig_CleanupAndTerm);  // 980903.2200
	  setupSigHandler(SIGQUIT, sig_CleanupAndTerm);  // 980903.2200
	  setupSigHandler(SIGPIPE, SIG_IGN);	// 19990605.1645
	  setupSigHandler(SIGHUP,  sig_Reload);	// 20000217.0430
	  setupSigHandler(SIGUSR1, sig_DebugSlots); // 20001001

#ifdef DUMP_CORE   // DUMP_CORE is 20010920.0910
	  {
		  struct rlimit rlim;
		  if (-1 == getrlimit (RLIMIT_CORE, &rlim)) {
			  fprintf (stderr, "\nWarning: Couldn't check max core file size\n");
		  } else {
			  if (rlim.rlim_cur == 0)
				  fprintf (stderr, "\nWARNING: Compiled to dump core in /tmp, but core file max size is 0\n");
			  else
				  fprintf (stdout, "\nCore file max size: %d (max limit %d)\n", (int) rlim.rlim_cur, (int) rlim.rlim_max);
		  }
	  }
#endif /* DUMP_CORE */
#endif  /* not windows */

	  fprintf (stdout, "\nReady for logins.\n");
	  if (shouldfork) {
		close( STDIN_FILENO );
		close( STDOUT_FILENO );
		close( STDERR_FILENO );
	  }

	  // set up the periodic idle-ping (19990702.1900)
#if PING_INTERVAL_SEC < 5
	  sked_alarm (PING_INTERVAL_SEC);
#else
	  sked_alarm (5);   // first one should be right away
#endif

	  // manage the room!  RIGHT HERE is where we run for weeks at a time.
	  while( (!gotTermSig) && (pr != NULL) ) {
	    manage_room( pr );
	  }
	  return 0;
	}
	else if( f==-1 )
	{
		perror( "error forking processes" );
		return 1;
	}
	fprintf (stdout, "And the child process is %d.\n", f );
	if (log_file != NULL) {
	  time_t tnow = time(NULL);
	  fprintf (log_file, LOGIN_HELLO_MSG_TXT );
	  fprintf (log_file, "\nRun started at %s", ctime(&tnow));
	  if (log_file != stdout)
	    fprintf (log_file, "Running on port %d, child process is %d.\n\n",
		     port, f);
	}
	return 0;	
}


