ncohafmuta-1.4.2/bot/
ncohafmuta-1.4.2/helpfiles/
ncohafmuta-1.4.2/lib/emailver/
ncohafmuta-1.4.2/tzinfo/Atlantic/
ncohafmuta-1.4.2/tzinfo/Brazil/
ncohafmuta-1.4.2/tzinfo/Chile/
ncohafmuta-1.4.2/tzinfo/Indian/
ncohafmuta-1.4.2/tzinfo/Mexico/
ncohafmuta-1.4.2/tzinfo/Mideast/
ncohafmuta-1.4.2/tzinfo/SystemV/
ncohafmuta-1.4.2/utils/
ncohafmuta-1.4.2/utils/code_fragments/new_config/
#if defined(HAVE_CONFIG_H)
#include "../hdrfiles/config.h"
#endif

#include "../hdrfiles/includes.h"

/*
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#if defined(SOL_SYS) || defined(LINUX_SYS)
#include <string.h>
#else
#include <strings.h>
#endif
*/

#include "../hdrfiles/osdefs.h"
#include "../hdrfiles/constants.h"
#include "../hdrfiles/protos.h"

extern int down_time;
extern int num_of_users;
extern int atmos_on;
extern int signl;
extern int treboot;
extern char mess[ARR_SIZE+25];



void init_signals()
{

/* Damn zombie kids..get rid of them when they cry for help */
(void)setsignal(SIGCHLD, zombie_killer); /* does win32 like us? */
              
/*------------------------------------------------*/
/* the following signal ignores may be desireable */
/* to comment out for debugging                   */
/*------------------------------------------------*/
           
(void)setsignal(SIGTERM,handle_sig);
(void)setsignal(SIGUSR1,handle_sig); /* does win32 like us? */
(void)setsignal(SIGUSR2,handle_sig); /* does win32 like us? */
(void)setsignal(SIGSEGV,handle_sig);

(void)setsignal(SIGILL,handle_sig);
(void)setsignal(SIGINT,(handler_t)SIG_IGN);
(void)setsignal(SIGABRT,(handler_t)SIG_IGN);
(void)setsignal(SIGFPE,(handler_t)SIG_IGN);

#if !defined(WINDOWS)
  /* we don't care about SIGPIPE, we notice it in select() and write() */
  (void)setsignal(SIGPIPE, (handler_t)SIG_IGN);
  (void)setsignal(SIGBUS,handle_sig);
#if !defined(__CYGWIN32__)
  (void)setsignal(SIGIOT,(handler_t)SIG_IGN);
#endif
  (void)setsignal(SIGTSTP,(handler_t)SIG_IGN);
  (void)setsignal(SIGCONT,(handler_t)SIG_IGN);
  (void)setsignal(SIGHUP,(handler_t)SIG_IGN);
  (void)setsignal(SIGQUIT,handle_sig);
#if !defined(__CYGWIN32__)
  (void)setsignal(SIGURG,(handler_t)SIG_IGN);  
#endif
  (void)setsignal(SIGTTIN,(handler_t)SIG_IGN);
  (void)setsignal(SIGTTOU,(handler_t)SIG_IGN);
#if !defined(LINUX_SYS)
(void)setsignal(SIGEMT,(handler_t)SIG_IGN); /* does win32 like us? */
#endif
#endif

}

/*----------------------------------------------------------------------*/
/* Function to clean up the zombied child process from a fork           */
/*                                                                      */
/* Zombie'd child processes occur when the the child finishes before    */
/* the parent process. The kernel still keeps some of the information   */
/* about the child in case the parent might need it. To be able to get  */
/* this info, the parent calls waitpid(). When this happens, the kernel */
/* can discard the information. Zombies dont take up any resources,     */
/* other than a process table entry. If the parent terminates without   */
/* calling waitpid(), the child is adopted by init, which handles the   */
/* work necessary to cleanup after the child.                           */
/*----------------------------------------------------------------------*/
RETSIGTYPE zombie_killer(int sig)
{
int status, child_val, i=0;
pid_t child_pid=-1;
pid_t get_pid;

#if defined(ZOMBIE_DEBUG)
 write_log(DEBUGLOG,YESTIME,"ZOMBIE: Calling zombie killer..\n");
#endif

/* (void *) casts to avoid warnings on systems that mis-declare */
/* the argument type. */
while ( (get_pid = waitpid(
        -1,             /* Wait for any child */
        (void *) &status,
        WNOHANG         /* Don't block waiting */
       )) > 0) {
           if (get_pid <= 0) break;
           else child_pid = get_pid;
          }

/* No child to clean up, or error */
if (child_pid <= 0) {
        if (child_pid == -1) {
#if defined(ZOMBIE_DEBUG)
        write_log(DEBUGLOG,YESTIME,"ZOMBIE: waitpid() error! %s\n",get_error());
#endif   
        }
        (void)setsignal(SIGCHLD, zombie_killer);
        return;
        }
else {
#if defined(ZOMBIE_DEBUG)
        write_log(DEBUGLOG,YESTIME,"ZOMBIE: waitpid() returned pid %u\n",(unsigned int)child_pid);
#endif
        }
        
        
/* Reset handler                    */
/* Doing this before the waitpid()  */
/* can lead to an infinite loop     */
(void)setsignal(SIGCHLD, zombie_killer);

/* Negative child_val indicates some error    */
/* Zero child_val indicates no data available */
         
    /*  
     * We now have the info in 'status' and can manipulate it using
     * the macros in wait.h.
     */
    if (WIFEXITED(status))                /* did child exit normally? */
    {
        child_val = WEXITSTATUS(status); /* get child's exit status */
#if defined(ZOMBIE_DEBUG)
        write_log(DEBUGLOG,YESTIME,"ZOMBIE: Child exited normally with status %d\n", child_val);
#endif

     
        /* Find the user who had this child and let them do remote whos again */
        for (i=0;i<MAX_USERS;++i) {
                if (ustr[i].rwho==child_pid) {
                ustr[i].rwho=1;
                break;   
                } /* end of if */
        } /* end of for */
    }

}       

/*** switching function ***/
RETSIGTYPE sigcall(int sig)
{
              /*-------------------------*/
              /* process timed events    */
              /*-------------------------*/

              /*--------------------------------------*/
              /* check for out of date board messages */
              /*--------------------------------------*/
              check_mess(0);

		if (down_time > 0)
		{
			check_shut();
		}

		if (num_of_users)
		{
			check_idle();
		}

		if (LOGIN_LIMITING)
		{
			check_connlist_entries(-2);
		}

		check_misc_connects();

		check_smtp();

		if (atmos_on)
		{
			atmospherics();
		}

                check_total_users(0);
                 
#if !defined(WINDOWS)
reset_alarm();   
#endif
              
signl = 1;
}

/*** reset alarm - first called from add_user ***/
void reset_alarm()
{
(void)setsignal(SIGALRM, sigcall);
alarm( MAX_ATIME );
}

/**** START OF SIGNAL FUNCTIONS ****/
RETSIGTYPE handle_sig(int sig)
{
                 
switch(sig) {
        case SIGTERM:
                shutdown_error(log_error(10));
		break;
        case SIGSEGV:
                if (REBOOT_A_CRASH==1)
                 treboot=1;
                shutdown_error(log_error(11));
		break;
        case SIGBUS: 
                if (REBOOT_A_CRASH==1)
                 treboot=1;
                shutdown_error(log_error(12));
		break;
        case SIGUSR1:
		/* command line shutdown */
                shutdown_error(log_error(13));
		break;
        case SIGUSR2:
		/* re-init config file */
                read_init_data(1);
		messcount();
		sprintf(mess,"%s Config file reinit done from command line",STAFF_PREFIX);
		writeall_str(mess, WIZ_ONLY, -1, 0, -1, BOLD, WIZT, 0);
		break;
        case SIGQUIT:
		/* soft-reboot */
		/* this only really works ONCE inside of a hard startup, we dont know why, */
		/* so it's not really a documented feature */
		treboot=1;
                shutdown_error(log_error(13));
		break;
        case SIGILL:
                if (REBOOT_A_CRASH==1)
                 treboot=1;
                shutdown_error(log_error(15));
		break;
  }
		/* Reset handler                    */
		(void)setsignal(sig, handle_sig);
}


/*
 * An os independent signal() with BSD semantics, e.g. the signal
 * catcher is restored following service of the signal.
 *
 * When sigset() is available, signal() has SYSV semantics and sigset()
 * has BSD semantics and call interface. Unfortunately, Linux does not
 * have sigset() so we use the more complicated sigaction() interface
 * there.
 *
 * Did I mention that signals suck?
 */
/* (*setsignal (int sig, RETSIGTYPE (*func)(int)))(int) */
handler_t
setsignal(int sig, handler_t handler)
{
#if defined(HAVE_SIGACTION)
        struct sigaction old, new;
#elif defined(HAVE_SIGMASK)
	struct sigvec nsv,osv;
#endif
	handler_t oldh;

#if defined(HAVE_SIGACTION)
        memset(&new, 0, sizeof(new));
        new.sa_handler = handler;
#if defined(SA_RESTART)
        new.sa_flags |= SA_RESTART;
#endif
        if (sigaction(sig, &new, &old) < 0)
                return ((handler_t)SIG_ERR);
        oldh = old.sa_handler;

#elif defined(HAVE_SIGMASK)
        memset(&nsv, 0, sizeof(nsv));
    nsv.sv_handler = handler;
    nsv.sv_mask = 0;                    /* punt */
    nsv.sv_flags = SV_INTERRUPT;        /* punt */
    sigvec(sig, &nsv, &osv);
    oldh = osv.sv_handler;
#elif defined(HAVE_SIGSET)
        oldh = (handler_t)sigset(sig, handler);
#else
        oldh = signal(sig, handler);
#endif
	return oldh;
}