/*
* newnews - Read in list of ids of new articles
*
* Copyright (C) 1992/93/94 Stephen Hebditch <steveh@tqmcomms.co.uk>.
* All rights reserved. TQM Communications, BCM Box 225, London, WC1N 3XX.
*
* See README for more information and disclaimers
*
* Using a previously initialised list of newsgroups, carries out a series
* of NEWNEWS requests to the connected NNTP server, storing the message
* ids of new articles in memory.
*
* $Id: newnews.c,v 1.9 1995/01/10 12:59:33 root Exp $
*
* $Log: newnews.c,v $
* Revision 1.9 1995/01/10 12:59:33 root
* Moved includes from slurp.h.
* Removed store_node and add_id - now in cache.c.
* Added progress reporting.
* If MAXCACHE limit reached, then uncollected ids written to a
* temp file which will be copied to the hostfile by write_hostfile().
*
* Revision 1.7 1993/06/14 15:22:24 root
* Modified parse_groups to only malloc enough space for arrays.
* Rewrote get_ids, incorporating the get_not_groups function. This
* makes the algorithm neater, fixes a problem with using memset on a
* zero length block, and fixes a problem whereby with certain
* newsgroup combinations a line could overflow its buffer.
* In process_id when in debug mode print after a message ID if ID
* discarded due to hitting maximum number of articles or was already
* present in the tree.
*
* Revision 1.5 1993/03/01 17:45:16 root
* Added cast to bzeroing of used_not_group_array.
*
* Revision 1.4 1993/02/14 14:55:41 root
* Malloc msgid space separately from mnode.
* Split-out process_id from do_newnews so it can be used in get_ntime
* to load the tree with the unretrieved message ids.
*
* Revision 1.3 1992/12/14
* Only malloc enough space for msgid, not whole mnode structure.
* Minor tidy-ups.
*
* Revision 1.1 1992/12/06
* Set no_time_flag if hit max no of messages
* Print line before it is sent to server when debugging is on.
* No longer need to handle null nn_distributions.
*
* Revision 1.0 1992/11/30
* Transferred functions from slurp.c
*/
#include "conf.h"
/* POSIX headers */
#define _POSIX_SOURCE 1
#include <sys/types.h>
#include <ctype.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Local headers */
#include "nntp.h"
#include "slurp.h"
#include "syslog.h"
/* File-scope variables */
static char **group_array;
static char **not_group_array;
static int *used_not_group_array;
static int groups_no = 1;
static int not_groups_no = 0;
/*
* parse_groups - Turn list of groups into two arrays containing
* pointers to groups to include and groups to exclude.
*/
static void
parse_groups (void)
{
char *cp;
int g = 0;
int got = TRUE;
int n = 0;
int not = FALSE;
/* Calculate number of group entries */
for (cp = nn_newsgroups; *cp != '\0'; cp++)
{
if (*cp == ',')
groups_no++;
if (*cp == '!')
{
not_groups_no++;
groups_no--;
}
}
/* Malloc space for include and exclude group arrays */
if ((group_array = (char **) malloc ((size_t) groups_no * sizeof (char *))) == NULL)
log_sys ("parse_groups: malloc %d bytes", groups_no * sizeof (char **));
if (not_groups_no > 0)
{
if ((not_group_array = (char **) malloc ((size_t) not_groups_no * sizeof (char *))) == NULL)
log_sys ("parse_groups: malloc %d bytes", not_groups_no * sizeof (char **));
if ((used_not_group_array = (int *) malloc ((size_t) not_groups_no * sizeof (int))) == NULL)
log_sys ("parse_groups: malloc %d bytes", not_groups_no * sizeof (int));
}
/* Now start parsing the newsgroup list */
for (cp = nn_newsgroups; *cp != '\0'; cp++)
{
if (*cp == '!')
got = FALSE;
if (got)
{
group_array [g++] = cp;
got = FALSE;
}
if (not)
{
not_group_array [n++] = cp;
not = FALSE;
}
if (*cp == ',')
{
*cp = '\0';
got = TRUE;
}
if (*cp == '!')
not = TRUE;
}
}
/*
* process_id - Check if id already exists in local history file, if not
* then add it to the message id tree if it isn't already in there.
*/
void
process_id (char *msgid)
{
char *cp;
#ifdef SITEEXCLUDING
char *host;
#endif /*SITEXCLUDING*/
/* Modify the message id appropriate to C-News history files */
if ((cp = strchr (msgid, '@')) != NULL)
{
#ifdef SITEEXCLUDING
host = cp;
#endif /*SITEXCLUDING*/
for (; *cp != '\0'; cp++)
if (isupper (*cp))
*cp = tolower (*cp);
}
if (debug_flag)
(void) fprintf (stderr, "-> %s", msgid);
#ifdef SITEEXCLUDING
if((host)&&(site_check(host)))
{
if (debug_flag)
(void) fprintf (stderr, " (Excluded host %s)", host);
/* Excluded host */
site_droparticle(msgid);
exclart++;
return;
}
#endif /*SITEXCLUDING*/
/* If hit maximum cache size, then store in a temporary file */
#ifdef MAXCACHE
if (waiting >= MAXCACHE)
{
if (no_id_write_flag)
{
if (debug_flag)
(void) fprintf (stderr, " discarded\n");
}
else
{
if (overflowfp == NULL)
if ((overflowfp = tmpfile ()) == NULL)
log_sys ("process_id: can't create overflow temporary file");
(void) fprintf (overflowfp, "%s\n", msgid);
if (debug_flag)
(void) fprintf (stderr, " overflowed\n");
}
return;
}
#endif
if (check_id (msgid))
{
if (add_id (msgid))
{
/* Article not in history file and isn't in cache yet */
waiting++;
if (debug_flag)
(void) fprintf (stderr, " new\n");
if (progress_flag)
{
if ((waiting % 20) == 0)
{
(void) fprintf (stdout, "%d waiting\r", waiting);
(void) fflush (stdout);
}
}
}
else
{
/* Article is already in cache */
if (debug_flag)
(void) fprintf (stderr, " present\n");
}
}
else
{
/* Article is already in history file */
dupart++;
if (debug_flag)
(void) fprintf (stderr, " duplicate\n");
}
}
/*
* do_newnews - Process a newnews for supplied list of groups, adding the
* resultant data to the message id tree.
*/
static void
do_newnews (char *groups)
{
char line [NNTP_STRLEN];
/* Create a full string to send to the server */
(void) sprintf (line, "NEWNEWS %s %s GMT %s", groups, nn_time,
nn_distributions);
/* Do the actual NEWNEWS */
if (debug_flag)
(void) fprintf (stderr, "<- %s\n", line);
put_server (line);
/* Get the response and check it's okay */
get_server (line, sizeof (line));
if (debug_flag)
(void) fprintf (stderr, "-> %s\n", line);
if (atoi (line) != OK_NEWNEWS)
{
log_msg ("do_newnews: NNTP protocol error: got '%s'", line);
exit (4);
}
/* Now get the data and stick it in the tree */
for (;;)
{
get_server (line, sizeof (line));
if (strcmp (line, ".") == 0)
break;
process_id (line);
}
}
/*
* restreql -- A small regular expression string equivalence routine
* purloined from nntp 1.5.11 which credits <lai@shadow.berkeley.edu>
* for its creation. Returns 1 if the string pointed to by 's' matches
* the asterisk-broadened regexp string pointed to by 'w', otherwise
* returns 0.
*/
static int
restreql (register char *w, register char *s)
{
while (*s && *w)
{
switch (*w)
{
case '*':
for (w++; *s; s++)
if (restreql (w, s))
return (1);
break;
default:
if (*w != *s)
return (0);
w++, s++;
break;
}
}
if (*s)
return (0);
while (*w)
if (*w++ != '*')
return 0;
return (1);
}
/*
* get_ids - Store in memory a tree of the message ids of new articles at
* the server which match the specified set of groups and distributions
* for the currently connected host.
*/
void
get_ids ()
{
char line [NNTP_STRLEN];
char newgroups [NNTP_STRLEN];
int i, j, add_comma;
size_t newlen, linelen;
size_t startlen = 30 + strlen (nn_distributions);
/* Turn comma-separated list of groups into 2 arrays */
parse_groups ();
/* Initialiase for first list of groups to send to server */
*line = '\0';
linelen = startlen;
if (not_groups_no)
(void) memset (used_not_group_array, 0, not_groups_no * sizeof (int));
add_comma = FALSE;
for (i = 0 ; i < groups_no ; i++)
{
/* Check group isn't so big it doesn't fit at all */
newlen = strlen (group_array [i]);
if ((newlen + startlen) > NNTP_STRLEN)
{
log_msg ("get_ids: not enough room in NNTP line for newsgroup %s",
group_array [i]);
exit (2);
}
/* Get list containing new group and matching ! groups */
(void) strcpy (newgroups, group_array [i]);
for (j = 0 ; j < not_groups_no ; j++)
if (!used_not_group_array [j])
if (restreql (group_array [i], not_group_array [j]))
{
newlen += strlen (not_group_array [j]) + 2;
if ((newlen + startlen) > NNTP_STRLEN)
{
log_msg ("get_ids: not enough room in NNTP line for exclusion list %s",
newgroups);
exit (2);
}
(void) strcat (newgroups, ",!");
(void) strcat (newgroups, not_group_array [j]);
used_not_group_array [j] = TRUE;
}
/* If can't add new groups to existing list, then do a newnews */
if ((linelen + newlen + add_comma) > NNTP_STRLEN)
{
do_newnews (line);
*line = '\0';
linelen = startlen;
if (not_groups_no)
(void) memset (used_not_group_array, 0, not_groups_no * sizeof (int));
add_comma = FALSE;
}
linelen += newlen + add_comma;
if (add_comma)
(void) strcat (line, ",");
else
add_comma = TRUE;
(void) strcat (line, newgroups);
}
do_newnews (line);
/* Report if couldn't fit everything in the tree */
#ifdef MAXCACHE
if (waiting >= MAXCACHE)
log_msg ("Maximum limit of %d messages hit", MAXCACHE);
#endif
if (debug_flag)
(void) fprintf (stderr, "%d articles waiting\n", waiting);
}
/* END-OF-FILE */
syntax highlighted by Code2HTML, v. 0.9.1