home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff319.lzh / CNewsSrc / cnews.orig.lzh / relay / ihave.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  6KB  |  213 lines

  1. /*
  2.  * Implement the Usenet ihave/sendme control messages,
  3.  * as per RFC 1036 (nee 850).
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <sys/types.h>
  9.  
  10. #include "libc.h"
  11. #include "news.h"
  12. #include "config.h"
  13. #include "headers.h"
  14. #include "article.h"
  15. #include "history.h"
  16. #include "fgetmfs.h"
  17. #include "msgs.h"
  18. #include "transmit.h"
  19.  
  20. #ifndef SENDMEDISTR
  21. #define SENDMEDISTR "sendme"    /* kludge: distinguished distribution for sendmes 
  22. /
  23. #endif
  24. #ifndef IHAVEDISTR
  25. #define IHAVEDISTR "ihave"    /* kludge: distinguished distribution for ihaves */
  26. #endif
  27. #ifndef AVEARTSIZE
  28. #define AVEARTSIZE 3000
  29. #endif
  30.  
  31. #define PROTO_IHAVE 0
  32. #define PROTO_SENDME 1
  33.  
  34. /* static forwards */
  35. FORWARD void doproto(), procmsgids(), procbodymsgids();
  36. FORWARD statust faketrans();
  37.  
  38. /*
  39.  * Read message-IDs from args or control message body,
  40.  * look them up in history, post a sendme to to.remotesys (via the batcher
  41.  * to avoid deadlock) consisting of the message-IDs not in history.
  42.  * The "posting" consists of transmitting to a system matching
  43.  * "to.remotesys" in sys, which had better have the I flag on.
  44.  * ihave message-ID-list remotesys    generate a sendme from message-ID-list
  45.  */
  46. void
  47. ihave(args, art)
  48. char *args;
  49. struct article *art;
  50. {
  51.     doproto(args, art, IHAVEDISTR, PROTO_IHAVE);
  52. }
  53.  
  54. /*
  55.  * Read message-IDs from args or control message body,
  56.  * transmit the corresponding articles to a system matching
  57.  * "to.remotesys/sendme" in sys, which will typically name a batch file.
  58.  * sendme message-ID-list remotesys    send articles named to remotesys
  59.  */
  60. void
  61. sendme(args, art)
  62. char *args;
  63. struct article *art;
  64. {
  65.     doproto(args, art, SENDMEDISTR, PROTO_SENDME);
  66. }
  67.  
  68. static void
  69. doproto(args, art, distr, proto)
  70. char *args;
  71. register struct article *art;
  72. char *distr;
  73. int proto;
  74. {
  75.     register char *argscp = skipsp(args), *remotesys;
  76.  
  77.     if (*argscp == '\n' || *argscp == '\0')    /* no args */
  78.         return;
  79.  
  80.     argscp = strsave(argscp);
  81.  
  82.     /* dig out the remote system name */
  83.     remotesys = rindex(argscp, ' ');    
  84.     if (remotesys == NULL)            /* no msg-ids in command */
  85.         remotesys = argscp;
  86.     else {
  87.         remotesys = argscp + strlen(argscp) - 1;    /* last byte */
  88.         while (isascii(*remotesys) && isspace(*remotesys))
  89.             *remotesys-- = '\0';    /* back up to non-whitespace */
  90.         remotesys = rindex(argscp, ' ');
  91.         if (remotesys == NULL)        /* no msg-ids in command */
  92.             remotesys = argscp;
  93.         else
  94.             *remotesys++ = '\0';    /* separate msg-ids & sys name */
  95.     }
  96.     if (strcmp(remotesys, hostname()) != 0)    /* remotesys may not be me */
  97.         if (remotesys != argscp)    /* msg-ids in command */
  98.             procmsgids(art, argscp, remotesys, distr, proto);
  99.         else
  100.             procbodymsgids(art, remotesys, distr, proto);
  101.     free(argscp);
  102. }
  103.  
  104. /*
  105.  * Process a list of message-ids in msgidln: look them up
  106.  * and "transmit" the articles to to.remotesys.
  107.  */
  108. static void
  109. procmsgids(art, msgidln, remotesys, distr, proto)
  110. struct article *art;
  111. char *msgidln, *remotesys, *distr;
  112. int proto;
  113. {
  114.     char *cpmsgid = strsave(skipsp(msgidln));
  115.     register char *msgid = cpmsgid, *endmsgid;
  116.     register int save, sendit;
  117.  
  118.     for (; *msgid != '\n' && *msgid != '\0'; msgid = skipsp(endmsgid)) {
  119.         for (endmsgid = msgid; *endmsgid != '\0' &&
  120.             isascii(*endmsgid) && !isspace(*endmsgid); ++endmsgid)
  121.             ;            /* skip msgid */
  122.  
  123.         save = *endmsgid;
  124.         *endmsgid = '\0';        /* terminate msgid at whitespace */
  125.         if (proto == PROTO_IHAVE)
  126.             sendit = !alreadyseen(msgid);    /* sendme from remotesys */
  127.         else
  128.             sendit = alreadyseen(msgid);    /* sendme to remotesys */
  129.         if (sendit)
  130.             art->a_status |= faketrans(msgid, remotesys, distr, proto);
  131.         *endmsgid = save;
  132.     }
  133.     free(cpmsgid);
  134. }
  135.  
  136. static void
  137. procbodymsgids(art, remotesys, distr, proto)
  138. register struct article *art;
  139. char *remotesys, *distr; 
  140. int proto;
  141. {
  142.     register FILE *arttext;
  143.  
  144.     arttext = fopenwclex(art->a_tmpf, "r");
  145.     if (arttext != NULL) {
  146.         char *line;
  147.  
  148.         while ((line = fgetms(arttext)) != NULL && *line != '\n')
  149.             nnfree(&line);        /* skip header */
  150.         if (line != NULL) {        /* article body exists */
  151.             nnfree(&line);        /* toss blank separating line */
  152.             while ((line = fgetms(arttext)) != NULL) {
  153.                 procmsgids(art, line, remotesys, distr, proto);
  154.                 nnfree(&line);
  155.             }
  156.         }
  157.         (void) nfclose(arttext);
  158.     }
  159. }
  160.  
  161. /*
  162.  * Fake up a minimal article struct for msgid using group to.remotesys and
  163.  * distribution distr, then invoke transmit().  If there is a history
  164.  * entry for msgid, supply the list of file names too.
  165.  * Generate a log entry for each message-id transmitted.
  166.  */
  167. static statust
  168. faketrans(msgid, remotesys, distr, proto)
  169. register char *msgid, *remotesys;
  170. char *distr;
  171. int proto;
  172. {
  173.     struct article fakeart;
  174.     register char *ng;
  175.     register char *histent;
  176.     register struct article *fap = &fakeart;
  177.     time_t now;
  178.     statust status = ST_OKAY;
  179.  
  180.     ng = nemalloc((unsigned)(STRLEN("to.") + strlen(remotesys) + 1));
  181.     (void) strcpy(ng, "to.");
  182.     (void) strcat(ng, remotesys);
  183.  
  184.     artinit(fap);
  185.  
  186.     fap->h.h_ngs = ng;
  187.     fap->h.h_distr = (distr != NULL? distr: ng);
  188.     fap->h.h_msgid = msgid;
  189.     fap->h.h_path = hostname();
  190.     fap->a_charswritten = AVEARTSIZE;
  191.     histent = gethistory(msgid);
  192.     if (histent == NULL || (fap->a_files = findfiles(histent)) == NULL)
  193.         fap->a_files = "no.such.article!";
  194.  
  195.     timestamp(stdout, &now);    /* start log line */
  196.     if (printf(" %s %c %s", sendersite(nullify(fap->h.h_path)),
  197.         (proto == PROTO_IHAVE? 'i': 's'), fap->h.h_msgid) == EOF)
  198.         fulldisk(fap, "stdout");
  199.     transmit(fap, "");    /* write on batch file; write sys name on stdout */
  200.     (void) putchar('\n');        /* end log line */
  201.     status |= fap->a_status;    /* pass back failure writing batch file */
  202.  
  203.     fap->h.h_ngs = NULL;
  204.     fap->h.h_distr = NULL;
  205.     fap->h.h_msgid = NULL;
  206.     fap->h.h_path = NULL;
  207.     fap->a_files = NULL;
  208.     artfree(fap);
  209.  
  210.     free(ng);
  211.     return status;
  212. }
  213.