/* This contains functions to send and receive data from the server */
/* ---------------------------------------------------------------- */

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

/* send data to server */
void send_data(char *fmt, ...)
{
   int res;
   int ch = 0;
   int size = 2;

#  ifndef NOSSL
   int sslerr = 0;
   int dobreak = 0;
#  endif

   va_list args;

   char *lnptr, *cmdptr;
   char writebuf[MAXWRITESIZE];
   
   memset(writebuf, 0, sizeof(writebuf));
   memset(logmsg.cmdmsg, 0, MAXSEGSIZE);
   
   va_start(args, fmt);
   (void)vsnprintf(writebuf, sizeof(writebuf) - 1, fmt, args);
   va_end(args);
   
   strncpy(logmsg.cmdmsg, writebuf, MAXSEGSIZE - 1);
   logmsg.cmdlen = strlen(logmsg.cmdmsg);

   if (child == 1)
      if (getpid() == chpid) ch = 1;

   if (((writebuf[0] == '\n') || (writebuf[0] == '\0')) && 
       (isprint((int)writebuf[1]) == 0)) 
   {
#     ifdef NOSSL
      if (silent != 1)
      {
         if (child == 1)
            debug("[in send_data] (in %s)\n"
                  "the data to send is bad.. returning\n\n",
                  (ch == 1 ? "child" : "parent"));

         else
            debug("(in send_data) the data to send is bad.. returning\n\n");
      
         debug("the bad data is:\n%s\n", writebuf);
      }

#     else
      error("server possibly disconnected... restarting\n\n");

      connected = 0;

      if (gotInfoServ == 1) longjmp(reconnect, 1);
      else longjmp(infoconn, 1);
#     endif

      return;
   }

   if ((didspool == 1) && (strncmp(writebuf, "STREAM :", 8) == 0))
   {   
      if (silent != 1)
      {
         if ((debugging == 1) && (silent != 1))
         {
            (void)putchar('\n');
            (void)write(dblogfd, "\n", 1);
         }

         if (strlen(writebuf) <= 11)
            debug("sending the following spooled data to server: %s\n",
                  writebuf);

         else
            debug("sending the following spooled data to server:\n%s\n",
                  writebuf);
      }
   }

   else 
   {
      if (silent != 1)
      {
         if (strlen(writebuf) <= 9)
         {
            if (child == 1)
               debug("(in %s) sending the following to the server: %s\n", 
                     (ch == 1 ? "child" : "parent"), writebuf);

            else debug("sending the following to the server: %s\n", writebuf);
         }

         else
         {
            if (child == 1)
               debug("(in %s) sending the following to the server:\n%s\n", 
                     (ch == 1 ? "child" : "parent"), writebuf);

            else
               debug("sending the following to the server:\n%s\n", writebuf);
         }
      }
   }

   errno = errors = 0;

   lnptr = exportInt(logmsg.cmdlen);
   size = 2;

   while(1)
   {
#     ifndef NOSSL
      res = SSL_write(sslconn, lnptr, (u_int)size);
#     else
      res = write(sockfd, lnptr, size);      
#     endif

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

#     ifndef NOSSL /* SSL error handling */
      sslerr = SSL_get_error(sslconn, res);
      switch (sslerr)
      {
         case SSL_ERROR_NONE:
            if (size == res)
            {
               dobreak = 1;
               break;
            }

            lnptr += res, size -= res;
            break;

         case SSL_ERROR_WANT_WRITE:
         case SSL_ERROR_WANT_READ:
         case SSL_ERROR_WANT_X509_LOOKUP:
            errors = 1, dobreak = 1;
            break;

         case SSL_ERROR_SYSCALL:
         case SSL_ERROR_SSL:
            errors = 1, dobreak = 1;
            break;

         case SSL_ERROR_ZERO_RETURN:
            errors = 1, dobreak = 1;
            break;
      }

      if (dobreak == 1)
      {
         dobreak = 0;
         break;
      }

#     else /* normal error handling */
      if (res <= 0)
      {
         if ((res == ERROR) && (errno = EINTR)) continue;

         errors = 1;
         break;
      }

      else if (res < size) 
      {
         lnptr += res, size -= res;
         continue;
      }

      else break;
#     endif /* SSL/NOSSL error handling */
   }

   if (errors != 1)
   {
      size = logmsg.cmdlen;
      cmdptr = logmsg.cmdmsg;

      while(1)
      {
#        ifndef NOSSL
         res = SSL_write(sslconn, cmdptr, (u_int)size);
#        else
         res = write(sockfd, cmdptr, size);
#        endif

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

#        ifndef NOSSL /* SSL error handling */
         sslerr = SSL_get_error(sslconn, res);
         switch (sslerr)
         {
            case SSL_ERROR_NONE:
               if (size == res)
               {
                  dobreak = 1;
                  break;
               }

               cmdptr += res, size -= res;
               break;

            case SSL_ERROR_WANT_WRITE:
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_X509_LOOKUP:
               errors = 1, dobreak = 1;
               break;

            case SSL_ERROR_SYSCALL:
            case SSL_ERROR_SSL:
               errors = 1, dobreak = 1;
               break;

            case SSL_ERROR_ZERO_RETURN:
               errors = 1, dobreak = 1;
               break;
         }

         if (dobreak == 1)
         {
            dobreak = 0;
            break;
         }

#        else /* normal error handling */
         if (res <= 0)
         {
            if ((res == ERROR) && (errno = EINTR)) continue;

            errors = 1;
            break;
         }

         else if (res < size)
         {
            cmdptr += res, size -= res;
            continue;
         }

         else break;
#        endif /* SSL/NOSSL error handling */
      }
   }

#  ifndef NOSSL /* SSL error handling */
   switch (sslerr)
   {
      case SSL_ERROR_NONE:
         /* we don't need to do anything for this */
         break;

      case SSL_ERROR_WANT_WRITE:
      case SSL_ERROR_WANT_READ:
      case SSL_ERROR_WANT_X509_LOOKUP:
         error("got SSL_ERROR_WANT_(WRITE/READ/X509_LOOKUP).. ignoring\n\n");

         errors = 0;
         break;

      case SSL_ERROR_SYSCALL:
      case SSL_ERROR_SSL:
         if (errno <= 0)
         {
            errors = 0;
            break;
         }

         error("error with SSL_write: %s\n\n", strerror(errno));

         ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
         if (debugging == 1) ERR_print_errors_fp(dblogfd1);

         debug("now restarting..\n");

         if (done == 1) return;

         connected = 0;

         if (gotInfoServ == 1) longjmp(reconnect, 1);
         else longjmp(infoconn, 1);

      case SSL_ERROR_ZERO_RETURN:
         error("server disconnected.. now restarting\n\n");

         if (done == 1) return;
  
         connected = 0;

         if (gotInfoServ == 1) longjmp(reconnect, 1);
         else longjmp(infoconn, 1);
   }

#  else /* normal error handling */
   if (res <= 0)
   {
      if (done == 1)
      {
         errors = 1;
         return;
      }

      if (res == 0)
      {
         connected = 0;

         if (child == 1)
            error("(in %s) server disconnected... %s\n\n", 
                  (ch == 1 ? "child" : "parent"), 
                  (ch == 1 ? "aborting" : "restarting"));

         else error("server disconnected... restarting\n\n");

         if ((child == 1) && (ch == 1)) quit(ERROR);
         else
         {
            signal(SIGPIPE, SIG_IGN);

            if (done == 1) return;

            connected = 0;

            if (gotInfoServ == 1) longjmp(reconnect, 1);
            else longjmp(infoconn, 1);
         }
      }

      else if (errno > 0)
      {
         if (child == 1)
         {
#           ifndef NOSSL
            ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
            if (debugging == 1) ERR_print_errors_fp(dblogfd1);

#           else
            error("(in %s) error sending data to the server: %s\n\n",
                  (ch == 1 ? "child" : "parent"), strerror(errno));
#           endif
         }

         else
         {
#           ifndef NOSSL
            ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
            if (debugging == 1) ERR_print_errors_fp(dblogfd1);

#           else
            error("error sending data to the server: %s\n\n", strerror(errno));
#           endif
         }

         if ((child == 1) && (ch == 1)) quit(ERROR);
         else
         {
            signal(SIGPIPE, SIG_IGN);

            debug("error with server.. restarting\n\n");

            if (done == 1) return;

            connected = 0;

            if (gotInfoServ == 1) longjmp(reconnect, 1);
            else longjmp(infoconn, 1);
         }
      }

      else if ((gotAlrm == 1) || (errors == 1))
      {
         errors = 1, gotAlrm = 0;

#        ifndef NOSSL
         ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
         if (debugging == 1) ERR_print_errors_fp(dblogfd1);

#        else
         error("(in recv_data) timeout or error occured in read()\n\n");
#        endif

         debug("now restarting\n\n");

         if (done == 1) return;

         connected = 0;

         if (gotInfoServ == 1) longjmp(reconnect, 1);
         else longjmp(infoconn, 1);
      }
   }
#  endif /* SSL/NOSSL error handling */

/*
   if (strncmp(writebuf, "OKAY", 4) != 0)
   {
      if (gotAlrm == 1) error("(in recv_data) gotAlrm = 1\n\n");

      signal(SIGALRM, okayTimeout);
      (void)alarm(MAXPAUSE * 3);

      * silent = 1, * getOkay(), silent = 0;
      (void)alarm(0);

      if ((errors == 1) || (gotAlrm == 1))
      {
         errors = 1, gotAlrm = 0;

         if (done == 1) return;
         else if ((child == 1) && (ch == 1)) quit(ERROR);
         else
         {
            signal(SIGPIPE, SIG_IGN);

            debug("error with server.. restarting\n\n");

            if (done == 1) return;

            connected = 0;

            if (gotInfoServ == 1) longjmp(reconnect, 1);
            else longjmp(infoconn, 1);
         }
      }
   }
*/

}

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

/* gets new data from server */
void recv_data(char *readbuf, int len)
{
   int res;
   int size = 2;

#  ifndef NOSSL
   int sslerr = 0;
   int dobreak = 0;
#  endif

   int ch = 0;      /* 0 == not child, 1 == child */
   int newdata = 0; /* indicate new data when oldbuf is null */

   char length[2];
   char *lnptr, *cmdptr;

   if (getpid() == chpid) ch = 1;

   if (silent != 1)
   {
      if (child == 1)
         debug("(in %s) receiving data...\n", (ch == 1 ? "child" : "parent"));
 
      else debug("receiving data...\n");
   }

   /* ------------------- */
   errno = errors = 0;

   if ((ch == 0) || (child == 0)) /* in parent */
   {
      errno = 0;
      memset(readbuf, 0, len);

      lnptr = length, cmdptr = readbuf;

      size = 2;
      while(1)
      {
#        ifndef NOSSL
         res = SSL_read(sslconn, lnptr, (u_int)size);
#        else
         res = read(sockfd, lnptr, size);
#        endif

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

#        ifndef NOSSL /* SSL error handling */
         sslerr = SSL_get_error(sslconn, res);
         switch (sslerr)
         {
            case SSL_ERROR_NONE:
               if (size == res)
               {
                  dobreak = 1;
                  break;
               }

               lnptr += res, size -= res;
               break;

            case SSL_ERROR_WANT_WRITE:
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_X509_LOOKUP:
               errors = 1, dobreak = 1;
               break;

            case SSL_ERROR_SYSCALL:
            case SSL_ERROR_SSL:
               errors = 1, dobreak = 1;
               break;

            case SSL_ERROR_ZERO_RETURN:
               errors = 1, dobreak = 1;
               break;
         }

         if (dobreak == 1)
         {
            dobreak = 0;
            break;
         }

#        else /* normal error handling */
         if (res <= 0)
         {
            if ((res == ERROR) && (errno == EINTR)) continue;

            errors = 1;
            break;
         }

         else if (res < size)
         {
            lnptr += res, size -= res;
            continue;
         }

         else break;
#        endif /* SSL/NOSSL error handling */
      }

      if (errors != 1)
      {
         logmsg.cmdlen = importInt(lnptr);

         if (logmsg.cmdlen > len - 1)
         {
            error("(in recv_data) cmdlen > buflen.. truncating\n\n");
            logmsg.cmdlen = len - 1;
         }

         size = logmsg.cmdlen;
         while(1)
         {
#           ifndef NOSSL
            res = SSL_read(sslconn, cmdptr, (u_int)size);
#           else
            res = read(sockfd, cmdptr, size);
#           endif

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

#           ifndef NOSSL /* SSL error handling */
            sslerr = SSL_get_error(sslconn, res);
            switch (sslerr)
            {
               case SSL_ERROR_NONE:
                  if (size == res)
                  {
                     dobreak = 1;
                     break;
                  }

                  cmdptr += res, size -= res;
                  break;

               case SSL_ERROR_WANT_WRITE:
               case SSL_ERROR_WANT_READ:
               case SSL_ERROR_WANT_X509_LOOKUP:
                  errors = 1, dobreak = 1;
                  break;

               case SSL_ERROR_SYSCALL:
               case SSL_ERROR_SSL:
                  errors = 1, dobreak = 1;
                  break;

               case SSL_ERROR_ZERO_RETURN:
                  errors = 1, dobreak = 1;
                  break;
            }

            if (dobreak == 1)
            {
               dobreak = 0;
               break;
            }

#           else /* normal error handling */
            if (res <= 0)
            {
               if ((res == ERROR) && (errno == EINTR)) continue;

               errors = 1;
               break;
            }

            else if (res < size)
            {
               cmdptr += res, size -= res;
               continue;
            }

            else break;
#           endif /* SSL/NOSSL error handling */
         }
      }

#     ifndef NOSSL /* SSL error handling */
      switch (sslerr)
      {
         case SSL_ERROR_NONE:
            /* we don't need to do anything for this */
            break;

         case SSL_ERROR_WANT_WRITE:
         case SSL_ERROR_WANT_READ:
         case SSL_ERROR_WANT_X509_LOOKUP:
            error("got SSL_ERROR_WANT_(WRITE/READ/X509_LOOKUP)..ignoring\n\n");
            errors = 0;

            break;
 
         case SSL_ERROR_SYSCALL:
         case SSL_ERROR_SSL:
            if (errno <= 0)
            {
               errors = 0;
               break;
            }

            error("error with SSL_read: %s\n\n", strerror(errno));

            ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
            if (debugging == 1) ERR_print_errors_fp(dblogfd1);

            debug("now restarting..\n");

            if (done == 1) return;

            if (gotInfoServ == 1) longjmp(reconnect, 1);
            else longjmp(infoconn, 1);

         case SSL_ERROR_ZERO_RETURN:
            error("server disconnected.. now restarting\n\n");

            if (done == 1) return;

            if (gotInfoServ == 1) longjmp(reconnect, 1);
            else longjmp(infoconn, 1);
      }

#     else /* normal error handling */
      if (res <= 0)
      {
         if (done == 1)
         {
            errors = 1;
            return;
         }

         if (res == 0)
         {
            signal(SIGPIPE, SIG_IGN);

            connected = 0;
            if (silent != 1)
            {
               if (child == 1)
                  error("(in parent) server disconnected... restarting\n\n");

               else
                  error("server disconnected... restarting\n\n");
            }

            if (done == 1) return;

            if (gotInfoServ == 1) longjmp(reconnect, 1);
            else longjmp(infoconn, 1);
         }

         else if (errno > 0)
         {         
            if (child == 1)
            {
#              ifndef NOSSL
               ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
               if (debugging == 1) ERR_print_errors_fp(dblogfd1);

#              else
               error("(in parent) "
                     "error receiving data from the server: %s\n\n",
                     (ch == 1 ? "child" : "parent"), strerror(errno));
#              endif
            }

            else
            {
#              ifndef NOSSL
               ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
               if (debugging == 1) ERR_print_errors_fp(dblogfd1);

#              else
               error("error receiving data from the server: %s\n\n",
                     strerror(errno));
#              endif
            }

            signal(SIGPIPE, SIG_IGN);

            if (done == 1) return;

            if (gotInfoServ == 1) longjmp(reconnect, 1);
            else longjmp(infoconn, 1);
         }

         else if ((gotAlrm == 1) || (errors == 1))
         {
            errors = 1, gotAlrm = 0;

            if (silent != 1)
            {
#              ifndef NOSSL
               ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
               if (debugging == 1) ERR_print_errors_fp(dblogfd1);

#              else
               error("(in recv_data) error or timeout while in read()\n\n");
#              endif
            }

            if (gotInfoServ == 1) 
            {
               if (done == 1) return;

               if (silent != 1)
                  error("now reconnecting to a new streaming server\n\n");

               longjmp(reconnect, 1);
            }

            else
            {
               if (done == 1) return;

               if (silent != 1)
                  error("now reconnecting to a new info server\n\n");

               longjmp(infoconn, 1);
            }
         }
      }
#     endif /* SSL/NOSSL error handling */

      if ((res == 0) || (((readbuf[0] == '\0') || (readbuf[0] == '\n')) &&
          (isprint((int)readbuf[1]) == 0)))
      {
#        ifdef NOSSL
         if (silent != 1)
         {
            if (child == 1)
               debug("[in recv_data] (in parent)\n"
                     "data received was bad.. returning\n\n");

            else
               debug("(in recv_data) data received was bad.. returning\n\n");

            debug("bad data is:\n%s\n", readbuf);
         }

#        else
         error("server possibly disconnected... restarting\n\n");

         if (gotInfoServ == 1) longjmp(reconnect, 1);
         else longjmp(infoconn, 1);
#        endif

         return;
      }

      if (silent != 1)
      {
         if (child == 1) debug("(in parent) data received from server..\n");
         else debug("data received from server..\n");

         if (strlen(readbuf) <= 44)
            debug("the data is: %s%c", readbuf,
                  (strchr(readbuf, '\n') == NULL ? '\n' : '\0'));

         else
            debug("the data is:\n%s%c", readbuf,
                  (strchr(readbuf, '\n') == NULL ? '\n' : '\0'));
      }

/*
      if (strncmp(readbuf, "OKAY", 4) != 0)
      {
         * (void)sleep(1); *
         * silent = 1, * send_data("OKAY"), silent = 0;

         if ((errors == 1) || (gotAlrm == 1))
         {
            (void)signal(SIGPIPE, SIG_IGN);
            
            errors = 1, gotAlrm = 0;
            if (done == 1) return;

            error("(in recv_data) error in send_data().. restarting\n\n");
            if (gotInfoServ == 1) longjmp(reconnect, 1);
            else longjmp(infoconn, 1);
         }
      }

      else  
*/    if (strncmp(readbuf, "ERROR", 5) == 0)
      {
         signal(SIGPIPE, SIG_IGN);

         error("ERROR received from the server..\n"
               "the message was: %s\n", readbuf);

         if (done == 1) return;

         if (gotInfoServ == 1) longjmp(reconnect, 1);
         else longjmp(infoconn, 1);
      }

      else if (strncmp(readbuf, "CHNGSERV", 8) == 0)
      {
         signal(SIGPIPE, SIG_IGN);
         error("server has requested 'chngserv' cmd.. restarting\n\n");

         if (done == 1) return;

         if (gotInfoServ == 1) longjmp(reconnect, 1);
         else longjmp(infoconn, 1);
      }

      /* junk.. just to make pretty */
      else if ((debugging == 1) &&
               (((strncmp(readbuf, "PING", 4) == 0)  &&
               (strncmp(readbuf, "CHECK", 5) != 0)) ||  
               (strncmp(readbuf, "OKAY", 4) == 0)))
      {
         if ((debugging == 1) && (silent != 1))
         {
            (void)putchar('\n');
            (void)write(dblogfd, "\n", 1);
         }
      }

      if (child == 0) return;  /* we don't need to do this if there */
                               /* is no child to notify...          */
      
      if (oldbuf[0] == '\0') 
      {
         if (silent != 1)
         {
            if (child == 1)
               debug("(in parent) no data in oldbuf.. putting it in\n");

            else debug("no data in oldbuf.. putting it in\n");
         }

         strncpy(oldbuf, readbuf, sizeof(oldbuf));
         newdata = 1;
      }

      if (((strcmp(oldbuf, readbuf) != 0) || (newdata == 1)) &&
          ((strncmp(readbuf, "PING", 4) == 0) || 
          (strncmp(readbuf, "OKAY", 4) == 0)))
      {
         /* new data has been receiveed */
      
         if (running == 0)
         { 
            if (silent != 1)
            {
               if ((debugging == 1) && (silent != 1))
               {
                  (void)putchar('\n');
                  (void)write(dblogfd, "\n", 1);
               }

               debug("running = 0, waiting..\n");
            }

            while (running == 0) (void)sleep(1);
         }

         if (silent != 1)
            debug("(in parent) got new data... sending SIGUSR1 to child\n\n");

         memset(segptr, 0, MAXSEGSIZE);
         
         /* put it in shared mem */
         (void)strncpy(segptr, readbuf, MAXSEGSIZE-1);

         if (silent != 1) 
            debug("shared segment data = %s%c", segptr,
                  (strchr(segptr, '\n') == NULL ? '\n' : '\0'));   
      
         running = 0;         
         (void)signal(SIGUSR2, startUp);

#       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

         /* notify child there is new data */
         res = kill(chpid, SIGUSR1);
         if (res == ERROR)
         {
            error("error killing the child process: %s\n\n",
                  strerror(errno));

#           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

            if (done != 1)
            {
               /* if something went wrong here.. forget pinging */
               child = 0, pinging = 0;
               if (done == 1) return;

               if (gotInfoServ == 1) longjmp(reconnect, 1);
               else longjmp(infoconn, 1);
            }
         }

#        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

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

         /* while (running == 0) sleep(1); */
         return;
      }
   }

   else /* if (ch == 1) */
   {
      errno = 0;

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

      if (newData == 0)
      {
         if (silent != 1) debug("newData = 0, waiting..\n");
         while (newData == 0) (void)sleep(1);
      }

      newData = 0; /* FIX - race condition.. block SIGUSR1.. */

      /* make sure buffer is blank */
      memset(readbuf, 0, len);
    
      if (silent == 1) debug("shared segment data = %s\n", segptr);
      memcpy(readbuf, segptr, len), readbuf[len] = '\0';
     
      if (silent != 1) debug("readbuf (after copying seg) = %s\n", readbuf);

      newData = 0; /* reset data marker */

      if (silent != 1) debug("(in child) sending parent SIGUSR2 now\n\n");

#    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

      /* tell parent we got data.. it can continue */
      res = kill(getppid(), SIGUSR2);
      if (res == ERROR)
      {
         error("(in child) error killing the parent process: %s\n\n",
               strerror(errno));  

         if (done != 1) quit(ERROR);
      }

      if (pwd != NULL)
      {
#       if !defined(SUN) && !defined(BSD)
#        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
      }

      return;
   }
}
