home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / listserv5.31 / part04 < prev    next >
Encoding:
Internet Message Format  |  1991-12-12  |  43.6 KB

  1. Subject: v25i038: listserv5.31 - mailing list management system, Part04/06
  2. Newsgroups: comp.sources.unix
  3. Approved: vixie@pa.dec.com
  4.  
  5. Submitted-By: tasos@cs.bu.edu
  6. Posting-Number: Volume 25, Issue 38
  7. Archive-Name: listserv5.31/part04
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 4 (of 6)."
  16. # Contents:  src/list.c
  17. # Wrapped by vixie@cognition.pa.dec.com on Fri Dec 13 18:31:09 1991
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'src/list.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'src/list.c'\"
  21. else
  22. echo shar: Extracting \"'src/list.c'\" \(42066 characters\)
  23. sed "s/^X//" >'src/list.c' <<'END_OF_FILE'
  24. X/*
  25. X  ----------------------------------------------------------------------------
  26. X  |           DISCUSSION LIST MAIL-DISTRIBUTION PROGRAM             |
  27. X  |                                         |
  28. X  |                 Version 2.6                     |
  29. X  |                                                                          |
  30. X  |                (or, when Computer Science gets to you)                   |
  31. X  |                                         |
  32. X  |               Written by Anastasios Kotsikonas                      |
  33. X  |                      (tasos@cs.bu.edu)                          |
  34. X  |                                                                         |
  35. X  | AGREEMENT: This software can be used and distributed freely as long      |
  36. X  | as you do not remove or alter the Copyright notice in the file defs.h;   |
  37. X  | this notice is #define'd in the symbol VERSION. Although you may alter   |
  38. X  | the code provided, you may not alter the functions create_header()       |
  39. X  | and create_multi_recipient_header() in list.c and listserv.c.         |
  40. X  | By using this software you are bound by this agreement.             |
  41. X  | This software comes with no warranties and cannot be sold for profit.    |
  42. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  43. X  | files when distributing this software.                     |
  44. X  | COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas                  |
  45. X  ----------------------------------------------------------------------------
  46. X
  47. X  NOTE: Anything appearing in capital letters refers to #define's in the
  48. X  header files provided.
  49. X
  50. X  PURPOSE: Create discussion lists. Members of the list send messages to
  51. X  them, and each of these messages is forwarded to the rest of the members.
  52. X  Any message(s) not from subscribers are returned to the original senders,
  53. X  or can be forwarded to MANAGER. Messages from "undesired" senders can be
  54. X  ignored by placing their email addresses in the IGNORED file (this would
  55. X  usually include root and the list's login name to avoid infinite loops).
  56. X
  57. X  OVERVIEW: A discussion list resides in a subdirectory of /usr/server/lists
  58. X  whose name is the list's alias (in the aliases file) in capital letters.
  59. X  When the program is killed or it abnormally dies, a message
  60. X  is sent to MANAGER (if using UCB mail) along with a copy of the current 
  61. X  report file (more on that below). Use the -1 flag when running the
  62. X  program. The discussion list to be processed is given as argument to the
  63. X  -L option in upper case. Any progress is reported to the list's REPORT_LIST
  64. X  file and to the administrator's terminal. All messages sent to this list are
  65. X  saved in the MBOX file. The program can be run as stand-alone, or in
  66. X  conjunction with the other programs provided (start, serverd and listserv).
  67. X  Please note that a line beginning with "From " and another one beginning
  68. X  with "From: " must appear in the header of each message, and a blank line
  69. X  must separate the header from the body of the message. Discussion lists
  70. X  can be linked with peers and have access to news groups.
  71. X
  72. X  COMMAND LINE OPTIONS:
  73. X    -r: Restricted mail; since it is possible to have another distribution
  74. X        list at some other site as a subscriber, then the following problem
  75. X    arises: if a message is coming from a member of the other list, his/
  76. X    her message was forwarded to the members of that list from the other
  77. X    site; we do not want to send this message back to them, because they
  78. X    will receive this message twice. Therefore, when this flag is on,
  79. X    for every message received, its sender is checked against a list
  80. X    of "restricted" mail addresses (a subset of the subscribers). If a
  81. X    match is found, then mail is forwarded to the people listed in the
  82. X    filename following this email address -- for the appropriate format
  83. X    see below. If no match is found, then the message is forwarded to
  84. X    to all of the subscribers. See also below.
  85. X    -1: Execute only once; this is used when the program is running in
  86. X        conjunction with listserv, in which case execution is interchanged
  87. X        and controlled by the serverd program.
  88. X    -e: Echo reports to the screen.
  89. X    -s: Do not check for subscriptions.
  90. X    -p: By default, replies to posted messages go to the list; this option 
  91. X        forces replies to be forwarded to the original author.
  92. X    -m: Usually, each outgoing message has a single recipient. This switches
  93. X        to multiple recipients -- the argument to it is the number of
  94. X    multiple recipients to be included in this message.
  95. X    -v: Display the version number of this package.
  96. X    -f: Forward any message(s) from unsubscribed senders to MANAGER. This
  97. X        way, any ordinary user account can be used as the list's address.
  98. X    -L: The argument following is the list name to process.
  99. X    -D: Turn debug on. A transaction of the last email sent out is kept
  100. X        in the files /usr/server/sent and /usr/server/received. This assumes
  101. X        use of the 'system' mail method.
  102. X
  103. X  DISCLAIMER: If for any reason during the use of this program, implied
  104. X  or not, you happen to die, or suffer any injury of any kind (physical
  105. X  or mental), I, Mr. Anastasios Kotsikonas, AM NOT RESPONSIBLE at all.
  106. X  In fact, I AM NOT RESPONSIBLE FOR ANYTHING that may happen to you, or
  107. X  your computer and operating system.
  108. X
  109. X  PLEASE: If you upgrade the code, send me a copy, and do not even attempt to
  110. X  put your name for credit. Send to tasos@cs.bu.edu or tasos@bucsf.bu.edu.
  111. X
  112. X  EXIT CODES:
  113. X    0: OK
  114. X    1: Could not open file
  115. X    2: Could not lock file
  116. X    3: Command line option error
  117. X    4: Syntax error in file
  118. X    5: Could not spawn
  119. X    6: Shutdown request
  120. X    7: Restart request
  121. X    8: Received system signal
  122. X    9: Too many multiple recipients
  123. X
  124. X  ENJOY!!!
  125. X
  126. X  Approximate algorithm:
  127. X  {
  128. X    Place a lock so that no other list program will access any files.
  129. X    Read LIST_MAIL_FILE
  130. X    If new message(s) have arrived then {
  131. X      Append messages to MBOX
  132. X      For each message do {
  133. X        If the person is in the IGNORED file, go on to the next message.
  134. X        If the person sending it is subscribed (listed in SUBSCRIBERS) then
  135. X      If the person does not acknowledge his/her message, he/she
  136. X        never receives his/her message back
  137. X      If the -r flag is on then
  138. X        check if the sender is listed in RESTRICTED
  139. X        If so then
  140. X          forward mail to all people listed in the file after the 
  141. X          restricted-sender's address
  142. X        Else
  143. X          distribute to all people in SUBSCRIBERS
  144. X      Else
  145. X        distribute to all people in SUBSCRIBERS, NEWSF (only to those
  146. X        newsgroups that are supposed to received messages) and PEERS
  147. X        according to the following:
  148. X          Email from regular SUBSCRIBERS is sent to NEWS and PEERS as well
  149. X          Email from news is sent to SUBSCRIBERS and PEERS
  150. X          Email from peers is sent to SUBSCRIBERS and NEWS
  151. X    Else if it news feed (listed in NEWSF)
  152. X      distribute to SUBSCRIBERS
  153. X        Else 
  154. X          if -f specified, forward it to MANAGER; otherwise return the
  155. X      message to the sender.
  156. X      }
  157. X      Remove mail files.
  158. X    }
  159. X    Repeat process after IDLE_TIME, or die if -1 specified.
  160. X  }
  161. X
  162. X  Required files:
  163. X    SUBSCRIBERS     <-- The list of subscribed people
  164. X    ALIASES        <-- Aliases of email addresses of subscribers, news & peers
  165. X    NEWSF        <-- List of news groups
  166. X    PEERS        <-- List of peer lists
  167. X    RESTRICTED      <-- Addresses of senders whose messages
  168. X                        require special handling (usually 
  169. X                addresses of other lists): mail is 
  170. X            forwarded only to people found in the 
  171. X            file after the sender's address; see below
  172. X    IGNORED         <-- The list of undesired people
  173. X    LIST_LOCK_FILE  <-- Lock file
  174. X
  175. X  Input files:
  176. X    LIST_MAIL_FILE  <-- File where new messages go
  177. X    MAIL_COPY       <-- Copy of this file (actual work file)
  178. X    MSG_NO          <-- Current message count
  179. X    SUBSCRIBERS
  180. X    RESTRICTED
  181. X    IGNORED
  182. X
  183. X  Output files:
  184. X    MBOX            <-- A log of all messages sent to date
  185. X    REPORT_LIST     <-- Progress report
  186. X    HEADERS        <-- A log of all emails sent (just the sender's address)
  187. X    MSG             <-- Body of message (no header)
  188. X    MSG_NO          <-- Write last message count
  189. X    MAILFORWARD     <-- Completed message (with header and a copy
  190. X                of MSG) to be forwarded
  191. X
  192. X  Format of the SUBSCRIBERS file:
  193. X    One entry per line; each entry is the full email address of the subscriber
  194. X    as it appears in the "From " field, followed by the word "ACK" (in which
  195. X    case his/her message will be sent back to him/her as an acknowledgement)
  196. X    "NOACK" (the opposite), or POSTPONE (no mail will be sent until the
  197. X    user changes mode again), followed by the subscriber's name 
  198. X    -- this option may be
  199. X    reset by the subscriber at any moment by sending a proper request to 
  200. X    listserv. Do not include any blank lines.
  201. X
  202. X  Format of the RESTRICTED file:
  203. X    One entry per line; each entry is the full email address of the
  204. X    subscriber, followed by a file name where email addresses of recipients
  205. X    are listed (just like in the SUBSCRIBERS file).When mail arrives from a 
  206. X    sender listed in the RESTRICTED file and the -r flag is on, then mail 
  207. X    will not be forwarded to SUBSCRIBERS, but instead to the people 
  208. X    listed in the file following the restricted-sender's address. Example:
  209. X      tasos@bucsf.bu.edu  /grad/tasos/.recipients
  210. X      tasos@cs.bu.edu     /grad/tasos/.otherrecipients
  211. X    If the recipient file given is the word "NONE", then no one will receive
  212. X    any messages. This is useful in the case that other distribution sites
  213. X    are subscribers and do forward the message back to the sender, 
  214. X    in which case we protect ourselves from multiple reception of the same
  215. X    messages. 
  216. X    For example, when two (or more) lists are mutual subscribers, and a 
  217. X    message originated by someone in our list, this message, after being 
  218. X    distributed locally, is sent to the other list; if the other site does
  219. X    send messages back to the sender, this message will be forwarded to us
  220. X    to be distributed again, something which is highly undesirable. 
  221. X    This precludes that the other site sends messages identified only by
  222. X    their original senders, something which is unlikely but possible.
  223. X    In this case, we would put our list as one of the entries in the 
  224. X    RESTRICTED file, with the word NONE next to it. Do not include 
  225. X    any blank lines.
  226. X
  227. X  Format of the PEERS file:
  228. X    One entry per line -- the email address of the peer list, followed
  229. X    by its mail mode (NOACK), followed by the remote alias (how the peer list
  230. X    is known in the remote host), followed by the email address of the
  231. X    remote server that handles the remote peer list.
  232. X
  233. X  Format of the NEWSF file:
  234. X    One entry per line -- the email address of the news group, followed
  235. X    by its mail mode (POSTPONE or NOACK), followed by the news group's name.
  236. X
  237. X  Format of the IGNORED file:
  238. X    One entry per line -- the email addresses of the people whose messages
  239. X    are to be ignored. This is a good place to put root, sys and other
  240. X    such undesired logins.
  241. X
  242. X  Format of the ALIASES file:
  243. X    One entry per line -- the new alias followed by the email address the
  244. X    user is subscribed with.
  245. X
  246. X  Recommended usage:
  247. X    % list [-r] -L ALIAS &
  248. X  or
  249. X    % list [-r] -1 -L ALIAS
  250. X
  251. X*/
  252. X
  253. X#include <stdio.h>
  254. X#include <malloc.h>
  255. X#include <string.h>
  256. X#include <unistd.h>
  257. X#include <sys/types.h>
  258. X#include <sys/stat.h>
  259. X#include <fcntl.h>
  260. X#include <signal.h>
  261. X#include "defs.h"
  262. X#include "list.h"
  263. X#include "struct.h"
  264. X#include "global.h"
  265. X
  266. X/* 
  267. X  Function prototypes:
  268. X*/
  269. X
  270. X#ifdef __STDC__
  271. X#include <stdarg.h>
  272. extern int  syscom (char *, ...);
  273. X#else
  274. X#include <varargs.h>
  275. extern int  syscom ();
  276. X#endif
  277. extern int  sys_config (FILE *, SYS *);
  278. extern void report_progress (FILE *, char *, int);
  279. extern void setup_string (char *, char *, char *);
  280. extern void init_signals (void);
  281. extern void catch_signals (void);
  282. extern void get_list_name (char *, char *);
  283. extern void extract_subscriber (FILE *, char *);
  284. extern void extract_origin (char *);
  285. extern int  get_list_id (char *, SYS *, int);
  286. extern int  getopt (int, char **, char *);
  287. extern char *upcase (char *);
  288. extern char *locase (char *);
  289. extern void shrink (char *);
  290. extern void distribute (FILE *, void (*)(char *, char *, unsigned short int),
  291. X            FILE *, char *, char *, char *, char *);
  292. extern BOOLEAN sysmail (char *);
  293. extern BOOLEAN strinstr (char *, char *, char *);
  294. extern BOOLEAN ignore_sender (FILE *, char *, FILE *);
  295. X
  296. void   main (int, char **, char **);
  297. void   create_header (FILE **, char *, char *, char *, char *, char *);
  298. void   create_multi_recipient_header (FILE **, char *, char *, char *, char *,
  299. X                      char *, int);
  300. void   create_news_header (FILE **, char *, char *, char *, char *, char *);
  301. void   create_gate_header (FILE **, char *, char *, char *, char *, char *,
  302. X               char *);
  303. void   process_message (char *, char *, BOOLEAN);
  304. void   do_distribute (FILE *, char *, BOOLEAN, char *, char *, char *, char *,
  305. X              char *, FILE *, BOOLEAN, BOOLEAN);
  306. BOOLEAN copy_msg (FILE *, BOOLEAN, char *);
  307. void   sendmail (char *, BOOLEAN, BOOLEAN, int, int, char *);
  308. void   usage (void);
  309. void   list_config (char *);
  310. void   version (void);
  311. void   gexit (void);
  312. X
  313. X/*
  314. X  The control structure of the mail-distributor. Check if mail has arrived.
  315. X  If so, copy it to MAIL_COPY and proceed to lower level.
  316. X*/
  317. X
  318. void main (int argc, char **argv, char **envp)
  319. X{
  320. X  struct stat stat_buf;
  321. X  char command [MAX_LINE], *options = "1fvrL:em:spD";
  322. X  int c;
  323. X  char error [MAX_LINE];
  324. X  int nlists;
  325. X  FILE *f;
  326. X  extern char *optarg;
  327. X  extern int optopt;
  328. X
  329. X  while ((c = getopt (argc, argv, options)) != EOF)
  330. X    switch ((char) c) {
  331. X      case '1': execute_once = TRUE; break;
  332. X      case 'f': errors_to_manager = TRUE; break;
  333. X      case 'r': send_to_subscribers = FALSE; break;
  334. X      case 'L': list_alias = optarg; break;
  335. X      case 'e': tty_echo = TRUE; break;
  336. X      case 's': do_not_check_subscriptions = TRUE; break;
  337. X      case 'p': article_replies_to_author = TRUE; break;
  338. X      case 'v': version ();
  339. X      case 'D': debug = TRUE; break;
  340. X      case 'm':
  341. X    multi_recip = TRUE;
  342. X    if ((maxrecipients = atoi (optarg)) < 1)
  343. X      fprintf (stderr, "-m %d -- yeah, right!\n", maxrecipients),
  344. X      exit (3);
  345. X    break;
  346. X      case ':': 
  347. X    fprintf (stderr, "list: Option '%c' requires an argument.\n", optopt);
  348. X    exit (3);
  349. X      case '?':
  350. X      default:
  351. X    usage ();
  352. X    }
  353. X#ifndef _MINIX
  354. X  if (lockf (open (LIST_LOCK_FILE, O_RDWR), F_TLOCK, 0))
  355. X    fprintf (stderr, "list: Unable to lock %s. Aborting.\n", LIST_LOCK_FILE),
  356. X    exit (2);
  357. X#endif
  358. X  init_signals();
  359. X  catch_signals();
  360. X  list_config (list_alias);
  361. X  if ((report = fopen (report_listf, "a")) == NULL)
  362. X    if ((report = fopen (REPORT_LIST, "a")) == NULL)
  363. X      fprintf (stderr, "list: Could not open %s and %s\n", report_listf,
  364. X           REPORT_LIST),
  365. X      exit (1);
  366. X  if (list_alias == NULL)
  367. X    report_progress (report, "\nlist: No list to process", TRUE),
  368. X    exit (3);
  369. X  nlists = sys_config (report, &sys);
  370. X  if ((listid = get_list_id (list_alias, &sys, nlists)) < 0)
  371. X    sprintf (error, "\nlist: Unknown list %s", list_alias),
  372. X    report_progress (report, error, TRUE),
  373. X    exit (3);
  374. X  if (!execute_once)
  375. X    printf ("%s\n", VERSION);
  376. X  if (sys.options & USE_ENV_VAR) {
  377. X    if ((sys.mail.method = (char *) malloc (256 * sizeof (char))) == NULL)
  378. X      report_progress (report, "\nmain(): malloc failed", TRUE),
  379. X      exit (16);
  380. X    sprintf (sys.mail.method, "env - %s=%s %s ", sys.mail.env_var,
  381. X             sys.lists[listid].address, sys.mail.mail_prog);
  382. X  }
  383. X  if ((msg_no = fopen (msg_nof, "r")) != NULL)
  384. X    fscanf (msg_no, "%d %d\n", &public_msg, &returned_msg),
  385. X    fclose (msg_no);
  386. X
  387. X  if (multi_recip)
  388. X    if ((multi_recipients = (char **) malloc (maxrecipients * sizeof (char *)))
  389. X    == NULL)
  390. X      report_progress (report, "\nmain(): malloc failed", TRUE),
  391. X      exit (16);
  392. X
  393. X  if ((f = fopen (PID_LIST, "w")) != NULL)
  394. X    fprintf (f, "%d", getpid()),
  395. X    fclose (f);
  396. X  signal (SIGINT, gexit);
  397. X
  398. X  do {
  399. X    if (!stat (list_mail_f, &stat_buf) && stat_buf.st_size > 0) {
  400. X      syscom ("cp %s %s", list_mail_f, mail_copyf);
  401. X      syscom ("cat %s >> %s", mail_copyf, mboxf);
  402. X      syscom ("echo >> %s", mboxf);
  403. X      syscom ("touch %s", list_moderated_f);
  404. X      syscom ("chmod 666 %s", list_moderated_f);
  405. X      if (!unlink (list_mail_f))
  406. X    syscom ("touch %s", list_mail_f), /* rewrite file */
  407. X    syscom ("chmod 666 %s", list_mail_f);
  408. X      if ((mail = fopen (mail_copyf, "r")) == NULL)
  409. X    sprintf (error, "\nlist: Could not open %s", mail_copyf),
  410. X    report_progress (report, error, TRUE),
  411. X    exit (1);
  412. X      if ((subscribers = fopen (subscribersf, "r")) == NULL)
  413. X        sprintf (error, "\nlist: Could not open %s", subscribersf),
  414. X        report_progress (report, error, TRUE),
  415. X    exit (1);
  416. X      if ((news = fopen (newsf, "r")) == NULL)
  417. X    sprintf (error, "\nlist: Could not open %s", newsf),
  418. X    report_progress (report, error, TRUE),
  419. X    exit (1);
  420. X      if ((peers = fopen (peersf, "r")) == NULL)
  421. X    sprintf (error, "\nlist: Could not open %s", peersf),
  422. X    report_progress (report, error, TRUE),
  423. X    exit (1);
  424. X      if ((restricted = fopen (restrictedf, "r")) == NULL)
  425. X    sprintf (error, "\nlist: Could not open %s", restrictedf),
  426. X    report_progress (report, error, TRUE),
  427. X    exit (1);
  428. X      if ((ignored = fopen (ignoredf, "r")) == NULL)
  429. X    sprintf (error, "\nlist: Could not open %s", ignoredf),
  430. X        report_progress (report, error, TRUE),
  431. X        exit (1);
  432. X      if ((headers = fopen (headersf, "a")) == NULL)
  433. X    sprintf (error, "\nlist: Could not open %s", headersf),
  434. X    report_progress, (report, error, TRUE),
  435. X    exit (1);
  436. X      report_progress (report, NEW_ARRIVAL, FALSE);
  437. X      distribute (mail, (void *) process_message, report, subscribersf, newsf,
  438. X          peersf, aliasesf);
  439. X      fclose (mail);  /* Done */
  440. X      fclose (subscribers);
  441. X      fclose (news);
  442. X      fclose (peers);
  443. X      fclose (restricted);
  444. X      fclose (ignored);
  445. X      fclose (headers);
  446. X      shrink (message_idsf);
  447. X      unlink (mail_copyf);  /* Done delivering */
  448. X    }
  449. X    else if (!execute_once) /* No mail to deliver */
  450. X      if (sys.frequency > 0)
  451. X        sleep (sys.frequency);
  452. X  } while (!execute_once);
  453. X  fclose (report);
  454. X  free ((char *) sys.mail.method);
  455. X  if (multi_recip)
  456. X    free ((char **) multi_recipients);
  457. X  gexit ();
  458. X}
  459. X
  460. X/* 
  461. X  Create a mail header.
  462. X*/
  463. X
  464. void create_header (FILE **f, char *filename, char *sender, char *originator,
  465. X            char *recipient, char *subject)
  466. X{
  467. X  char error [MAX_LINE];
  468. X  char origin [MAX_LINE];
  469. X
  470. X  strcpy (origin, originator);
  471. X  locase (origin);
  472. X  if ((*f = fopen (filename, "w")) == NULL)
  473. X    RESET (error),
  474. X    sprintf (error, "\ncreate_header(): Could not open %s", filename),
  475. X    report_progress (report, error, TRUE),
  476. X    exit (1);
  477. X  locase (recipient);
  478. X  if (sys.options & USE_TELNET)
  479. X    fprintf (*f, "HELO\nMAIL From: <%s>\nRCPT To: <%s>\nDATA\n",
  480. X         sys.lists[listid].address, recipient);
  481. X  if (message_id[0] != EOS)
  482. X    fprintf (*f, "Message-Id: %s\n", message_id);
  483. X  fprintf (*f, "Comment: %s\nOriginator: %s\nErrors-To: %s\n\
  484. Reply-To: <%s>\nSender: %s\nVersion: %s\n\
  485. XFrom: %s\nTo: %s\nSubject: %s\n\n",
  486. X       sys.lists[listid].comment, origin, sys.manager, 
  487. X       sys.lists[listid].address, sys.lists[listid].address, 
  488. X       VERSION, sender, recipient, subject);
  489. X}
  490. X
  491. X/* 
  492. X  Create a mail header with multiple recipients.
  493. X*/
  494. X
  495. void create_multi_recipient_header (FILE **f, char *filename, char *sender,
  496. X                    char *originator, char *recipient,
  497. X                    char *subject, int nrecipients)
  498. X{
  499. X  char error [MAX_LINE];
  500. X  char origin [MAX_LINE];
  501. X  int  i;
  502. X
  503. X  strcpy (origin, originator);
  504. X  locase (origin);
  505. X  if ((*f = fopen (filename, "w")) == NULL)
  506. X    RESET (error),
  507. X    sprintf (error, "\ncreate_multi_recipient_header(): Could not open %s",
  508. X         filename),
  509. X    report_progress (report, error, TRUE),
  510. X    exit (1);
  511. X  if (sys.options & USE_TELNET) {
  512. X    fprintf (*f, "HELO\nMAIL From: <%s>\n", sys.lists[listid].address);
  513. X    for (i = 0; i < nrecipients; i++)
  514. X      fprintf (*f, "RCPT To: <%s>\n", multi_recipients[i]),
  515. X      free ((char *) multi_recipients[i]);
  516. X    fprintf (*f, "DATA\n");
  517. X  }
  518. X  if (message_id[0] != EOS)
  519. X    fprintf (*f, "Message-Id: %s\n", message_id);
  520. X  fprintf (*f, "Comment: %s\nOriginator: %s\nErrors-To: %s\n\
  521. Reply-To: <%s>\nSender: %s\nVersion: %s\n\
  522. XFrom: %s\nTo: %s\nSubject: %s\n\n",
  523. X       sys.lists[listid].comment, origin, sys.manager, 
  524. X       sys.lists[listid].address, sys.lists[listid].address, 
  525. X       VERSION, sender, recipient, subject);
  526. X}
  527. X
  528. X/*
  529. X  Create a news header for a message to be posted.
  530. X*/
  531. X
  532. void create_news_header (FILE **f, char *filename, char *sender,
  533. X             char *originator, char *group, char *subject)
  534. X{
  535. X  char error [MAX_LINE];
  536. X  char origin [MAX_LINE];
  537. X
  538. X  strcpy (origin, originator);
  539. X  locase (origin);
  540. X  if ((*f = fopen (filename, "w")) == NULL)
  541. X    RESET (error),
  542. X    sprintf (error, "\ncreate_news_header(): Could not open %s", filename),
  543. X    report_progress (report, error, TRUE),
  544. X    exit (1);
  545. X  locase (group);
  546. X  if (message_id[0] != EOS)
  547. X    fprintf (*f, "Message-Id: %s\n", message_id);
  548. X  fprintf (*f, "Path: %s\nNewsgroups: %s\nDistribution: world\n\
  549. Organization: %s\n\
  550. Originator: %s\nReply-To: <%s>\nSender: %s\nFrom: %s\nSubject: %s\n\n",
  551. X       (article_replies_to_author ? sender : sys.lists[listid].address),
  552. X       group, sys.organization, origin, 
  553. X       (article_replies_to_author ? sender : sys.lists[listid].address),
  554. X       sys.lists[listid].address,
  555. X       sender, subject);
  556. X}
  557. X
  558. X/*
  559. X  Create a gateway header.
  560. X*/
  561. X
  562. void create_gate_header (FILE **f, char *filename, char *sender,
  563. X             char *originator, char *recipient, 
  564. X             char *group, char *subject)
  565. X{
  566. X  char error [MAX_LINE];
  567. X  char origin [MAX_LINE];
  568. X
  569. X  strcpy (origin, originator);
  570. X  locase (origin);
  571. X  if ((*f = fopen (filename, "w")) == NULL)
  572. X    RESET (error),
  573. X    sprintf (error, "\ncreate_gate_header(): Could not open %s", filename),
  574. X    report_progress (report, error, TRUE),
  575. X    exit (1);
  576. X  locase (group);
  577. X  if (sys.options & USE_TELNET)
  578. X    fprintf (*f, "HELO\nMAIL From: <%s>\nRCPT To: <%s>\nDATA\n",
  579. X         sys.lists[listid].address, recipient);
  580. X  if (message_id[0] != EOS)
  581. X    fprintf (*f, "Message-Id: %s\n", message_id);
  582. X  fprintf (*f, "Newsgroups: %s\nDistribution: world\nOrganization: %s\n\
  583. Originator: %s\nErrors-To: %s\nReply-To: <%s>\nSender: %s\n\
  584. XFrom: %s\nTo: %s\nSubject: %s\n\n",
  585. X       group, sys.organization, origin, sys.manager, 
  586. X       (article_replies_to_author ? sender : sys.lists[listid].address),
  587. X       sys.lists[listid].address, sender, recipient, subject);
  588. X}
  589. X
  590. X/*
  591. X  The heart of the distribution. Since we are now at the beginning of the
  592. X  message (as guaranteed by distribute ()), gather the rest of the message
  593. X  -- that is until the beginning of the next message, or EOF. Note that
  594. X  only the "From: ", "Originator: " and "Subject: " lines from the header
  595. X  are saved.
  596. X  The beginning of the next and every message is "From ". The actual
  597. X  text of each message is separated from its header by a blank line (universal
  598. X  format). The message is processed only if the sender is not listed in
  599. X  IGNORED.
  600. X  The entire message is stored in MSG. To distribute the message, prepare
  601. X  a new header; the completed message is stored in MAILFORWARD. Actually,
  602. X  for each subscriber we prepare a different header (different "To:" field) 
  603. X  and append MSG to MAILFORWARD. Distribute that mail to the members,
  604. X  or, either return it to the sender if he/she is not subscribed, or
  605. X  forward it to MANAGER if -f specified. Messages from MAILER_DAEMON are
  606. X  always forwarded to MANAGER. A message from a mailer daemon is identified
  607. X  by the presence of MAILER_DAEMON anywhere in the sender's email address,
  608. X  to cover local and remote mailer daemon addresses. Please look at the
  609. X  documentation for defs.h for the syntax of the MAILER_DAEMON string.
  610. X  The parameter "sender" is used for report purposes and when we are sending
  611. X  the sender's message back to him/her.
  612. X  Messages from regular subscribers are sent to peer lists and news groups.
  613. X  Messages from news groups are only distributed to local subscribers and
  614. X  peer lists. Finally, messages from peer lists are distributed locally
  615. X  and may be posted to news groups.
  616. X  In the case of restricted mail, check if the sender is listed in 
  617. X  RESTRICTED; if so, forward the message to the people listed in the
  618. X  filename found after the restricted-sender's address in RESTRICTED.
  619. X*/
  620. X
  621. void process_message (char *sender, char *linecopy, BOOLEAN sender_subscribed)
  622. X{
  623. X  char line [MAX_LINE];            /* ... from the the current message */
  624. X  char senders_subject [MAX_LINE]; /* the sender's subject */
  625. X  char subject_copy [MAX_LINE];    /* a copy of the subject */
  626. X  char report_msg [MAX_LINE];      /* place for report/error messages */
  627. X  char original_sender [MAX_LINE]; /* as it appears in his message */
  628. X  char originator [MAX_LINE];       /* Holds the Originator: address */
  629. X  char reply_to [MAX_LINE];       /* Holds the Reply-To: address */
  630. X  char id_copy [MAX_LINE];       /* Holds the Message-Id: */
  631. X  FILE *forwardmail = NULL;        /* completed message to be forwarded */
  632. X  FILE *msg = NULL;
  633. X
  634. X  line[0] = 
  635. X    senders_subject[0] = 
  636. X      subject_copy[0] = 
  637. X    originator[0] =
  638. X      reply_to[0] =
  639. X        message_id[0] =
  640. X          id_copy[0]=
  641. X            RESET (original_sender);
  642. X
  643. X  /* Remove message header, but store the "From: " and "Subject: " fields to
  644. X     be used later when sending the message to all subscribers. */
  645. X
  646. X  while (!feof (mail) && line[0] != '\n') {
  647. X    if (!strncmp (line, FROM, strlen (FROM)))
  648. X      strcpy (original_sender, line + strlen (FROM)), /* Save From: */
  649. X      original_sender [strlen (original_sender) - 1] = EOS; /* \n -> \0 */
  650. X    if (!strncmp (line, SUBJECT, strlen (SUBJECT)))
  651. X      strcpy (senders_subject, line + strlen (SUBJECT)), /* Save Subject: */
  652. X      senders_subject [strlen (senders_subject) - 1] = EOS, /* \n -> \0 */
  653. X      strcpy (subject_copy, senders_subject);
  654. X    if (!strncmp (line, ORIGIN, strlen (ORIGIN)))
  655. X      strcpy (originator, line + strlen (ORIGIN)),  /* Remove "Originator: " */
  656. X      extract_origin (originator),
  657. X      upcase (originator);
  658. X    if (!strncmp (line, REPLY_TO, strlen (REPLY_TO)))
  659. X      strcpy (reply_to, line + strlen (REPLY_TO)), /* Remove "Reply-To: " */
  660. X      extract_origin (reply_to),
  661. X      upcase (reply_to);
  662. X    if (!strncmp (line, MESSAGE_ID1, strlen (MESSAGE_ID1)) ||
  663. X        !strncmp (line, MESSAGE_ID2, strlen (MESSAGE_ID2)) ||
  664. X    !strncmp (line, MESSAGE_ID3, strlen (MESSAGE_ID3)))
  665. X      strcpy (message_id, line + strlen ("Message-") + 4),
  666. X      message_id [strlen (message_id) - 1] = EOS; /* \n -> \0 */
  667. X    RESET (line);
  668. X    fgets (line, MAX_LINE - 2, mail);
  669. X  }
  670. X
  671. X  /* Gather message into MSG; check if we have reached the next message, 
  672. X     or EOF */
  673. X  if ((msg = fopen (msgf, "w")) == NULL)
  674. X    sprintf (report_msg, "\nprocess_message(): Could not open %s", msgf),
  675. X    report_progress (report, report_msg, TRUE),
  676. X    exit (1);
  677. X  RESET (line);
  678. X  while (!feof (mail) && 
  679. X     (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))) {
  680. X    if (!strcmp (line, ".\n"))
  681. X      PREPEND (".", line);
  682. X    fprintf (msg, "%s", line);
  683. X    fgets (line, MAX_LINE - 2, mail);
  684. X  }
  685. X  fclose (msg);
  686. X
  687. X  strcpy (linecopy, line); /*** VERY IMPORTANT: we are now at the next msg ***/
  688. X  /* Check the IGNORED file */
  689. X  if (ignore_sender (ignored, sender, report))
  690. X    return;
  691. X  if (originator[0] != EOS) /* Check for mail loop using Originator: */
  692. X    if (ignore_sender (ignored, originator, report))
  693. X      return;
  694. X  if (reply_to[0] != EOS) /* Check for mail loop using Reply-To: */
  695. X    if (ignore_sender (ignored, reply_to, report))
  696. X      return;
  697. X  if (message_id[0] != EOS) { /* Check for mail loop using Message-Id: */
  698. X    strcpy (id_copy, message_id);
  699. X    upcase (id_copy);
  700. X    if (message_ids = fopen (message_idsf, "r")) {
  701. X      if (ignore_sender (message_ids, id_copy, report)) {
  702. X        fclose (message_ids);
  703. X        return;
  704. X      }
  705. X      fclose (message_ids);
  706. X    }
  707. X    if ((message_ids = fopen (message_idsf, "a")) == NULL)
  708. X      sprintf (report_msg, "\nprocess_message(): Could not open %s",
  709. X           message_idsf),
  710. X      report_progress (report, report_msg, TRUE),
  711. X      exit (1);
  712. X    fprintf (message_ids, "%s %s\n", message_id, sender); /* Save new id */
  713. X    fclose (message_ids);
  714. X  }
  715. X  if (sender_subscribed == NEWS)
  716. X    if (ignore_sender (peers, originator, report))
  717. X      return;
  718. X
  719. X  if (originator[0] == EOS) /* Fresh message originating from this list */
  720. X    sprintf (originator, "%s", sys.lists[listid].address);
  721. X  upcase (originator);
  722. X
  723. X  if (do_not_check_subscriptions)
  724. X    sender_subscribed = SUBSCRIBED;
  725. X  RESET (report_msg);
  726. X  if (sender_subscribed == NOTSUBSCRIBED ||
  727. X      strinstr (MAILER_DAEMON, sender, "|")) {/* Send error message to sender */
  728. X    sprintf (report_msg, "Invalid message #%04d. Forwarding error message to \
  729. X%s.\n%s",  ++returned_msg,
  730. X         ((strinstr (MAILER_DAEMON, sender, "|") || errors_to_manager) ? 
  731. X          sys.manager : sender), 
  732. X         sender);
  733. X    report_progress (report, report_msg, TRUE);
  734. X    if ((msg_no = fopen (msg_nof, "w")) == NULL)
  735. X      sprintf (report_msg, "\nprocess_message(): Could not open %s", msg_nof),
  736. X      report_progress (report, report_msg, TRUE),
  737. X      exit (1);
  738. X    fprintf (msg_no, "%d %d\n", public_msg, returned_msg);
  739. X    fclose (msg_no);
  740. X    if ((msg = fopen (msgf, "r")) == NULL)
  741. X      sprintf (report_msg, "\nprocess_message(): Could not open %s", msgf),
  742. X      report_progress (report, report_msg, TRUE),
  743. X      exit (1);
  744. X    /* Prepare header */
  745. X    create_header (&forwardmail, mailforwardf, sys.lists[listid].address,
  746. X      originator,
  747. X      ((strinstr (MAILER_DAEMON, sender, "|") || errors_to_manager) ?
  748. X       sys.manager : sender),
  749. X      senders_subject);
  750. X    if (errors_to_manager || strinstr (MAILER_DAEMON, sender, "|"))
  751. X      fprintf (forwardmail, "\nRejected message sent to %s by %s\n\
  752. follows.\n",
  753. X           sys.lists[listid].address, sender);
  754. X    else
  755. X      fprintf (forwardmail, "\n%s: You are not subscribed to %s\n\
  756. Your message is returned to you unprocessed.\n", sender, 
  757. sys.lists[listid].address);
  758. X    fprintf (forwardmail, "-----------------------------------------------\
  759. X--------------------------------\n");
  760. X    while (!feof (msg))  /* Copy actual message */
  761. X      RESET (line),
  762. X      fgets (line, MAX_LINE - 2, msg),
  763. X      fprintf (forwardmail, "%s", line);
  764. X    COMPLETE_TELNET (forwardmail);
  765. X    fclose (msg);
  766. X    fclose (forwardmail);
  767. X    /* Form UNIX sendmail command */
  768. X    if (sys.options & USE_SYSMAIL)
  769. X      sysmail (mailforwardf);
  770. X    else
  771. X      syscom ("%s %s < %s", sys.mail.method,
  772. X              (((sys.options & USE_TELNET) == 0) ?
  773. X               ((strinstr (MAILER_DAEMON, sender, "|") || errors_to_manager) ?
  774. X                sys.manager : locase (sender)) : ""),
  775. X              mailforwardf);
  776. X    return;
  777. X  }
  778. X  /* Distribute to all subscribers */
  779. X  fprintf (headers, "%s\n", sender);
  780. X  fflush (headers);
  781. X  sprintf (report_msg, "Public message #%04d%s. Distributing to all \
  782. subscribers%s.\n%s",
  783. X       ++public_msg, (sender_subscribed == NEWS ? " (news)" : 
  784. X              (sender_subscribed == PEER ? " (peer)" : "")), 
  785. X       (sender_subscribed == SUBSCRIBED ? ", news groups and peers" : 
  786. X        (sender_subscribed == NEWS ? ", peers" : ", news")),
  787. X       sender);
  788. X  report_progress (report, report_msg, TRUE);
  789. X  if ((msg_no = fopen (msg_nof, "w")) == NULL)
  790. X    sprintf (report_msg, "\nprocess_message(): Could not open %s", msg_no),
  791. X    report_progress (report, report_msg, TRUE),
  792. X    exit (1);
  793. X  fprintf (msg_no, "%d %d\n", public_msg, returned_msg);
  794. X  fclose (msg_no);
  795. X  do_distribute (subscribers, subscribersf, send_to_subscribers, sender,
  796. X         original_sender, senders_subject, subject_copy, originator,
  797. X         report, FALSE, multi_recip);
  798. X  if (sender_subscribed == SUBSCRIBED || sender_subscribed == PEER)
  799. X    do_distribute (news, newsf, TRUE, sender, original_sender, senders_subject,
  800. X           subject_copy, originator, report, 
  801. X           TRUE, FALSE); /* Send to news also */
  802. X  if (sender_subscribed == SUBSCRIBED || sender_subscribed == NEWS)
  803. X    do_distribute (peers, peersf, TRUE, sender, original_sender, 
  804. X           senders_subject, subject_copy, originator, 
  805. X           report, FALSE, FALSE); /* Send to peers also */
  806. X}
  807. X
  808. X/*
  809. X  Do the distribution of the message to the specified list of subscribers.
  810. X  The BOOLEAN argument 'posting' should be TRUE when posting AND gating to
  811. X  news, and FALSE otherwise.
  812. X*/
  813. X
  814. void do_distribute (FILE *recipient_list, char *file,
  815. X            BOOLEAN send_to_subscribers, 
  816. X            char *sender, char *original_sender, char *senders_subject,
  817. X            char *subject_copy, char *originator, FILE *report,
  818. X            BOOLEAN posting, BOOLEAN multi_recip)
  819. X{
  820. X  char name [MAX_LINE];            /* holds each subscribers name */
  821. X  char mailmode [MAX_LINE];        /* send message back to sender or not */
  822. X  char subscriber [MAX_LINE];      /* holds each subscriber's address */
  823. X  char report_msg [MAX_LINE];      /* place for report/error messages */
  824. X  char recipient_file [MAX_LINE];  /* file of subscribers to use when -r */
  825. X  char restricted_subscriber [MAX_LINE]; /* name of subscriber in RESTRICTED */
  826. X  char line [MAX_LINE];
  827. X  FILE *forwardmail;
  828. X  BOOLEAN alternate_file = FALSE;
  829. X  int  nrecipients = 0;
  830. X
  831. X  if (!send_to_subscribers) {  /* -r: Check if restricted mail has arrived */
  832. X    rewind (restricted);
  833. X    while (!feof (restricted)) {
  834. X      alternate_file = TRUE;
  835. X      restricted_subscriber[0] = RESET (recipient_file);
  836. X      fscanf (restricted, "%s %s", restricted_subscriber, recipient_file);
  837. X      upcase (restricted_subscriber);
  838. X      if (!strcmp (restricted_subscriber, sender)) {
  839. X    if (!strcmp (recipient_file, NO_RECIPIENT_FILE)) {
  840. X      /* Do not forward to anyone */
  841. X      report_progress (report, "No alternate recipient file specified. \
  842. Message ignored.\n", FALSE);
  843. X      return;
  844. X    }
  845. X    /* Restricted mail; forward message only to the people listed
  846. X       in recipient_file */
  847. X    if ((recipient_list = fopen (recipient_file, "r")) == NULL)
  848. X      sprintf (report_msg, "\ndo_distribute(): Could not open alternate \
  849. recipient file %s", recipient_file),
  850. X      report_progress (report, report_msg, TRUE),
  851. X      exit (1);
  852. X    RESET (report_msg);
  853. X    sprintf (report_msg, "Restricted mail. Distributing only to \
  854. individuals listed in %s", recipient_file);
  855. X    report_progress (report, report_msg, TRUE);
  856. X    break;
  857. X      }
  858. X    }
  859. X  }
  860. X  rewind (recipient_list);
  861. X  while (!feof (recipient_list)) { /* Send to all of them */
  862. X    subscriber[0] = mailmode[0] = RESET (name);
  863. X    extract_subscriber (recipient_list, subscriber);
  864. X    fscanf (recipient_list, "%s ", mailmode);
  865. X    if (subscriber[0] == EOS)
  866. X      continue;
  867. X    fgets (name, MAX_LINE - 2, recipient_list); /* Skip name */
  868. X    name [strlen (name) - 1] = EOS;
  869. X    upcase (mailmode);
  870. X    if (!strcmp (mailmode, NOACK)) {
  871. X      upcase (subscriber);
  872. X      if (!strcmp (subscriber, sender) || !strcmp (subscriber, originator))
  873. X    continue;
  874. X    }
  875. X    else if (!strcmp (mailmode, POSTPONE))  /* No email to this subscriber */
  876. X      continue;
  877. X    else if (mailmode[0] != EOS && strcmp (mailmode, ACK))
  878. X      sprintf (report_msg, "\ndo_distribute(): Unrecognized mail mode %s in %s",
  879. X           mailmode, file), 
  880. X      report_progress (report, report_msg, TRUE),
  881. X      exit (4);
  882. X    RESET (senders_subject);
  883. X    strcpy (senders_subject, subject_copy);
  884. X    if (multi_recip) {
  885. X      if ((multi_recipients[nrecipients] =
  886. X      (char *) malloc ((strlen (subscriber) + 1) * sizeof (char))) == NULL)
  887. X        report_progress (report, "\ndo_distribute(): malloc failed", TRUE),
  888. X    exit (16);
  889. X      strcpy (multi_recipients[nrecipients++], locase (subscriber));
  890. X    }
  891. X    /* Prepare header */
  892. X    if (posting) {
  893. X      if (sys.options & POST_MAIL) /* Post to news group */
  894. X    create_news_header (&forwardmail, mailforwardf, original_sender,
  895. X                originator, name, senders_subject);
  896. X      else if (sys.options & GATE_MAIL) /* Gate to news gateway */
  897. X    create_gate_header (&forwardmail, mailforwardf, original_sender,
  898. X                originator, subscriber, name, senders_subject),
  899. X    posting = FALSE;
  900. X      if (!copy_msg (forwardmail, posting, original_sender))
  901. X    return;
  902. X    }
  903. X    else { /* Regular mail */
  904. X      if (multi_recip) { /* Multi recipient header */
  905. X    if (nrecipients == maxrecipients) {
  906. X      sprintf (report_msg, "Multiple recipients of list <%s>",
  907. X           sys.lists[listid].address);
  908. X      create_multi_recipient_header (&forwardmail, mailforwardf,
  909. X                     original_sender, originator,
  910. X                     report_msg, senders_subject,
  911. X                     nrecipients);
  912. X      if (!copy_msg (forwardmail, posting, original_sender))
  913. X        return;
  914. X    }
  915. X      }
  916. X      else { /* Single recipient header */
  917. X    create_header (&forwardmail, mailforwardf, original_sender, originator,
  918. X               subscriber, senders_subject);
  919. X    if (!copy_msg (forwardmail, posting, original_sender))
  920. X      return;
  921. X      }
  922. X    }
  923. X    sendmail (subscriber, posting, multi_recip, nrecipients, maxrecipients,
  924. X          mailforwardf);
  925. X    if (nrecipients == maxrecipients)
  926. X      nrecipients = 0;
  927. X  }
  928. X  if (alternate_file)  /* Close alternate recipient file */
  929. X    fclose (recipient_list);
  930. X
  931. X  if (multi_recip && (nrecipients != 0)) { /* Left overs */
  932. X    sprintf (report_msg, "Multiple recipients of list <%s>",
  933. X         sys.lists[listid].address);
  934. X    create_multi_recipient_header (&forwardmail, mailforwardf,
  935. X                   original_sender, originator,
  936. X                   report_msg, senders_subject,
  937. X                   nrecipients);
  938. X    if (copy_msg (forwardmail, posting, original_sender))
  939. X      sendmail (subscriber, posting, multi_recip, nrecipients, nrecipients, 
  940. X            mailforwardf);
  941. X  }
  942. X}
  943. X
  944. X/*
  945. X  Copy the original message to the outgoing message.
  946. X*/
  947. X
  948. BOOLEAN copy_msg (FILE *forwardmail, BOOLEAN posting, char *sender)
  949. X{
  950. X  FILE *msg;
  951. X  char line [MAX_LINE];
  952. X  char report_msg [MAX_LINE];
  953. X  int count = 0;
  954. X
  955. X  if ((msg = fopen (msgf, "r")) == NULL)
  956. X    sprintf (report_msg, "\ncopy_msg(): Could not open %s", msgf),
  957. X    report_progress (report, report_msg, TRUE),
  958. X    exit (1);
  959. X  while (!feof (msg)) { /* Copy actual message */
  960. X    RESET (line);
  961. X    fgets (line, MAX_LINE - 2, msg);
  962. X    fprintf (forwardmail, "%s", line);
  963. X    count += strlen (line);
  964. X    if ((sys.options & LIMIT_MSG) && (count > sys.limits.msg)) {
  965. X      fclose (forwardmail);
  966. X      rewind (msg);
  967. X      create_header (&forwardmail, mailforwardf, sys.lists[listid].address, 
  968. X             sys.lists[listid].address, sender, "Posting rejected");
  969. X      fprintf (forwardmail, "Your posting to list %s was rejected.\n\
  970. Reason: message size limit exceeded (maximum allowed: %ld bytes)\n\
  971. The first few lines of your message are included herein for reference:\n\n",
  972. sys.lists[listid].alias, sys.limits.msg);
  973. X      report_progress (report, "Message rejected: maximum size exceeded",
  974. X               TRUE);
  975. X      count = 0;
  976. X      while (!feof (msg) && count < 10)
  977. X    RESET (line),
  978. X    fgets (line, MAX_LINE - 2, msg),
  979. X    fprintf (forwardmail, "%s", line),
  980. X    ++count;
  981. X      COMPLETE_TELNET (forwardmail);
  982. X      fclose (forwardmail);
  983. X      fclose (msg);
  984. X      sendmail (sender, FALSE, FALSE, 0, 0, mailforwardf);
  985. X      return FALSE;
  986. X    }
  987. X  }
  988. X  if (!posting && (sys.options & USE_TELNET))
  989. X    COMPLETE_FILE (forwardmail);
  990. X  fclose (forwardmail);
  991. X  fclose (msg);
  992. X  return TRUE;
  993. X}
  994. X
  995. X/*
  996. X  Send email (to subscribers/news/gateways/peers). It may send one single
  997. X  copy to one recipient, or one copy to multiple recipients.
  998. X*/
  999. X
  1000. void sendmail (char *subscriber, BOOLEAN posting, BOOLEAN multi_recip,
  1001. X           int nrecipients, int maxrecipients, char *mailforwardf)
  1002. X{
  1003. X  char *buf;
  1004. X  int size, i;
  1005. X
  1006. X  /* Form UNIX sendmail command */
  1007. X  if (posting && (sys.options & POST_MAIL)) /* Post to news */
  1008. X    syscom ("%s -h < %s", INEWS, mailforwardf);
  1009. X  else { /* Send email */
  1010. X    if (multi_recip) { 
  1011. X      if (nrecipients == maxrecipients) {
  1012. X    if ((sys.options & USE_TELNET) == 0) { /* Line up recipients */
  1013. X      size = strlen (multi_recipients[0]) + 1;
  1014. X      if ((buf = (char *) malloc (size * sizeof (char))) == NULL)
  1015. X        report_progress (report, "\nsendmail(): malloc failed", TRUE),
  1016. X        exit (16);
  1017. X      strcpy (buf, multi_recipients[0]);
  1018. X      for (i = 1; i < nrecipients; i++)
  1019. X        size += strlen (multi_recipients[i]) + 2,
  1020. X        buf = (char *) realloc (buf, size * sizeof (char)),
  1021. X        sprintf (buf + strlen (buf), " %s", multi_recipients[i]);
  1022. X      if (strlen (buf) > 10000)
  1023. X        report_progress (report, "Too many multiple recipients", TRUE),
  1024. X        exit (9);
  1025. X      syscom ("%s %s < %s", sys.mail.method, buf, mailforwardf);
  1026. X      free ((char *) buf);
  1027. X    }
  1028. X    else if (sys.options & USE_SYSMAIL)
  1029. X      sysmail (mailforwardf);
  1030. X    else /* telnet */
  1031. X      syscom ("%s < %s", sys.mail.method, mailforwardf);
  1032. X      }
  1033. X    }
  1034. X    else  /* Single recipient */
  1035. X      if (sys.options & USE_SYSMAIL)
  1036. X    sysmail (mailforwardf);
  1037. X      else
  1038. X        syscom ("%s %s < %s", sys.mail.method,
  1039. X                (((sys.options & USE_TELNET) == 0) ? locase (subscriber) : ""),
  1040. X                mailforwardf);
  1041. X  }
  1042. X}
  1043. X
  1044. void usage ()
  1045. X{
  1046. X  fprintf (stderr, "Usage: list <-L LIST_ALIAS> [-r] [-m #] [-1] [-f] [-e] \
  1047. X[-s] [-p] [-v] [-D]\n\
  1048. X-L: Process LIST_ALIAS (LIST_ALIAS has to be all in capital letters).\n\
  1049. X-r: Restricted mail.\n\
  1050. X-m: Specify number of multiple recipients in one outgoing message.\n\
  1051. X-1: Execute only once.\n\
  1052. X-f: Forward rejected messages to manager.\n\
  1053. X-e: Echo reports to the screen.\n\
  1054. X-s: Do not check for subscriptions.\n\
  1055. X-p: Replies to posted messages will go to the author.\n\
  1056. X-v: Version number.\n\
  1057. X-D: Turn debug on.\n");
  1058. X  exit (3);
  1059. X}
  1060. X
  1061. void list_config (char *alias)
  1062. X{
  1063. X  if (alias == NULL)
  1064. X    return;
  1065. X  setup_string (subscribersf, alias, SUBSCRIBERS);
  1066. X  setup_string (headersf, alias, HEADERS);
  1067. X  setup_string (restrictedf, alias, RESTRICTED);
  1068. X  setup_string (newsf, alias, NEWSF);
  1069. X  setup_string (peersf, alias, PEERS);
  1070. X  setup_string (aliasesf, alias, ALIASES);
  1071. X  setup_string (ignoredf, alias, IGNORED);
  1072. X  setup_string (list_mail_f, alias, LIST_MAIL_FILE);
  1073. X  setup_string (list_moderated_f, alias, LIST_MODERATED_F);
  1074. X  setup_string (mboxf, alias, MBOX);
  1075. X  setup_string (msg_nof, alias, MSG_NO);
  1076. X  setup_string (mailforwardf, alias, MAILFORWARD);
  1077. X  setup_string (msgf, alias, MSG);
  1078. X  setup_string (mail_copyf, alias, MAIL_COPY);
  1079. X  setup_string (report_listf, alias, REPORT_LIST);
  1080. X  setup_string (message_idsf, alias, MESSAGE_IDS_F);
  1081. X}
  1082. X
  1083. void version ()
  1084. X{
  1085. X  fprintf (stderr, "%s\n", VERSION);
  1086. X  exit (0);
  1087. X}
  1088. X
  1089. X/*
  1090. X  Graceful exit. Remove pid file.
  1091. X*/
  1092. X
  1093. void gexit ()
  1094. X{
  1095. X  unlink (PID_LIST);
  1096. X  exit (0);
  1097. X}
  1098. END_OF_FILE
  1099. if test 42066 -ne `wc -c <'src/list.c'`; then
  1100.     echo shar: \"'src/list.c'\" unpacked with wrong size!
  1101. fi
  1102. # end of 'src/list.c'
  1103. fi
  1104. echo shar: End of archive 4 \(of 6\).
  1105. cp /dev/null ark4isdone
  1106. MISSING=""
  1107. for I in 1 2 3 4 5 6 ; do
  1108.     if test ! -f ark${I}isdone ; then
  1109.     MISSING="${MISSING} ${I}"
  1110.     fi
  1111. done
  1112. if test "${MISSING}" = "" ; then
  1113.     echo You have unpacked all 6 archives.
  1114.     rm -f ark[1-9]isdone
  1115. else
  1116.     echo You still need to unpack the following archives:
  1117.     echo "        " ${MISSING}
  1118. fi
  1119. ##  End of shell archive.
  1120. exit 0
  1121.