home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume36 / slurp / part01 / slurp.c < prev   
Encoding:
C/C++ Source or Header  |  1993-03-12  |  16.7 KB  |  767 lines

  1. /*
  2.  * slurp - a passive nntp news client
  3.  *
  4.  * Copyright (C) 1992/93 Stephen Hebditch. All rights reserved.
  5.  * TQM Communications, BCM Box 225, London, WC1N 3XX.
  6.  * steveh@orbital.demon.co.uk  +44 836 825962
  7.  *
  8.  * See README for more information and disclaimers
  9.  *
  10.  * This is the main routine for slurp together with the routines to
  11.  * handle the configuration files and command line arguments.
  12.  *
  13.  *
  14.  * $Id: slurp.c,v 1.5 1993/03/01 17:51:33 root Exp $
  15.  *
  16.  * $Log: slurp.c,v $
  17.  * Revision 1.5  1993/03/01  17:51:33  root
  18.  * read_sys can cope with lines longer than BUFSIZ.
  19.  * report when attempting to load unretrieved message ids.
  20.  * Move sublist to a parameter after the hostname, separate by a slash.
  21.  * Changed some system error checking.
  22.  *
  23.  * Revision 1.4  1993/02/14  14:57:43  root
  24.  * Added support for simple authorisation protocol.
  25.  * Added support for INN's 'MODE READER' command.
  26.  * Re-arranged command line options.
  27.  * Rewrote read_sys and added flags and authorisation options to it.
  28.  * Rewrote get_ntime and set_ntime to use a filename of slurp.<hostname>
  29.  * instead of slurp.tim, solving lack of locking and allowing the file
  30.  * to contain a list of unretrieved message ids on the lines following
  31.  * the time.
  32.  * Don't care if slurp.<hostname> doesn't exist already.
  33.  * If RNEWS is not defined, then change to INDIR for writing out batch
  34.  * files.
  35.  *
  36.  * Revision 1.3  1992/12/15
  37.  * Open syslog *before* we start doing things that might write to it.
  38.  * Informational messages logged as LOG_INFO.
  39.  * Assorted minor tidy-ups.
  40.  *
  41.  * Revision 1.2  1992/12/07
  42.  * Corrected test for 4.2/4.3 BSD syslog open.
  43.  *
  44.  * Revision 1.1  1992/12/06
  45.  * Made no_time_flag global.
  46.  * Fixed null dereferencing of nn_distributions.
  47.  *
  48.  * Revision 1.0  1992/08/07
  49.  * Initial coding.
  50.  *
  51.  */
  52.  
  53. #include "slurp.h"
  54. #include <sys/stat.h>
  55.  
  56. char *hostname = NULL;
  57. char *pname;
  58.  
  59. int debug_flag = FALSE;
  60. int no_time_flag = FALSE;
  61. int no_id_load_flag = FALSE;
  62. static int local_time_flag = FALSE;
  63. static int mode_reader_flag = FALSE;
  64.  
  65. int  dupart = 0;
  66. int  misart = 0;
  67. int  newart = 0;
  68. long totalsize = 0;
  69.  
  70. char *nn_newsgroups    = NULL;
  71. char *nn_time          = NULL;
  72. char *nn_distributions = NULL;
  73.  
  74. static char *sublist = NULL;
  75. static char *ai_username = NULL;
  76. static char *ai_password = NULL;
  77.  
  78. struct mnode *root = NULL;
  79. int entries = 0;
  80.  
  81. static long newdate, newtime;
  82.  
  83.  
  84. /*
  85.  * test_time - Check NEWNEWS time string is in the right format (ish)
  86.  */
  87.  
  88.     static int
  89. test_time ()
  90.     {
  91.     return (!(isdigit (nn_time [0]) &&
  92.               isdigit (nn_time [1]) &&
  93.               isdigit (nn_time [2]) &&
  94.               isdigit (nn_time [3]) &&
  95.               isdigit (nn_time [4]) &&
  96.               isdigit (nn_time [5]) &&
  97.               isspace (nn_time [6]) &&
  98.               isdigit (nn_time [7]) &&
  99.               isdigit (nn_time [8]) &&
  100.               isdigit (nn_time [9]) &&
  101.               isdigit (nn_time [10]) &&
  102.               isdigit (nn_time [11]) &&
  103.               isdigit (nn_time [12])));
  104.     }
  105.  
  106.  
  107. /*
  108.  * parse_args - Parse the command line arguments. Returns 1 if there is
  109.  * an error, otherwise returns 0.
  110.  */
  111.  
  112.     static int
  113. parse_args (int argc, char **argv)
  114.     {
  115.     int c;
  116.     extern int optind;
  117.     extern char *optarg;
  118.     char *pos;
  119.     
  120.     while ((c = getopt (argc, argv, "a:g:t:dilrw")) != EOF)
  121.         switch (c)
  122.             {
  123.             case 'a':    /* Do an authinfo */
  124.                 if (pos = strchr (optarg, '/'))
  125.                     {
  126.                     ai_username = optarg;
  127.                     *pos++ = '\0';
  128.                     ai_password = pos;
  129.                     }
  130.                 else
  131.                     {
  132.                     (void) fprintf (stderr, "Invalid authinfo username/password");
  133.                     return (1);
  134.                     }
  135.                 break;
  136.             case 'g':    /* Newsgroups list */
  137.                 if (pos = strchr (optarg, '/'))
  138.                     {
  139.                     *pos++ = '\0';
  140.                     nn_distributions = pos;
  141.                     }
  142.                 else
  143.                     nn_distributions = "";
  144.                 nn_newsgroups = optarg;
  145.                 no_time_flag++;
  146.                 break;
  147.             case 't':    /* Start time */
  148.                 nn_time = optarg;
  149.                 break;
  150.             case 'd':    /* Debugging on */
  151.                 debug_flag++;
  152.                 break;
  153.             case 'i':    /* Don't load unprocessed ids */
  154.                 no_id_load_flag++;
  155.                 break;
  156.             case 'l':    /* Use local time */
  157.                 local_time_flag++;
  158.                 break;
  159.             case 'r':    /* Do a 'MODE READER' */
  160.                 mode_reader_flag++;
  161.                 break;
  162.             case 'w':    /* Don't set next time */
  163.                 no_time_flag++;
  164.                 break;
  165.             default:
  166.                 return (1);
  167.             }
  168.  
  169.     /* Get server name */
  170.     if (optind < argc)
  171.         {
  172.         hostname = argv [optind];
  173.         if (pos = strchr (hostname, '/'))
  174.             {
  175.             *pos++ = '\0';
  176.             sublist = pos;
  177.             }
  178.         }
  179.     else
  180.         {
  181.         (void) fprintf (stderr, "No server name supplied\n");
  182.         return (1);
  183.         }
  184.  
  185.     /* If groups are specified, then must have a time */
  186.     if ((nn_newsgroups != NULL) && (nn_time == NULL))
  187.         {
  188.         (void) fprintf (stderr, "Time must be specified for -g option\n");
  189.         return (1);
  190.         }
  191.  
  192.     /* Verify that the time is in something like the right format */
  193.     if (nn_time)
  194.         if (test_time ())
  195.             {
  196.             (void) fprintf (stderr, "Invalid time specification - should be 'YYMMDD HHMMSS'\n");
  197.             return (1);
  198.             }
  199.  
  200.     return (0);
  201.     }
  202.  
  203.  
  204. /*
  205.  * read_sys_line - Read a line from the slurp.sys file, skipping lines
  206.  * which are blank or all comments, truncating lines at comments.
  207.  * If the line has not yet all been read or the continued-on-next-line
  208.  * token '\' is present, then returns 1; if eof then returns -1, otherwise
  209.  * returns 0.
  210.  */
  211.  
  212.     static int
  213. read_sys_line (char *line, int size, FILE *sysfp)
  214.     {
  215.     int status;
  216.     char *pos;
  217.  
  218.     for (;;)
  219.         {
  220.         status = 0;
  221.  
  222.         (void) fgets (line, size, sysfp);
  223.         if (feof (sysfp))
  224.             return (-1);
  225.         if (ferror (sysfp))
  226.             log_sys ("read_sys: Error reading %s", SYSFILE);
  227.  
  228.         if (pos = strchr (line, '\n'))
  229.             *pos = '\0';
  230.         else
  231.             status = 1;
  232.  
  233.         if (pos = strchr (line, '\\'))
  234.             {
  235.             *pos = '\0';
  236.             status = 1;
  237.             }
  238.  
  239.         if (pos = strchr (line, '#'))
  240.             *pos = '\0';
  241.  
  242.         if (strlen (line))
  243.             return (status);
  244.         }
  245.     }
  246.  
  247.  
  248. /*
  249.  * read_sys - Read in the appropriate entry from the slurp.sys file
  250.  * for the specified hostname. Stores the relevant newsgroups for that
  251.  * host in nn_newsgroups and the relevant distribution in nn_distributions.
  252.  * Returns 0 if an appropriate entry for the current host is found, 
  253.  * otherwise returns 1.
  254.  */
  255.  
  256.     static int
  257. read_sys ()
  258.     {
  259.     FILE *sysfp;
  260.     char buf [BUFSIZ];
  261.     char searchname [BUFSIZ];
  262.     struct stat stbuf;
  263.     size_t tlen;
  264.     char *pos;
  265.     char *mbuf;
  266.     int status;
  267.     int object;
  268.  
  269.     /* Attempt to open the sys file */
  270.     if ((sysfp = fopen (SYSFILE, "r")) == NULL)
  271.         log_sys ("read_sys: Error opening %s", SYSFILE);
  272.  
  273.     /* Allocate memory block for storing the details */
  274.     if (fstat (fileno (sysfp), &stbuf) < 0)
  275.         log_sys ("read_sys: Can't fstat %s", SYSFILE);
  276.     if (stbuf.st_size == 0)
  277.         {
  278.         log_msg ("read_sys: Host %s not found in %s", hostname, SYSFILE);
  279.         return (1);
  280.         }
  281.     if ((mbuf = (char *) malloc (stbuf.st_size)) == NULL)
  282.         log_sys ("read_sys: malloc %d bytes", stbuf.st_size);
  283.     
  284.     /* Create pattern to search for in the sys file */
  285.     (void) strcpy (searchname, hostname);
  286.     if (sublist)
  287.         {
  288.         (void) strcat (searchname, "/");
  289.         (void) strcat (searchname, sublist);
  290.         }
  291.     (void) strcat (searchname, ":");
  292.     tlen = strlen (searchname);
  293.  
  294.     /* Read in file until we find hostname */
  295.     for (;;)
  296.         {
  297.         if ((status = read_sys_line (buf, sizeof (buf), sysfp)) == -1)
  298.             {
  299.             log_msg ("read_sys: Host %s not found in %s",
  300.                      hostname, SYSFILE);
  301.             return (1);
  302.             }
  303.         if (strncmp (buf, searchname, tlen) == 0)
  304.             break;
  305.         }
  306.  
  307.     /* Strip off hostname stuff from front of line */
  308.     (void) strcpy (buf, buf + tlen);
  309.     object = 1;
  310.     nn_newsgroups = mbuf;
  311.  
  312.     /* Loop through entry */
  313.     for (;;)
  314.         {
  315.         /* Currently adding newsgroups */
  316.         if (object == 1)
  317.             {
  318.             if (pos = strchr (buf, ':'))        /* Flags next */
  319.                 {
  320.                 *pos++ = '\0';
  321.                 object = 3;
  322.                 (void) strcpy (mbuf, buf);
  323.                 mbuf += strlen (buf) + 1;
  324.                 ai_username = mbuf;
  325.                 (void) strcpy (buf, pos);
  326.                 }
  327.             else if (pos = strchr (buf, '/'))    /* Distributions next */
  328.                 {
  329.                 *pos++ = '\0';
  330.                 object = 2;
  331.                 (void) strcpy (mbuf, buf);
  332.                 mbuf += strlen (buf) + 1;
  333.                 nn_distributions = mbuf;
  334.                 (void) strcpy (buf, pos);
  335.                 }
  336.             else
  337.                 {
  338.                 (void) strcpy (mbuf, buf);        /* Nothing else this line */
  339.                 mbuf += strlen (buf);
  340.                 }
  341.             }
  342.  
  343.         /* Currently adding distributions */
  344.         if (object == 2)
  345.             {
  346.             if (pos = strchr (buf, ':'))        /* Flags next */
  347.                 {
  348.                 *pos++ = '\0';
  349.                 object = 3;
  350.                 (void) strcpy (mbuf, buf);
  351.                 mbuf += strlen (buf) + 1;
  352.                 ai_username = mbuf;
  353.                 (void) strcpy (buf, pos);
  354.                 }
  355.             else                                /* Nothing else this line */
  356.                 {
  357.                 (void) strcpy (mbuf, buf);
  358.                 mbuf += strlen (buf);
  359.                 }
  360.             }
  361.  
  362.         /* Currently setting flags */
  363.         if (object == 3)
  364.             {
  365.             if (pos = strchr (buf, ':'))        /* authinfo user next */
  366.                 *pos++ = '\0';
  367.             if (strchr (buf, 'i'))
  368.                 no_id_load_flag++;
  369.             if (strchr (buf, 'l'))
  370.                 local_time_flag++;
  371.             if (strchr (buf, 'r'))
  372.                 mode_reader_flag++;
  373.             if (pos)
  374.                 {
  375.                 (void) strcpy (buf, pos);
  376.                 object = 4;
  377.                 }
  378.             }
  379.  
  380.         /* Currently setting username */
  381.         if (object == 4)
  382.             {
  383.             if (pos = strchr (buf, '/'))        /* authinfo pass next */
  384.                 {
  385.                 *pos++ = '\0';
  386.                 object = 5;
  387.                 (void) strcpy (mbuf, buf);
  388.                 mbuf += strlen (buf) + 1;
  389.                 ai_password = mbuf;
  390.                 (void) strcpy (buf, pos);
  391.                 }
  392.             else
  393.                 {
  394.                 (void) strcpy (mbuf, buf);
  395.                 break;
  396.                 }
  397.             }
  398.  
  399.         /* Currently setting password */
  400.         if (object == 5)
  401.             {
  402.             (void) strcpy (mbuf, buf);
  403.             mbuf += strlen (buf) +1;
  404.             }
  405.  
  406.         if (status != 1)
  407.             break;
  408.  
  409.         status = read_sys_line (buf, sizeof (buf), sysfp);
  410.         }
  411.  
  412.     (void) fclose (sysfp);
  413.  
  414.     if (nn_distributions == NULL)
  415.         nn_distributions = "";
  416.  
  417.     return (0);
  418.     }
  419.  
  420.  
  421. /*
  422.  * get_ntime - Get the start time for this NEWNEWS for system. Returns 0
  423.  * if an appropriate entry for the current host is found, otherwise 1.
  424.  */
  425.  
  426.     static int
  427. get_ntime ()
  428.     {
  429.     FILE *timefp;
  430.     char buf [BUFSIZ];
  431.     char filename [PATH_MAX];
  432.     char *pos;
  433.  
  434.     /* Attempt to open the time file */
  435.     (void) strcpy (filename, TIMFILE);
  436.     (void) strcat (filename, hostname);
  437.     if (sublist)
  438.         {
  439.         (void) strcat (filename, ".");
  440.         (void) strcat (filename, sublist);
  441.         }
  442.     if ((timefp = fopen (filename, "r")) == NULL)
  443.         log_sys ("get_ntime: error opening %s", filename);
  444.  
  445.     /* Read in the time and store it */
  446.     nn_time = (char *) malloc (14);
  447.     (void) fgets (nn_time, 14, timefp);
  448.     if (ferror (timefp))
  449.         log_sys ("get_ntime: Error reading %s", filename);
  450.     
  451.     /* Return if time doesn't look ok */
  452.     if (test_time ())
  453.         return (1);
  454.  
  455.     /* Load in any message ids following */
  456.     if (!no_id_load_flag)
  457.         {
  458.         if (debug_flag)
  459.             (void) fprintf (stderr, "Loading any unretrieved message IDs\n");
  460.         for (;;)
  461.             {
  462.             (void) fgets (buf, sizeof (buf), timefp);
  463.             if (feof (timefp))
  464.                 break;
  465.             if (ferror (timefp))
  466.                 log_sys ("get_ntime: Error reading %s", filename);
  467.             if (pos = strchr (buf, '\n'))
  468.                 *pos = '\0';
  469.             if (strlen (buf))
  470.                 if ((buf [0] == '<') && (buf [strlen (buf) - 1] == '>'))
  471.                     process_id (buf);
  472.             }
  473.         }
  474.  
  475.     (void) fclose (timefp);
  476.     return (0);
  477.     }
  478.  
  479.  
  480. /*
  481.  * write_tree - Traverse the tree writing out ids of articles that were
  482.  * not successfully retrieved.
  483.  */
  484.  
  485.     static void
  486. write_tree (struct mnode *p, FILE *timefp)
  487.     {
  488.     if (p != NULL)    
  489.         {
  490.         write_tree (p->left, timefp);
  491.         if (!p->used)
  492.             {
  493.             (void) fprintf (timefp, "%s\n", p->msgid);
  494.             if (ferror (timefp))
  495.                 log_sys ("write_tree: Error writing ids");
  496.             }
  497.         write_tree (p->right, timefp);
  498.         }
  499.     }
  500.  
  501.  
  502. /*
  503.  * set_ntime - Set the start time for the next NEWNEWS for system
  504.  */
  505.  
  506.     void
  507. set_ntime ()
  508.     {
  509.     FILE *timefp;
  510.     char filename [PATH_MAX];
  511.     char backup [PATH_MAX];
  512.  
  513.     /* Copy the file to a backup */
  514.     (void) strcpy (filename, TIMFILE);
  515.     (void) strcat (filename, hostname);
  516.     if (sublist)
  517.         {
  518.         (void) strcat (filename, ".");
  519.         (void) strcat (filename, sublist);
  520.         }
  521.     (void) strcpy (backup, filename);
  522.     (void) strcat (backup, ".o");
  523.     if (rename (filename, backup))
  524.         if (errno != ENOENT)
  525.             {
  526.             log_ret ("set_ntime: Error renaming %s to %s", filename, backup);
  527.             exit (1);
  528.             }
  529.  
  530.     /* Open new file */
  531.     if ((timefp = fopen (filename, "w")) == NULL)
  532.         {
  533.         log_ret ("get_ntime: Error opening %s", filename);
  534.         exit (1);
  535.         }
  536.  
  537.     /* Write the new time for current host */
  538.     (void) fprintf (timefp, "%06ld %06ld\n", newdate, newtime);
  539.     if (ferror (timefp))
  540.         {
  541.         log_ret ("set_ntime: Error writing %s", filename);
  542.         exit (1);
  543.         }
  544.  
  545.     /* Write out any message ids not read in */
  546.     write_tree (root, timefp);
  547.  
  548.     (void) fclose (timefp);
  549.     }
  550.  
  551.  
  552. /*
  553.  * do_authinfo - Check in the authinfo username and password with the
  554.  * server.
  555.  */
  556.  
  557.     static void
  558. do_authinfo ()
  559.     {
  560.     char buf [NNTP_STRLEN];
  561.  
  562.     /* Send the username to the server */
  563.     (void) sprintf (buf, "AUTHINFO USER %s", ai_username);
  564.     if (debug_flag)
  565.         (void) fprintf (stderr, "<- %s\n", buf);
  566.     put_server (buf);
  567.  
  568.     /* Get the response and check it's okay */
  569.     get_server (buf, sizeof (buf));
  570.     if (debug_flag)
  571.         (void) fprintf (stderr, "-> %s\n", buf);
  572.     if (atoi (buf) != NEED_AUTHDATA)
  573.         {
  574.         log_msg ("do_authinfo: NNTP protocol error: got '%s'", buf);
  575.         exit (4);
  576.         }
  577.                     
  578.     /* Send the password to the server */
  579.     (void) sprintf (buf, "AUTHINFO PASS %s", ai_password);
  580.     if (debug_flag)
  581.         (void) fprintf (stderr, "<- %s\n", buf);
  582.     put_server (buf);
  583.  
  584.     /* Get the response and check it's okay */
  585.     get_server (buf, sizeof (buf));
  586.     if (debug_flag)
  587.         (void) fprintf (stderr, "-> %s\n", buf);
  588.     if (atoi (buf) != OK_AUTH)
  589.         {
  590.         log_msg ("do_authinfo: NNTP protocol error: got '%s'", buf);
  591.         exit (4);
  592.         }
  593.     }
  594.  
  595.  
  596. /*
  597.  * do_mode_reader - Send mode reader command to INN to switch to nnrpd
  598.  * so we can do a NEWNEWS.
  599.  */
  600.  
  601.     static void
  602. do_mode_reader ()
  603.     {
  604.     char buf [NNTP_STRLEN];
  605.  
  606.     /* Send the command to the server */
  607.     if (debug_flag)
  608.         (void) fprintf (stderr, "<- MODE reader\n");
  609.     put_server ("MODE READER");
  610.  
  611.     /* Get the response and check it's okay */
  612.     get_server (buf, sizeof (buf));
  613.     if (debug_flag)
  614.         (void) fprintf (stderr, "-> %s\n", buf);
  615.     switch (atoi (buf))
  616.         {
  617.         case OK_CANPOST :
  618.         case OK_NOPOST :
  619.             break;
  620.         default :
  621.             log_msg ("do_authinfo: NNTP protocol error: got '%s'", buf);
  622.             exit (4);
  623.         }
  624.     }
  625.  
  626.  
  627. /*
  628.  * MAIN PROCEDURE
  629.  */
  630.  
  631.     int
  632. main (int argc, char **argv)
  633.     {
  634.     int ret;
  635.     time_t clock, starttime, endtime;
  636.     struct tm *now;
  637.  
  638.     /* Set the name of the program and parse the args */
  639.     pname = (pname = (char *) strrchr (argv [0], '/')) ? pname + 1 : argv [0];
  640.     if (parse_args (argc, argv))
  641.         {
  642.         (void) fprintf (stderr, "Usage: %s [-g newsgroups/distribution] [-t time] [-a username/password]\n", pname);
  643.         (void) fprintf (stderr, "       [-d] [-i] [-l] [-r] [-w] server[/sublist]\n");
  644.         exit (2);
  645.         }
  646.  
  647.     /* Open syslog if required with appropriate BSD 4.2/4.3 call */
  648. #ifdef SYSLOG
  649. #ifdef LOG_AUTH
  650.     openlog(pname, LOG_PID, SYSLOG);
  651. #else
  652.     openlog(pname, LOG_PID);
  653. #endif
  654. #endif
  655.  
  656.     /* If groups not supplied in args, then get from slurp.sys file */
  657.     if (nn_newsgroups == NULL)
  658.         if (read_sys ())
  659.             exit (2);
  660.  
  661.     /* If start time not supplied in args, then get from slurp.tim file */
  662.     if (nn_time == NULL)
  663.         if (get_ntime ())
  664.             exit (2);
  665.  
  666.     if (debug_flag)
  667.         {
  668.         (void) fprintf (stderr, "server: %s\n", hostname);
  669.         (void) fprintf (stderr, "time: %s\n", nn_time);
  670.         (void) fprintf (stderr, "newsgroups: '%s'\n", nn_newsgroups);
  671.         (void) fprintf (stderr, "distributions: '%s'\n", nn_distributions);
  672.         }
  673.  
  674.     /* Unless don't write flag set, get time for next NEWNEWS */
  675.     if (!no_time_flag)
  676.         {
  677.         if (local_time_flag)
  678.             clock = time ((time_t *) 0);
  679.         else
  680.             if ((clock = server_time (hostname)) == 0)
  681.                 exit (3);
  682.  
  683.         now = gmtime (&clock);
  684.         newdate = (now->tm_year * 10000) +
  685.                  ((now->tm_mon + 1) * 100) +
  686.                    now->tm_mday;
  687.         newtime = (now->tm_hour * 10000) +
  688.                   (now->tm_min * 100) +
  689.                    now->tm_sec;
  690.         }
  691.  
  692.     /* Open the history file */
  693.     if (open_history ())
  694.         log_sys ("Can't open history file %s", HISTORY_FILE);
  695.  
  696. #ifndef RNEWS
  697.     /* Change to the incoming batch directory */
  698.     if (chdir (INDIR))
  699.         log_sys ("Can't change directory to %s", INDIR);
  700. #endif
  701.  
  702.     /* Set up the connection to the server */
  703.     switch (ret = server_init (hostname))
  704.         {
  705.         case -1 :
  706.             exit (3);
  707.         case OK_CANPOST :
  708.         case OK_NOPOST :
  709.             break;
  710.         default :
  711.             log_msg ("Can't talk to %s: got response code %d", hostname, ret);
  712.             exit (4);
  713.         }
  714.  
  715.     /* If authinfo details supplied, then use 'em */
  716.     if (ai_username)
  717.         do_authinfo ();
  718.  
  719.     /* Switch INN to nnrpd instead of innd if needed */
  720.     if (mode_reader_flag)
  721.         do_mode_reader ();
  722.  
  723.     /* Get a list of the new articles */
  724.     get_ids ();
  725.  
  726.     /* Now get the actual articles */
  727.     starttime = time ((time_t *) 0);
  728.     if (entries > 0)
  729.         get_articles ();
  730.     endtime = time ((time_t *) 0);
  731.  
  732.     /* Time to say goodbye */
  733.     close_server ();
  734.     close_history ();
  735.  
  736.     /* Submit the remaining batch, if present */
  737.     enqueue_batch ();
  738.  
  739.     /* do we want to update the timestamp file? */
  740.     if (!no_time_flag)
  741.         set_ntime ();
  742.  
  743. #ifdef SYSLOG
  744.     if (!debug_flag)
  745.         syslog (LOG_INFO,"Processed %d new, %d duplicate, %d missing articles",
  746.                 newart, dupart, misart);
  747.     else
  748. #endif
  749.         (void) fprintf (stderr, "Processed %d new, %d duplicate, %d missing articles\n",
  750.                         newart, dupart, misart);
  751.  
  752. #ifdef SPEEDSTATS
  753.   #ifdef SYSLOG
  754.     if (!debug_flag)
  755.         syslog (LOG_INFO, "Average transfer speed %ld cps",
  756.                 totalsize / (starttime == endtime ? 1 : endtime - starttime));
  757.     else
  758.   #endif
  759.         (void) fprintf (stderr, "Average transfer speed %ld cps\n",
  760.                 totalsize / (starttime == endtime ? 1 : endtime - starttime));
  761. #endif
  762.  
  763.     exit (0);
  764.     }
  765.  
  766. /* END-OF-FILE */
  767.