/*  READ ME READ ME READ ME READ ME READ ME READ ME READ ME READ ME  */
/*    This file is _horrendous_! Do not even attempt to follow it.   */
/*    I'm going to have to wait til SRSv2 to clean it up. There is   */
/*    just not enough time.                                          */
/*                                                                   */
/*    There is a lot of repetitious and redundant code.. and huge    */
/*    function sizes. Once we clean up it will be a lot smaller      */
/*  READ ME READ ME READ ME READ ME READ ME READ ME READ ME READ ME  */

/* This has functions to parse various data from server */
/* ---------------------------------------------------- */

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

/* this function parses the client ID and puts it in the struct */
void getID(char *str)
{
   int count = 0; /* prevent overflows */

   char ID[8];
   char *IDptr, *dataptr;

   memset(ID, 0, sizeof(ID));
   IDptr = ID, dataptr = strstr(str, "ID");

   dataptr += 3; /* skip "ID " */

   while ((*dataptr) && (*dataptr != ' ') &&
          (isprint(*dataptr) != 0) && (count < (int)sizeof(ID)))
   {
      *IDptr++ = *dataptr++;
      count++;
   }

   clients[curClient].ID = atoi(ID);
}


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


/* parse options from config file */
void parseSysConf(char *str)
{   
   register int i, j;

   int count = 0;
   int didfacs = 0, numfacs = 0; 

   char filename[MAXFNAMESIZE];
   char facility[16], priority[16];

   char *dataptr, *facptr, *priptr, *fnameptr;

   memset(filename, 0, sizeof(filename));
   memset(facility, 0, sizeof(facility));
   memset(priority, 0, sizeof(priority));

   dataptr = str;
   facptr = facility, priptr = priority, fnameptr = filename;

   if ((str[0] == '\0') || (str[0] == '\n') || (isprint(str[0]) == 0)) 
      return;

   else if (strchr(str, '#') != NULL)
   {
      if (str[0] == '#') return;
      else
      {
         char *ptr = strchr(str, '#');
         if (ptr != NULL) *ptr = '\0'; 
      }   
   }

   else if ((strstr(str, "ifdef(") != NULL) ||
       (strstr(str, "ifndef(") != NULL) ||
       (strstr(str, "elif(") != NULL) ||
       (strstr(str, "else(") != NULL))
   {
      /* FIX - do we need to set any values to ERROR? */
      error("ifdef(), ifndef(), elif(), and else() "
            "aren't supported at this time\n\n");

      return;
   }

   else if (strchr(str, ')') != NULL) 
   {
      debug("possibly the end of an ifdef().. ignoring\n");
      return;
   }

   /* --------------------- facility stuff ---------------------- */

   curlogfd++;
   debug("(in parseSysConf) curlogfd = %d, curClient = %d\n", curlogfd,
         curClient);

   if (curlogfd >= MAXLOGTYPES)
   {
      error("error parsing /etc/syslog.conf.. overflowed logs[]\n\n");
      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
      quit(ERROR);
   }

   if (str[0] == '*') 
   {
      clients[curClient].logs[curlogfd].facility = ALL;

      memset(facility, 0, sizeof(facility));
      strcpy(facility, "*");

      debug("facility = * (all facilities)\n\n");
   }

   else if (str[0] == '-')
      clients[curClient].logs[curlogfd].nsync = 1;

   /* parse facility.* */
   else /* no tricks for us.. just do it normally */
   {
      facptr = facility;
      memset(facility, 0, sizeof(facility));

      /* do manual parsing */
      count = 0;
      while ((*dataptr) && (*dataptr != ' ') &&
             (*dataptr != '.') && (*dataptr != ',') && 
             (isprint(*dataptr) != 0) && (count < (int)sizeof(facility)-1))
      {
         *facptr++ = *dataptr++;
         count++;
      }

      debug("facility = %s\n", facility);

      if (isprint(*dataptr) != 0)
         debug("current seperator = %c\n", *dataptr);

      else
         debug("current seperator = 0x%x (in hex)\n", *dataptr);

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

      clients[curClient].logs[curlogfd].facility = facNameToVal(facility);

      if (clients[curClient].logs[curlogfd].facility == ERROR)
      {
         error("(in parseSysConf) error parsing line:\n%s"
               "unknown facility type\n\n", str);

         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
         quit(ERROR);
      }

      clients[curClient].logs[curlogfd].facility = facNameToVal(facility);

      if (*dataptr == ',')
      {
         parsePri(str); /* parse the previous one */
         dataptr += 1; 

         curlogfd++, numfacs = 0;
         if (curlogfd >= MAXLOGTYPES)
         {
            error("error parsing /etc/syslog.conf.. overflowed logs[]\n\n");
            send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
            quit(ERROR);
         }
/*
         if (debugging == 1)
         {
            (void)putchar('\n');
            (void)write(dblogfd, "\n", 1);
         }
*/
         debug("curlogfd = %d\n", curlogfd);

         debug("---before parseFac---\n");
         numfacs = parseFac(dataptr, numfacs);
         debug("---after parseFac---\n");

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

   /* --------------------- priority stuff ---------------------- */

   /* "*.*" probably -- try a shortcut/hack */
   if (str[3] == '*') /* do we have a shortcut? */
   {
      clients[curClient].logs[curlogfd].priority.priority = ALL;

      memset(priority, 0, sizeof(priority));
      strcpy(priority, "*");

      debug("priority = * (all priorities)\n");
   }

   /* parse *.priority */
   else if (didfacs != 1) /* no tricks for us.. just do it normally */
   {
      dataptr = strchr(str, '.');
      if (dataptr == NULL)
      {
         error("(in sysLogConf) unable to parse:\n%s\n", str);
         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);

         quit(ERROR);
      }

      dataptr += 1; /* skip '.' */

      /* can be "*.!=*" or "*.=*" */
      if (*dataptr == '!') 
      {
         /* check for possible bugs */
         if ((*(dataptr + 1)) == '*')
         {
            error("error parsing line (no '*' allowed after '!'):\n%s\n", str);
            send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
            quit(ERROR);
         }

         debug("exclude ('!') on\n");
         clients[curClient].logs[curlogfd].priority.exclude = 1;
      }

      if ((*dataptr == '=') || ((*(dataptr+1)) == '=')) 
      {
         /* check for possible bugs */
         if (((*(dataptr + 1)) == '*') || ((*(dataptr + 2)) == '*'))
         {
            error("error parsing line (no '*' allowed after '='):\n%s\n", str);
            send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
            quit(ERROR);
         }

         debug("single ('=') on\n");
         clients[curClient].logs[curlogfd].priority.single = 1;
      }

      /* skip to next valid data to parse */
      if (clients[curClient].logs[curlogfd].priority.single == 1)
      {
         if (clients[curClient].logs[curlogfd].priority.exclude == 1)
            dataptr += 2; /* skip both '!' and '=' */

         else dataptr += 1;
      }

      else if (clients[curClient].logs[curlogfd].priority.exclude == 1)
         dataptr += 1;
         
      priptr = priority;
      memset(priority, 0, sizeof(priority));
      
      count = 0;
      while ((*dataptr) && (*dataptr != ' ') &&
             (*dataptr != ';') && (isprint(*dataptr) != 0) && 
             (count < (int)sizeof(priority)-1))
      {
         *priptr++ = *dataptr++;
         count++;
      }

      if (strchr(priority, '*') != NULL)
      {
         if (clients[curClient].logs[curlogfd].priority.exclude == 1)
         {
            (void)strcpy(priority, "none");
            clients[curClient].logs[curlogfd].priority.priority = NONE;
            debug("priority = %s (no priorities)\n", priority);
         }

         else
         {
            clients[curClient].logs[curlogfd].priority.priority = ALL;
            debug("priority = %s (all priorities)\n", priority);
         }
      }

      else if (strncmp(priority, "none", 4) == 0)
      {
         if (clients[curClient].logs[curlogfd].priority.exclude == 1)
         {
            (void)strcpy(priority, "all");
            clients[curClient].logs[curlogfd].priority.priority = ALL;
            debug("priority = !none (all priorities)\n");
         }

         else
         {
            (void)strcpy(priority, "none");
            clients[curClient].logs[curlogfd].priority.priority = NONE;
            debug("priority = %s (no priorities)\n", priority);
         }
      }

      else 
      {
         if (clients[curClient].logs[curlogfd].priority.exclude == 1)
         {
            if (clients[curClient].logs[curlogfd].priority.single == 1)
            {
               clients[curClient].logs[curlogfd].priority.priority = ERROR;
               clients[curClient].logs[curlogfd].priority.ignpri = 
			priNameToVal(priority);
            }
         }

         else
            clients[curClient].logs[curlogfd].priority.priority = 
			priNameToVal(priority);

         debug("priority = %s\n", priority);
      }

      if (isprint(*dataptr) != 0)
         debug("current seperator = '%c'\n", *dataptr);

      else
         debug("current seperator = 0x%x (in hex)\n", *dataptr);

      if (*dataptr == ';')
      {
         errors = 0, dataptr += 1;
         parseFile(dataptr, didfacs, numfacs, facility, priority);

         if (errors == 1)
         {
            errors = 0;
            return;
         }

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

         debug("---before parseSysConf---\n");
         parseSysConf(dataptr);
/*
         if (debugging == 1)
         {
            (void)putchar('\n');
            (void)write(dblogfd, "\n", 1);
         }
*/
         return;
      }
   }
   
   /* -------------- little error checking -------------- */

   if (didfacs == 1)
      while ((isprint(*dataptr) != 0) && (*dataptr != ' ')) dataptr += 1;

   /* get to file name */
   while ((isprint(*dataptr) == 0) || (*dataptr == ' ')) dataptr += 1;

   if (*dataptr == '\0')
   {
      error("error parsing line:\n%s"
            "found an unexpected null..\n\n", str);

      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
      quit(ERROR);
   }

   else if (*dataptr == '\n')
   {
      error("error parsing line:\n%s"
            "found an unexpected newline..\n\n", str);

      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR);
      quit(ERROR);
   }

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

   debug("dataptr = '%c' (1)\n", (*dataptr));
   if (*dataptr == '/')
   {
      char *mvptr = strrchr(dataptr, '/');
      mvptr += 1, dataptr = mvptr; 

      memset(filename, 0, sizeof(filename));
      if (getcwd(filename, (sizeof(filename) / 2) - 1) == NULL)
      {
         error("error with getcwd(): %s\n\n", strerror(errno));
         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR);
         quit(ERROR);
      }

      (void)strcat(filename, "/");
      fnameptr += strlen(filename);

      count = 0;
      while ((*dataptr) && (isprint(*dataptr) != 0) && 
            (count < (((int)sizeof(filename) / 2) - 
                       (int)strlen(filename) - 1)))
      {
         *fnameptr++ = *dataptr++;
         count++;
      }    

      if (didfacs != 1)
         debug("logging %s.%s to: %s\n", facility, priority, filename);

      else
      {
         for (i = curlogfd - numfacs; i <= curlogfd; i++)
         {
            strcpy(facility, 
                   facValToName(clients[curClient].logs[i].facility));

            if (clients[curClient].logs[i].priority.priority == ALL)
               strcpy(priority, "*");

            else if (clients[curClient].logs[i].priority.priority == NONE)
               strcpy(priority, "none");

            else
               strcpy(priority, 
                 priValToName(clients[curClient].logs[i].priority.priority));

            debug("logging %s.%s to: %s\n", facility, priority, filename);
         }
      }

      /* malloc filenames and open fd's */
      if (didfacs != 1)
      {
         clients[curClient].logs[curlogfd].filename = 
			(char *)malloc(strlen(filename)+1);

         if (clients[curClient].logs[curlogfd].filename == NULL)
         {
            error("error with malloc(): %s\n\n", strerror(errno));
            send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
            quit(ERROR);
         }

         memset(clients[curClient].logs[curlogfd].filename, 0, 
                strlen(filename)+1);

         strcpy(clients[curClient].logs[curlogfd].filename, filename);
 
         for (i = 0; i <= curlogfd; i++)
         {
            if ((clients[curClient].logs[i].filename == NULL) || 
                (clients[curClient].logs[i].fd <= 0)) continue;

            if (strcmp(clients[curClient].logs[curlogfd].filename, 
                       clients[curClient].logs[i].filename) == 0)
            {
               clients[curClient].logs[curlogfd].fd = 
			clients[curClient].logs[i].fd;

               break;
            }
         }

         if (clients[curClient].logs[curlogfd].fd <= 0)
         {
            clients[curClient].logs[curlogfd].fd =
		 open(clients[curClient].logs[curlogfd].filename, 
                      O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600);

            if (clients[curClient].logs[curlogfd].fd == ERROR)
            {
               error("error opening %s: %s\n\n", 
                     clients[curClient].logs[curlogfd].filename, 
                     strerror(errno));

               send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
               quit(ERROR);
            }
         }

         if (isatty(clients[curClient].logs[curlogfd].fd) == 1) 
            debug("%s is a tty (device)\n", 
                  clients[curClient].logs[curlogfd].filename);
      }

      /* either a facility or colon was parsed */
      else
      {
         for (i = curlogfd - numfacs; i <= curlogfd; i++)
         {
            clients[curClient].logs[i].filename = 
			(char *)malloc(strlen(filename)+1);

            if (clients[curClient].logs[i].filename == NULL)
            {
               error("error with malloc(): %s\n\n", strerror(errno));
               send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
               quit(ERROR);
            }

            memset(clients[curClient].logs[i].filename, 0, 
                   strlen(filename)+1);

            strcpy(clients[curClient].logs[i].filename, filename);
 
            for (j = 0; j <= curlogfd; j++)
            {
               if ((clients[curClient].logs[j].filename == NULL) || 
                   (clients[curClient].logs[j].fd <= 0)) continue;

               if (strcmp(clients[curClient].logs[i].filename, 
                          clients[curClient].logs[j].filename) == 0)
               {
                  clients[curClient].logs[i].fd = clients[curClient].logs[j].fd;
                  break;
               }
            }

            if (clients[curClient].logs[i].fd <= 0)
            {
               clients[curClient].logs[curlogfd].fd = 
		  open(clients[curClient].logs[i].filename, 
                       O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600);

               if (clients[curClient].logs[curlogfd].fd == ERROR)
               {
                  error("error opening %s: %s\n\n", 
                        clients[curClient].logs[i].filename, strerror(errno));

                  send_data(clients[curClient].sockfd, "ERROR: %s\n", 
                            INTERROR); 
 
                  quit(ERROR);
               }
            }

            if (isatty(clients[curClient].logs[i].fd) == 1) 
               debug("%s is a tty (device)\n", 
                     clients[curClient].logs[i].filename);
         }

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

   /* determine the device, file, or host to log to */
   else if (*dataptr == '@') /* '@' == remote host logging  */
      parseRemHost(str);

   else if (*dataptr == '|') /* '|' == output to named pipe */
      parseNamedPipe(str);

   else if (*dataptr == '*')
   {
      char filename[MAXFNAMESIZE];

      /* 'wall' everyone online... */

      memset(filename, 0, sizeof(filename));
      if (getcwd(filename, (sizeof(filename) - 11)) == NULL)
      {
         error("error with getcwd(): %s\n\n", strerror(errno));
         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
         quit(ERROR);
      }

      strcat(filename, "/wall.log");

      clients[curClient].logs[curlogfd].filename = 
		malloc(strlen(filename) + 1);

      if (clients[curClient].logs[curlogfd].filename == NULL)
      {
         error("error with malloc(): %s\n\n", strerror(errno));
         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
         quit(ERROR);
      }

      memset(clients[curClient].logs[curlogfd].filename, 0, 
             strlen(filename) + 1);

      strcpy(clients[curClient].logs[curlogfd].filename, filename);

      error("wall'ing is not supported at this time..\n"
            "outputting %s.%s to %s instead\n\n", facility, priority, 
            clients[curClient].logs[curlogfd].filename);

      clients[curClient].logs[curlogfd].fd =
		 open(clients[curClient].logs[curlogfd].filename, 
                      O_CREAT | O_WRONLY | O_APPEND, 0600);

      if (clients[curClient].logs[curlogfd].fd == ERROR)
      {
         error("error opening %s: %s\n\n", 
               clients[curClient].logs[curlogfd].filename, strerror(errno));

         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
	
         quit(ERROR);
      }
   }

   /* check if they are users in /etc/passwd.. and if they're online */
   else if (isalpha(*dataptr) != 0)
   {
      int new1 = 1;

      char *userptr;
      char filename[MAXFNAMESIZE];

      /* just some more error checking */
      if (strchr(dataptr, '/') != NULL)
      {
         /* FIX - send err.. follow default behavior */
         error("file names must begin with '/':\n%s\n", str);
         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR); 
         quit(ERROR);
      }

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

      error("logging msgs to users is not supported yet..\n"
            "outputting to the following instead:\n\n");

      while(1)
      {
         if (new1 == 1) new1 = 0;
         else /* we've already been in this loop once before */
         {
            if (curlogfd+1 >= MAXLOGTYPES)
            {
               error("overflowed logs[]\n\n"); 
               send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
               quit(ERROR);
            }

            else 
            {
               copyLogStruct(curlogfd, curlogfd+1);
               curlogfd++;
            }
         }

         memset(filename, 0, sizeof(filename));
         if (getcwd(filename, ((sizeof(filename) / 2) - 11)) == NULL)
         {
            error("error with getcwd(): %s\n\n", strerror(errno));
            send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
            quit(ERROR);
         }

         clients[curClient].logs[curlogfd].filename = 
		(char *)malloc(sizeof(filename) + 1);

         if (clients[curClient].logs[curlogfd].filename == NULL)
         {
            error("error with malloc(): %s\n\n", strerror(errno));
            quit(ERROR);
         }

         memset(clients[curClient].logs[curlogfd].filename, 0,
                sizeof(filename) + 1);

         strcpy(clients[curClient].logs[curlogfd].filename, filename);
         strcat(clients[curClient].logs[curlogfd].filename, "/");

         userptr = clients[curClient].logs[curlogfd].filename + 
                   strlen(clients[curClient].logs[curlogfd].filename);

         /* now parsing the user names.. check for ','s */
         count = 0;
         while ((*dataptr) && (isprint(*dataptr) != 0) &&
                (*dataptr != ',') && (count < MAXUSERNAME))
         {
            *userptr++ = *dataptr++;
            count++;
         }

         strcat(clients[curClient].logs[curlogfd].filename, "-user.log");
         error("%s.%s to %s\n", facility, priority, 
               clients[curClient].logs[curlogfd].filename);

         /* (void)write(errlogfd, "\n", 1); */

         clients[curClient].logs[curlogfd].fd = 
			open(clients[curClient].logs[curlogfd].filename,
                             O_CREAT | O_APPEND | O_WRONLY, 0600);

         if (clients[curClient].logs[curlogfd].fd == ERROR)
         { 
            error("error opening %s: %s\n\n", 
                  clients[curClient].logs[curlogfd].filename);

            send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
            quit(ERROR);
         }

         if (*dataptr == ',') dataptr += 1;
         else break;
      }

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

      (void)write(errlogfd, "\n", 1);
   }

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

   return;
}


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


/* functions to parse specific log types ('@', '|', etc.) */ 

/* parse '@' from syslog.conf */
void parseRemHost(char *str)
{
   register int i;

   int count = 0; /* prevent overflows */

   char *dataptr, *fnameptr;
   char filename[MAXFNAMESIZE];

   dataptr = str, fnameptr = filename;
   memset(filename, 0, sizeof(filename));

   if (getcwd(filename, (sizeof(filename) / 2) - 11) == NULL)
   {
      error("error with getcwd(): %s\n\n", strerror(errno));
      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
      quit(ERROR);
   }

   /* strcpy(filename, "./"); */
   /* fnameptr += 2; */

   strcat(filename, "/");
   fnameptr += strlen(filename);

   dataptr = strchr(str, '@'), dataptr += 1;

   count = 0;
   while ((*dataptr) && (*dataptr != ' ') && 
          (isprint(*dataptr) != 0) && 
          (count < (((int)sizeof(filename) / 2) - (int)strlen(filename) - 1)))
   {
         *fnameptr++ = *dataptr++;
         count++;
   }

   (void)strcat(filename, "-host.log");

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

   error("remote logging ('@') is not supported at this time..\n"
         "outputting to %s instead\n\n", filename);

   if (debugging == 1) (void)write(dblogfd, "\n", 1);

   /* curlogfd++; */

   clients[curClient].logs[curlogfd].filename = 
		(char *)malloc(strlen(filename)+1);

   if (clients[curClient].logs[curlogfd].filename == NULL)
   {
      error("error with malloc(): %s\n\n", strerror(errno));
      quit(ERROR);
   }

   memset(clients[curClient].logs[curlogfd].filename, 0, strlen(filename)+1);
   strcpy(clients[curClient].logs[curlogfd].filename, filename);
 
   for (i = 0; i <= curlogfd; i++)
   {
      if ((clients[curClient].logs[i].filename == NULL) || 
          (clients[curClient].logs[i].fd <= 0)) continue;

      if (strcmp(clients[curClient].logs[curlogfd].filename, 
                 clients[curClient].logs[i].filename) == 0)
      {
         clients[curClient].logs[curlogfd].fd = clients[curClient].logs[i].fd;
         break;
      }
   }

   if (clients[curClient].logs[curlogfd].fd <= 0)
   {
      clients[curClient].logs[curlogfd].fd = 
		open(clients[curClient].logs[curlogfd].filename, 
                     O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600);

      if (clients[curClient].logs[curlogfd].fd == ERROR)
      {
         error("error opening %s: %s\n\n", 
               clients[curClient].logs[curlogfd].filename, strerror(errno));

         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
         quit(ERROR);
      }
   }

   return;
}


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


/* parse '|' from syslog.conf */
void parseNamedPipe(char *str)
{
   register int i;

   int count = 0; /* prevent overflows */

   char filename[MAXFNAMESIZE];
   char *dataptr, *fnameptr;

   fnameptr = filename;
   memset(filename, 0, sizeof(filename));

   dataptr = strrchr(str, '/');

   if (dataptr != NULL) dataptr += 1;
   else
   {
      error("error parsing:\n%s"
            "filenames must begin with '/'\n\n", str);

      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
      quit(ERROR);
   }

   if (getcwd(filename, (sizeof(filename) / 2) - 11) == NULL)
   {
      error("error with getcwd(): %s\n\n", strerror(errno));
      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR);
      quit(ERROR);
   }

   (void)strcat(filename, "/");
   fnameptr += strlen(filename);

   count = 0;
   while ((*dataptr) && (isprint(*dataptr) != 0) && 
          (count < (((int)sizeof(filename) / 2) - (int)strlen(filename) - 1)))
   {
      *fnameptr++ = *dataptr++;
      count++;
   }    

   (void)strcat(filename, "-pipe.log");

   if (debugging == 1) (void)write(dblogfd, "\n", 1);
   error("named pipes ('|') aren't supported at this time..\n"
         "outputting to %s instead\n\n", filename);

   /* open the parsed file */
   /* -------------------- */
   clients[curClient].logs[curlogfd].filename = 
		(char *)malloc(strlen(filename)+1);

   if (clients[curClient].logs[curlogfd].filename == NULL)
   {
      error("error with malloc(): %s\n\n", strerror(errno));
      quit(ERROR);
   }

   memset(clients[curClient].logs[curlogfd].filename, 0, strlen(filename)+1);
   strcpy(clients[curClient].logs[curlogfd].filename, filename);

   for (i = 0; i <= curlogfd; i++)
   {
      if ((clients[curClient].logs[i].filename == NULL) || 
          (clients[curClient].logs[i].fd <= 0)) continue;

      else if (strcmp(clients[curClient].logs[curlogfd].filename, 
                      clients[curClient].logs[i].filename) == 0)
      {
         clients[curClient].logs[curlogfd].fd = clients[curClient].logs[i].fd;
         break;
      }
   }

   if (clients[curClient].logs[curlogfd].fd <= 0)
   {
      clients[curClient].logs[curlogfd].fd =
		open(clients[curClient].logs[curlogfd].filename, 
                     O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600);

      if (clients[curClient].logs[curlogfd].fd == ERROR)
      {
         error("error opening %s: %s\n\n", 
               clients[curClient].logs[curlogfd].filename, strerror(errno));

         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
         quit(ERROR);
      }
   }

   return;
}


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


/* parse next facility.. called when there are multi-facilities */
int parseFac(char *str, int numfacs)
{
   int count;

   char *facptr;
   char *dataptr = str;

   char facility[16];

   facptr = facility;
   memset(facility, 0, sizeof(facility));

   /* do manual parsing */
   count = 0;

   while ((*dataptr) && (*dataptr != ' ') &&
          (*dataptr != '.') && (*dataptr != ',') && 
          (*dataptr != ';') && (isprint(*dataptr) != 0) && 
          (count < (int)sizeof(facility)-1))
   {
      *facptr++ = *dataptr++;
      count++;
   }

   if (isprint(*dataptr) != 0)
      debug("current seperator = %c\n", *dataptr);

   else
      debug("current seperator = 0x%x (in hex)\n", *dataptr);

   clients[curClient].logs[curlogfd].facility = facNameToVal(facility);
   if (clients[curClient].logs[curlogfd].facility == ERROR)
   {
      error("(in parseSysConf) error parsing line:\n%s"
            "unknown facility type..\n\n");

      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
      quit(ERROR);
   }

   debug("(in parseFac) curlogfd = %d, facility = %s (in str = %s)\n",
         numfacs, facility, 
         facValToName(clients[curClient].logs[curlogfd].facility));

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

   parsePri(str);

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

   numfacs++;

   if (*dataptr == ',') 
   {
      dataptr += 1;

      curlogfd++;
      if (curlogfd >= MAXLOGTYPES)
      {
         error("error parsing /etc/syslog.conf.. overflowed logs[]\n\n");
         send_data(clients[curClient].sockfd, "ERROR: %s\n", LOGOFERROR); 
         quit(ERROR);
      }

      numfacs = parseFac(dataptr, numfacs);
   }

   return numfacs;
}


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


/* parse the priority */
void parsePri(char *str)
{
   int count = 0;

   char priority[16];
   char *priptr, *dataptr;

   dataptr = strchr(str, '.');
   if (dataptr == NULL)
   {
      error("(in sysLogConf) unable to parse:\n%s\n", str);
      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
      quit(ERROR);
   }

   dataptr += 1; /* skip '.' */

   /* can be "*.!=*" or "*.=*" */
   if (*dataptr == '!') 
   {
      /* check for possible bugs */
      if ((*(dataptr + 1)) == '*')
      {
         error("error parsing line (no '*' allowed after '!'):\n"
               "%s\n", str);

         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
         quit(ERROR);
      }

      debug("exclude ('!') on\n");
      clients[curClient].logs[curlogfd].priority.exclude = 1;
   }

   if ((*dataptr == '=') || ((*(dataptr+1)) == '=')) 
   {
      /* check for possible bugs */
      if (((*(dataptr + 1)) == '*') || ((*(dataptr + 2)) == '*'))
      {
         error("error parsing line (no '*' allowed after '='):\n"
               "\n%s", str);

         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
         quit(ERROR);
      }

      debug("single ('!') on\n");
      clients[curClient].logs[curlogfd].priority.single = 1;
   }

   /* skip to next valid data to parse */
   if (clients[curClient].logs[curlogfd].priority.single == 1) dataptr += 1;
   if (clients[curClient].logs[curlogfd].priority.exclude == 1) dataptr += 1;
         
   priptr = priority;
   memset(priority, 0, sizeof(priority));
      
   count = 0;
   while ((*dataptr) && (*dataptr != ' ') &&
          (*dataptr != ';') && (isprint(*dataptr) != 0) && 
          (count < (int)sizeof(priority)-1))
   {
      *priptr++ = *dataptr++;
      count++;
   }


   if (strchr(priority, '*') != NULL)
   {
      if (clients[curClient].logs[curlogfd].priority.exclude == 1)
      {
         (void)strcpy(priority, "none");
         clients[curClient].logs[curlogfd].priority.priority = NONE;
         debug("priority = %s (no priorities)\n", priority);
      }

      else
      {
         clients[curClient].logs[curlogfd].priority.priority = ALL;
         debug("priority = %s (all priorities)\n", priority);
      }
   }

   else if (strncmp(priority, "none", 4) == 0)
   {
      if (clients[curClient].logs[curlogfd].priority.exclude == 1)
      {
         /* !none == ALL.. double negatives.. */

         (void)strcpy(priority, "all");
         clients[curClient].logs[curlogfd].priority.priority = ALL;
         debug("priority = !none (all priorities)\n");
      }

      else
      {
         (void)strcpy(priority, "none");
         clients[curClient].logs[curlogfd].priority.priority = NONE;
         debug("priority = %s (no priorities)\n", priority);
      }
   }

   else 
   {
      if (clients[curClient].logs[curlogfd].priority.exclude == 1)
      {
         if (clients[curClient].logs[curlogfd].priority.single == 1)
         {
            clients[curClient].logs[curlogfd].priority.ignpri = 
			priNameToVal(priority);

            if (clients[curClient].logs[curlogfd].priority.ignpri == ERROR)
            {
               error("(in parseSysConf) error parsing line:\n%s"
                     "unknown priority..\n\n", str);

               send_data(clients[curClient].sockfd, "ERROR: %s\n",
                         INTPARERROR);

               quit(ERROR);
            }

            clients[curClient].logs[curlogfd].priority.priority = ERROR;
         }
      }    
     
      clients[curClient].logs[curlogfd].priority.priority = 
			priNameToVal(priority);

      debug("priority = %s\n", priority);
   }


   if (isprint(*dataptr) != 0)
      debug("current seperator = '%c'\n", *dataptr);

   else
      debug("current seperator = 0x%x (in hex)\n", *dataptr);
}


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


/* parse the file name and things */
void parseFile(char *str, int didfacs, int numfacs, char *fac, char *pri)
{
   int count;
   register int i, j;

   char *fnameptr;
   char *dataptr = str;

   char filename[MAXFNAMESIZE];
   char facility[16], priority[16];

   fnameptr = filename;

   memset(facility, 0, sizeof(facility));
   memset(priority, 0, sizeof(priority));
   memset(filename, 0, sizeof(filename));

   (void)strcpy(facility, fac), (void)strcpy(priority, pri);

   /* -------------- little error checking -------------- */

   while ((isprint(*dataptr) != 0) && (*dataptr != ' ')) dataptr += 1;
   while ((isprint(*dataptr) == 0) || (*dataptr == ' ')) dataptr += 1;

   if (*dataptr == '\0')
   {
      error("error parsing line:\n%sfound an unexpected null..\n",
            str);

      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
      quit(ERROR);
   }

   else if (*dataptr == '\n')
   {
      error("error parsing line:\n%s"
            "found an unexpected newline..\n", str);

      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR);
      quit(ERROR);
   }

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

   debug("dataptr = '%c' (2)\n", (*dataptr));
   if (*dataptr == '/')
   {
      char *mvptr = strrchr(dataptr, '/');
      mvptr += 1, dataptr = mvptr;
      
      memset(filename, 0, sizeof(filename));
      if (getcwd(filename, (sizeof(filename) / 2) - 1) == NULL)
      {
         error("error with getcwd(): %s\n\n", strerror(errno));
         send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR);
         quit(ERROR);
      }

      (void)strcat(filename, "/");
      fnameptr += strlen(filename);

      count = 0;
      while ((*dataptr) && (isprint(*dataptr) != 0) && 
            (count < (((int)sizeof(filename) / 2) - 
                       (int)strlen(filename) - 1)))
      {
         *fnameptr++ = *dataptr++;
         count++;
      }    

      if (didfacs != 1)
         debug("logging %s.%s to: %s\n", facility, priority, filename);

      else
      {
         for (i = curlogfd - numfacs; i <= curlogfd; i++)
         {
            strcpy(facility, 
                   facValToName(clients[curClient].logs[i].facility));

            if (clients[curClient].logs[i].priority.priority == ALL)
               strcpy(priority, "*");


            else if (clients[curClient].logs[i].priority.priority == NONE)
               strcpy(priority, "none");

            else
               strcpy(priority, 
                  priValToName(clients[curClient].logs[i].priority.priority));

            debug("logging %s.%s to: %s\n", facility, priority, filename);
         }
      }

      /* malloc filenames and open fd's */
      if (didfacs != 1)
      {
         clients[curClient].logs[curlogfd].filename = 
			(char *)malloc(strlen(filename)+1);

         if (clients[curClient].logs[curlogfd].filename == NULL)
         {
            error("error with malloc(): %s\n\n", strerror(errno));
            quit(ERROR);
         }

         memset(clients[curClient].logs[curlogfd].filename, 0, 
                strlen(filename)+1);

         strcpy(clients[curClient].logs[curlogfd].filename, filename);
 
         for (i = 0; i <= curlogfd; i++)
         {
            if ((clients[curClient].logs[i].filename == NULL) || 
                (clients[curClient].logs[i].fd <= 0)) continue;

            else if (strcmp(clients[curClient].logs[curlogfd].filename,
                            clients[curClient].logs[i].filename) == 0)
            {
               clients[curClient].logs[curlogfd].fd = clients[curClient].logs[i].fd;
               break;
            }
         }

         if (clients[curClient].logs[curlogfd].fd <= 0)
         {
            clients[curClient].logs[curlogfd].fd = 
		open(clients[curClient].logs[curlogfd].filename, 
                     O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600);

            if (clients[curClient].logs[curlogfd].fd == ERROR)
            {
               error("error opening %s: %s\n\n", 
                     clients[curClient].logs[curlogfd].filename, 
                     strerror(errno));

               send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR); 
               quit(ERROR);
            }
         }

         if (isatty(clients[curClient].logs[curlogfd].fd) == 1) 
            debug("%s is a tty (device)\n", 
                  clients[curClient].logs[curlogfd].filename);
      }

      /* either a facility or colon was parsed */
      else
      {
         for (i = curlogfd - numfacs; i <= curlogfd; i++)
         {
            clients[curClient].logs[i].filename = 
			(char *)malloc(strlen(filename)+1);

            if (clients[curClient].logs[i].filename == NULL)
            {
               error("error with malloc(): %s\n\n", strerror(errno));
               quit(ERROR);
            }

            memset(clients[curClient].logs[i].filename, 0, 
                   strlen(filename)+1);

            strcpy(clients[curClient].logs[i].filename, filename);
 
            for (j = 0; j <= curlogfd; j++)
            {
               if ((clients[curClient].logs[j].filename == NULL) || 
                   (clients[curClient].logs[j].fd <= 0)) continue;

               if (strcmp(clients[curClient].logs[i].filename, 
                          clients[curClient].logs[j].filename) == 0)
               {
                  clients[curClient].logs[i].fd = clients[curClient].logs[j].fd;
                  break;
               }
            }

            if (clients[curClient].logs[i].fd <= 0)
            {
               clients[curClient].logs[curlogfd].fd = 
		  open(clients[curClient].logs[i].filename, 
                       O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600);

               if (clients[curClient].logs[curlogfd].fd == ERROR)
               {
                  error("error opening %s: %s\n\n", 
                        clients[curClient].logs[i].filename, strerror(errno));

                  send_data(clients[curClient].sockfd, "ERROR: %s\n", 
                            INTERROR); 

                  quit(ERROR);
               }
            }

            if (isatty(clients[curClient].logs[i].fd) == 1) 
               debug("%s is a tty (device)\n", 
                     clients[curClient].logs[i].filename);
         }
      }
   }

   /* determine the device, file, or host to log to */
   else if (*dataptr == '@') /* '@' == remote host logging  */
      parseRemHost(str);

   else if (*dataptr == '|') /* '|' == output to named pipe */
      parseNamedPipe(str);

   else if (*dataptr == '*')
   {
      char filename[MAXFNAMESIZE];

      /* 'wall' everyone online... */

      memset(filename, 0, sizeof(filename));
      if (getcwd(filename, (sizeof(filename) - 11)) == NULL)
      {
         error("error with getcwd(): %s\n\n", strerror(errno));
         quit(ERROR);
      }

      strcat(filename, "/wall.log");

      clients[curClient].logs[curlogfd].filename = 
		malloc(strlen(filename) + 1);

      if (clients[curClient].logs[curlogfd].filename == NULL)
      {
         error("error with malloc(): %s\n\n", strerror(errno));
         quit(ERROR);
      }

      memset(clients[curClient].logs[curlogfd].filename, 0, 
             strlen(filename) + 1);

      strcpy(clients[curClient].logs[curlogfd].filename, filename);

      error("wall'ing is not supported at this time..\n"
            "outputting %s.%s to %s instead\n\n", facility, priority, 
            clients[curClient].logs[curlogfd].filename);

      clients[curClient].logs[curlogfd].fd =
		 open(clients[curClient].logs[curlogfd].filename, 
                      O_CREAT | O_WRONLY | O_APPEND, 0600);

      if (clients[curClient].logs[curlogfd].fd == ERROR)
      {
         error("error opening %s: %s\n\n", 
               clients[curClient].logs[curlogfd].filename, strerror(errno));

         quit(ERROR);
      }
   }

   /* check if they are users in /etc/passwd.. and if they're online */
   else if (isalpha(*dataptr) != 0)
   {
      int new1 = 1;

      char *userptr;
      char filename[MAXFNAMESIZE];

      /* just some more error checking */
      if (strchr(dataptr, '/') != NULL)
      {
         error("file names must begin with '/':\n%s\n", str);
         quit(ERROR);
      }

      error("logging msgs to users is not supported yet.."
            "outputting to the following instead:\n\n");

      while(1)
      {
         if (new1 == 1) new1 = 0;
         else /* we've already been in this loop once before */
         {
            if (curlogfd+1 >= MAXLOGTYPES)
            {
               error("overflowed logs[]\n\n"); 
               quit(ERROR);
            }

            else 
            {
               copyLogStruct(curlogfd, curlogfd+1);
               curlogfd++;
            }
         }

         memset(filename, 0, sizeof(filename));
         if (getcwd(filename, ((sizeof(filename) / 2) - 11)) == NULL)
         {
            error("error with getcwd(): %s\n\n", strerror(errno));
            quit(ERROR);
         }

         clients[curClient].logs[curlogfd].filename = 
		(char *)malloc(sizeof(filename) + 1);

         if (clients[curClient].logs[curlogfd].filename == NULL)
         {
            error("error with malloc(): %s\n\n", strerror(errno));
            quit(ERROR);
         }

         memset(clients[curClient].logs[curlogfd].filename, 0,
                sizeof(filename) + 1);

         strcpy(clients[curClient].logs[curlogfd].filename, filename);
         strcat(clients[curClient].logs[curlogfd].filename, "/");

         userptr = clients[curClient].logs[curlogfd].filename + 
                   strlen(clients[curClient].logs[curlogfd].filename);

         /* now parsing the user names.. check for ','s */
         count = 0;
         while ((*dataptr) && (isprint(*dataptr) != 0) &&
                (*dataptr != ',') && (count < MAXUSERNAME))
         {
            *userptr++ = *dataptr++;
            count++;
         }

         strcat(clients[curClient].logs[curlogfd].filename, "-user.log");
         error("%s.%s to %s\n\n", facility, priority, 
               clients[curClient].logs[curlogfd].filename);

         clients[curClient].logs[curlogfd].fd = 
			open(clients[curClient].logs[curlogfd].filename,
                             O_CREAT | O_APPEND | O_WRONLY, 0600);

         if (clients[curClient].logs[curlogfd].fd == ERROR)
         { 
            error("error opening %s: %s\n\n", 
                  clients[curClient].logs[curlogfd].filename);

            quit(ERROR);
         }

         if (*dataptr == ',') dataptr += 1;
         else break;
      }

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

      (void)write(errlogfd, "\n", 1);
   }

   return;
}


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


/* parse priority/facility of log message client */
void doLogging(char *str)
{
   register int i, j;

   int res;
   int count = 0;

   int restart;
   int fds[MAXLOGTYPES];

   int glued = 0; /* part of a glued message */

   int data; /* the priority/facility OR'd together  */
   int fac, pri; /* facility and priority of the message */

   int dup;

   char pristr[16]; /* priority as a string */

   char writebuf[MAXWRITESIZE];

   char gluebuf[MAXWRITESIZE];
   char dupstrs[MAXLOGTYPES][MAXFNAMESIZE];

   char *priptr, *dataptr, *markptr, *writeptr;

   memset(pristr, 0, sizeof(pristr));
   memset(writebuf, 0, sizeof(writebuf));

   priptr = pristr, writeptr = writebuf;
   dataptr = str;

   if (*dataptr != '<')
   {
      debug("incoming data did not have a \"<>\"\n");

      markptr = strchr(str, '!');
      if (markptr != NULL)
      {
        debug("incoming data is a marker ('!')\n");

        markptr += 1;
        for (i = 0; i < MAXLOGTYPES; i++)
        {
           if (clients[curClient].logs[i].filename != NULL)
           {
              dup = 0;

              for (j = 0; j < MAXLOGTYPES; j++)
                 if (strncmp(dupstrs[j], clients[curClient].logs[i].filename,
                             strlen(dupstrs[j])) == 0) dup = 1;

              if (dup != 1)
              {
                 debug("[%s] %s\n", clients[curClient].logs[i].filename,
                       markptr);

                 memset(gluebuf, 0, sizeof(gluebuf));
                 snprintf(gluebuf, sizeof(gluebuf)-1, "%s\n", markptr);

                 res = write(clients[curClient].logs[i].fd, gluebuf,
                             strlen(gluebuf));

                 if (res == ERROR)
                 {
                    error("error writing to %s: %s\n",
                          clients[curClient].logs[i].filename,
                          strerror(errno));

                    quit(ERROR);
                 }

                 snprintf(dupstrs[i], MAXFNAMESIZE,
                          clients[curClient].logs[i].filename);
            } 
          }
        }

        /* since we got an END marker, we need to sleep for 5 seconds */

        if (strstr(markptr, "END") != NULL)
        {
          debug("now sleeping, allowing our cron jobs to catchup."), 
          sleep (MAXPAUSE);
        }

        return;
      }

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

         /* it is probably the next part of a truncated log */
         debug("received next part of log\n");
         glued = 1, data = prevmsg;
      
         goto Domsg;
      }
   }

   dataptr += 1; /* skip "<" */

   while (isdigit(*dataptr) != 0)
      *priptr++ = *dataptr++;

   if (*dataptr != '>')
   {
      error("error parsing message ('>' was expected):\n%s\n", str);
      send_data(clients[curClient].sockfd, "ERROR: %s\n", INTPARERROR);
      quit(ERROR);
   }

   data = atoi(pristr);
   dataptr += 1; /* skip ">" */

Domsg:
   count = 0;
   while ((*dataptr) && (count < (int)sizeof(writebuf)))
   {
      *writeptr++ = *dataptr++;
      count++;
   }
   
   if (glued != 1)
   {
      if ((data <= 0) || (data >= (LOG_NFACILITIES << 3)))
         data = DEFUPRI;

      else if (data &~ (LOG_FACMASK | LOG_PRIMASK))
        data = DEFUPRI;

      if (LOG_PRI(data) == LOG_KERN)
         data |= LOG_USER;

      prevmsg = data;
   }

   fac = LOG_FAC(data), pri = LOG_PRI(data);

   if (glued != 1)
   {
     debug("facility = %d, priority = %d\n", fac, pri);
     debug("facility = %s, priority = %s\n\n", facValToName(fac),
           priValToName(pri));
   }

   for (i = 0; i <= curlogfd; i++)
   {
      if ((clients[curClient].logs[i].fd <= 0) || 
          (clients[curClient].logs[i].filename == NULL)) break;

      else if ((clients[curClient].logs[i].facility == ALL) || 
               (clients[curClient].logs[i].facility == (fac << 3)) || 
               (fac == LOG_DAEMON))
      {
         if (clients[curClient].logs[i].priority.priority == NONE) continue;
         else if (clients[curClient].logs[i].priority.priority == ALL)
         {
            for (j = 0; j < MAXLOGTYPES; j++)
            {
                if (fds[j] <= 0) continue;
                else if (fds[j] == clients[curClient].logs[i].fd)
                {
                   restart = 1; 
                   break;
                }
            }

            if (restart == 1)
            {
               restart = 0;
               continue;
            }

            else
            {
               for (j = 0; j < MAXLOGTYPES; j++)
                  if (fds[j] <= 0) 
                  {
                     fds[j] = clients[curClient].logs[i].fd;
                     break;
                  }
            }

            debug("writing the following to %s:\n%s\n",
                  clients[curClient].logs[i].filename, writebuf);

            res = write(clients[curClient].logs[i].fd, writebuf, 
                        strlen(writebuf));

            if ((res == 0) || ((res == ERROR) && (errno > 0)))
            {
               error("error writing to %s: %s\n\n", 
                     clients[curClient].logs[i].filename, strerror(errno));

               if (res == ERROR)
               {
                  send_data(clients[curClient].sockfd, "ERROR: %s\n", INTERROR);
                  quit(ERROR); 
               }
            }
 
            if (strchr(writebuf, '\n') == NULL) 
               (void)write(clients[curClient].logs[i].fd, "\n", 1);

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

         else if (clients[curClient].logs[i].priority.priority <= pri) 
         {

            if (clients[curClient].logs[i].priority.exclude == 1) 
               if (clients[curClient].logs[i].priority.ignpri <= pri) 
               {
                  if (clients[curClient].logs[i].priority.single != 1) 
                     continue;

                  else if (clients[curClient].logs[i].priority.ignpri == pri) 
                     continue;
               }

            if (clients[curClient].logs[i].priority.single == 1)
               if (clients[curClient].logs[i].priority.priority != pri) 
                  continue;

            for (j = 0; j < MAXLOGTYPES; j++)
            {
                if (fds[j] <= 0) continue;
                else if (fds[j] == clients[curClient].logs[i].fd)
                {
                   restart = 1; 
                   break;
                }
            }

            if (restart == 1)
            {
               restart = 0;
               continue;
            }

            else
            {
               for (j = 0; j < MAXLOGTYPES; j++)
                  if (fds[j] <= 0) 
                  {
                     fds[j] = clients[curClient].logs[i].fd;
                     break;
                  }
            }

            debug("writing the following to %s:\n%s\n",
                  clients[curClient].logs[i].filename, writebuf);

            res = write(clients[curClient].logs[i].fd, writebuf, 
                        strlen(writebuf));

            if ((res == 0) || ((res == ERROR) && (errno > 0)))
            {
               error("error writing to %s: %s\n\n", 
                     clients[curClient].logs[i].filename, strerror(errno));

               if (res == ERROR)
               {
                  send_data(clients[curClient].sockfd, "ERROR: %s\n", 
                            INTERROR);

                  quit(ERROR); 
               }
            }

            if (strchr(writebuf, '\n') == NULL) 
               (void)write(clients[curClient].logs[i].fd, "\n", 1);

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

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