home *** CD-ROM | disk | FTP | other *** search
- /*
- * newnews - Read in list of ids of new articles
- *
- * Copyright (C) 1992/93 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.
- *
- * $Id: newnews.c,v 1.5 1993/03/01 17:45:16 root Exp $
- *
- * $Log: newnews.c,v $
- * 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 "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;
- }
- }
-
-
- /*
- * store_node - Store a new node in the binary tree
- */
-
- static struct mnode *
- store_node (char *msgid)
- {
- struct mnode *node;
-
- node = (struct mnode *) malloc (sizeof (struct mnode));
- if (node == NULL)
- log_sys ("add_id: malloc %d bytes", sizeof (struct mnode));
- node->left = NULL;
- node->right = NULL;
- node->used = FALSE;
- node->msgid = (char *) malloc (strlen (msgid) + sizeof (char));
- if (node->msgid == NULL)
- log_sys ("store_node: malloc %d bytes",
- strlen (msgid) + sizeof (char));
- (void) strcpy (node->msgid, msgid);
- entries++;
- return (node);
- }
-
-
- /*
- * 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;
-
- /* Test if hit the maximum number of entries in the cache */
- if (entries >= MAXCACHE)
- return (-1);
-
- /* Handle the case when the tree is empty */
- if (root == NULL) {
- root = store_node (msgid);
- 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 = store_node (msgid);
- return (0);
- }
- else
- current = current->left;
- }
- else if (test > 0)
- {
- if (current->right == NULL) {
- current->right = store_node (msgid);
- return (0);
- }
- else
- current = current->right;
- }
- else
- return (1);
- }
- }
-
-
- /*
- * 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;
-
- /* Modify the message id appropriate to C-News history files */
- cp = (char *) strchr (msgid, '@');
- if (cp != NULL)
- {
- for (; *cp != '\0'; ++cp)
- if (isupper (*cp))
- *cp = tolower (*cp);
- }
-
- if (debug_flag)
- (void) fprintf (stderr, "-> %s", msgid);
-
- if (check_id (msgid))
- {
- switch (add_id (msgid))
- {
- 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");
- }
- }
-
-
- /*
- * 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];
-
- /* 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 */
- get_server (buf, sizeof (buf));
- 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 (;;)
- {
- get_server (buf, sizeof (buf));
- if (!strcmp (buf, "."))
- break;
-
- process_id (buf);
- }
- }
-
-
- /*
- * 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 ((char *) 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';
- bzero ((char *) 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 */
-