/*
    signals.c  Signal handlers for cheezmud.
    Copyright (C) 1995  David Flater.

    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 <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>

int pipe_broke = 0;

void
sig_other ();
void
sig_pipe ();
void
sig_truncate_log ();
void
sig_flush ();
extern void
checkpoint ();


/* Log something with a timestamp */
void
cheezlog (char *text)
{
  time_t cal;
  fflush (stderr);
  fflush (stdout);
  time (&cal);
  printf ("%24.24s %s\n", ctime (&cal), text);
  fflush (stdout);
}

void
sig_setup ()
{
  int a;

  /* All unexpected signals except SIGCONT result in a shutdown. */
  for (a=1;a<NSIG;a++)
    if (a != SIGCONT)
      signal (a, sig_other);

  /* The following are the expected signals. */
  signal (SIGPIPE, sig_pipe);
  signal (SIGUSR1, sig_truncate_log);
  signal (SIGUSR2, sig_flush);
}

/* Truncate stdout and stderr.  They are assumed to be truncatable.
 */
void
sig_truncate_log ()
{
  signal (SIGUSR1, sig_truncate_log);
  lseek (1, 0, SEEK_SET);    /* stdout */
  lseek (2, 0, SEEK_SET);    /* stderr */
  ftruncate (1, 0);          /* stdout */
  ftruncate (2, 0);          /* stderr */
}

void
sig_other (int sig)
{
  char temp[120];
  checkpoint ();
  sprintf (temp, "Received unexpected signal %d -- shutting down.", sig);
  cheezlog (temp);
  exit (-1);
}

/* Flush stdout and stderr, if log files don't appear to be complete */
void
sig_flush ()
{
  signal (SIGUSR2, sig_flush);
  fflush (stdout);
  fflush (stderr);
}

/* SIGPIPE is generated on write to a broken socket. */
void
sig_pipe ()
{
  signal (SIGPIPE, sig_pipe);
  pipe_broke = 1;
}

/* Indirection to accomodate old Sun compiler. */
int
broke_pipe ()
{
  return pipe_broke;
}

void
unbreak_pipe ()
{
  pipe_broke = 0;
}