[comp.sources.unix] v23i011: Netnews transmission daemon, Part01/03

rsalz@bbn.com (Rich Salz) (08/31/90)

Submitted-by: Chris Myers <chris@wugate.wustl.edu>
Posting-number: Volume 23, Issue 11
Archive-name: newsxd/part01

[  This is used at UUNET; is that becoming the seal of approval for
   Usenet software?  --r$  ]

The newsxd program is a configurable daemon for controlling the
transmission of netnews.  It allows the definition of multiple categories
of service, by setting a number of parameters defining things such as how
often news is to be transmitted, the number of news transmitters that can
be active at one time, the maximum time a transmitter may spend sending
netnews to a single host, and the maximum system load at which netnews
transmitters may be started.  newsxd can also be used to start up other
programs which must be restarted upon exit, or which must be run at
regular intervals with greater granularity than cron(8) allows.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents:  README MANIFEST config.c newsxd.8
# Wrapped by rsalz@litchi.bbn.com on Fri Jul 13 15:03:56 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 1 (of 3)."'
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
  echo shar: Extracting \"'README'\" \(1385 characters\)
  sed "s/^X//" >'README' <<'END_OF_FILE'
XThe newsxd program is a configurable daemon for controlling the
Xtransmission of netnews.  It allows the definition of multiple
Xcategories of service, by setting a number of parameters defining
Xthings such as how often news is to be transmitted, the number of news
Xtransmitters that can be active at one time, the maximum time a
Xtransmitter may spend sending netnews to a single host, and the maximum
Xsystem load at which netnews transmitters may be started.  newsxd can
Xalso be used to start up other programs which must be restarted upon
Xexit, or which must be run at regular intervals with greater
Xgranularity than cron(8) allows.
X
X                       newsxd Installation
X
XTo compile newsxd, you need to do the following things:
X
X1) Edit newsxd.h, and make any changes necessary to the default
X   locations for the newsxd data files.  Also select whether you want to
X   have newsxd log to syslog or to it's own log file.
X
X2) Edit the Makefile and define the correct locations to store newsxd
X   and it's manpage on your system.
X
X3) make depend
X
X4) make install
X
X5) Create a newsxd.conf file and install it in the appropriate location
X   (the default is /usr/local/etc/newsxd.conf).  Sample configuration files
X   are included as complex.conf and simple.conf.
X
X6) Turn off any nntpxmit's, sendbatch's, etc. so they don't conflict with
X   the ones started by newsxd.
X
X7) Run newsxd
END_OF_FILE
  if test 1385 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
  fi
  # end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
  echo shar: Extracting \"'MANIFEST'\" \(593 characters\)
  sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X----------------------------------------------------------
XREADME                     1	
XMANIFEST                   1	This shipping list
XMakefile                   3	
Xcomplex.conf               3	
Xconfig.c                   1	
Xdefs.h                     2	
Xlog.c                      3	
Xmain.c                     3	
Xnewsxd.8                   1	
Xnewsxd.conf                3	
Xnewsxd.h                   3	
Xpatchlevel.h               2	
Xprocess.c                  2	
Xsimple.conf                2	
Xutil.c                     2	
Xversion.c                  2	
END_OF_FILE
  if test 593 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
  fi
  # end of 'MANIFEST'
fi
if test -f 'config.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config.c'\"
else
  echo shar: Extracting \"'config.c'\" \(28527 characters\)
  sed "s/^X//" >'config.c' <<'END_OF_FILE'
X/*
X * #include <legal/bs.h>
X >
X > Copyright (c) 1989 Washington University in Saint Louis, Missouri and
X > Chris Myers. All rights reserved.
X >
X > Permission is hereby granted to copy, reproduce, redistribute or
X > otherwise use this software as long as: (1) there is no monetary
X > profit gained specifically from the use or reproduction of this
X > software, (2) it is not sold, rented, traded, or otherwise marketed,
X > (3) the above copyright notice and this paragraph is included
X > prominently in any copy made, and (4) that the name of the University
X > is not used to endorse or promote products derived from this software
X > without the specific prior written permission of the University.
X > THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X > IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X > WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X >
X */
X
X#include "defs.h"
X
X/*************************************************************************/
X/* FUNCTION  : getclass                                                  */
X/* PURPOSE   : Return a pointer to the class structure given the name of */
X/*             a class                                                   */
X/* ARGUMENTS : The name of a class                                       */
X/*************************************************************************/
X
Xstruct class *
Xgetclass(classname)
X   char *classname;
X
X{
Xstruct  class   *classptr;
X
X   if (strlen(classname) > MAXCLASSNAMELEN - 1) {
X      Dprintf("(getclass): classname %s is too long, no match\n", classname);
X      return((struct class *) NULL);
X   }
X
X   foreach (classptr, classlist) {
X      Dprintf("(getclass): now checking class %s\n", classptr->classname);
X      if (strcmp(classname, classptr->classname) == 0) break;
X   }
X
X   return(classptr);
X
X}
X
X/*************************************************************************/
X/* FUNCTION  : addclass                                                  */
X/* PURPOSE   : Add a class to or modify a class in the class list        */
X/* ARGUMENTS : All the information needed to define a class...           */
X/*************************************************************************/
X
Xvoid
Xaddclass(classname,maxxmits,interval,startint,maxload,ttl,ttlpenalty,nice,flags,         debugflags)
X   char *classname, *debugflags;
X   int  maxxmits, interval, startint, maxload, ttl, ttlpenalty, nice, flags;
X
X{
Xstruct  class   *classptr = classlist;
Xchar    *flagbuf;
Xint     loop,
X        newclass = 0;
X
X   if (strlen(classname) > MAXCLASSNAMELEN - 1) {
X      logerr("(addclass) Class name %s too long, max %d - ignoring\n",
X         classname, MAXCLASSNAMELEN - 1);
X      return;
X   }
X
X   if ((classptr = getclass(classname)) == NULL) {
X      Dprintf("(addclass): CALLOCing new class structure\n");
X      classptr = (struct class *) calloc(1, sizeof(struct class));
X      if (classptr == NULL) {
X         logerr("(addclass) Can't calloc struct class for class %s\n",
X            classname);
X         return;
X      }
X      for (loop = 0; loop < MAXCLASSXMITTERS; loop++)
X         classptr->slots[loop] = '.';
X      newclass++;
X   } else if (classptr->valid == 1) {
X      logerr("(addclass) Duplicated class %s\n", classname);
X      return;
X   }
X
X   /*
X    * Build class structure for this class and insert at the head of the
X    * class list
X    */
X
X   (void) strcpy(classptr->classname, classname);
X   classptr->maxxmits = maxxmits;
X   classptr->options.maxload = maxload;
X   classptr->options.interval = interval;
X   classptr->options.startint = startint;
X   classptr->options.ttl = ttl;
X   classptr->options.deltanice = nice;
X   classptr->options.ttlpenalty = ttlpenalty;
X   classptr->valid = 1;
X   classptr->xmitsernum = 0;
X   classptr->members = 0;
X   classptr->debugargc = 0;
X
X   if (debug && strlen(debugflags) > 0) {
X      if ((flagbuf = (char *) calloc(1, strlen(debugflags) + 1)) != NULL) {
X         (void) strcpy(flagbuf, debugflags);
X         while (1) {
X            classptr->debugargv[classptr->debugargc++] = flagbuf;
X            if ((flagbuf = STRCHR(flagbuf, '|')) == (char *) NULL) break;
X            *flagbuf++ = '\0';
X         }
X         Dprintf("(addclass) %s: debugargc = %d\n", classname,
X            classptr->debugargc);
X      }
X   }
X
X   /*
X    * Set all of the class flags.  flag is a bitmap.
X    */
X
X   for (loop = 0; loop < MAXCLASSFLAGS; loop++) {
X      if (flags & (1 << loop))
X         classptr->flags[loop] = 1;
X      else
X         classptr->flags[loop] = 0;
X      Dprintf("(addclass): flags[%d] = %d\n", loop,
X         classptr->flags[loop]);
X   }
X
X   /*
X    * Check to see if we are just overwriting a class description, if so don't
X    * wipe the pointer to the next entry in the list.
X    */
X
X   if (newclass) {
X      classptr->next = classlist;
X      classlist = classptr;
X   }
X
X   Dprintf("(addclass): classlist = %d\n", classlist);
X}
X
X/*************************************************************************/
X/* FUNCTION  : addhost                                                   */
X/* PURPOSE   : Add a host to the list of hosts to transmit to            */
X/* ARGUMENTS : Name of the host, class name, start and stop times        */
X/*************************************************************************/
X
Xvoid
Xaddhost(hostname, classname, times, deltanice, maxload, interval, startint,
X	ttl, ttlpenalty, flags)
X
X   char *hostname, *classname, *times, *flags;
X   int  deltanice, maxload, interval, startint, ttl, ttlpenalty;
X
X{
Xstruct  host    *hostptr,
X                *loopptr,
X                *lastptr = NULL;
Xstruct  class   *classptr;
Xint     loop;
Xchar    *flagbuf;
X
X   if (strlen(hostname) > MAXHOSTNAMELEN - 1) {
X      logerr("(addhost) Host name %s too long, max %d - ignoring\n",
X         classname, MAXHOSTNAMELEN - 1);
X      return;
X   }
X
X   if (strlen(times) > MAXTIMENAMELEN - 1) {
X      logerr("(addhost) Host time %s too long, max %d - ignoring\n",
X         classname, MAXTIMENAMELEN - 1);
X      return;
X   }
X
X   if ((classptr = getclass(classname)) == NULL) {
X      logerr("(addhost) Host's (%s) class %s doesn't exist - ignoring host\n",
X         hostname, classname);
X      return;
X   }
X
X   if (classptr->valid == 0) {
X      logerr("(addhost) Host's (%s) class %s is invalid - ignoring host\n",
X         hostname, classname);
X      return;
X   }
X
X   if (strcmp(classname, "DEFAULT") == 0) {
X      logerr("(addhost) Host (%s) can't be a member of class DEFAULT\n",
X         hostname);
X      return;
X   }
X
X   lastptr = NULL;
X   foreach (hostptr, hostlist) {
X      Dprintf("(addhost): now checking host %s\n", hostptr->hostname);
X      if (strcmp(hostname, hostptr->hostname) == 0) break;
X      lastptr = hostptr;
X   }
X
X   if (hostptr != NULL) {
X      if (hostptr->valid == 1) {
X         logerr("(addhost) Duplicated host %s\n", hostname);
X         return;
X      }
X      if (lastptr != NULL) {
X         lastptr->next = hostptr->next;
X         Dprintf("(addhost) host %s next was %s, now %s\n", lastptr->hostname,
X            hostptr->hostname, hostptr->next ? hostptr->next->hostname : NULL);
X      } else
X         hostlist = hostptr->next;
X   } else {
X      Dprintf("(addhost): CALLOCing new host structure\n");
X      hostptr = (struct host *) calloc(1, sizeof(struct host));
X      if (hostptr == NULL) {
X         logerr("(addhost) Can't calloc struct host for host %s\n",
X            hostname);
X         return;
X      }
X   }
X
X   (void) strcpy(hostptr->hostname, hostname);
X   (void) strcpy(hostptr->class, classname);
X   (void) strcpy(hostptr->times, times);
X   hostptr->valid = 1;
X   hostptr->options.deltanice = deltanice;
X   hostptr->options.maxload = maxload;
X   hostptr->options.interval = interval;
X   hostptr->options.startint = startint;
X   hostptr->options.ttl = ttl;
X   hostptr->options.ttlpenalty = ttlpenalty;
X   hostptr->xmitsernum = 0;
X   hostptr->xargc = 0;
X   classptr->members++;
X
X   if (flags && strlen(flags) > 0) {
X      if ((flagbuf = (char *) calloc(1, strlen(flags) + 1)) != NULL) {
X         (void) strcpy(flagbuf, flags);
X         while (1) {
X            hostptr->xargv[hostptr->xargc++] = flagbuf;
X            if ((flagbuf = STRCHR(flagbuf, '|')) == (char *) NULL) break;
X            *flagbuf++ = '\0';
X         }
X      }
X   }
X
X   for (loop = 0; loop < hostptr->xargc; loop++)
X      Dprintf("host %s: flag[%d] = %s\n", hostname, loop, hostptr->xargv[loop]);
X
X   /*
X    * If this is a new host, do a two-key insertion sort based on the
X    * hostname and name of the transmission class.  Makes things look nice
X    * in the status display...
X    */
X
X   lastptr = NULL;
X
X   if (hostlist == NULL) {
X      Dprintf("(addhost): %s IS hostlist now\n", hostname);
X      hostlist = hostptr;
X   } else {
X      foreach (loopptr, hostlist) {
X         if (((strcmp(hostptr->hostname, loopptr->hostname) < 0) &
X             (strcmp(hostptr->class, loopptr->class) == 0)) | 
X             (strcmp(hostptr->class, loopptr->class) < 0)) {
X            Dprintf("(addhost): Inserting %s before %s\n", hostname,
X               loopptr->hostname);
X            hostptr->next = loopptr;
X            if (lastptr != NULL) lastptr->next = hostptr;
X            if (loopptr == hostlist) hostlist = hostptr;
X            break;
X         }
X         lastptr = loopptr;
X      }
X      if (loopptr == NULL) {
X         Dprintf("(addhost): appending host %s to hostlist\n", hostname);
X         lastptr->next = hostptr; /* append to current host list */
X         hostptr->next = NULL;
X      }
X   }
X   Dprintf("(addhost): hostlist = %d\n", hostlist);
X}
X
X/*************************************************************************/
X/* FUNCTION  : make_invalid                                              */
X/* PURPOSE   : Mark all hosts and classes as invalid                     */
X/* ARGUMENTS : none                                                      */
X/*************************************************************************/
X
Xvoid
Xmake_invalid()
X
X{
Xstruct  class   *classptr,
X                *nextclass;
Xstruct  host    *hostptr,
X                *nexthost;
X
X   dprintf("(make_invalid) marking all classes as invalid\n");
X   for (classptr = classlist; classptr != NULL; classptr = nextclass) {
X      Dprintf("(make_invalid) marking class %s as invalid\n",
X         classptr->classname);
X      classptr->valid = 0;
X      classptr->members = 0;
X      nextclass = classptr->next;
X   }
X
X   dprintf("(make_invalid) marking all hosts as invalid\n");
X   for (hostptr = hostlist; hostptr != NULL; hostptr = nexthost) {
X      Dprintf("(make_invalid) marking host %s as invalid\n", hostptr->hostname);
X      hostptr->valid = 0;
X      nexthost = hostptr->next;
X   }
X
X}
X
X/*************************************************************************/
X/* FUNCTION  : clear_invalid                                             */
X/* PURPOSE   : Remove all hosts and classes which are not valid anymore  */
X/* ARGUMENTS : none                                                      */
X/*************************************************************************/
X
Xvoid
Xclear_invalid()
X
X{
Xstruct  class   *lastclass = NULL,
X                *classptr,
X                *nextclass;
Xstruct  host    *lasthost = NULL,
X                *hostptr,
X                *nexthost;
Xint     loop;
X
X   dprintf("(clear_invalid) clearing all invalid hosts\n");
X   for (hostptr = hostlist; hostptr != NULL; hostptr = nexthost) {
X      nexthost = hostptr->next;
X      if (hostptr->valid == 0) {
X         if (hostptr->pid > 0) {
X            dprintf("(clear_invalid): killing transmitter for host %s\n",
X               hostptr->hostname);
X            if (kill(hostptr->pid, SIGTERM) != 0) xmit_done(-hostptr->pid);
X         }
X         Dprintf("(clear_invalid): clearing host %s\n", hostptr->hostname);
X         if (hostlist == hostptr) hostlist = nexthost;
X         (void) free(hostptr);
X         if (lasthost) lasthost->next = nexthost;
X      } else {
X         lasthost = hostptr;
X      }
X   }
X
X   dprintf("(clear_invalid) clearing all invalid classes\n");
X   for (classptr = classlist; classptr != NULL; classptr = nextclass) {
X      nextclass = classptr->next;
X      if (classptr->valid == 0) {
X         Dprintf("(clear_invalid): clearing class %s\n", classptr->classname);
X         for (loop = 0; loop < classptr->xargc; loop++) {
X            Dprintf("(clear_invalid): clearing class %s argv %d\n",
X               classptr->classname, loop);
X            (void) free(classptr->xargv[loop]);
X         }
X         if (classlist == classptr) classlist = nextclass;
X         (void) free(classptr);
X         if (lastclass) lastclass->next = nextclass;
X      } else {
X         lastclass = classptr;
X      }
X   }
X}
X
X/*************************************************************************/
X/* FUNCTION  : read_config                                               */
X/* PURPOSE   : Read the newsxd configuration file                        */
X/* ARGUMENTS : none                                                      */
X/*************************************************************************/
X
Xvoid
Xread_config(sig)
X   int  sig;
X
X{
XFILE    *config;
X
Xchar    line[MAXPATHLEN],       /* buffer used for inputting lines           */
X        buf[10][MAXPATHLEN],    /* buffers for various command parameters    */
X        *comment;               /* used to trim comments from input lines    */
X
Xint     loop,
X        deltanice,              /* Amount to change proc's nice for xmit     */
X        optioncnt,              /* number of parameters found by sscanf      */
X        maxxmits,               /* number of allowed simul. transmitters     */
X        interval,               /* interval between xmits to a single host   */
X        startint,               /* interval between starting xmits 4 a class */
X        maxload,                /* max allowed load for starting new xmits   */
X        ttl,                    /* maximum time-to-live for a transmitter    */
X        ttlpenalty,             /* time penalty for exceeding ttl            */
X        flags;                  /* option flags for this transmission class  */
X
Xstruct  class   *classptr;      /* used to traverse the class list           */
Xstruct  stat    statbuf;
X
X   if (!(config = fopen(configfile, "r"))) {
X      logerr("Couldn't open config file (%s) - aborting\n", configfile);
X      (void) exit(1);
X   }
X
X   /*
X    * Mark all hosts and classes as undefined, but don't delete 'em yet
X    */
X
X   if (sig) log(LOG_INFO, "reinitializing\n");
X
X   make_invalid();
X
X   CONFIGCHANGED = 1;
X#ifdef FAKESYSLOG
X   CONFIGCHANGEDFILE = 1;
X#endif
X   daemon_idle = 0; /* Allow newsxd to begin running the queue again */
X
X   /*
X    * Reset all of the various data files to their default location
X    */
X
X   (void) strcpy(batchfile, default_batchfile);
X   (void) strcpy(workfile, default_workfile);
X   (void) strcpy(xmitlogs, default_xmitlogs);
X
X   locking  = 0;                /* locking defaults to OFF                */
X   tallying = 0;                /* use of the tally file defaults to OFF  */
X   queueinterval = 60;          /* default queue run interval of 1 minute */
X
X   /*
X    * Add the DEFAULT pseudo-class so that a default xmitter can be specified
X    */
X
X   addclass("DEFAULT", 0, 0, 0, 0, 0, 0, 0, 0, 0);
X
X   while (fgets(line, 255, config) != NULL) {
X
X      if ((comment = index(line, '#')) != NULL)
X         (void) strcpy(comment, "\n");
X
X      Dprintf("> %s", line);
X
X      if (sscanf(line, "tallyfile %s\n", tallyfile) > 0) {
X         dprintf("tallyfile is %s\n", tallyfile);
X         tallying = 1;
X      }
X
X      if (sscanf(line, "batchfile %s\n", batchfile) > 0)
X         dprintf("batchfile is %s\n", batchfile);
X
X      if (sscanf(line, "xmitlogs %s\n", xmitlogs) > 0) {
X         dprintf("xmitlogs is %s\n", xmitlogs); continue; }
X
X      if (sscanf(line, "workfile %s\n", workfile) > 0)
X         dprintf("workfile is %s\n", workfile);
X
X      if (sscanf(line, "queueinterval %d\n", &queueinterval) > 0)
X         dprintf("queueinterval is %d\n", queueinterval);
X
X      if ((optioncnt = sscanf(line, "class %s %s %s %s %s %s %s %s", buf[0],
X         buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8])) > 0) {
X
X         maxxmits = 1;
X         interval = 60;
X         startint = 0;
X         maxload = 99;
X         ttl = 999999;
X         ttlpenalty = 0;
X         flags = 0;
X         deltanice = 0;
X         *buf[9] = '\0';
X
X         Dprintf("optioncnt = %d\n", optioncnt);
X
X         for (loop = 1; loop < optioncnt; loop++) {
X            (void) sscanf(buf[loop], "maxxmits=%d", &maxxmits);
X            (void) sscanf(buf[loop], "maxload=%d", &maxload);
X            (void) sscanf(buf[loop], "nice=%d", &deltanice);
X            (void) sscanf(buf[loop], "interval=%d/%d", &interval, &startint);
X            (void) sscanf(buf[loop], "ttl=%d/%d", &ttl, &ttlpenalty);
X            (void) sscanf(buf[loop], "debug=%s", buf[9]);
X            if (strcmp(buf[loop], "noworkfile") == 0) flags |= (1<<C_NOWORK);
X            if (strcmp(buf[loop], "nobatchfile") == 0) flags |= (1<<C_NOBATCH);
X         }
X
X         dprintf("class %s, maxxmits %d, intvl %d/%d, maxload %d, ttl %d/%d, nice %d, flags=%d, debug=%s\n",
X            buf[0], maxxmits, interval, startint, maxload, ttl, ttlpenalty,
X            deltanice, flags, buf[9]);
X
X         addclass(buf[0], maxxmits, interval, startint, maxload, ttl,
X                  ttlpenalty, deltanice, flags, buf[9]);
X      }
X
X      if ((optioncnt = sscanf(line, "xmit %s %s %s %s %s %s %s %s %s", buf[0],
X         buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8])) > 0) {
X
X         classptr = getclass(buf[0]);
X         if (!classptr | (classptr->valid == 0)) {
X            logerr("(read_config) xmit class for invalid class %s ignored\n",
X               buf[0]);
X         }
X
X         if (stat(buf[1], &statbuf) != 0) {
X            logerr("(read_config) xmit program %s for class %s unavailable\n",
X               buf[1], buf[0]);
X            logerr("(read_config) no xmit for class %s, invalidating class\n",
X               buf[0]);
X            classptr->valid = 0;
X            continue;
X         }
X
X         (void) strcpy(classptr->xpath, buf[1]);
X         for (loop = 2; loop < optioncnt; loop++) {
X            Dprintf("class %s: setting xmit parm %d = %s\n",
X               classptr->classname, loop - 2, buf[loop]);
X            classptr->xargv[loop-2] = (char *) malloc(strlen(buf[loop])+1);
X            (void) strcpy(classptr->xargv[loop-2], buf[loop]);
X         }
X         classptr->xargv[optioncnt - 2] = NULL;
X         classptr->xargc = optioncnt - 2;
X      }
X
X      if ((optioncnt = sscanf(line, "host %s %s %s %s %s %s %s %s", buf[0],
X         buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])) > 0) {
X
X         Dprintf("optioncnt = %d\n", optioncnt);
X
X         interval   = 0;
X         startint   = 0;
X         maxload    = 0;
X         ttl        = 0;
X         ttlpenalty = 0;
X         deltanice  = 0;
X         *buf[9]    = '\0';
X
X         for (loop = 3; loop < optioncnt; loop++) {
X            (void) sscanf(buf[loop], "maxload=%d", &maxload);
X            (void) sscanf(buf[loop], "interval=%d/%d", &interval, &startint);
X            (void) sscanf(buf[loop], "ttl=%d/%d", &ttl, &ttlpenalty);
X            (void) sscanf(buf[loop], "nice=%d", &deltanice);
X            (void) sscanf(buf[loop], "flags=%s", buf[9]);
X         }
X
X         dprintf("host %s, class %s, times %s, deltanice %d, maxload %d, intvl %d/%d, ttl %d/%d, flags=\"%s\"\n",
X               buf[0], buf[1], buf[2], deltanice, maxload, interval, startint,
X               ttl, ttlpenalty, buf[9]);
X
X         addhost(buf[0], buf[1], buf[2], deltanice, maxload, interval, startint,
X               ttl, ttlpenalty, buf[9]);
X      }
X   }
X
X   /*
X    * Remove any hosts or classes not defined anymore
X    */
X
X   clear_invalid();
X
X   (void) fclose(config);
X}
X
X/*************************************************************************/
X/* FUNCTION  : dump_config                                               */
X/* PURPOSE   : Write the current configuration and status of newsxd to   */
X/*             a file                                                    */
X/* ARGUMENTS : none                                                      */
X/*************************************************************************/
X
Xvoid
Xdump_config()
X
X{
Xstruct  host    *hostptr;
Xstruct  class   *classptr;
X
Xchar    lastxmittime[30],          /* bunches of buffers for ctime */
X        buf1[30],
X        buf2[30],
X        pid[30];                /* holds (pid) or "none" */
X
XFILE    *status;
X
Xint	curtime;
X
X   if ((debug <= 0) || (DEBUG <= 0)) {
X      status = fopen(statusfile, "w");
X      if (status == NULL) {
X         logerr("Can't open statusfile (%s, \"w\")\n", statusfile);
X         return;
X      }
X   } else
X      status = stderr;
X
X   curtime = time((long *) NULL);
X   (void) fprintf(status, "%s", ctime(&curtime));
X   if (daemon_idle) (void) fprintf(status, "Newsxd is idled\n");
X
X   if (classlist == NULL) {
X      (void) fprintf(status, "No valid classes defined!\n");
X      return;
X   }
X
X   (void) fputc('\n', status);
X   foreach (classptr, classlist) {
X      if (strcmp(classptr->classname, "DEFAULT") == 0) continue;
X
X      (void) fprintf(status, "Class %-7.7s : %2d active transmitters (%2d max)",
X         classptr->classname, classptr->curxmits, classptr->maxxmits);
X      if (getla() > classptr->options.maxload)
X         (void) fprintf(status, " [no new xmits, load %d > %d max]",
X            getla(), classptr->options.maxload);
X      (void) fputc('\n', status);
X   }
X
X   (void) fputc('\n', status);
X   (void) fprintf(status, "                         Service   Valid Start   Last XMIT  Xmitter  Why Not\n");
X   (void) fprintf(status, "Hostname                  Class       Times       Started     pid    Running\n");
X   (void) fprintf(status, "-----------------------  -------  -------------  ---------  -------  ----------\n");
X
X   if (hostlist == NULL) {
X      (void) fprintf(status, "No valid hosts defined!\n");
X   }
X
X   foreach (hostptr, hostlist) {
X      if (hostptr->lasttime == NULL)
X         (void) strcpy(lastxmittime, "* NEVER *");
X      else {
X         (void) sscanf(ctime(&hostptr->lasttime), "%s %*s %*s %s", buf1, buf2);
X         (void) sprintf(lastxmittime, "%s %5.5s", buf1, buf2);
X      }
X
X      (void) sprintf(pid, (hostptr->pid) ? "%d" : "none", hostptr->pid);
X
X      (void) fprintf(status, "%-23.23s  %-7s  %-13.13s  %9s   %5s   ",
X         hostptr->hostname, hostptr->class, hostptr->times, lastxmittime, pid);
X
X      if (daemon_idle && hostptr->whynot != WN_RUNNING)
X         (void) fputs("newsxd Idl", status);
X      else
X         (void) fputs(wnlist[hostptr->whynot], status);
X      (void) fputc('\n', status);
X   }
X   if ((debug <= 0) || (DEBUG <= 0)) (void) fclose(status);
X}
X
X/*************************************************************************/
X/* FUNCTION  : dump_info                                                 */
X/* PURPOSE   : Dump newsxd's data structures to a file.                  */
X/* ARGUMENTS : none                                                      */
X/*************************************************************************/
X
Xvoid
Xdump_info()
X
X{
Xstruct  host    *hostptr;
Xstruct	class	*classptr;
X
Xlong	curtime;
X
Xint	loop, which;
X
XFILE	*status;
X
Xchar	outfile[MAXPATHLEN];
X
X   if ((debug <= 0) || (DEBUG <= 0)) {
X      (void) sprintf(outfile, "%s.dump", statusfile);
X      status = fopen(outfile, "w");
X      if (status == NULL) {
X         logerr("Can't open statusfile (%s, \"w\")\n", statusfile);
X         return;
X      }
X   } else
X      status = stderr;
X
X   curtime = time((long *) NULL);
X
X   (void) fprintf(status, "Newsxd data structures at %s\n", ctime(&curtime));
X
X   (void) fprintf(status, "debug is %s, DEBUG is %s, newsxdebug is %s\n",
X      debug ? "On" : "Off", DEBUG ? "On" : "Off", newsxdebug ? "On" : "Off");
X
X   (void) fprintf(status, "Queue runs occur every %d seconds, newsxd %s idled\n\n",
X      queueinterval, daemon_idle ? "IS" : "is not");
X
X   (void) fprintf(status, "Active transmitter PID mappings:\n");
X
X   which = 0;
X   for (loop = 0; loop < MAXXMITTERS; loop++) {
X      if (pidlist[loop] != 0) {
X         if (!which) (void) fputc('\n', status);
X         (void) fprintf(status, "pid %5d --> %-25.25s ", pidlist[loop],
X            pidmap[loop]->hostname);
X         which = !which;
X      }
X   }
X
X   (void) fputs("\n\n", status);
X
X   (void) fprintf(status, "batchfile is                 %s\n", batchfile);
X   (void) fprintf(status, "workfile is                  %s\n", workfile);
X   (void) fprintf(status, "xmitlogs is                  %s\n", xmitlogs);
X   (void) fprintf(status, "newsxd status written to     %s\n", statusfile);
X   (void) fprintf(status, "newsxd pid written to        %s\n", pidfile);
X   (void) fprintf(status, "newsxd config file is        %s\n", configfile);
X   (void) fprintf(status, "\n");
X
X   if (classlist == NULL) (void) fprintf(status, "NO DEFINED CLASSES\n");
X
X   foreach (classptr, classlist) {
X      (void) fprintf(status, "CLASS %s (%02d members)\n\n", classptr->classname,
X         classptr->members);
X      (void) fprintf(status, "     xmit prog  %s", classptr->xpath);
X      for (loop = 0; loop < classptr->xargc; loop++)
X         (void) fprintf(status, " %s", classptr->xargv[loop]);
X      (void) fprintf(status, "\n");
X      (void) fprintf(status, "     xmitters   %02d running, %02d max\n",
X         classptr->curxmits, classptr->maxxmits);
X      (void) fprintf(status, "     last xmit  %s", ctime(&classptr->laststart));
X      (void) fprintf(status, "     sernum     %d\n", classptr->xmitsernum);
X
X      (void) fprintf(status, "     options   ");
X      if (classptr->options.deltanice)
X         (void) fprintf(status, " nice=%d", classptr->options.deltanice);
X      if (classptr->options.interval)
X         (void) fprintf(status, " interval=%d", classptr->options.interval);
X      if (classptr->options.startint)
X         (void) fprintf(status, " startint=%d", classptr->options.startint);
X      if (classptr->options.ttl)
X         (void) fprintf(status, " ttl=%d", classptr->options.ttl);
X      if (classptr->options.ttlpenalty)
X         (void) fprintf(status, " ttlpenalty=%d", classptr->options.ttlpenalty);
X      if (classptr->options.maxload)
X         (void) fprintf(status, " maxload=%d", classptr->options.maxload);
X
X      (void) fputc('\n', status);
X      (void) fprintf(status, "     slots      ");
X      for (loop = 0; loop < MAXCLASSXMITTERS; loop++) {
X         if ((loop > 0) & ((loop % 50) == 0))
X            (void) fputs("\n                ", status);
X         (void) fputc(classptr->slots[loop], status);
X      }
X
X      (void) fputs("\n\n", status);
X   }
X
X   if (hostlist == NULL) (void) fprintf(status, "NO DEFINED HOSTS\n");
X
X   foreach (hostptr, hostlist) {
X      (void) fprintf(status, "HOST %s\n", hostptr->hostname);
X
X      (void) fprintf(status, "     class      %s\n", hostptr->class);
X      (void) fprintf(status, "     xmit times %s\n", hostptr->times);
X      (void) fprintf(status, "     xmit pid   %d\n", hostptr->pid);
X      (void) fprintf(status, "     last xmit  %s", hostptr->lasttime ? 
X         ctime(&hostptr->lasttime) : "NEVER\n");
X      (void) fprintf(status, "     penalty to %s", hostptr->penaltytime ?
X         ctime(&hostptr->penaltytime) : "NONE\n");
X      (void) fprintf(status, "     xmitsernum %d\n", hostptr->xmitsernum);
X      (void) fprintf(status, "     whynot     %s (%d)\n", 
X         wnlist[hostptr->whynot], hostptr->whynot);
X      (void) fprintf(status, "     xmit slot  %d\n", hostptr->classslot);
X      (void) fprintf(status, "     xmit flags");
X
X      for (loop = 0; loop < hostptr->xargc; loop++)
X         (void) fprintf(status, " %s", hostptr->xargv[loop]);
X
X      (void) fputc('\n', status);
X      (void) fprintf(status, "     options   ");
X      if (hostptr->options.deltanice)
X         (void) fprintf(status, " nice=%d", hostptr->options.deltanice);
X      if (hostptr->options.interval)
X         (void) fprintf(status, " interval=%d", hostptr->options.interval);
X      if (hostptr->options.startint)
X         (void) fprintf(status, " startint=%d", hostptr->options.startint);
X      if (hostptr->options.ttl)
X         (void) fprintf(status, " ttl=%d", hostptr->options.ttl);
X      if (hostptr->options.ttlpenalty)
X         (void) fprintf(status, " ttlpenalty=%d", hostptr->options.ttlpenalty);
X      if (hostptr->options.maxload)
X         (void) fprintf(status, " maxload=%d", hostptr->options.maxload);
X
X      (void) fputs("\n\n", status);
X   }
X
X   if ((debug <= 0) || (DEBUG <= 0)) (void) fclose(status);
X}
END_OF_FILE
  if test 28527 -ne `wc -c <'config.c'`; then
    echo shar: \"'config.c'\" unpacked with wrong size!
  fi
  # end of 'config.c'
fi
if test -f 'newsxd.8' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'newsxd.8'\"
else
  echo shar: Extracting \"'newsxd.8'\" \(17954 characters\)
  sed "s/^X//" >'newsxd.8' <<'END_OF_FILE'
X.TH newsxd 8
X.SH NAME
Xnewsxd \- daemon for managing the transmission of news
X.SH SYNTAX
X.B newsxd
X[\-debug] [\-DEBUG] [\-newsxdebug] [\-c \fIfile\fR] [\-v]
X[\-pid \fIfile\fR\|] [\-status \fIfile\fR] [\-log \fIfile\fR]
X.br
X.SH DESCRIPTION
XThe
X.I newsxd
Xprogram
Xis a configurable daemon for controlling the transmission
Xof netnews.  It allows the definition of multiple categories of service,
Xby setting a number of parameters defining things such as how often news is to
Xbe transmitted, the number of news transmitters that can be active at one
Xtime, the maximum time a transmitter may spend sending netnews to a single
Xhost, and the maximum system load at which netnews transmitters may be
Xstarted.
X.I newsxd
Xcan also be used to start up other programs which must be restarted
Xupon exit, or which must be run at regular intervals with greater granularity
Xthan
X.I cron(8)
Xallows.
X.PP
XWhen starting up, the
X.I newsxd
Xprogram reads a configuration file
X(usually \fI/usr/local/etc/newsxd.conf\fR) which specifies all of the
Xclasses of service and their characteristics, where certain data files
Xare to be stored and what hosts netnews is to be transmitted to.
X.PP
X.I newsxd
Xis a daemon, and while it replaces such programs as
X.I nntpsend,
Xit is not meant to be run from
X.I cron(8),
Xbut rather from /etc/rc.local.  If you have multiple copies of
X.I newsxd
Xrunning the results will be unpredictable.
X.SH OPTIONS
X.IP -debug 15
XEnables debugging.  If debugging is enabled,
X.I newsxd
Xwill not switch to daemon mode (i.e. will not detach itself from the
Xcontrolling terminal).
X.IP -DEBUG
XEnables painfully verbose debugging.
X.IP -newsxdebug
XEnables debugging when running
X.I nntpxmit.
XAlso causes
X.I nntpxmit
Xto be run synchronously
X.I (newsxd
Xwill wait for the
X.I nntpxmit
Xto complete before continuing with other hosts).
X.IP "-c \fIfile\fR"
XSpecifies an alternate configuration file for
X.I newsxd
Xto load.
X.IP "-pid \fIfile\fR"
XSpecifies an alternate file for
X.I newsxd
Xto write its PID into when starting up.
X.IP "-status \fIfile\fR"
XSpecifies an alternate file for
X.I newsxd
Xto write its status into upon receipt of a QUIT signal.
X.IP "-log \fIfile\fR"
XSpecifies an alternate file for
X.I newsxd
Xto write its logging information into when FAKESYSLOG is being used.
X.IP "-v"
XDisplays the version of newsxd that you are running.  \fINewsxd\fR
Xdoes NOT start running if the -v switch is specified.
X.RE
X.PP
XThe configuration file for
X.I newsxd
Xconsists of commands from the list below.  Comments are preceded by
Xpound (\#) signs and continue to the end of the line.  Case is significant.
X.PP
X
Xclass \fItype [options]\fR
X
Xdefines a class of service.  \fItype\fR can be any printable string less than
Xeight characters long (0, 5, 9, high, low, boring, etc.)  There are a number
Xof options that can be specified (as a space-separated list) that will modify
Xthe behavior of a service class:
X.RS +.5i
X.IP maxxmits=\fIn\fR 15
Xspecifies the maximum number of netnews transmitters that
X.I newsxd
Xwill allow to be running simultaneously for this service class.  The
Xdefault value is 1.
X.IP interval=\fIn[/m]\fR
Xspecifies the start-to-start interval (in seconds) between successive
Xinvocations of a netnews transmitter for a single host.  The default value
Xis 60 seconds.  The optional parameter \fIm\fR specifies the number of
Xseconds to wait between starting new transmitters for ANY host in this
Xservice class; this is useful to prevent many transmitters from being
Xstarted simultaneously and spiking the system load.  The intra-class
Xstartup interval, \fIm\fR, should not divide the \fIqueueinterval\fR
X(below) evenly.
X.IP maxload=\fIn\fR
Xdefines the maximum load at which
X.I newsxd
Xwill start transmitters for this service class.  If the load passes beyond
Xthis value, no new transmitters will be started until the load drops.  Any
Xcurrently running transmitters will not be affected.
X.IP ttl=\fIn[/m]\fR
Xgives the maximum time-to-live in seconds for any invocation of a netnews
Xtransmitter.  The default value is 999999 seconds (about 11 days).  The
Xoptional parameter, \fIm\fR, gives the number of seconds to penalize a
Xtransmitter that has exceeded its ttl; this is the number of seconds to
Xprevent a new transmitter from starting up for the penalized host.
X.IP noworkfile
XNormally the article batch file for the host is renamed before executing
Xthe netnews transmitter as defined by the \fIworkfile\fR below.  This option
Xcauses the renaming to be bypassed.
X.IP nobatchfile
XNormally an article batch file must exist for the host before
X.I newsxd
Xwill execute the transmitter for the host.  If this option is defined,
Xthe check for a batch file will be bypassed.
X.RE
X.IN -5
X.PP
X
Xxmit \fIclassname programpath programname [parameters]\fR
X
Xdefines an alternate netnews transmission program, for which command-line
Xoptions can be specified.  You *MUST* define a transmission program for the
Xclass
X.I DEFAULT,
Xwhich will be used as the default news transmitter for all other classes.
XSee the example configuration shown below.  \fINewsxd\fR will use the
Xenvironment variable PATH that it was invoked with to search for the program
Xif an explicit path is not given.
X.RS +.5i
X.IP classname 15
Xis the name of an already-defined service class which is to
Xuse this transmission program.
X.IP programpath
Xis the path of the file to execute
X.IP programname
Xis the name to be passed to the program as argv[0];
Xusually the last component of \fIprogrampath\fR.
X.IP [parameters]
Xoptional parameters and options (up to nine) to be
Xpassed to the news transmitter.  In
X.I parameters,
Xthe following conversions will be made:
X.RS 15
X.IP %f 5
Xwill be replaced with the per-host flags specified by the
X.I host
Xcommand (see below).
X.IP %h
Xwill be replaced with the host name.
X.IP %w
Xwill be replaced with the name of the workfile for the host.
X.IP %b
Xwill be replaced with the name of the batchfile for the host.
X.IP %s
Xwill be replaced by an integer which is unique to all of the active
Xtransmitters for that class.  Newsxd will select the lowest unused integer
Xeach time a transmitter is started.  These 'slot numbers' start at 0.
X.RE
X.RE
X.PP
X
Xqueueinterval \fIseconds\fR
X
Xspecifies the number of seconds between "queue runs".  During each queue
Xrun
X.I newsxd
Xwill check each host to see if a netnews transmitter can be started for
Xthat host.  The queueinterval should be at least as small as the smallest
Xinterval specified in all of the \fIclass\fR definitions.  The default value
Xfor \fIqueueinterval\fR is 60 seconds.
X.PP
X
Xbatchfile \fIfile\fR
X
Xspecifies the file path where the batch files (files listing article paths
Xor IDs to be used by a netnews transmitter) are stored.  A %s in \fIfile\fR
Xwill be replaced by the name of the current host.  Unless the
X.I nobatchfile
Xoption was specified for the host's service class, this
Xfile must exist before a netnews transmitter will be executed for the host.
XThe default value for \fIbatchfile\fR is defined in newsxd.h and is normally
X\fI/usr/spool/batch/%s\fR.
X.PP
X
Xworkfile \fIfile\fR
X
Xspecifies the file path which the batch files are to be renamed to before
Xexecuting the netnews transmitter.  A %s in \fIfile\fR will be replaced by
Xthe name of the current host.  If the \fInoworkfile\fR option was specified
Xfor this host's service class, the batch file will NOT be renamed.  The
Xdefault value for \fIworkfile\fR is defined in newsxd.h and is normally
X\fI/usr/spool/batch/%s.work\fR.
X.PP
X
Xxmitlogs \fIfile\fR
X
Xwhere to log the output of each netnews transmitter.  If you need to keep
Xthe information printed by a transmitter, use this option.  If you don't
Xneed to use up the disk space, leave \fIxmitlogs\fR undefined and output
Xwill be sent to /dev/null.
X.PP
X
Xhost \fIhostname classname xmittimes [options]\fR
X
Xdefines a host which to which
X.I newsxd
Xwill transmit netnews.
X.RS +.5i
X.IP hostname 15
XThe name of the host to pass to the netnews transmitter.
X.IP classname
XThe name of the service class that this host is in.
X.IP xmittimes
XThe time(s) to allow new transmitters to start for this host.  See the
Xmanpage for
X.I L.sys(5)
Xfor the format of
X.I xmittimes.
X.IP [options]
XThere are some options which can be used to modify the behavior of the
Xnetnews transmitter for a host:
X.RS +.5i
X.IP nice=\fIn\fR 15
XThis optional value is added to the \fInice(3)\fR of the netnews
Xtransmitter.  To be able to run at higher priorities (a lower \fInice\fR
Xvalue),
X.I newsxd
Xmust be
X.I setuid(3)
Xroot; otherwise
X.I newsxd
Xshould be
X.I setuid(3)
Xnews.  If no
X\fIdeltanice\fR value is specified, the nice of the transmitter is not
Xmodified by
X.I newsxd.
X.IP flags=\fIn\fR 15
XUsed to specify optional flags to be passed to the netnews transmitter for
Xthe host.  The flags must be separated by vertical bars (|), not spaces,
Xin the 
X.I newsxd.conf
Xfile.  Note that "-l something" would be TWO flags and you would say
Xflags=-l|something.
X.I Newsxd
Xwill automatically separate the flags before calling the netnews
Xtransmitter.
XXXX
X.IP ttl=\fIn[/m]\fR
XThe \fIttl\fR option may be used to override the default value established 
Xby the \fIclass\fR command (described above).
X.IP interval=\fIn[/m]\fR
XThe \fIinterval\fR option may be used to override the default value established 
Xby the \fIclass\fR command (described above).
X.IP maxload=\fIn\fR
XThe \fImaxload\fR option may be used to override the default value established 
Xby the \fIclass\fR command (described above).
X.IP maxxmits=\fIn\fR
XThe \fImaxxmits\fR option may be used to override the default value established 
Xby the \fIclass\fR command (described above).
X.RE
X.IN -5
X.PP
X.SH "SIMPLE EXAMPLE"
XThe following is an example of a simple configuration file:
X
X.nf
X.ft CW
X# Define a service class that just runs an nntpxmit to each host
X# every hour.  Don't run nntpxmit if the load goes over 8.
X
Xclass   normal  maxxmits=1  interval=3600  maxload=8
X
X# Define the default news transmitter
Xxmit    DEFAULT /usr/local/lib/news/nntpxmit nntpxmit %h:%w
X
X# Check the list of hosts every 10 minutes to see if we can send news to
X# someone yet.
Xqueueinterval    600
X
X# In all of the following options, %s is replaced by the host name of the
X# system being sent to.
X
X# File news places articles paths/ids in
Xbatchfile   /usr/spool/batch/%s
X
X# File a news transmitter wants articles paths/ids in
Xworkfile    /usr/spool/batch/%s.work
X
X# Hosts to send news to.  Each line is of the format:
X#                            CLASS   VALID START
X# host HOSTNAME              NAME       TIMES
X
Xhost dorothy                 normal  Any
Xhost toto                    normal  Any
Xhost wizard                  normal  Any
Xhost witch                   normal  Any
Xhost tinman                  normal  Any
Xhost lion                    normal  Any
X.ft P
X.fi
X.PP
X.RE
X.LP
X.SH "COMPLEX EXAMPLE"
XThe following is an example of a more complex configuration file that
Xuses most of the options supported by
X.I newsxd:
X
X.nf
X.ft CW
X# Define a series of service classes for sending news to other sites:
X#     nlink     NNTPlink Transmits (Continuous NNTPXMITs)
X#     high      High Priority Transmits (Top-40)
X#     med       Medium Prio Transmits (Non Top-40)
X#     low       Low Priority Transmits (Endnodes)
X#     batch     Batched (with sendbatch) newsfeeds
X
Xclass   nlink   maxxmits=20 interval=60    maxload=10  noworkfile
Xxmit    nlink   /usr/local/lib/news/nntplink nntplink %h:%b
X
Xclass   high    maxxmits=99 interval=60/20 maxload=8   ttl=1800
X
Xclass   med     maxxmits=5  interval=300   maxload=6   ttl=1800/60
X
Xclass   low     maxxmits=3  interval=1200  maxload=5   ttl=1100/60
X
Xclass   batch   maxxmits=1  interval=3600  maxload=5   ttl=1800/1800
Xxmit    batch   /usr/local/lib/news/sendbatch sendbatch %f %h
X
X# Define the default news transmitter
Xxmit    DEFAULT /usr/local/lib/news/nntpxmit nntpxmit %h:%w
X
X# Check the transmit queue every <n> seconds (this should be at least as
X# low as the smallest "interval" in all of the transmission classes).
Xqueueinterval    20
X
X# In all of the following options, %s is replaced by the host name of the
X# system being sent to.
X
X# File news places articles paths/ids in
Xbatchfile   /usr/spool/batch/%s
X
X# File a news transmitter wants articles paths/ids in
Xworkfile    /usr/spool/batch/%s.work
X
X# Where to log the output of a news transmitter (default is /dev/null)
X# xmitlogs   /usr/spool/batch/%s.log
X
X# Hosts to send news to.  Each line is of the format:
X#                            CLASS   VALID START
X# host HOSTNAME              NAME       TIMES          OPTIONS
X
Xhost dorothy                 low     Any               nice=10
Xhost toto                    low     Any               nice=10
Xhost wizard                  low     Any               nice=10
Xhost witch                   low     Any               nice=10
Xhost tinman                  low     Any               nice=10
Xhost lion                    low     Any               nice=10
Xhost cactus.biz.com          low     Any               nice=10
Xhost endnode.foobar.edu      low     Any2000-0500      nice=10
Xhost biggernode.foobar.edu   med     SaSu|Wk1730-0730
Xhost bignode.company.com     med     Any             
Xhost midsize.company.com     med     Any             
Xhost university.podunk.edu   med     Any             
Xhost mrbackbone.bigu.edu     high    Any             
Xhost gateway.bizness.com     high    Any             
Xhost supernews.hellou.edu    high    Any             
Xhost mrnntp.aloha.edu        high    Any             
Xhost hello.world.edu         high    Any             
Xhost supernews.foou.edu      nlink   Any
Xhost backbone.newssite.edu   nlink   Any
Xhost fred                    batch   Any nice=20 flags=-s500000 interval=86400
Xhost barney                  batch   Any nice=20 flags=-s250000 interval=86400
Xhost wilma                   batch   Any nice=20 flags=-s500000
Xhost betty                   batch   Any nice=20 flags=-s500000|-m500000
Xhost kitty                   batch   SaSu|Wk1730-730 flags=-c|-s250000
Xhost dino                    batch   SaSu|Wk1730-730 flags=-c|-s250000
Xhost bambam                  batch   Sa interval=86400
X
X# Notes: Only send news to biggernode.foobar.edu during non-business hours
X#        endnode.foobar.edu only wants news transmitted from 8PM to 5AM.
X#        Only send news to fred and barney once per day (every 24 hours).
X#        Do one batching run for bambam each Saturday.
X.ft P
X.fi
X.PP
X.RE
X.LP
X.SH "CONTROLLING NEWSXD"
XThe following signals have the specified effect when sent to the
Xserver
X.I named
Xprocess using the
X.I kill
Xcommand:
X.IP SIGHUP 13
XCauses newsxd to reload newsxd.conf and remove (kill) any hosts or
Xtransmitters which are no longer defined.
X.IP SIGTERM
XCauses newsxd to shut down, killing all active transmitters
X.IP SIGQUIT
XDumps the current newsxd status to
X.I /usr/tmp/newsxd.status
X.IP SIGIOT
XCauses newsxd to kill all active transmitters and go into idle mode.
XSend a HUP signal to newsxd to return to normal operating mode.
X.IP SIGIO
XCauses newsxd to go into idle mode, where no new transmitters are started.
XSend a HUP signal to newsxd to return to normal operating mode.
X.IP SIGTRAP
XCauses newsxd to write a DETAILED list of the contents of all important
Xinternal data structures to
X.I /usr/tmp/newsxd.status.dump
X.IP SIGUSR1
XIncreases the current debugging level.  Caution: the debugging information
Xcan get very voluminous, especially if DEBUG is enabled.
X.IP SIGUSR2
XDecreases the current debugging level.
X.SH "THE STATUS FILE"
XThe
X.I newsxd.status
Xfile, which is created when a SIGQUIT signal is sent to 
X.I newsxd,
Xshows the current state of all of the hosts managed by
X.I newsxd.
XThere are several pieces of information listed for each host,
Xincluding the host name, the times during which a new netnews transmitter
Xcan be started, the last time a netnews transmitter was started, and a
X"Why Not Running" field which indicates why a netnews transmitter is not
Xcurrently running for that host.  The various types of "Why Not Running"
Xmessages include:
X
X.IP "TTL Penlty" 15
XThe netnews transmitter for the host ran longer than the time-to-live
Xdefined for the service class, and the host is currently being penalized.
X.IP "TTL Kill"
XThe netnews transmitter for the host was just killed because it ran
Xlonger than the time-to-live defined for the service class.
X.IP "Class Intv"
XNo new transmitters in this service class can start up yet because the
Xintra-class transmitter startup interval hasn't passed.  See the
X.I interval
Xoption under
X.I class,
Xabove.
X.IP "Host Intvl"
XNo new transmitters for this host can start up yet because a transmitter
Xhas already been run for this host recently (see the 
X.I interval
Xoption under
X.I class,
Xabove).
X.IP "High Load"
XThe system load is too high to start new netnews transmitters for this
Xservice class.  See the
X.I maxload
Xoption under
X.I class,
Xabove.
X.IP "Wrong Time"
XThe current time doesn't fit any of the allowed startup times specified
Xfor the host.
X.IP "Max Xmits"
XThe maximum number of netnews transmitters for this class are already
Xrunning.  See the
X.I maxxmits
Xoption under
X.I class,
Xabove.
X.IP "RUNNING"
XA netnews transmitter for this host is currently running.
X.IP "No Work"
XThere are currently no articles to send to this host.
X.IP "Bad Rename"
X.I newsxd
Xcouldn't rename the host's
X.I batchfile
Xto the
X.I workfile.
X.IP "NotMyTurn"
XThe host has already had a chance to transmit news and now it's time for
Xthe other hosts to get a chance.  
X.I Newsxd
Xuses a round-robin scheduling algorithm to insure the fair transmission
Xof netnews.
X
X.SH RESTRICTIONS
XDoes not do exponential backoff when the transmitter for a host fails.
X.SH BUGS
XNo known bugs exist in
X.I newsxd,
Xbut the wish list of features to add is quite long...
X.SH FILES
X.IP /usr/local/etc/newsxd.conf 28
X.I newsxd
Xconfiguration file
X.IP /usr/tmp/newsxd.pid 
XProcess ID number
X.IP /usr/tmp/newsxd.status 
XDump of
X.I newsxd
Xstatus
X.IP /usr/spool/batch/*
Xbatch and work files for
X.I newsxd
Xand netnews transmitters.
X.SH "SEE ALSO"
Xnntpxmit(1)
X.SH AUTHOR
XChris Myers <chris@wugate.wustl.edu>
END_OF_FILE
  if test 17954 -ne `wc -c <'newsxd.8'`; then
    echo shar: \"'newsxd.8'\" unpacked with wrong size!
  fi
  # end of 'newsxd.8'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.