chiark / gitweb /
REORG Delete everything that's not innduct or build system or changed for innduct
[innduct.git] / backends / innxbatch.c
diff --git a/backends/innxbatch.c b/backends/innxbatch.c
deleted file mode 100644 (file)
index 9ebfe9c..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-/*  $Id: innxbatch.c 6351 2003-05-19 02:00:06Z rra $
-**
-**  Transmit batches to remote site, using the XBATCH command
-**  Modelled after innxmit.c and nntpbatch.c
-**
-**  Invocation:
-**     innxbatch [options] <serverhost> <file> ...
-#ifdef FROMSTDIN
-**     innxbatch -i <serverhost>
-#endif FROMSTDIN
-**  will connect to serverhost's nntp port, and transfer the named files,
-**  with an xbatch command for every file. Files that have been sent
-**  successfully are unlink()ed. In case of any error, innxbatch terminates
-**  and leaves any remaining files untouched, for later transmission.
-**  Options:
-**     -D      increase debug level
-**     -v      report statistics to stdout
-#ifdef FROMSTDIN
-**     -i      read batch file names from stdin instead from command line.
-**             For each successfully transmitted batch, an OK is printed on
-**             stdout, to indicate that another file name is expected.
-#endif
-**     -t      Timeout for connection attempt
-**     -T      Timeout for batch transfers.
-**  We do not use any file locking. At worst, a batch could be transmitted
-**  twice in parallel by two independant invocations of innxbatch.
-**  To prevent this, innxbatch should be invoked by a shell script that uses
-**  shlock(1) to achieve mutual exclusion.
-*/
-
-#include "config.h"
-#include "clibrary.h"
-#include "portable/socket.h"
-#include "portable/time.h"
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <syslog.h>
-#include <sys/stat.h>
-
-/* Needed on AIX 4.1 to get fd_set and friends. */
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
-#endif
-
-#include "inn/innconf.h"
-#include "inn/messages.h"
-#include "inn/timer.h"
-#include "libinn.h"
-#include "nntp.h"
-
-/*
-** Syslog formats - collected together so they remain consistent
-*/
-static char    STAT1[] =
-       "%s stats offered %lu accepted %lu refused %lu rejected %lu";
-static char    STAT2[] = "%s times user %.3f system %.3f elapsed %.3f";
-static char    CANT_CONNECT[] = "%s connect failed %s";
-static char    CANT_AUTHENTICATE[] = "%s authenticate failed %s";
-static char    XBATCH_FAIL[] = "%s xbatch failed %s";
-static char    UNKNOWN_REPLY[] = "Unknown reply after sending batch -- %s";
-static char    CANNOT_UNLINK[] = "cannot unlink %s: %m";
-/*
-**  Global variables.
-*/
-static bool            Debug = 0;
-static bool            STATprint;
-static char            *REMhost;
-static double          STATbegin;
-static double          STATend;
-static char            *XBATCHname;
-static int             FromServer;
-static int             ToServer;
-static sig_atomic_t    GotAlarm;
-static sig_atomic_t    GotInterrupt;
-static sig_atomic_t    JMPyes;
-static jmp_buf         JMPwhere;
-static unsigned long   STATaccepted;
-static unsigned long   STAToffered;
-static unsigned long   STATrefused;
-static unsigned long   STATrejected;
-
-/*
-**  Send a line to the server. \r\n will be appended
-*/
-static bool
-REMwrite(int fd, char *p)
-{
-  int          i;
-  int          err;
-  char         *dest;
-  static char          buff[NNTP_STRLEN];
-
-  for (dest = buff, i = 0; p[i]; ) *dest++ = p[i++];
-  *dest++ = '\r';
-  *dest++ = '\n';
-  *dest++ = '\0';
-
-  for (dest = buff, i+=2; i; dest += err, i -= err) {
-    err = write(fd, dest, i);
-    if (err < 0) {
-      syswarn("cannot write %s to %s", dest, REMhost);
-      return false;
-    }
-  }
-  if (Debug)
-    fprintf(stderr, "> %s\n", p);
-
-  return true;
-}
-
-/*
-**  Print transfer statistics, clean up, and exit.
-*/
-static void
-ExitWithStats(int x)
-{
-  static char          QUIT[] = "quit";
-  double               usertime;
-  double               systime;
-
-  REMwrite(ToServer, QUIT);
-
-  STATend = TMRnow_double();
-  if (GetResourceUsage(&usertime, &systime) < 0) {
-    usertime = 0;
-    systime = 0;
-  }
-
-  if (STATprint) {
-    printf(STAT1,
-       REMhost, STAToffered, STATaccepted, STATrefused, STATrejected);
-    printf("\n");
-    printf(STAT2, REMhost, usertime, systime, STATend - STATbegin);
-    printf("\n");
-  }
-
-  syslog(L_NOTICE, STAT1,
-        REMhost, STAToffered, STATaccepted, STATrefused, STATrejected);
-  syslog(L_NOTICE, STAT2, REMhost, usertime, systime, STATend - STATbegin);
-
-  exit(x);
-  /* NOTREACHED */
-}
-
-
-/*
-**  Clean up the NNTP escapes from a line.
-*/
-static char *
-REMclean(char *buff)
-{
-    char       *p;
-
-    if ((p = strchr(buff, '\r')) != NULL)
-       *p = '\0';
-    if ((p = strchr(buff, '\n')) != NULL)
-       *p = '\0';
-
-    /* The dot-escape is only in text, not command responses. */
-    return buff;
-}
-
-
-/*
-**  Read a line of input, with timeout. We expect only answer lines, so
-**  we ignore \r\n-->\n mapping and the dot escape.
-**  Return true if okay, *or we got interrupted.*
-*/
-static bool
-REMread(char *start, int size)
-{
-  char *p, *h;
-  struct timeval t;
-  fd_set rmask;
-  int i;
-
-  for (p = start; size; ) {
-    FD_ZERO(&rmask);
-    FD_SET(FromServer, &rmask);
-    t.tv_sec = 10 * 60;
-    t.tv_usec = 0;
-    i = select(FromServer + 1, &rmask, NULL, NULL, &t);
-    if (GotInterrupt) return true;
-    if (i < 0) {
-      if (errno == EINTR) continue;
-      else return false;
-    }
-    if (i == 0 || !FD_ISSET(FromServer, &rmask)) return false;
-    i = read(FromServer, p, size-1);
-    if (GotInterrupt) return true;
-    if (i <= 0) return false;
-    h = p;
-    p += i;
-    size -= i;
-    for ( ; h < p; h++) {
-      if (h > start && '\n' == *h && '\r' == h[-1]) {
-       *h = h[-1] = '\0';
-       size = 0;
-      }
-    }
-  }
-
-  if (Debug)
-    fprintf(stderr, "< %s\n", start);
-
-  return true;
-}
-
-
-/*
-**  Handle the interrupt.
-*/
-static void
-Interrupted(void)
-{
-  warn("interrupted");
-  ExitWithStats(1);
-}
-
-
-/*
-**  Send a whole xbatch to the server. Uses the global variables
-**  REMbuffer & friends
-*/
-static bool
-REMsendxbatch(int fd, char *buf, int size)
-{
-  char *p;
-  int          i;
-  int          err;
-
-  for (i = size, p = buf; i; p += err, i -= err) {
-    err = write(fd, p, i);
-    if (err < 0) {
-      syswarn("cannot write xbatch to %s", REMhost);
-      return false;
-    }
-  }
-  if (GotInterrupt) Interrupted();
-  if (Debug)
-    fprintf(stderr, "> [%d bytes of xbatch]\n", size);
-
-  /* What did the remote site say? */
-  if (!REMread(buf, size)) {
-    syswarn("no reply after sending xbatch");
-    return false;
-  }
-  if (GotInterrupt) Interrupted();
-  
-  /* Parse the reply. */
-  switch (atoi(buf)) {
-  default:
-    warn("unknown reply after sending batch -- %s", buf);
-    syslog(L_ERROR, UNKNOWN_REPLY, buf);
-    return false;
-    /* NOTREACHED */
-    break;
-  case NNTP_RESENDIT_VAL:
-  case NNTP_GOODBYE_VAL:
-    syslog(L_NOTICE, XBATCH_FAIL, REMhost, buf);
-    STATrejected++;
-    return false;
-    /* NOTREACHED */
-    break;
-  case NNTP_OK_XBATCHED_VAL:
-    STATaccepted++;
-    if (Debug) fprintf(stderr, "will unlink(%s)\n", XBATCHname);
-    if (unlink(XBATCHname)) {
-      /* probably another incarantion was faster, so avoid further duplicate
-       * work
-       */
-      syswarn("cannot unlink %s", XBATCHname);
-      syslog(L_NOTICE, CANNOT_UNLINK, XBATCHname);
-      return false;
-    }
-    break;
-  }
-  
-  /* Article sent */
-  return true;
-}
-
-/*
-**  Mark that we got interrupted.
-*/
-static RETSIGTYPE
-CATCHinterrupt(int s)
-{
-    GotInterrupt = true;
-
-    /* Let two interrupts kill us. */
-    xsignal(s, SIG_DFL);
-}
-
-
-/*
-**  Mark that the alarm went off.
-*/
-/* ARGSUSED0 */
-static RETSIGTYPE
-CATCHalarm(int s UNUSED)
-{
-    GotAlarm = true;
-    if (JMPyes)
-       longjmp(JMPwhere, 1);
-}
-
-
-/*
-**  Print a usage message and exit.
-*/
-static void
-Usage(void)
-{
-    warn("Usage: innxbatch [-Dv] [-t#] [-T#] host file ...");
-#ifdef FROMSTDIN
-    warn("       innxbatch [-Dv] [-t#] [-T#] -i host");
-#endif
-    exit(1);
-}
-
-
-int
-main(int ac, char *av[])
-{
-  int                  i;
-  char                  *p;
-  FILE                 *From;
-  FILE                 *To;
-  char                 buff[NNTP_STRLEN];
-  RETSIGTYPE           (*old)(int) = NULL;
-  unsigned int         ConnectTimeout;
-  unsigned int         TotalTimeout;
-  struct stat          statbuf;
-  int                  fd;
-  int                  err;
-  char                 *XBATCHbuffer = NULL;
-  int                  XBATCHbuffersize = 0;
-  int                  XBATCHsize;
-
-  openlog("innxbatch", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG);
-  message_program_name = "innxbatch";
-
-  /* Set defaults. */
-  if (!innconf_read(NULL))
-      exit(1);
-  ConnectTimeout = 0;
-  TotalTimeout = 0;
-  umask(NEWSUMASK);
-
-  /* Parse JCL. */
-  while ((i = getopt(ac, av, "Dit:T:v")) != EOF)
-    switch (i) {
-    default:
-      Usage();
-      /* NOTREACHED */
-      break;
-    case 'D':
-      Debug++;
-      break;
-#ifdef FROMSTDIN
-    case 'i':
-      FromStdin = true;
-      break;
-#endif
-    case 't':
-      ConnectTimeout = atoi(optarg);
-      break;
-    case 'T':
-      TotalTimeout = atoi(optarg);
-      break;
-    case 'v':
-      STATprint = true;
-      break;
-    }
-  ac -= optind;
-  av += optind;
-
-  /* Parse arguments; host and filename. */
-  if (ac < 2)
-    Usage();
-  REMhost = av[0];
-  ac--;
-  av++;
-
-  /* Open a connection to the remote server. */
-  if (ConnectTimeout) {
-    GotAlarm = false;
-    old = xsignal(SIGALRM, CATCHalarm);
-    JMPyes = true;
-    if (setjmp(JMPwhere))
-      die("cannot connect to %s: timed out", REMhost);
-    alarm(ConnectTimeout);
-  }
-  if (NNTPconnect(REMhost, NNTP_PORT, &From, &To, buff) < 0 || GotAlarm) {
-    i = errno;
-    warn("cannot connect to %s: %s", REMhost,
-         buff[0] ? REMclean(buff): strerror(errno));
-    if (GotAlarm)
-      syslog(L_NOTICE, CANT_CONNECT, REMhost, "timeout");
-    else
-      syslog(L_NOTICE, CANT_CONNECT, REMhost,
-            buff[0] ? REMclean(buff) : strerror(i));
-    exit(1);
-  }
-
-  if (Debug)
-    fprintf(stderr, "< %s\n", REMclean(buff));
-  if (NNTPsendpassword(REMhost, From, To) < 0 || GotAlarm) {
-    i = errno;
-    syswarn("cannot authenticate with %s", REMhost);
-    syslog(L_ERROR, CANT_AUTHENTICATE,
-          REMhost, GotAlarm ? "timeout" : strerror(i));
-    /* Don't send quit; we want the remote to print a message. */
-    exit(1);
-  }
-  if (ConnectTimeout) {
-    alarm(0);
-    xsignal(SIGALRM, old);
-    JMPyes = false;
-  }
-  
-  /* We no longer need standard I/O. */
-  FromServer = fileno(From);
-  ToServer = fileno(To);
-
-#if    defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF)
-  i = 24 * 1024;
-  if (setsockopt(ToServer, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof i) < 0)
-    perror("cant setsockopt(SNDBUF)");
-  if (setsockopt(FromServer, SOL_SOCKET, SO_RCVBUF, (char *)&i, sizeof i) < 0)
-    perror("cant setsockopt(RCVBUF)");
-#endif /* defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) */
-
-  GotInterrupt = false;
-  GotAlarm = false;
-
-  /* Set up signal handlers. */
-  xsignal(SIGHUP, CATCHinterrupt);
-  xsignal(SIGINT, CATCHinterrupt);
-  xsignal(SIGTERM, CATCHinterrupt);
-  xsignal(SIGPIPE, SIG_IGN);
-  if (TotalTimeout) {
-    xsignal(SIGALRM, CATCHalarm);
-    alarm(TotalTimeout);
-  }
-
-  /* Start timing. */
-  STATbegin = TMRnow_double();
-
-  /* main loop over all specified files */
-  for (XBATCHname = *av; ac && (XBATCHname = *av); av++, ac--) {
-
-    if (Debug) fprintf(stderr, "will work on %s\n", XBATCHname);
-
-    if (GotAlarm) {
-      warn("timed out");
-      ExitWithStats(1);
-    }
-    if (GotInterrupt) Interrupted();
-
-    if ((fd = open(XBATCHname, O_RDONLY, 0)) < 0) {
-      syswarn("cannot open %s, skipping", XBATCHname);
-      continue;
-    }
-
-    if (fstat(fd, &statbuf)) {
-      syswarn("cannot stat %s, skipping", XBATCHname);
-      close(i);
-      continue;
-    }
-
-    XBATCHsize = statbuf.st_size;
-    if (XBATCHsize == 0) {
-      warn("batch file %s is zero length, skipping", XBATCHname);
-      close(i);
-      unlink(XBATCHname);
-      continue;
-    } else if (XBATCHsize > XBATCHbuffersize) {
-      XBATCHbuffersize = XBATCHsize;
-      if (XBATCHbuffer) free(XBATCHbuffer);
-      XBATCHbuffer = xmalloc(XBATCHsize);
-    }
-
-    err = 0; /* stupid compiler */
-    for (i = XBATCHsize, p = XBATCHbuffer; i; i -= err, p+= err) {
-      err = read(fd, p, i);
-      if (err < 0) {
-        syswarn("error reading %s, skipping", XBATCHname);
-       break;
-      } else if (0 == err) {
-        syswarn("unexpected EOF reading %s, truncated", XBATCHname);
-       XBATCHsize = p - XBATCHbuffer;
-       break;
-      }
-    }
-    close(fd);
-    if (err < 0)
-      continue;
-
-    if (GotInterrupt) Interrupted();
-
-    /* Offer the xbatch. */
-    snprintf(buff, sizeof(buff), "xbatch %d", XBATCHsize);
-    if (!REMwrite(ToServer, buff)) {
-      syswarn("cannot offer xbatch to %s", REMhost);
-      ExitWithStats(1);
-    }
-    STAToffered++;
-    if (GotInterrupt) Interrupted();
-
-    /* Does he want it? */
-    if (!REMread(buff, (int)sizeof buff)) {
-      syswarn("no reply to XBATCH %d from %s", XBATCHsize, REMhost);
-      ExitWithStats(1);
-    }
-    if (GotInterrupt) Interrupted();
-
-    /* Parse the reply. */
-    switch (atoi(buff)) {
-    default:
-      warn("unknown reply to %s -- %s", XBATCHname, buff);
-      ExitWithStats(1);
-      /* NOTREACHED */
-      break;
-    case NNTP_RESENDIT_VAL:
-    case NNTP_GOODBYE_VAL:
-      /* Most likely out of space -- no point in continuing. */
-      syslog(L_NOTICE, XBATCH_FAIL, REMhost, buff);
-      ExitWithStats(1);
-      /* NOTREACHED */
-    case NNTP_CONT_XBATCH_VAL:
-      if (!REMsendxbatch(ToServer, XBATCHbuffer, XBATCHsize))
-       ExitWithStats(1);
-      /* NOTREACHED */
-      break;
-    case NNTP_SYNTAX_VAL:
-    case NNTP_BAD_COMMAND_VAL:
-      warn("server %s seems not to understand XBATCH: %s", REMhost, buff);
-      syslog(L_FATAL, XBATCH_FAIL, REMhost, buff);
-      break;
-    }
-  }
-  ExitWithStats(0);
-  /* NOTREACHED */
-  return 0;
-}