home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 1 / GoldFishApril1994_CD2.img / d4xx / d473 / cnewssrc / cnews_src.lzh / relay / ihave.c < prev    next >
C/C++ Source or Header  |  1990-05-28  |  6KB  |  216 lines

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