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 >
C/C++ Source or Header  |  1992-12-20  |  9KB  |  394 lines

  1. /*
  2.  * newnews - Read in list of ids of new articles
  3.  *
  4.  * Copyright (C) 1992 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.  * Using a previously initialised list of newsgroups, carries out a series
  11.  * of NEWNEWS requests to the connected NNTP server, storing the message
  12.  * ids of new articles in a binary tree in memory.
  13.  *
  14.  * 1.00  30 Nov 92  SH  Transferred from slurp.c
  15.  * 1.01   4 Dec 92  SH  No longer need to handle null nn_distributions
  16.  * 1.01   4 Dec 92  SH  Print line before it is sent to server when
  17.  *                      debugging is on.
  18.  * 1.01   6 Dec 92  SH  Set no_time_flag if hit max no of messages.
  19.  * 1.03  14 Dec 92  SH  Only malloc enough space for msgid, not whole
  20.  *                      mnode structure.
  21.  *                      Minor tidy-ups.
  22.  *
  23.  */
  24.  
  25. #include "slurp.h"
  26.  
  27. static int hit_max = FALSE;
  28.  
  29. static char **group_array;
  30. static char **not_group_array;
  31. static int  *used_not_group_array;
  32.  
  33. static int  groups_no;
  34. static int  not_groups_no;
  35.  
  36.  
  37. static void parse_groups ();
  38. static int  add_id (char *msgid);
  39. static void do_newnews (char *line);
  40. static int  restreql (register char *w, register char *s);
  41. static int  get_not_groups (char *group);
  42.  
  43.  
  44. /*
  45.  * parse_groups - Turn list of groups into two arrays containing 
  46.  * pointers to groups to include and groups to exclude.
  47.  */
  48.  
  49.     static void
  50. parse_groups ()
  51.     {
  52.     int i, got, not;
  53.     char *cp;
  54.  
  55.     /* Calculate number of group entries */
  56.     for (i = 1, cp = nn_newsgroups; *cp != '\0'; cp++)
  57.         if (*cp == ',')
  58.             i++;
  59.  
  60.     /* Malloc space for include and exclude group arrays */
  61.     if ((group_array = (char **) malloc (i * (sizeof (char *)))) == NULL)
  62.         log_sys ("parse_groups: malloc %d bytes", i * sizeof (char **));
  63.  
  64.     if ((not_group_array = (char **) malloc (i * (sizeof (char *)))) == NULL)
  65.         log_sys ("parse_groups: malloc %d bytes", i * sizeof (char **));
  66.  
  67.     if ((used_not_group_array = (int *) malloc (i * (sizeof (int)))) == NULL)
  68.         log_sys ("parse_groups: malloc %d bytes", i * sizeof (int));
  69.  
  70.     /* Now start parsing the newsgroup list */
  71.     groups_no = 0;
  72.     not_groups_no = 0;
  73.     got = TRUE;
  74.     not = FALSE;
  75.  
  76.     for (cp = nn_newsgroups; *cp != '\0'; ++cp)
  77.         {
  78.         if (*cp == '!')
  79.             got = FALSE;
  80.  
  81.         if (got)
  82.             {
  83.             group_array [groups_no] = cp;
  84.             groups_no++;
  85.             got = FALSE;
  86.             }
  87.  
  88.         if (not)
  89.             {
  90.             not_group_array [not_groups_no] = cp;
  91.             not_groups_no++;
  92.             not = FALSE;
  93.             }
  94.  
  95.         if (*cp == ',')
  96.             {
  97.             *cp = '\0';
  98.             got = TRUE;
  99.             }
  100.  
  101.         if (*cp == '!')
  102.             not = TRUE;
  103.         }
  104.     }
  105.  
  106.  
  107. /*
  108.  * add_id - Add a message id to the binary tree if not already present.
  109.  * Returns -1 if the maximum number of entries in the tree has been
  110.  * reached, 0 if the item is added okay, 1 if an entry with that 
  111.  * particular message id already exists.
  112.  */
  113.  
  114.     static int
  115. add_id (char *msgid)
  116.     {
  117.     struct mnode *current;
  118.     int test;
  119.     size_t msize;
  120.  
  121.     /* Test if hit the maximum number of entries in the cache */
  122.     if (entries >= MAXCACHE)
  123.         return (-1);
  124.  
  125.     /* Calculate size to malloc - not the full structure size */
  126.     msize = 2 * (sizeof (struct mnode *)) + strlen (msgid) + sizeof (char);
  127.  
  128.     /* Handle the case when the tree is empty */
  129.     if (root == NULL) {
  130.         root = (struct mnode *) malloc (msize);
  131.         if (root == NULL)
  132.             log_sys ("add_id: malloc %d bytes", msize);
  133.         root->left = NULL;
  134.         root->right = NULL;
  135.         (void) strcpy (root->msgid, msgid);
  136.         entries++;
  137.         return (0);
  138.     }
  139.  
  140.     /* Search the tree for correct position to insert node */
  141.     current = root;
  142.     
  143.     for (;;)
  144.         {
  145.         test = strcmp (msgid, current->msgid);
  146.         if (test < 0)
  147.             {
  148.             if (current->left == NULL)
  149.                 {
  150.                 current->left = (struct mnode *) malloc (msize);
  151.                 if (current->left == NULL)
  152.                     log_sys ("add_id: malloc %d bytes", msize);
  153.                 current->left->left = NULL;
  154.                 current->left->right = NULL;
  155.                 (void) strcpy (current->left->msgid, msgid);
  156.                 entries++;
  157.                 return (0);
  158.                 }
  159.             else
  160.                 current = current->left;
  161.             }
  162.         else if (test > 0)
  163.             {
  164.             if (current->right == NULL) {
  165.                 current->right = (struct mnode *) malloc (msize);
  166.                 if (current->right == NULL)
  167.                     log_sys ("add_id: malloc %d bytes", msize);
  168.                 current->right->left = NULL;
  169.                 current->right->right = NULL;
  170.                 (void) strcpy (current->right->msgid, msgid);
  171.                 entries++;
  172.                 return (0);
  173.                 }
  174.             else
  175.                 current = current->right;
  176.             }
  177.         else
  178.             return (1);
  179.         }
  180.     }
  181.  
  182.  
  183. /*
  184.  * do_newnews - Process a newnews for supplied list of groups, adding the
  185.  * resultant data to the message id tree.
  186.  */
  187.  
  188.     static void
  189. do_newnews (char *line)
  190.     {
  191.     char buf [NNTP_STRLEN];
  192.     char *cp;
  193.  
  194.     /* Create a full string to send to the server */
  195.     (void) sprintf (buf, "NEWNEWS %s %s GMT %s", line, nn_time,
  196.                     nn_distributions);
  197.  
  198.     /* Do the actual NEWNEWS */
  199.     if (debug_flag)
  200.         (void) fprintf (stderr, "<- %s\n", buf);
  201.     put_server (buf);
  202.     
  203.     /* Get the response and check it's okay */
  204.     if (get_server (buf, sizeof (buf)))
  205.         exit (1);
  206.     if (debug_flag)
  207.         (void) fprintf (stderr, "-> %s\n", buf);
  208.     if (atoi (buf) != OK_NEWNEWS)
  209.         {
  210.         log_msg ("do_newnews: NNTP protocol error: got '%s'", buf);
  211.         exit (4);
  212.         }
  213.                     
  214.     /* Now get the data and stick it in the tree */
  215.     for (;;)
  216.         {
  217.         if (get_server (buf, sizeof (buf)))
  218.             exit (1);
  219.         if (!strcmp (buf, "."))
  220.             break;
  221.  
  222.     /* Modify the message id appropriate to C-News history files */
  223.         cp = (char *) strchr (buf, '@');
  224.         if (cp != NULL)
  225.             {
  226.             for (; *cp != '\0'; ++cp)
  227.                 if (isupper (*cp))
  228.                     *cp = tolower (*cp);
  229.             }
  230.  
  231.         if (debug_flag)
  232.             (void) fprintf (stderr, "-> %s", buf);
  233.  
  234.         if (check_id (buf))
  235.             {
  236.             switch (add_id (buf))
  237.                 {
  238.                 case -1 :
  239.                     hit_max = TRUE;
  240.                     break;
  241.                 case  0 :
  242.                     newart++;
  243.                     if (debug_flag)
  244.                         (void) fprintf (stderr, " new\n");
  245.                     break;
  246.                 default :
  247.                     break;
  248.                 }
  249.             }
  250.         else
  251.             {
  252.             dupart++;
  253.             if (debug_flag)
  254.                 (void) fprintf (stderr, " dup\n");
  255.             }
  256.         }
  257.     }
  258.  
  259.  
  260. /*
  261.  * restreql -- A small regular expression string equivalence routine
  262.  * purloined from nntp 1.5.11 which credits <lai@shadow.berkeley.edu>
  263.  * for its creation. Returns 1 if the string pointed to by 's' matches
  264.  * the asterisk-broadened regexp string pointed to by 'w', otherwise
  265.  * returns 0.
  266.  */
  267.  
  268.     static int
  269. restreql (register char *w, register char *s)
  270.     {
  271.     while (*s && *w)
  272.         {
  273.         switch (*w)
  274.             {
  275.             case '*':
  276.                 for (w++; *s; s++)
  277.                     if (restreql(w, s))
  278.                         return (1);
  279.                 break;
  280.             default:
  281.                 if (*w != *s)
  282.                     return (0);
  283.                 w++, s++;
  284.                 break;
  285.             }
  286.         }
  287.     if (*s)
  288.         return (0);
  289.     while (*w)
  290.         if (*w++ != '*')
  291.             return 0;
  292.  
  293.     return (1);
  294.     }
  295.  
  296.  
  297. /*
  298.  * get_not_groups - Add appropriate groups from the exclusion list to
  299.  * a group that is to be requested from the server.
  300.  */
  301.  
  302.     static int
  303. get_not_groups (char *group)
  304.     {
  305.     char matchgroups [NNTP_STRLEN];
  306.     int i;
  307.     size_t tlen;
  308.  
  309.     matchgroups [0] = '\0';
  310.     tlen = strlen (group);
  311.     for (i = 0 ; i < not_groups_no ; i ++)
  312.         if (!used_not_group_array [i])
  313.             if (restreql (group, not_group_array [i]))
  314.                 if ((strlen (matchgroups) + tlen + 3) < NNTP_STRLEN)
  315.                     {
  316.                     (void) strcat (matchgroups, ",!");
  317.                     (void) strcat (matchgroups, not_group_array [i]);
  318.                     used_not_group_array [i] = TRUE;
  319.                     }
  320.                 else
  321.                     return (1);
  322.     (void) strcat (group, matchgroups);
  323.     return (0);
  324.     }
  325.  
  326.  
  327. /*
  328.  * get_ids - Store in memory a tree of the message ids of new article at
  329.  * the server which match the specified set of groups and distributions
  330.  * for the currently connected host.
  331.  */
  332.  
  333.     void
  334. get_ids ()
  335.     {
  336.     char line [NNTP_STRLEN];
  337.     char newgroups [NNTP_STRLEN];
  338.     int i, add_comma;
  339.  
  340.     parse_groups ();
  341.  
  342.     line [0] = '\0';
  343.     bzero (used_not_group_array, not_groups_no * sizeof (int));
  344.     add_comma = FALSE;
  345.  
  346.     for (i = 0 ; i < groups_no ; i++)
  347.         {
  348.         (void) strcpy (newgroups, group_array [i]);
  349.  
  350.         if (get_not_groups (newgroups))
  351.             {
  352.             log_msg ("get_ids: Not enough room in NNTP line for exclusion list %s",
  353.                      newgroups);
  354.             exit (2);
  355.             }
  356.  
  357.         if ((strlen (line) + strlen (newgroups) + 
  358.              strlen (nn_distributions) + (size_t) 31) > NNTP_STRLEN)
  359.             {
  360.             do_newnews (line);
  361.             line [0] = '\0';
  362.             (void) bzero (used_not_group_array, not_groups_no * sizeof (int));
  363.             add_comma = FALSE;
  364.             }
  365.  
  366.         if ((strlen (line) + strlen (newgroups) + 
  367.              strlen (nn_distributions) + (size_t) 31) > NNTP_STRLEN)
  368.             {
  369.             log_msg ("get_ids: Not enough room in NNTP line for newsgroup %s",
  370.                      newgroups);
  371.             exit (2);
  372.             }
  373.         else
  374.             {
  375.             if (add_comma)
  376.                 (void) strcat (line, ",");
  377.             else
  378.                 add_comma = TRUE;
  379.             (void) strcat (line, newgroups);
  380.             }
  381.         }
  382.  
  383.     do_newnews (line);
  384.  
  385.     /* Report if couldn't fit everything in the tree */
  386.     if (hit_max)
  387.         {
  388.         log_msg ("Maximum limit of %d messages hit", MAXCACHE);
  389.         no_time_flag++;
  390.         }
  391.     }
  392.  
  393. /* END-OF-FILE */
  394.