nbatcher re-posting

Bob Esposito espo at bpa.BELL-ATL.COM
Wed Aug 20 08:29:55 AEST 1986


        This is a re-posting of the nbatcher source for spooling
        news articles.  The fixes are mostly the inclusion of
        newlines where needed, but the most important one is to
        prevent copies of the news articles being written to the
        logfile, is some cases.


        A copy was also sent to rs at mirror (mod.sources) for archive
        purposes.

--
        //////////////////////////////////////////
        * Bob Esposito  ...espo at bpa.bell-atl.com *
        //////////////////////////////////////////

---------cut-here------------cut-here--------------cut-here--------------------
#!/bin/sh
# shar: Shell Archiver
#       Run the following text with /bin/sh to create:
#       define.c
#       main.c
#       parse.c
#       checkwork.c
#       nbatcher.c
#       logger.c
#       nbatcher.h
#       bst.c
#       README
#       nbatcher.ctl
#       nbatcher.doc
#       nbatcher.1
#       Makefile
echo x - extracting define.c
sed 's/^X//' << 'SHAR_EOF' > define.c
X/* char        sccsid[] = "@(#)define.c 1.4 8/14/86"; */
X
X/*******************************************************
X *     define.c - global defines for nbatcher.
X *
X *     R.J. Esposito
X *     Bell of Penna.
X *     June 1986
X *
X ******************************************************/
X
X#include <stdio.h>
X#include "nbatcher.h"
X
XFILE   *lfp,
X       *tfp,
X       *log = NULL;
X
Xlong   n_bytes,
X       cu_bytes;
X
Xchar   *tfile = NULL;
X
Xshort  vflg = 0,
X       nfiles = 10;
X
Xint    fcnt = 0,
X       scnt = 0;
X
SHAR_EOF
echo x - extracting main.c
sed 's/^X//' << 'SHAR_EOF' > main.c
Xchar   sccsid[] = "nbatcher 1.4 8/14/86";
X
X/********************************************
X *
X *     main.c - for nbatcher
X *
X *     R.J. Esposito
X *     Bell of Penna.
X *     June 1986
X *
X ********************************************/
X
X#include <stdio.h>
X#include "nbatcher.h"
X
Xmain()
X{
X       int     uid, nowork;
X       FILE    *cfp;
X       char    fbuf[BUFSIZ];
X
X       uid = getuid();
X
X       if (uid && uid != NEWSUID)
X               xerror ("permission denied - not NEWSUSER\n");
X
X       if (chdir(LIBDIR) < 0)
X               xerror ("can't chdir to %s\n", LIBDIR);
X
X       if ((cfp=fopen("nbatcher.ctl", "r")) == NULL)
X               xerror ("no `batcher.ctl' file found\n");
X
X       if (isatty(0)) {
X               vflg = TRUE;
X               (void) fprintf(stderr, "%s\n", sccsid);
X       }
X
X       nowork = TRUE;
X       while ((fgets(fbuf, sizeof(fbuf), cfp)) != NULL) {
X               if (fbuf[0] == '*' || fbuf[0] == '\n')
X                       continue;
X               parse_entry (fbuf);
X               if (!work_to_do())
X                       continue;
X               batch_it ();
X               nowork = FALSE;
X       }
X
X       fclose (cfp);
X       fclose (tfp);
X       unlink (tfile);
X       if (vflg == TRUE && nowork == TRUE)
X               (void) fprintf(stderr, "no work to do\n");
X       exit (0);
X}
X
SHAR_EOF
echo x - extracting parse.c
sed 's/^X//' << 'SHAR_EOF' > parse.c
X/* char        sccsid[] = "@(#)parse.c 1.4 8/14/86"; */
X
X/****************************************************************
X *
X *     parse.c - nbatcher line parser for the control file
X *
X *
X *     R.J. Esposito
X *     Bell of Penna.
X *     June 1986
X *
X ****************************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <ctype.h>
X#include "nbatcher.h"
X
X#define MAX_BYTES      1000000L        /* max allowable bytes */
X
Xparse_entry (line)
Xchar *line;
X{
X       register char   *p;
X       short   num, upper;
X       short   lower, dash;
X       long    l_num;
X
X       upper = 23;     /* upper hour limit */
X       lower = 0;      /* lower hour limit */
X       dash = 0;
X
X       clear_entry (&ep);      /* zero out the structure */
X
X       p = (char *) ep.site;
X
X       /* get the site name and copy
X          it to the structure */
X
X       while (*line && *line != COLON)
X               *p++ = *line++;
X       *p = '\0';
X       if (*++line == '\n' || *line == '\0')
X               xerror ("illegal number of fields\n");
X
X       /* check that its valid */
X
X       if (ep.site[0] == '\0')
X               xerror ("null site name in control file\n");
X
X       /* now, parse the hour string and check
X          for valid syntax */
X
X       p = (char *) ep.hour;
X       while (*line && *line != COLON)
X               *p++ = *line++;
X
X       *p = '\0';
X       if (*++line == '\n' || *line == '\0')
X               xerror ("illegal number of fields\n");
X
X       if (ep.hour[0] == '\0')
X               xerror ("null hour string in control file\n");
X
X       /* now re-scan the hour in structure and
X          weed out the badies */
X
X       if (ep.hour[0] == '*' && ep.hour[1] != '\0')
X               xerror ("invalid hour string syntax: %s\n", ep.hour);
X       else if (ep.hour[0] == '*')
X               goto h_skip;
X
X       if (strcmp(ep.hour, "off", 3) == 0 && ep.hour[3] != '\0')
X               xerror ("invalid hour string syntax: %s\n", ep.hour);
X       else if (strncmp(ep.hour, "off", 3) == 0)
X               goto h_skip;
X
X       p = (char *) ep.hour;
X       if (!isdigit(*p))
X               xerror ("non-numeric char in hour string: %c\n", *p);
X
X       while (*p) {
X               num = 0;
X               do {
X                       num = num*10 + (*p - '0');
X               } while (isdigit(*++p));
X
X               if (num < lower || num > upper)
X                       xerror ("illegal hour: %d\n", num);
X
X               if (!*p)
X                       break;
X
X               if (*p == '-' && dash)
X                       xerror ("syntax error in hour field\n");
X               else if (*p == '-')
X                       dash = TRUE;
X
X               if (*p != ',' && *p != '-')
X                       xerror ("non-numeric char in hour string: %c\n", *p);
X               else if (!isdigit(*++p))
X                       xerror ("syntax error in hour field\n");
X
X       }
X
X       /* now that thats over with, let do the compression
X          field.  Only 9-16 is allowed, except a null field
X          indicates no compression for this site. */
X
Xh_skip:
X       num = 0;
X       while (*line && *line != COLON) {
X               if (!isdigit(*line))
X                       xerror ("non-numeric in compression field\n");
X               num = num*10 + (*line++ - '0');
X       }
X       if (*++line == '\n' || *line == '\0')
X               xerror ("illegal number of fields\n");
X
X       if (num != 0 && (num < 9 || num > 16))
X               xerror ("illegal compression bits: %d\n", num);
X
X       ep.c_bits = num;
X
X       /* now check the max. bytes for UUCP queue.
X          Note: There is a max. allowable # of bytes
X                here, set at 1MB.  Change it at your
X                own risk.
X       */
X
X       l_num = 0;
X       while (*line && *line != COLON) {
X               if (!isdigit(*line))
X                       xerror ("non-numeric in max. bytes field\n");
X
X               l_num = l_num*10 + (*line++ - '0');
X       }
X
X       if (l_num > MAX_BYTES)
X               xerror ("%ld max. bytes exceeds allowable maximun\n", l_num);
X
X       if (l_num != 0)
X               ep.m_bytes = l_num;
X       else
X               ep.m_bytes = DFL_BYTES;
X
X       /* and finally the command line (if there is one) */
X
X       p = (char *) ep.command;
X
X       if (*++line != '\n' && *line != '\0') {
X               while (*line && *line != '\n')
X                       *p++ = *line++;
X
X               *p = '\0';
X       }
X}
X
X#ifdef USE_PORT_CODE
Xxerror (fmt, a1, a2)
Xchar *fmt;
Xchar *a1, *a2;
X{
X       char    buf[BUFSIZ];
X
X       sprintf (buf, fmt, a1, a2);
X       printf ("\nnbatcher: %s\n", fmt);
X       exit (99);
X}
X
X#else
Xxerror (fmt, argp)
Xchar *fmt;
Xint argp;
X{
X       char    buf[BUFSIZ];
X       char    fbuf[BUFSIZ];
X       FILE    prwbuf;
X       register char   *cp;
X
X       prwbuf._flag = _IOWRT;
X       prwbuf._file = _NFILE;
X       prwbuf._cnt = 32767;
X       prwbuf._ptr = (unsigned char *)buf;
X       prwbuf._base = (unsigned char *)buf;
X       sprintf (fbuf, "\n%s: %s", "nbatcher", fmt);
X       _doprnt (fbuf, (char *)&argp, &prwbuf);
X       putc ('\0', &prwbuf);
X       for (cp = buf; *cp != '\0'; cp++)
X               putchar (*cp);
X
X       exit (99);
X}
X#endif /* USE_PORT_CODE */
X
Xclear_entry (s)
Xchar *s;
X{
X       register int i;
X
X       for (i=0; i<sizeof(struct file_entry); *s++ = '\0', i++)
X                               ;
X
X}
SHAR_EOF
echo x - extracting checkwork.c
sed 's/^X//' << 'SHAR_EOF' > checkwork.c
X/* char        sccsid[] = "@(#)checkwork.c 1.4 8/14/86"; */
X
X/************************************************************
X *
X *     checkwork.c - look to see if there's any work
X *                   to do for a site.
X *
X *     R.J. Esposito
X *     Bell of Penna.
X *     June 1986
X *
X ************************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/utsname.h>
X#include <sys/dir.h>
X#include <ctype.h>
X#include <time.h>
X#include "nbatcher.h"
X
Xwork_to_do ()
X{
X       register char   *p;
X       struct tm       *localtime(), *tp;
X       struct stat     st;
X       char    buf[BUFSIZ];
X       long    time(), clock;
X       int     hour;
X       short   num, upper, lower;
X
X       sprintf (buf, "%s/%s", BATCHDIR, ep.site);
X
X       if (stat(buf, &st) < 0)
X               xerror ("bad stat on %s\n", buf);
X
X       /* if the size of the batch file is
X          zero, return FALSE
X       */
X
X       if (st.st_size == 0)
X               return (FALSE);
X
X       /* now see if it time to do anything */
X
X       clock = time ((long *)0);
X       tp = localtime (&clock);
X       hour = tp->tm_hour;
X
X       p = (char *) ep.hour;
X
X       if (*p == '*')          /* match any hour */
X               return (check_uucp());
X
X       if (strncmp(p, "off", 3) == 0)  /* just what it says, off */
X               return (FALSE);
X
X       /* parse thru hour field to see if
X          this is the hour to do work */
X
X       num = 0;
X       do {
X               num = num*10 + (*p - '0');
X       } while (isdigit(*++p));
X       if (num == hour)
X               return (check_uucp());
X
X       if (*p == '-') {
X               lower = num;
X               p++;
X               num = 0;
X               do {
X                       num = num*10 + (*p - '0');
X               } while (isdigit(*++p));
X               upper = num;
X
X               if (lower < upper) {    /* normal hour range */
X                       if (hour >= lower && hour <= upper)
X                               return (check_uucp());
X               } else if (lower > upper) {     /* 24 hr. cycle thru */
X                       if (hour >= lower || hour <= upper)
X                               return (TRUE);
X               } else
X                       return (FALSE);
X       }
X
X       if (*p == ',') {
X               p++;
X               while (*p) {
X                       num = 0;
X                       do {
X                               num = num*10 + (*p - '0');
X                       } while (isdigit(*++p));
X                       if (num == hour)
X                               return (check_uucp());
X                       p++;
X               }
X       }
X
X       return (FALSE);
X}
X
X/*     If check_uucp cannot find the remote site
X *     directory, just bypass the byte counting
X *     routine.  This is necessary because the
X *     uucpcleanup daemon, on some sites, removes
X *     the site directory when there's nothing there.
X */
X
Xcheck_uucp()
X{
X       struct utsname  utsn;
X       struct direct   dp;
X       struct stat     st;
X       FILE    *dfp;
X       char    u_name[9], buf[80];
X       short   prefix_len;
X
X       if (uname(&utsn) < 0)
X               xerror ("can't get local nodename\n");
X
X       sprintf (buf, "%s/%s", UUCPDIR, ep.site);
X       if (chdir(buf) < 0) {
X          fprintf (stderr, "\nnbatcher: can't chdir to %s - bypassing UUCP check\n", buf);
X          return (TRUE);
X       }
X
X       if ((dfp=fopen(".", "r")) == NULL) {
X          fprintf (stderr, "\nnbatcher: fopen error on %s - bypassing UUCP check\n", UUCPDIR);
X          return (TRUE);
X       }
X
X       sprintf (buf, "D.%s", utsn.nodename);
X       prefix_len = (short) strlen(buf);
X       n_bytes = 0;
X       while ((fread((char *)&dp, sizeof(dp), 1, dfp)) == 1) {
X               if (dp.d_ino == 0 || dp.d_name[0] == '.')
X                       continue;
X               if (strncmp(dp.d_name, buf, prefix_len))
X                       continue;
X               if (stat(dp.d_name, &st) < 0) {
X                 fprintf (stderr, "\nnbatcher: bad stat on UUCP_file %s - bypassing\n", dp.d_name);
X                 continue;
X               }
X               n_bytes += st.st_size;
X               if (n_bytes > ep.m_bytes) {
X                       fclose (dfp);
X                       return (FALSE);
X               }
X       }
X       fclose (dfp);
X       if (chdir(LIBDIR) < 0)
X               xerror ("can't chdir back to %s\n", LIBDIR);
X
X       return (TRUE);
X}
SHAR_EOF
echo x - extracting nbatcher.c
sed 's/^X//' << 'SHAR_EOF' > nbatcher.c
X/* char        sccsid[] = "@(#)nbatcher.c 1.4 8/14/86"; */
X
X/****************************************************
X *
X *     nbatcher.c - where it really happens.
X *
X *     R.J. Esposito
X *     Bell of Penna.
X *     June 1986
X *
X ***************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <time.h>
X#include "nbatcher.h"
X
Xbatch_it ()
X{
X       struct stat     st;
X       FILE    *bfp, *afp;
X       char    fbuf[BUFSIZ], lckfile[40];
X       char    tbuf[80];
X       short   count;
X       int     c;
X
X       if (chdir(BATCHDIR) < 0)
X               xerror ("can't chdir to %s\n", BATCHDIR);
X
X       /* we create a lock file for two purposes,
X          first to make sure a previous nbatcher
X          didn't blowup and leave the lock file
X          laying around, and second to put the
X          remaining news article filenames when
X          we go over the max UUCP bytes and there's
X          still files remaining for batching.
X       */
X
X       sprintf (lckfile, ".%s.lock", ep.site);
X       if (!access(lckfile, 0))
X               xerror ("lockfile already exists for %s\n", ep.site);
X
X       if ((lfp=fopen(lckfile, "w")) == NULL)
X               xerror ("can't create lockfile for %s\n", ep.site);
X
X       /* now that we've locked ourselves for this site,
X          lets carry on */
X
X       if ((bfp=fopen(ep.site, "r")) == NULL)
X               xerror ("can't open %s/%s for reading\n", BATCHDIR, ep.site);
X
X       if (tfile == NULL) {
X               tfile = mktemp("/tmp/bnewsXXXXXX");
X               if ((tfp=fopen(tfile, "w")) == NULL)
X                       xerror ("can't open %s for writing\n", tfile);
X       }
X
X       count = fcnt = scnt = 0;
X       cu_bytes = 0;
X       while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL) {
X               fbuf[strlen(fbuf)-1] = '\0';    /* remove the newline */
X               if ((afp=fopen(fbuf, "r")) == NULL) {
X                  fprintf (stderr, "\nbypassing article %s: can't read it\n",
X                           fbuf);
X                       continue;
X               }
X               if (fstat(fileno(afp), &st) < 0)
X                       xerror ("fstat failed on %s\n", fbuf);
X
X               cu_bytes += st.st_size;
X
X               /* if the max byte count is exceeded,
X                  save the remaining files for later */
X
X               if ((cu_bytes + n_bytes) > ep.m_bytes) {
X                       fprintf (lfp, "%s\n", fbuf); /* put the '\n' back */
X                       while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL)
X                               fputs (fbuf, lfp);
X                       fclose (bfp);
X                       fclose (lfp);
X                       fclose (afp);
X                       unlink (ep.site);
X                       if (link(lckfile, ep.site) < 0)
X                          xerror ("can't link lockfile to %s\n", ep.site);
X                       unlink (lckfile);
X                       chown (ep.site, NEWSUID, NEWSGID);
X                       if (count)
X                               spoolit ();
X                       if (cu_bytes - st.st_size)
X                               log_it (cu_bytes - st.st_size);
X
X                       return;
X               }
X               sprintf (tbuf, "



More information about the Comp.sources.unix mailing list