talker/
talker/bin/
talker/files/whois/
talker/update/
talker/update/bin/
/*
 * glue.c
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <memory.h>
#include <malloc.h>

#include "config.h"
#include "player.h"
#include "fix.h"
#include "file.h"
#define ABS(x) (((x)>0)?(x):-(x))

/* extern definitions */
extern unsigned int sleep(unsigned int seconds);
extern void     lower_case(char *);
extern char    *sys_errlist[];
extern void     init_rooms(), init_plist(),
                save_player(), sync_all(), do_update();
extern void     do_update();
extern void     do_tests();
void            close_down();

/* External variables */

extern int num_residents, num_psu, num_su, num_ladmin, num_admin,
           num_banished;

/* Internal func's definitions */


/* return a string of the system time */

char           *sys_time()
{
   time_t          t;
   static char     time_string[25];
   t = time(0);
   strftime(time_string, 25, "%H:%M:%S - %d/%m/%y", localtime(&t));
   return time_string;
}

char           *end_string(char *str)
{
   str = strchr(str, 0);
   str++;
   return str;
}

void            log(char *file, char *string)
{
   int             fd, length;

   sprintf(stack, "logs/%s.log", file);
   fd = open(stack, O_CREAT | O_WRONLY | O_SYNC, S_IRUSR | S_IWUSR);
   length = lseek(fd, 0, SEEK_END);
   if (length > MAX_LOG_SIZE)
   {
      close(fd);
      fd = open(stack, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, S_IRUSR | S_IWUSR);
   }
   sprintf(stack, "%s - %s\n", sys_time(), string);
   if (!(sys_flags & NO_PRINT_LOG))
      printf(stack);
   write(fd, stack, strlen(stack));
   close(fd);
}

/* what happens when *shriek* an error occurs */

void            handle_error(char *error_msg)
{
   char            dump[80];

   if (sys_flags & PANIC)
   {
      stack = stack_start;
      log("error", "Immediate PANIC shutdown.");
      exit(-1);
   }
   sys_flags |= PANIC;
   stack = stack_start;

   if ( sys_flags & UPDATE )
      sys_flags &= ~NO_PRINT_LOG;

   log("error", error_msg);
   log("boot", "Abnormal exit from error handler");

   /* dump possible useful info */

   log("dump", "------------ Starting dump");

   sprintf(stack_start, "Errno set to %d, %s", errno, sys_errlist[errno]);
   stack = end_string(stack_start);
   log("dump", stack_start);

   if (current_player)
   {
      log("dump", current_player->name);
      if (current_player->location)
      {
    sprintf(stack_start, "player %s.%s",
       current_player->location->owner->lower_name,
       current_player->location->id);
    stack = end_string(stack_start);
    log("dump", stack_start);
      } else
    log("dump", "No room of current player");

      sprintf(stack_start, "flags %d saved %d residency %d", current_player->flags,
         current_player->system_flags, current_player->residency);
      stack = end_string(stack_start);
      log("dump", stack_start);
      log("dump", current_player->ibuffer);
   } else
      log("dump", "No current player !");
   if (current_room)
   {
      sprintf(stack_start, "current %s.%s", current_room->owner->lower_name,
         current_room->id);
      stack = end_string(stack_start);
      log("dump", stack_start);
   } else
      log("dump", "No current room");

   sprintf(stack_start, "global flags %d, players %d", sys_flags, current_players);
   stack = end_string(stack_start);
   log("dump", stack_start);

   sprintf(stack_start, "action Updating player files");
   stack = end_string(stack_start);
   log("dump", stack_start);

   log("dump", "---------- End of dump info");


   close_down();
   exit(-1);
}

/* load a file into memory */

file            load_file_verbose(char *filename, int verbose)
{
   file            f;
   int             d;
   char           *oldstack;

   oldstack = stack;

   d = open(filename, O_RDONLY);
   if (d < 0)
   {
      sprintf(oldstack, "Can't find file:%s", filename);
      stack = end_string(oldstack);
      if (verbose)
    log("error", oldstack);
      f.where = (char *) MALLOC(1);
      *(char *) f.where = 0;
      f.length = 0;
      stack = oldstack;
      return f;
   }
   f.length = lseek(d, 0, SEEK_END);
   lseek(d, 0, SEEK_SET);
   f.where = (char *) MALLOC(f.length + 1);
   memset(f.where, 0, f.length + 1);
   if (read(d, f.where, f.length) < 0)
   {
      sprintf(oldstack, "Error reading file:%s", filename);
      stack = end_string(oldstack);
      log("error", oldstack);
      f.where = (char *) MALLOC(1);
      *(char *) f.where = 0;
      f.length = 0;
      stack = oldstack;
      return f;
   }
   close(d);
   if (sys_flags & VERBOSE)
   {
      sprintf(oldstack, "Loaded file:%s", filename);
      stack = end_string(oldstack);
      log("boot", oldstack);
      stack = oldstack;
   }
   stack = oldstack;
   *(f.where + f.length) = 0;
   return f;
}

file            load_file(char *filename)
{
   return load_file_verbose(filename, 1);
}

/* convert a string to lower case */

void            lower_case(char *str)
{
   while (*str)
      *str++ = tolower(*str);
}

/* close down sequence */

void            close_down()
{
   player         *scan, *old_current;

   for (scan = flatlist_start; scan; scan = scan->flat_next)
      save_player(scan);
   sync_all();
   old_current = current_player;
   current_player = 0;
   current_player = old_current;

   for (scan = flatlist_start; scan; scan = scan->flat_next)
      close(scan->fd);

}


/* the boot sequence */

void init_update()
{
   char *oldstack;
   int i;

   oldstack = stack;
   flatlist_start = 0;
   for (i = 0; i < 27; i++)
      hashlist[i] = 0;
   stdout_player = (player *) MALLOC(sizeof(player));
   memset(stdout_player, 0, sizeof(player));
   srand(time(0));
   init_plist();
   init_rooms();
   current_players = 0;
   stack = oldstack;
}



void main(int argc, char *argv[])
{
  int mem_used;

  /* Initialise rc_options struct */
  rc_options = (rc_type *) malloc(sizeof(rc_type));
  memset(rc_options, 0, sizeof(rc_type));
  stack_start = (char *) MALLOC(STACK_SIZE);
  memset(stack_start, 0, STACK_SIZE);
  stack = stack_start;
  /* Initialise ressie counters */
  num_residents = 0;
  num_psu = 0;
  num_su = 0;
  num_ladmin = 0;
  num_admin = 0;
  num_banished = 0;
  /* Read in .rc file and process */
  init_updaterc(".updaterc");
  /* Make sure update will be successful */
  do_tests();
  printf(" Starting update .....\n");
  sys_flags |= SHUTDOWN | UPDATE;
  /* Do actual update */
  init_update();
  do_update();
  close_down();
  free(rc_options);
  printf(" Finished !!\n\n");
  printf(" ===========================\n");
  printf("     Resident Statistics\n"
	 " ===========================\n");
  printf("  Normal Residents  (%d)\n", num_residents);
  printf("  Pseudo Su's       (%d)\n", num_psu);
  printf("  Super Users       (%d)\n", num_su);
  printf("  Lower Admins      (%d)\n", num_ladmin);
  printf("  Admins            (%d)\n", num_admin);
  printf(" ===========================\n");
  printf("  Total             [%d]\n", (num_residents+num_psu+
					num_su+num_ladmin+num_admin));
  printf("  Banished Pfiles   [%d]\n", num_banished);
  printf(" ===========================\n");
  printf(" Update for PG96 Run Completed.\n");
}