/* functions to terminate program */
/* ------------------------------ */

#include "headers.h" /* has all important stuff */

/* free structures and exit */
void quit(int stat)
{
   int jumped; /* 1 if returning from longjmp() */
	
   jumped = setjmp(doquit);
   if ((jumped == ERROR) && (errno != 0)) 
      error("error with setjmp(): %s\n\n", strerror(errno));

   if (stat == INIT) return;

   silent = 0;

   if (debugging == 1)
   {
      (void)putchar('\n');
      (void)write(dblogfd, "\n", 1);
   }

   if (child == 1)
   {
      if (chpid == getpid())
         debug("(in quit) I'm the child\n");

      else
         debug("(in quit) I'm the parent\n");
   }

   error("received a signal/error to abort.. now exiting\n\n");

/*
   if (debugging == 1)
   {
      (void)putchar('\n');
      (void)write(dblogfd, "\n", 1);
   }
*/

   done = 1;

   /* ----------------------- */

   (void)signal(SIGHUP, SIG_IGN);

   (void)signal(SIGINT, SIG_IGN);
   (void)signal(SIGTERM, SIG_IGN);

   (void)signal(SIGPIPE, SIG_IGN);

   (void)signal(SIGCHLD, SIG_IGN);

   (void)signal(SIGUSR1, SIG_IGN);
   (void)signal(SIGUSR2, SIG_IGN);

   if (debugging != 1)
   {
      (void)signal(SIGILL, SIG_IGN);
      (void)signal(SIGBUS, SIG_IGN);
      (void)signal(SIGSEGV, SIG_IGN);

      (void)signal(SIGQUIT, SIG_IGN);
   }

   /* ----------------------- */

   if (chpid != getpid()) 
   {
      if (connected == 1)
      {
         gotAlrm = 0, errors = 0, errno = 0;

         debug("sending server quit request\n");

         if (streaming) send_data("END STREAM\n");   
         send_data("QUIT\n"); 
      }

      debug("closing sockets\n");

      (void)fclose(confd);
      if (sockfd > 0) (void)close(sockfd);
      if (klogfd > 0) (void)close(klogfd);
      if (funix > 0) (void)close(funix);

      if (spoolfd != NULL) (void)fclose(spoolfd);

      closeLogFiles();

      debug("freeing serverlist\n");
      freeServList(), freeSharedMem();

   }

   if (getpid() != chpid)
   {
      doKills();

      if (debugging == 1)
      {
         (void)printf("\n%cinished closing...\n",
                     (debugging != 1 ? 'F' : 'f'));

         (void)fprintf(stderr,
                       "%cee %s/%s for the error log for errors (if any)..\n", 
                       (debugging != 1 ? 'S' : 's'), SRSdir, ERRLOG);
      }
   }

   if (debugging == 1)
   {
      (void)putchar('\n');
      (void)write(dblogfd, "\n", 1);
   }

   if (getpid() != chpid)
   {
      (void)close(errlogfd), (void)fclose(errlogfd1);

      if (debugging == 1)
      {
         (void)close(dblogfd);
         (void)fclose(dblogfd1);
      }
   }

   /* jumped == value passed to longjmp() */
   if (jumped == 0) exit(stat);
   else exit(jumped);
} 
   

/* --------------------------- */


/* close the facility.priority log files we spooled locally */
void closeLogFiles()
{
   register int i;

   for (i = 0; i <= curlogfd; i++) 
   {
      if (logs[i].fd > 0) (void)close(logs[i].fd);
      if (logs[i].filename != NULL) free(logs[i].filename);
   }
}


/* --------------------------- */


/* free/detach shared memory */
void freeSharedMem()
{
   int res;

   debug("detaching shared memory\n");

   res = shmdt(segptr);
   if (res == ERROR) 
       error("error detaching the shared memory: %s\n\n",
             strerror(errno));
}


/* --------------------------- */


/* free server list structures */         
void freeServList()
{
   register int i;

   if (curServ != ERROR)
      for (i = 0; i <= useServ ; i++)
         if (servList[i].name != NULL) free(servList[i].name);
}


/* --------------------------- */


/* kill the parent process */
void doKills()
{   
#  if !defined(BSD) && !defined(SUN)
   int res;
#  endif

# if !defined(SUN) && !defined(BSD)
#  ifdef _POSIX_SAVED_IDS
   res = setuid(0);
#  else
   res = seteuid(0);
#  endif

   if (res == ERROR)
   {
      error("error setting [e]uid: %s\n\n", strerror(errno));
      quit(ERROR);
   }
# endif

   if ((child == 1) && (chpid > 0))
   {
      if (debugging == 1) 
         (void)printf("[DEBUG (pid %d)]: "
                      "killing the ping (pid %d) process\n",
                      (int)getpid(), (int)chpid);
 
      kill(chpid, SIGTERM);
   }

#  if !defined(SUN) && !defined(BSD)
   if (pwd != NULL)
   {
#     ifdef _POSIX_SAVED_IDS
      res = setuid(pwd->pw_uid);
#     else
      res = seteuid(pwd->pw_uid);
#     endif

      if (res == ERROR)
      {
         error("error setting [e]uid: %s\n\n", strerror(errno));
         quit(ERROR);
      }
   }
#  endif
}
