DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T c

⟦fe1ee8bd3⟧ TextFile

    Length: 28919 (0x70f7)
    Types: TextFile
    Names: »config.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦f1ce22008⟧ »EurOpenD3/news/newsxd2.5.0.tar.Z« 
        └─⟦caa165e81⟧ 
            └─⟦this⟧ »config.c« 

TextFile

/*
 * #include <legal/bs.h>
 >
 > Copyright (c) 1989 Washington University in Saint Louis, Missouri and
 > Chris Myers. All rights reserved.
 >
 > Permission is hereby granted to copy, reproduce, redistribute or
 > otherwise use this software as long as: (1) there is no monetary
 > profit gained specifically from the use or reproduction of this
 > software, (2) it is not sold, rented, traded, or otherwise marketed,
 > (3) the above copyright notice and this paragraph is included
 > prominently in any copy made, and (4) that the name of the University
 > is not used to endorse or promote products derived from this software
 > without the specific prior written permission of the University.
 > THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 > IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 > WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 >
 */

#include "defs.h"

/*************************************************************************/
/* FUNCTION  : getclass                                                  */
/* PURPOSE   : Return a pointer to the class structure given the name of */
/*             a class                                                   */
/* ARGUMENTS : The name of a class                                       */
/*************************************************************************/

struct class *
getclass(classname)
   char *classname;

{
struct  class   *classptr;

   if (strlen(classname) > MAXCLASSNAMELEN - 1) {
      Dprintf("(getclass): classname %s is too long, no match\n", classname);
      return((struct class *) NULL);
   }

   foreach (classptr, classlist) {
      Dprintf("(getclass): now checking class %s\n", classptr->classname);
      if (strcmp(classname, classptr->classname) == 0) break;
   }

   return(classptr);

}

/*************************************************************************/
/* FUNCTION  : addclass                                                  */
/* PURPOSE   : Add a class to or modify a class in the class list        */
/* ARGUMENTS : All the information needed to define a class...           */
/*************************************************************************/

void
addclass(classname,maxxmits,interval,startint,maxload,ttl,ttlpenalty,nice,flags)
   char *classname;
   int  maxxmits, interval, startint, maxload, ttl, ttlpenalty, nice, flags;

{
struct  class   *classptr = classlist;
int     loop,
        newclass = 0;

   if (strlen(classname) > MAXCLASSNAMELEN - 1) {
      logerr("(addclass) Class name %s too long, max %d - ignoring\n",
         classname, MAXCLASSNAMELEN - 1);
      return;
   }

   if ((classptr = getclass(classname)) == NULL) {
      Dprintf("(addclass): CALLOCing new class structure\n");
      classptr = (struct class *) calloc(1, sizeof(struct class));
      if (classptr == NULL) {
         logerr("(addclass) Can't calloc struct class for class %s\n",
            classname);
         return;
      }
      for (loop = 0; loop < MAXCLASSXMITTERS; loop++)
         classptr->slots[loop] = '.';
      newclass++;
   } else if (classptr->valid == 1) {
      logerr("(addclass) Duplicated class %s\n", classname);
      return;
   }

   /*
    * Build class structure for this class and insert at the head of the
    * class list
    */

   (void) strcpy(classptr->classname, classname);
   classptr->maxxmits = maxxmits;
   classptr->options.maxload = maxload;
   classptr->options.interval = interval;
   classptr->options.startint = startint;
   classptr->options.ttl = ttl;
   classptr->options.deltanice = nice;
   classptr->options.ttlpenalty = ttlpenalty;
   classptr->valid = 1;
   classptr->xmitsernum = 0;
   classptr->members = 0;

   /*
    * Set all of the class flags.  flag is a bitmap.
    */

   for (loop = 0; loop < MAXCLASSFLAGS; loop++) {
      if (flags & (1 << loop))
         classptr->flags[loop] = 1;
      else
         classptr->flags[loop] = 0;
      Dprintf("(addclass): flags[%d] = %d\n", loop,
         classptr->flags[loop]);
   }

   /*
    * Check to see if we are just overwriting a class description, if so don't
    * wipe the pointer to the next entry in the list.
    */

   if (newclass) {
      classptr->next = classlist;
      classlist = classptr;
   }

   Dprintf("(addclass): classlist = %d\n", classlist);
}

/*************************************************************************/
/* FUNCTION  : addhost                                                   */
/* PURPOSE   : Add a host to the list of hosts to transmit to            */
/* ARGUMENTS : Name of the host, class name, start and stop times        */
/*************************************************************************/

void
addhost(hostname, classname, times, deltanice, maxload, interval, startint,
	ttl, ttlpenalty, flags)

   char *hostname, *classname, *times, *flags;
   int  deltanice, maxload, interval, startint, ttl, ttlpenalty;

{
struct  host    *hostptr,
                *loopptr,
                *lastptr = NULL;
struct  class   *classptr;
int     loop;
char    *flagbuf;

   if (strlen(hostname) > MAXHOSTNAMELEN - 1) {
      logerr("(addhost) Host name %s too long, max %d - ignoring\n",
         classname, MAXHOSTNAMELEN - 1);
      return;
   }

   if (strlen(times) > MAXTIMENAMELEN - 1) {
      logerr("(addhost) Host time %s too long, max %d - ignoring\n",
         classname, MAXTIMENAMELEN - 1);
      return;
   }

   if ((classptr = getclass(classname)) == NULL) {
      logerr("(addhost) Host's (%s) class %s doesn't exist - ignoring host\n",
         hostname, classname);
      return;
   }

   if (classptr->valid == 0) {
      logerr("(addhost) Host's (%s) class %s is invalid - ignoring host\n",
         hostname, classname);
      return;
   }

   if (strcmp(classname, "DEFAULT") == 0) {
      logerr("(addhost) Host (%s) can't be a member of class DEFAULT\n",
         hostname);
      return;
   }

   lastptr = NULL;
   foreach (hostptr, hostlist) {
      Dprintf("(addhost): now checking host %s\n", hostptr->hostname);
      if (strcmp(hostname, hostptr->hostname) == 0) break;
      lastptr = hostptr;
   }

   if (hostptr != NULL) {
      if (hostptr->valid == 1) {
         logerr("(addhost) Duplicated host %s\n", hostname);
         return;
      }
      if (lastptr != NULL) {
         lastptr->next = hostptr->next;
         Dprintf("(addhost) host %s next was %s, now %s\n", lastptr->hostname,
            hostptr->hostname, hostptr->next ? hostptr->next->hostname : NULL);
      } else
         hostlist = hostptr->next;
   } else {
      Dprintf("(addhost): CALLOCing new host structure\n");
      hostptr = (struct host *) calloc(1, sizeof(struct host));
      if (hostptr == NULL) {
         logerr("(addhost) Can't calloc struct host for host %s\n",
            hostname);
         return;
      }
   }

   (void) strcpy(hostptr->hostname, hostname);
   (void) strcpy(hostptr->class, classname);
   (void) strcpy(hostptr->times, times);
   hostptr->valid = 1;
   hostptr->options.deltanice = deltanice;
   hostptr->options.maxload = maxload;
   hostptr->options.interval = interval;
   hostptr->options.startint = startint;
   hostptr->options.ttl = ttl;
   hostptr->options.ttlpenalty = ttlpenalty;
   hostptr->xmitsernum = 0;
   hostptr->xargc = 0;
   classptr->members++;

   if (strlen(flags) > 0) {
      if ((flagbuf = (char *) calloc(1, strlen(flags) + 1)) != NULL) {
         (void) strcpy(flagbuf, flags);
         while (1) {
            hostptr->xargv[hostptr->xargc++] = flagbuf;
            if ((flagbuf = STRCHR(flagbuf, '|')) == (char *) NULL) break;
            *flagbuf++ = '\0';
         }
      }
   }

   for (loop = 0; loop < hostptr->xargc; loop++)
      Dprintf("host %s: flag[%d] = %s\n", hostname, loop, hostptr->xargv[loop]);

   /*
    * If this is a new host, do a two-key insertion sort based on the
    * hostname and name of the transmission class.  Makes things look nice
    * in the status display...
    */

   lastptr = NULL;

   if (hostlist == NULL) {
      Dprintf("(addhost): %s IS hostlist now\n", hostname);
      hostlist = hostptr;
   } else {
      foreach (loopptr, hostlist) {
         if (((strcmp(hostptr->hostname, loopptr->hostname) < 0) &
             (strcmp(hostptr->class, loopptr->class) == 0)) | 
             (strcmp(hostptr->class, loopptr->class) < 0)) {
            Dprintf("(addhost): Inserting %s before %s\n", hostname,
               loopptr->hostname);
            hostptr->next = loopptr;
            if (lastptr != NULL) lastptr->next = hostptr;
            if (loopptr == hostlist) hostlist = hostptr;
            break;
         }
         lastptr = loopptr;
      }
      if (loopptr == NULL) {
         Dprintf("(addhost): appending host %s to hostlist\n", hostname);
         lastptr->next = hostptr; /* append to current host list */
         hostptr->next = NULL;
      }
   }
   Dprintf("(addhost): hostlist = %d\n", hostlist);
}

/*************************************************************************/
/* FUNCTION  : make_invalid                                              */
/* PURPOSE   : Mark all hosts and classes as invalid                     */
/* ARGUMENTS : none                                                      */
/*************************************************************************/

void
make_invalid()

{
struct  class   *classptr,
                *nextclass;
struct  host    *hostptr,
                *nexthost;

   dprintf("(make_invalid) marking all classes as invalid\n");
   for (classptr = classlist; classptr != NULL; classptr = nextclass) {
      Dprintf("(make_invalid) marking class %s as invalid\n",
         classptr->classname);
      classptr->valid = 0;
      classptr->members = 0;
      nextclass = classptr->next;
   }

   dprintf("(make_invalid) marking all hosts as invalid\n");
   for (hostptr = hostlist; hostptr != NULL; hostptr = nexthost) {
      Dprintf("(make_invalid) marking host %s as invalid\n", hostptr->hostname);
      hostptr->valid = 0;
      nexthost = hostptr->next;
   }

}

/*************************************************************************/
/* FUNCTION  : clear_invalid                                             */
/* PURPOSE   : Remove all hosts and classes which are not valid anymore  */
/* ARGUMENTS : none                                                      */
/*************************************************************************/

void
clear_invalid()

{
struct  class   *lastclass = NULL,
                *classptr,
                *nextclass;
struct  host    *lasthost = NULL,
                *hostptr,
                *nexthost;
int     loop;

   dprintf("(clear_invalid) clearing all invalid hosts\n");
   for (hostptr = hostlist; hostptr != NULL; hostptr = nexthost) {
      nexthost = hostptr->next;
      if (hostptr->valid == 0) {
         if (hostptr->pid > 0) {
            dprintf("(clear_invalid): killing transmitter for host %s\n",
               hostptr->hostname);
            if (kill(hostptr->pid, SIGTERM) != 0) xmit_done(-hostptr->pid);
         }
         Dprintf("(clear_invalid): clearing host %s\n", hostptr->hostname);
         (void) free(hostptr);
         if (hostlist == hostptr) hostlist = nexthost;
         if (lasthost) lasthost->next = nexthost;
      } else {
         lasthost = hostptr;
      }
   }

   dprintf("(clear_invalid) clearing all invalid classes\n");
   for (classptr = classlist; classptr != NULL; classptr = nextclass) {
      nextclass = classptr->next;
      if (classptr->valid == 0) {
         Dprintf("(clear_invalid): clearing class %s\n", classptr->classname);
         for (loop = 0; loop < classptr->xargc; loop++) {
            Dprintf("(clear_invalid): clearing class %s argv %d\n",
               classptr->classname, loop);
            free(classptr->xargv[loop]);
         }
         free(classptr);
         if (classlist == classptr) classlist = nextclass;
         if (lastclass) lastclass->next = nextclass;
      } else {
         lastclass = classptr;
      }
   }
}

/*************************************************************************/
/* FUNCTION  : read_config                                               */
/* PURPOSE   : Read the newsxd configuration file                        */
/* ARGUMENTS : none                                                      */
/*************************************************************************/

void
read_config(sig)
   int  sig;

{
FILE    *config;

char    line[MAXPATHLEN],       /* buffer used for inputting lines           */
        buf[9][MAXPATHLEN],     /* buffers for various command parameters    */
        *comment;               /* used to trim comments from input lines    */

int     loop,
        deltanice,              /* Amount to change proc's nice for xmit     */
        optioncnt,              /* number of parameters found by sscanf      */
        maxxmits,               /* number of allowed simul. transmitters     */
        interval,               /* interval between xmits to a single host   */
        startint,               /* interval between starting xmits 4 a class */
        maxload,                /* max allowed load for starting new xmits   */
        ttl,                    /* maximum time-to-live for a transmitter    */
        ttlpenalty,             /* time penalty for exceeding ttl            */
        flags;                  /* option flags for this transmission class  */

struct  class   *classptr;      /* used to traverse the class list           */
struct  stat    statbuf;

   if (!(config = fopen(configfile, "r"))) {
      logerr("Couldn't open config file (%s) - aborting\n", configfile);
      (void) exit(1);
   }

   /*
    * Mark all hosts and classes as undefined, but don't delete 'em yet
    */

   if (sig) log(LOG_INFO, "reinitializing\n");

   make_invalid();

   CONFIGCHANGED = 1;
#ifdef FAKESYSLOG
   CONFIGCHANGEDFILE = 1;
#endif
   daemon_idle = 0; /* Allow newsxd to begin running the queue again */

   /*
    * Reset all of the various data files to their default location
    */

   (void) strcpy(batchfile, default_batchfile);
   (void) strcpy(workfile, default_workfile);
   (void) strcpy(xmitlogs, default_xmitlogs);

   locking  = 0;                /* locking defaults to OFF                */
   tallying = 0;                /* use of the tally file defaults to OFF  */
   queueinterval = 60;          /* default queue run interval of 1 minute */

   /*
    * Add the DEFAULT pseudo-class so that a default xmitter can be specified
    */

   addclass("DEFAULT", 0, 0, 0, 0, 0, 0, 0, 0);

   while (fgets(line, 255, config) != NULL) {

      if ((comment = index(line, '#')) != NULL)
         (void) strcpy(comment, "\n");

      Dprintf("> %s", line);

      if (sscanf(line, "tallyfile %s\n", tallyfile) > 0) {
         dprintf("tallyfile is %s\n", tallyfile);
         tallying = 1;
      }

/*
      if (sscanf(line, "perhostlock %s\n", perhostlock) > 0) {
         dprintf("perhostlock is %s\n", perhostlock);
         locking = 1;
      }
*/

      if (sscanf(line, "batchfile %s\n", batchfile) > 0)
         dprintf("batchfile is %s\n", batchfile);

      if (sscanf(line, "xmitlogs %s\n", xmitlogs) > 0) {
         dprintf("xmitlogs is %s\n", xmitlogs); continue; }

      if (sscanf(line, "workfile %s\n", workfile) > 0)
         dprintf("workfile is %s\n", workfile);

      if (sscanf(line, "queueinterval %d\n", &queueinterval) > 0)
         dprintf("queueinterval is %d\n", queueinterval);

      if ((optioncnt = sscanf(line, "class %s %s %s %s %s %s %s %s", buf[0],
         buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8])) > 0) {

         maxxmits = 1;
         interval = 60;
         startint = 0;
         maxload = 99;
         ttl = 999999;
         ttlpenalty = 0;
         flags = 0;
         deltanice = 0;

         Dprintf("optioncnt = %d\n", optioncnt);

         for (loop = 1; loop < optioncnt; loop++) {
            (void) sscanf(buf[loop], "maxxmits=%d", &maxxmits);
            (void) sscanf(buf[loop], "maxload=%d", &maxload);
            (void) sscanf(buf[loop], "nice=%d", &deltanice);
            (void) sscanf(buf[loop], "interval=%d/%d", &interval, &startint);
            (void) sscanf(buf[loop], "ttl=%d/%d", &ttl, &ttlpenalty);
            if (strcmp(buf[loop], "noworkfile") == 0) flags |= (1<<C_NOWORK);
            if (strcmp(buf[loop], "nobatchfile") == 0) flags |= (1<<C_NOBATCH);
         }

         dprintf("class %s, maxxmits %d, intvl %d/%d, maxload %d, ttl %d/%d, nice %d, flags=%d\n",
            buf[0], maxxmits, interval, startint, maxload, ttl, ttlpenalty,
            deltanice, flags);

         addclass(buf[0], maxxmits, interval, startint, maxload, ttl,
                  ttlpenalty, deltanice, flags);
      }

      if ((optioncnt = sscanf(line, "xmit %s %s %s %s %s %s %s %s %s", buf[0],
         buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8])) > 0) {

         classptr = getclass(buf[0]);
         if (!classptr | (classptr->valid == 0)) {
            logerr("(read_config) xmit class for invalid class %s ignored\n",
               buf[0]);
         }

         if (stat(buf[1], &statbuf) != 0) {
            logerr("(read_config) xmit program %s for class %s unavailable\n",
               buf[1], buf[0]);
            logerr("(read_config) no xmit for class %s, invalidating class\n",
               buf[0]);
            classptr->valid = 0;
            continue;
         }

         (void) strcpy(classptr->xpath, buf[1]);
         for (loop = 2; loop < optioncnt; loop++) {
            Dprintf("class %s: setting xmit parm %d = %s\n",
               classptr->classname, loop - 2, buf[loop]);
            classptr->xargv[loop-2] = (char *) malloc(strlen(buf[loop])+1);
            (void) strcpy(classptr->xargv[loop-2], buf[loop]);
         }
         classptr->xargv[optioncnt - 2] = NULL;
         classptr->xargc = optioncnt - 2;
      }

      if ((optioncnt = sscanf(line, "host %s %s %s %s %s %s %s %s", buf[0],
         buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])) > 0) {

         Dprintf("optioncnt = %d\n", optioncnt);

         interval   = 0;
         startint   = 0;
         maxload    = 0;
         ttl        = 0;
         ttlpenalty = 0;
         deltanice  = 0;
         *buf[9]    = '\0';

         for (loop = 3; loop < optioncnt; loop++) {
            (void) sscanf(buf[loop], "maxload=%d", &maxload);
            (void) sscanf(buf[loop], "interval=%d/%d", &interval, &startint);
            (void) sscanf(buf[loop], "ttl=%d/%d", &ttl, &ttlpenalty);
            (void) sscanf(buf[loop], "nice=%d", &deltanice);
            (void) sscanf(buf[loop], "flags=%s", buf[9]);
         }

         dprintf("host %s, class %s, times %s, deltanice %d, maxload %d, intvl %d/%d, ttl %d/%d, flags=\"%s\"\n",
               buf[0], buf[1], buf[2], deltanice, maxload, interval, startint,
               ttl, ttlpenalty, buf[9]);

         addhost(buf[0], buf[1], buf[2], deltanice, maxload, interval, startint,
               ttl, ttlpenalty, buf[9]);
      }
   }

   /*
    * Remove any hosts or classes not defined anymore
    */

   clear_invalid();
}

/*************************************************************************/
/* FUNCTION  : dump_config                                               */
/* PURPOSE   : Write the current configuration and status of newsxd to   */
/*             a file                                                    */
/* ARGUMENTS : none                                                      */
/*************************************************************************/

void
dump_config()

{
struct  host    *hostptr;
struct  class   *classptr;

char    lastxmittime[30],          /* bunches of buffers for ctime */
        buf1[30],
        buf2[30],
        pid[30];                /* holds (pid) or "none" */

FILE    *status;

int	curtime;

   if ((debug <= 0) || (DEBUG <= 0)) {
      status = fopen(statusfile, "w");
      if (status == NULL) {
         logerr("Can't open statusfile (%s, \"w\")\n", statusfile);
         return;
      }
   } else
      status = stderr;

   curtime = time((long *) NULL);
   (void) fprintf(status, "%s", ctime(&curtime));
   if (daemon_idle) (void) fprintf(status, "Newsxd is idled\n");

   if (classlist == NULL) {
      (void) fprintf(status, "No valid classes defined!\n");
      return;
   }

   (void) fputc('\n', status);
   foreach (classptr, classlist) {
      if (strcmp(classptr->classname, "DEFAULT") == 0) continue;

      (void) fprintf(status, "Class %-7.7s : %2d active transmitters (%2d max)",
         classptr->classname, classptr->curxmits, classptr->maxxmits);
      if (getla() > classptr->options.maxload)
         (void) fprintf(status, " [no new xmits, load %d > %d max]",
            getla(), classptr->options.maxload);
      (void) fputc('\n', status);
   }

   (void) fputc('\n', status);
   (void) fprintf(status, "                         Service   Valid Start   Last XMIT  Xmitter  Why Not\n");
   (void) fprintf(status, "Hostname                  Class       Times       Started     pid    Running\n");
   (void) fprintf(status, "-----------------------  -------  -------------  ---------  -------  ----------\n");

   if (hostlist == NULL) {
      (void) fprintf(status, "No valid hosts defined!\n");
   }

   foreach (hostptr, hostlist) {
      if (hostptr->lasttime == NULL)
         (void) strcpy(lastxmittime, "* NEVER *");
      else {
         (void) sscanf(ctime(&hostptr->lasttime), "%s %*s %*s %s", buf1, buf2);
         (void) sprintf(lastxmittime, "%s %5.5s", buf1, buf2);
      }

      (void) sprintf(pid, (hostptr->pid) ? "%d" : "none", hostptr->pid);

      (void) fprintf(status, "%-23.23s  %-7s  %-13.13s  %9s   %5s   ",
         hostptr->hostname, hostptr->class, hostptr->times, lastxmittime, pid);

      switch (hostptr->whynot) {

         case WN_PENALTYTIME:
            (void) fputs("TTL Penlty", status);
            break;
         case WN_TTL:
            (void) fputs("TTL Kill", status);
            break;
         case WN_CLASSSTARTINT:
            (void) fputs("Class Intv", status);
            break;
         case WN_HOSTSTARTINT:
            (void) fputs("Host Intvl", status);
            break;
         case WN_LOAD:
            (void) fputs("High Load", status);
            break;
         case WN_BADTIME:
            (void) fputs("Wrong Time", status);
            break;
         case WN_MAXXMITS:
            (void) fputs("Max Xmits", status);
            break;
         case WN_RUNNING:
            (void) fputs("RUNNING", status);
            break;
         case WN_NOWORK:
            (void) fputs("No Work", status);
            break;
         case WN_RENAMEFAILED:
            (void) fputs("Bad Rename", status);
            break;
         case WN_NOTMYTURN:
            (void) fputs("NotMyTurn", status);
            break;
         case WN_NOSLOT:
            (void) fputs("No Slot!", status);
            break;
      }
      (void) fputc('\n', status);
   }
   if ((debug <= 0) || (DEBUG <= 0)) (void) fclose(status);
}

/*************************************************************************/
/* FUNCTION  : dump_info                                                 */
/* PURPOSE   : Dump newsxd's data structures to a file.                  */
/* ARGUMENTS : none                                                      */
/*************************************************************************/

void
dump_info()

{
struct  host    *hostptr;
struct	class	*classptr;

long	curtime;

int	loop, which;

FILE	*status;

char	outfile[MAXPATHLEN];

   if ((debug <= 0) || (DEBUG <= 0)) {
      (void) sprintf(outfile, "%s.dump", statusfile);
      status = fopen(outfile, "w");
      if (status == NULL) {
         logerr("Can't open statusfile (%s, \"w\")\n", statusfile);
         return;
      }
   } else
      status = stderr;

   curtime = time((long *) NULL);

   (void) fprintf(status, "Newsxd data structures at %s\n", ctime(&curtime));

   (void) fprintf(status, "debug is %s, DEBUG is %s, newsxdebug is %s\n",
      debug ? "On" : "Off", DEBUG ? "On" : "Off", newsxdebug ? "On" : "Off");

   (void) fprintf(status, "Queue runs occur every %d seconds, newsxd %s idled\n\n",
      queueinterval, daemon_idle ? "is" : "is not");

   (void) fprintf(status, "Active transmitter PID mappings:\n");

   which = 0;
   for (loop = 0; loop < MAXXMITTERS; loop++) {
      if (pidlist[loop] != 0) {
         if (!which) (void) fputc('\n', status);
         (void) fprintf(status, "pid %5d --> host %-20.20s ", pidlist[loop],
            pidmap[loop]->hostname);
         which = !which;
      }
   }

   (void) fputs("\n\n", status);

   (void) fprintf(status, "batchfile is                 %s\n", batchfile);
   (void) fprintf(status, "workfile is                  %s\n", workfile);
   (void) fprintf(status, "xmitlogs is                  %s\n", xmitlogs);
   (void) fprintf(status, "newsxd status written to     %s\n", statusfile);
   (void) fprintf(status, "newsxd pid written to        %s\n", pidfile);
   (void) fprintf(status, "newsxd config file is        %s\n", configfile);
   (void) fprintf(status, "\n");

   if (classlist == NULL) (void) fprintf(status, "NO DEFINED CLASSES\n");

   foreach (classptr, classlist) {
      (void) fprintf(status, "CLASS %s (%02d members)\n\n", classptr->classname,
         classptr->members);
      (void) fprintf(status, "     xmit prog  %s", classptr->xpath);
      for (loop = 0; loop < classptr->xargc; loop++)
         (void) fprintf(status, " %s", classptr->xargv[loop]);
      (void) fprintf(status, "\n");
      (void) fprintf(status, "     xmitters   %02d running, %02d max\n",
         classptr->curxmits, classptr->maxxmits);
      (void) fprintf(status, "     last xmit  %s", ctime(&classptr->laststart));
      (void) fprintf(status, "     sernum     %d\n", classptr->xmitsernum);

      (void) fprintf(status, "     options   ");
      if (classptr->options.deltanice)
         (void) fprintf(status, " nice=%d", classptr->options.deltanice);
      if (classptr->options.interval)
         (void) fprintf(status, " interval=%d", classptr->options.interval);
      if (classptr->options.startint)
         (void) fprintf(status, " startint=%d", classptr->options.startint);
      if (classptr->options.ttl)
         (void) fprintf(status, " ttl=%d", classptr->options.ttl);
      if (classptr->options.ttlpenalty)
         (void) fprintf(status, " ttlpenalty=%d", classptr->options.ttlpenalty);
      if (classptr->options.maxload)
         (void) fprintf(status, " maxload=%d", classptr->options.maxload);

      (void) fputc('\n', status);
      (void) fprintf(status, "     slots      ");
      for (loop = 0; loop < MAXCLASSXMITTERS; loop++) {
         if ((loop > 0) & ((loop % 50) == 0))
            (void) fputs("\n                ", status);
         (void) fputc(classptr->slots[loop], status);
      }

      (void) fputs("\n\n", status);
   }

   if (hostlist == NULL) (void) fprintf(status, "NO DEFINED HOSTS\n");

   foreach (hostptr, hostlist) {
      (void) fprintf(status, "HOST %s\n", hostptr->hostname);

      (void) fprintf(status, "     class      %s\n", hostptr->class);
      (void) fprintf(status, "     xmit times %s\n", hostptr->times);
      (void) fprintf(status, "     xmit pid   %d\n", hostptr->pid);
      (void) fprintf(status, "     last xmit  %s", hostptr->lasttime ? 
         ctime(&hostptr->lasttime) : "NEVER\n");
      (void) fprintf(status, "     penalty to %s", hostptr->penaltytime ?
         ctime(&hostptr->penaltytime) : "NONE\n");
      (void) fprintf(status, "     xmitsernum %d\n", hostptr->xmitsernum);
      (void) fprintf(status, "     whynot     %d\n", hostptr->whynot);
      (void) fprintf(status, "     xmit slot  %d\n", hostptr->classslot);
      (void) fprintf(status, "     xmit flags");

      for (loop = 0; loop < hostptr->xargc; loop++)
         (void) fprintf(status, " %s", hostptr->xargv[loop]);

      (void) fputc('\n', status);
      (void) fprintf(status, "     options   ");
      if (hostptr->options.deltanice)
         (void) fprintf(status, " nice=%d", hostptr->options.deltanice);
      if (hostptr->options.interval)
         (void) fprintf(status, " interval=%d", hostptr->options.interval);
      if (hostptr->options.startint)
         (void) fprintf(status, " startint=%d", hostptr->options.startint);
      if (hostptr->options.ttl)
         (void) fprintf(status, " ttl=%d", hostptr->options.ttl);
      if (hostptr->options.ttlpenalty)
         (void) fprintf(status, " ttlpenalty=%d", hostptr->options.ttlpenalty);
      if (hostptr->options.maxload)
         (void) fprintf(status, " maxload=%d", hostptr->options.maxload);

      (void) fputs("\n\n", status);
   }

   if ((debug <= 0) || (DEBUG <= 0)) (void) fclose(status);
}