home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
s
/
slurp103.zip
/
NEWNEWS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-20
|
9KB
|
394 lines
/*
* newnews - Read in list of ids of new articles
*
* Copyright (C) 1992 Stephen Hebditch. All rights reserved.
* TQM Communications, BCM Box 225, London, WC1N 3XX.
* steveh@orbital.demon.co.uk +44 836 825962
*
* 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 a binary tree in memory.
*
* 1.00 30 Nov 92 SH Transferred from slurp.c
* 1.01 4 Dec 92 SH No longer need to handle null nn_distributions
* 1.01 4 Dec 92 SH Print line before it is sent to server when
* debugging is on.
* 1.01 6 Dec 92 SH Set no_time_flag if hit max no of messages.
* 1.03 14 Dec 92 SH Only malloc enough space for msgid, not whole
* mnode structure.
* Minor tidy-ups.
*
*/
#include "slurp.h"
static int hit_max = FALSE;
static char **group_array;
static char **not_group_array;
static int *used_not_group_array;
static int groups_no;
static int not_groups_no;
static void parse_groups ();
static int add_id (char *msgid);
static void do_newnews (char *line);
static int restreql (register char *w, register char *s);
static int get_not_groups (char *group);
/*
* parse_groups - Turn list of groups into two arrays containing
* pointers to groups to include and groups to exclude.
*/
static void
parse_groups ()
{
int i, got, not;
char *cp;
/* Calculate number of group entries */
for (i = 1, cp = nn_newsgroups; *cp != '\0'; cp++)
if (*cp == ',')
i++;
/* Malloc space for include and exclude group arrays */
if ((group_array = (char **) malloc (i * (sizeof (char *)))) == NULL)
log_sys ("parse_groups: malloc %d bytes", i * sizeof (char **));
if ((not_group_array = (char **) malloc (i * (sizeof (char *)))) == NULL)
log_sys ("parse_groups: malloc %d bytes", i * sizeof (char **));
if ((used_not_group_array = (int *) malloc (i * (sizeof (int)))) == NULL)
log_sys ("parse_groups: malloc %d bytes", i * sizeof (int));
/* Now start parsing the newsgroup list */
groups_no = 0;
not_groups_no = 0;
got = TRUE;
not = FALSE;
for (cp = nn_newsgroups; *cp != '\0'; ++cp)
{
if (*cp == '!')
got = FALSE;
if (got)
{
group_array [groups_no] = cp;
groups_no++;
got = FALSE;
}
if (not)
{
not_group_array [not_groups_no] = cp;
not_groups_no++;
not = FALSE;
}
if (*cp == ',')
{
*cp = '\0';
got = TRUE;
}
if (*cp == '!')
not = TRUE;
}
}
/*
* add_id - Add a message id to the binary tree if not already present.
* Returns -1 if the maximum number of entries in the tree has been
* reached, 0 if the item is added okay, 1 if an entry with that
* particular message id already exists.
*/
static int
add_id (char *msgid)
{
struct mnode *current;
int test;
size_t msize;
/* Test if hit the maximum number of entries in the cache */
if (entries >= MAXCACHE)
return (-1);
/* Calculate size to malloc - not the full structure size */
msize = 2 * (sizeof (struct mnode *)) + strlen (msgid) + sizeof (char);
/* Handle the case when the tree is empty */
if (root == NULL) {
root = (struct mnode *) malloc (msize);
if (root == NULL)
log_sys ("add_id: malloc %d bytes", msize);
root->left = NULL;
root->right = NULL;
(void) strcpy (root->msgid, msgid);
entries++;
return (0);
}
/* Search the tree for correct position to insert node */
current = root;
for (;;)
{
test = strcmp (msgid, current->msgid);
if (test < 0)
{
if (current->left == NULL)
{
current->left = (struct mnode *) malloc (msize);
if (current->left == NULL)
log_sys ("add_id: malloc %d bytes", msize);
current->left->left = NULL;
current->left->right = NULL;
(void) strcpy (current->left->msgid, msgid);
entries++;
return (0);
}
else
current = current->left;
}
else if (test > 0)
{
if (current->right == NULL) {
current->right = (struct mnode *) malloc (msize);
if (current->right == NULL)
log_sys ("add_id: malloc %d bytes", msize);
current->right->left = NULL;
current->right->right = NULL;
(void) strcpy (current->right->msgid, msgid);
entries++;
return (0);
}
else
current = current->right;
}
else
return (1);
}
}
/*
* do_newnews - Process a newnews for supplied list of groups, adding the
* resultant data to the message id tree.
*/
static void
do_newnews (char *line)
{
char buf [NNTP_STRLEN];
char *cp;
/* Create a full string to send to the server */
(void) sprintf (buf, "NEWNEWS %s %s GMT %s", line, nn_time,
nn_distributions);
/* Do the actual NEWNEWS */
if (debug_flag)
(void) fprintf (stderr, "<- %s\n", buf);
put_server (buf);
/* Get the response and check it's okay */
if (get_server (buf, sizeof (buf)))
exit (1);
if (debug_flag)
(void) fprintf (stderr, "-> %s\n", buf);
if (atoi (buf) != OK_NEWNEWS)
{
log_msg ("do_newnews: NNTP protocol error: got '%s'", buf);
exit (4);
}
/* Now get the data and stick it in the tree */
for (;;)
{
if (get_server (buf, sizeof (buf)))
exit (1);
if (!strcmp (buf, "."))
break;
/* Modify the message id appropriate to C-News history files */
cp = (char *) strchr (buf, '@');
if (cp != NULL)
{
for (; *cp != '\0'; ++cp)
if (isupper (*cp))
*cp = tolower (*cp);
}
if (debug_flag)
(void) fprintf (stderr, "-> %s", buf);
if (check_id (buf))
{
switch (add_id (buf))
{
case -1 :
hit_max = TRUE;
break;
case 0 :
newart++;
if (debug_flag)
(void) fprintf (stderr, " new\n");
break;
default :
break;
}
}
else
{
dupart++;
if (debug_flag)
(void) fprintf (stderr, " dup\n");
}
}
}
/*
* 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_not_groups - Add appropriate groups from the exclusion list to
* a group that is to be requested from the server.
*/
static int
get_not_groups (char *group)
{
char matchgroups [NNTP_STRLEN];
int i;
size_t tlen;
matchgroups [0] = '\0';
tlen = strlen (group);
for (i = 0 ; i < not_groups_no ; i ++)
if (!used_not_group_array [i])
if (restreql (group, not_group_array [i]))
if ((strlen (matchgroups) + tlen + 3) < NNTP_STRLEN)
{
(void) strcat (matchgroups, ",!");
(void) strcat (matchgroups, not_group_array [i]);
used_not_group_array [i] = TRUE;
}
else
return (1);
(void) strcat (group, matchgroups);
return (0);
}
/*
* get_ids - Store in memory a tree of the message ids of new article 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, add_comma;
parse_groups ();
line [0] = '\0';
bzero (used_not_group_array, not_groups_no * sizeof (int));
add_comma = FALSE;
for (i = 0 ; i < groups_no ; i++)
{
(void) strcpy (newgroups, group_array [i]);
if (get_not_groups (newgroups))
{
log_msg ("get_ids: Not enough room in NNTP line for exclusion list %s",
newgroups);
exit (2);
}
if ((strlen (line) + strlen (newgroups) +
strlen (nn_distributions) + (size_t) 31) > NNTP_STRLEN)
{
do_newnews (line);
line [0] = '\0';
(void) bzero (used_not_group_array, not_groups_no * sizeof (int));
add_comma = FALSE;
}
if ((strlen (line) + strlen (newgroups) +
strlen (nn_distributions) + (size_t) 31) > NNTP_STRLEN)
{
log_msg ("get_ids: Not enough room in NNTP line for newsgroup %s",
newgroups);
exit (2);
}
else
{
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 */
if (hit_max)
{
log_msg ("Maximum limit of %d messages hit", MAXCACHE);
no_time_flag++;
}
}
/* END-OF-FILE */