ml.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "common.h"
  2. #include "dat.h"
  3. Biobuf in;
  4. Addr *al;
  5. int na;
  6. String *from;
  7. String *sender;
  8. void printmsg(int fd, String *msg, char *replyto, char *listname);
  9. void appendtoarchive(char* listname, String *firstline, String *msg);
  10. void printsubject(int fd, Field *f, char *listname);
  11. void
  12. usage(void)
  13. {
  14. fprint(2, "usage: %s address-list-file listname\n", argv0);
  15. exits("usage");
  16. }
  17. void
  18. main(int argc, char **argv)
  19. {
  20. String *msg;
  21. String *firstline;
  22. char *listname, *alfile;
  23. Waitmsg *w;
  24. int fd;
  25. char *replytoname = nil;
  26. ARGBEGIN{
  27. case 'r':
  28. replytoname = ARGF();
  29. break;
  30. }ARGEND;
  31. rfork(RFENVG|RFREND);
  32. if(argc < 2)
  33. usage();
  34. alfile = argv[0];
  35. listname = argv[1];
  36. if(replytoname == nil)
  37. replytoname = listname;
  38. readaddrs(alfile);
  39. if(Binit(&in, 0, OREAD) < 0)
  40. sysfatal("opening input: %r");
  41. msg = s_new();
  42. firstline = s_new();
  43. /* discard the 'From ' line */
  44. if(s_read_line(&in, firstline) == nil)
  45. sysfatal("reading input: %r");
  46. /* read up to the first 128k of the message. more is ridiculous.
  47. Not if word documents are distributed. Upped it to 2MB (pb) */
  48. if(s_read(&in, msg, 2*1024*1024) <= 0)
  49. sysfatal("reading input: %r");
  50. /* parse the header */
  51. yyinit(s_to_c(msg), s_len(msg));
  52. yyparse();
  53. /* get the sender */
  54. getaddrs();
  55. if(from == nil)
  56. from = sender;
  57. if(from == nil)
  58. sysfatal("message must contain From: or Sender:");
  59. if(strcmp(listname, s_to_c(from)) == 0)
  60. sysfatal("can't remail messages from myself");
  61. addaddr(s_to_c(from));
  62. /* start the mailer up and return a pipe to it */
  63. fd = startmailer(listname);
  64. /* send message adding our own reply-to and precedence */
  65. printmsg(fd, msg, replytoname, listname);
  66. close(fd);
  67. /* wait for mailer to end */
  68. while(w = wait()){
  69. if(w->msg != nil && w->msg[0])
  70. sysfatal("%s", w->msg);
  71. free(w);
  72. }
  73. /* if the mailbox exists, cat the mail to the end of it */
  74. appendtoarchive(listname, firstline, msg);
  75. exits(0);
  76. }
  77. /* send message filtering Reply-to out of messages */
  78. void
  79. printmsg(int fd, String *msg, char *replyto, char *listname)
  80. {
  81. Field *f, *subject;
  82. Node *p;
  83. char *cp, *ocp;
  84. subject = nil;
  85. cp = s_to_c(msg);
  86. for(f = firstfield; f; f = f->next){
  87. ocp = cp;
  88. for(p = f->node; p; p = p->next)
  89. cp = p->end+1;
  90. if(f->node->c == REPLY_TO)
  91. continue;
  92. if(f->node->c == PRECEDENCE)
  93. continue;
  94. if(f->node->c == SUBJECT){
  95. subject = f;
  96. continue;
  97. }
  98. write(fd, ocp, cp-ocp);
  99. }
  100. printsubject(fd, subject, listname);
  101. fprint(fd, "Reply-To: %s\nPrecedence: bulk\n", replyto);
  102. write(fd, cp, s_len(msg) - (cp - s_to_c(msg)));
  103. }
  104. /* if the mailbox exists, cat the mail to the end of it */
  105. void
  106. appendtoarchive(char* listname, String *firstline, String *msg)
  107. {
  108. String *mbox;
  109. int fd;
  110. mbox = s_new();
  111. mboxpath("mbox", listname, mbox, 0);
  112. if(access(s_to_c(mbox), 0) < 0)
  113. return;
  114. fd = open(s_to_c(mbox), OWRITE);
  115. if(fd < 0)
  116. return;
  117. s_append(msg, "\n");
  118. write(fd, s_to_c(firstline), s_len(firstline));
  119. write(fd, s_to_c(msg), s_len(msg));
  120. }
  121. /* add the listname to the subject */
  122. void
  123. printsubject(int fd, Field *f, char *listname)
  124. {
  125. char *s, *e;
  126. Node *p;
  127. char *ln;
  128. if(f == nil || f->node == nil){
  129. fprint(fd, "Subject: [%s]\n", listname);
  130. return;
  131. }
  132. s = e = f->node->end + 1;
  133. for(p = f->node; p; p = p->next)
  134. e = p->end;
  135. *e = 0;
  136. ln = smprint("[%s]", listname);
  137. if(ln != nil && strstr(s, ln) == nil)
  138. fprint(fd, "Subject: %s%s\n", ln, s);
  139. else
  140. fprint(fd, "Subject:%s\n", s);
  141. free(ln);
  142. }