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 / transmit.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  8KB  |  277 lines

  1. /*
  2.  * transmit - transmit incoming articles to neighbouring machines
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include "libc.h"
  8. #include "news.h"
  9. #include "config.h"
  10. #include "headers.h"
  11. #include "active.h"
  12. #include "article.h"
  13. #include "msgs.h"
  14. #include "system.h"
  15. #include "trbatch.h"
  16. #include "transmit.h"
  17.  
  18. /* forwards */
  19. FORWARD boolean oktransmit();
  20. FORWARD void ejaculate(), trappend();
  21.  
  22. /* private */
  23. static boolean debug = NO;
  24.  
  25. void
  26. transdebug(state)
  27. boolean state;
  28. {
  29.     debug = state;
  30. }
  31.  
  32. /*
  33.  * For each system in "sys" other than this one,
  34.  * transmit this article when its ng pattern matches
  35.  * art->h.h_distr (which may be just a copy of art->h.h_ngs).
  36.  */
  37. void
  38. transmit(art, exclude)
  39. register struct article *art;
  40. char *exclude;                    /* no copy to this site */
  41. {
  42.     register struct system *sys;
  43.     register int bsysno = 0;    /* ordinal # of batch sys entry */
  44.  
  45.     rewndsys();
  46.     if (debug)
  47.         (void) fprintf(stderr, "just rewound sys file\n");
  48.     while ((sys = nextsys()) != NULL) {
  49.         if (debug)
  50.             (void) fprintf(stderr,
  51.                 "sy_name=%s sy_ngs=%s sy_distr=%s\n",
  52.                 sys->sy_name, sys->sy_ngs, sys->sy_distr);
  53.         if (oktransmit(art, sys, exclude))
  54.             ejaculate(art, sys, bsysno);
  55.         if (sys->sy_flags&FLG_BATCH)
  56.             ++bsysno;
  57.     }
  58.     if (debug)
  59.         (void) fprintf(stderr, "just finished reading sys file\n");
  60. }
  61.  
  62. /*
  63.  * Is it okay to send the article corresponding to "art" to site "sys",
  64.  * excluding site "exclude"?
  65.  *
  66.  * If L(n) flag is on, must have been posted within n hops of here.
  67.  * Never send to this site, nor the "exclude" site, nor any site with a host
  68.  * in sys->sy_excl named in Path:, nor any site named in Path:.
  69.  *
  70.  * Newsgroups: must match sys's subscription list.
  71.  * Distribution: must match sys's distribution list.  (RFC 850 is wrong:
  72.  * Distribution:s are *not* patterns, they are lists.  See RFC 1036.)
  73.  *
  74.  * If m flag is on, group(s) must be moderated; if u flag is on,
  75.  * must be unmoderated.  (If both are on, act as if neither is on.)
  76.  */
  77. STATIC boolean
  78. oktransmit(art, sys, exclude)
  79. register struct article *art;
  80. register struct system *sys;
  81. char *exclude;                /* no copy to him */
  82. {
  83.     register int flags = sys->sy_flags;
  84.     register char *site = sys->sy_name;
  85.     register char *path =
  86.         canonpath(art->h.h_path, art->h.h_approved, art->h.h_sender);
  87.     register int result;
  88.  
  89.     if (flags&FLG_LOCAL && hopcount(path) > sys->sy_lochops ||
  90.         STREQ(hostname(), site) ||
  91.         exclude != NULL && STREQ(exclude, site) || hostin(site, path) ||
  92.         sys->sy_excl != NULL && anyhostin(sys->sy_excl, path) ||
  93.         !ngmatch(sys->sy_ngs, art->h.h_ngs) ||
  94.         !ngmatch(sys->sy_distr, art->h.h_distr))
  95.         result = NO;
  96.     else if (flags&(FLG_MOD|FLG_UNMOD)) {    /* u, m flag selection */
  97.         if ((flags&(FLG_MOD|FLG_UNMOD)) == (FLG_MOD|FLG_UNMOD))
  98.             result = YES;        /* too silly */
  99.         else
  100.             result = (flags&FLG_MOD? moderated(art->h.h_ngs):
  101.                         !moderated(art->h.h_ngs));
  102.     } else
  103.         result = YES;
  104.     free(path);
  105.     return result;
  106. }
  107.  
  108. /*
  109.  * Send the article denoted by art to the system denoted by sys.
  110.  *
  111.  * When a filename is needed, we use the first one in art->a_files
  112.  * rather than art->a_tmpf because we want a permanent name, and
  113.  * translate it to a full path name to avoid ambiguity.
  114.  *
  115.  * Side-effect: prints the system name on stdout for logging.
  116.  */
  117. STATIC void
  118. ejaculate(art, sys, bsysno)
  119. register struct article *art;
  120. register struct system *sys;
  121. int bsysno;
  122. {
  123.     register char *fullname;    /* sometimes is a message-id */
  124.  
  125.     if (debug)
  126.         (void) fprintf(stderr, "transmitting %s to %s\n",
  127.             art->h.h_msgid, sys->sy_name);
  128.         (void) printf(" %s", sys->sy_name);    /* logging */
  129.     if (sys->sy_flags&FLG_IHAVE)
  130.         fullname = art->h.h_msgid;
  131.     else {
  132.         register char *filename = first(art->a_files);
  133.  
  134.         mkfilenm(filename);
  135.             fullname = fullartfile(filename);
  136.         free(filename);
  137.     }
  138. #ifdef PARANOID
  139.     fullname = strsave(fullname);
  140. #endif
  141.     if (sys->sy_flags&FLG_BATCH)
  142.             trbatch(art, sys, fullname, bsysno);
  143.     else
  144.         trcmd(art, sys, fullname);
  145. #ifdef PARANOID
  146.     free(fullname);
  147. #endif
  148. }
  149.  
  150. /*
  151.  * Execute sys->sy_cmd with the current article as stdin
  152.  * and filename substituted for %s in sys->sy_cmd (if any).
  153.  *
  154.  * Search path includes $NEWSCTL/bin and $NEWSBIN/relay.
  155.  * redirect stdin to prevent consuming my stdin & so cmd's stdin
  156.  * is filename by default.
  157.  *
  158.  * We use strcat instead of sprintf if syscmd contains no %.
  159.  * this avoids the 128-byte restriction on printf output
  160.  * (see printf(3) BUGS, at least in V7).
  161.  */
  162. void
  163. trcmd(art, sys, filename)
  164. struct article *art;
  165. struct system *sys;
  166. char *filename;
  167. {
  168.     register char *cmd;
  169.     int exitstat;
  170.     char *syscmd = sys->sy_cmd, *percent;
  171.     static char *ctlcmd = NULL, *bincmd = NULL;
  172.  
  173.     if (ctlcmd == NULL)
  174.         ctlcmd = strsave(ctlfile("bin"));
  175.     if (bincmd == NULL)
  176.         bincmd = strsave(binfile("relay"));
  177.     cmd = nemalloc((unsigned)(STRLEN("PATH=") + strlen(ctlcmd) +
  178.         STRLEN(":") + strlen(bincmd) + STRLEN(":") + strlen(newspath()) +
  179.         STRLEN(" <") + strlen(filename) + STRLEN(" ") +
  180.         strlen(syscmd) + strlen(filename) + 1));
  181.     (void) strcpy(cmd, "PATH=");
  182.     (void) strcat(cmd, ctlcmd);
  183.     (void) strcat(cmd, ":");
  184.     (void) strcat(cmd, bincmd);
  185.     (void) strcat(cmd, ":");
  186.     (void) strcat(cmd, newspath());
  187.     (void) strcat(cmd, " <");
  188.     (void) strcat(cmd, filename);
  189.     (void) strcat(cmd, " ");
  190.     percent = index(syscmd, '%');
  191.     if (percent == NULL)
  192.         (void) strcat(cmd, syscmd);
  193.     else {
  194.         char *pcent2;
  195.  
  196.         ++percent;
  197.         pcent2 = index(percent, '%');
  198.         if (pcent2 != NULL) {
  199.             art->a_status |= ST_DROPPED;
  200.             (void) fprintf(stderr, "%s: `%s' contains two %%'s\n",
  201.                 progname, cmd);
  202.         } else if (*percent != 's' && *percent != '%') {
  203.             art->a_status |= ST_DROPPED;
  204.             (void) fprintf(stderr, "%s: `%s' contains %%%c, not %%s\n",
  205.                 progname, cmd, *percent);
  206.         } else
  207.             (void) sprintf(cmd+strlen(cmd), syscmd, filename);
  208.     }
  209.     exitstat = system(cmd);
  210.     if (exitstat != 0) {
  211.         art->a_status |= ST_DROPPED;
  212.         (void) fprintf(stderr, "%s: `%s' returned exit status 0%o\n",
  213.             progname, cmd, exitstat);
  214.     }
  215.     free(cmd);
  216. }
  217.  
  218. /*
  219.  * Append "filename" to sys->sy_cmd.  bsysno is the ordinal # of this batch
  220.  * sys line.  If bsysno is low enough, use the batchfile cache of batch file
  221.  * descriptors.
  222.  */
  223. void
  224. trbatch(art, sys, filename, bsysno)
  225. register struct article *art;
  226. struct system *sys;
  227. char *filename;
  228. register int bsysno;
  229. {
  230.     register struct batchfile *bf = bfopen(sys->sy_cmd, bsysno);
  231.  
  232.     if (bf == NULL || bf->bf_str == NULL)
  233.         art->a_status |= ST_DROPPED;
  234.     else {
  235.         trappend(art, sys, bf, filename);
  236.         art->a_status |= bffkclose(bsysno);
  237.     }
  238. }
  239.  
  240. /*
  241.  * write filename, message-id or size on batch file "bf".
  242.  * under the 'f' flag (FLG_SZBATCH), include the size in bytes of the article
  243.  * after "name" to assist the C news batcher.  under the 'n' flag (FLG_NBATCH),
  244.  * write the article's message-id.  afterward, flush "bf" in case
  245.  * the machine crashes before the stream is closed.
  246.  */
  247. STATIC void
  248. trappend(art, sys, bf, name)
  249. register struct article *art;
  250. register struct system *sys;
  251. register struct batchfile *bf;
  252. char *name;
  253. {
  254.     if (fputs(name, bf->bf_str) == EOF)
  255.         fulldisk(art, bf->bf_name);
  256.     if (sys->sy_flags&FLG_SZBATCH &&
  257.         fprintf(bf->bf_str, " %ld", art->a_charswritten) == EOF)
  258.         fulldisk(art, bf->bf_name);
  259.     if (sys->sy_flags&FLG_NBATCH &&
  260.         fprintf(bf->bf_str, " %s", art->h.h_msgid) == EOF)
  261.         fulldisk(art, bf->bf_name);
  262.  
  263.     /* don't check putc return value for portability; use ferror */
  264.     (void) putc('\n', bf->bf_str);
  265.     if (ferror(bf->bf_str) || bfflush(bf) == EOF)
  266.         fulldisk(art, bf->bf_name);        
  267. }
  268.  
  269. /*
  270.  * really close all the open batch files
  271.  */
  272. statust
  273. trclose()
  274. {
  275.     return bfrealclose();
  276. }
  277.