home *** CD-ROM | disk | FTP | other *** search
- Subject: v25i038: listserv5.31 - mailing list management system, Part04/06
- Newsgroups: comp.sources.unix
- Approved: vixie@pa.dec.com
-
- Submitted-By: tasos@cs.bu.edu
- Posting-Number: Volume 25, Issue 38
- Archive-Name: listserv5.31/part04
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 4 (of 6)."
- # Contents: src/list.c
- # Wrapped by vixie@cognition.pa.dec.com on Fri Dec 13 18:31:09 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/list.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/list.c'\"
- else
- echo shar: Extracting \"'src/list.c'\" \(42066 characters\)
- sed "s/^X//" >'src/list.c' <<'END_OF_FILE'
- X/*
- X ----------------------------------------------------------------------------
- X | DISCUSSION LIST MAIL-DISTRIBUTION PROGRAM |
- X | |
- X | Version 2.6 |
- X | |
- X | (or, when Computer Science gets to you) |
- X | |
- X | Written by Anastasios Kotsikonas |
- X | (tasos@cs.bu.edu) |
- X | |
- X | AGREEMENT: This software can be used and distributed freely as long |
- X | as you do not remove or alter the Copyright notice in the file defs.h; |
- X | this notice is #define'd in the symbol VERSION. Although you may alter |
- X | the code provided, you may not alter the functions create_header() |
- X | and create_multi_recipient_header() in list.c and listserv.c. |
- X | By using this software you are bound by this agreement. |
- X | This software comes with no warranties and cannot be sold for profit. |
- X | The AGREEMENT and COPYRIGHT notices should be included in all source |
- X | files when distributing this software. |
- X | COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas |
- X ----------------------------------------------------------------------------
- X
- X NOTE: Anything appearing in capital letters refers to #define's in the
- X header files provided.
- X
- X PURPOSE: Create discussion lists. Members of the list send messages to
- X them, and each of these messages is forwarded to the rest of the members.
- X Any message(s) not from subscribers are returned to the original senders,
- X or can be forwarded to MANAGER. Messages from "undesired" senders can be
- X ignored by placing their email addresses in the IGNORED file (this would
- X usually include root and the list's login name to avoid infinite loops).
- X
- X OVERVIEW: A discussion list resides in a subdirectory of /usr/server/lists
- X whose name is the list's alias (in the aliases file) in capital letters.
- X When the program is killed or it abnormally dies, a message
- X is sent to MANAGER (if using UCB mail) along with a copy of the current
- X report file (more on that below). Use the -1 flag when running the
- X program. The discussion list to be processed is given as argument to the
- X -L option in upper case. Any progress is reported to the list's REPORT_LIST
- X file and to the administrator's terminal. All messages sent to this list are
- X saved in the MBOX file. The program can be run as stand-alone, or in
- X conjunction with the other programs provided (start, serverd and listserv).
- X Please note that a line beginning with "From " and another one beginning
- X with "From: " must appear in the header of each message, and a blank line
- X must separate the header from the body of the message. Discussion lists
- X can be linked with peers and have access to news groups.
- X
- X COMMAND LINE OPTIONS:
- X -r: Restricted mail; since it is possible to have another distribution
- X list at some other site as a subscriber, then the following problem
- X arises: if a message is coming from a member of the other list, his/
- X her message was forwarded to the members of that list from the other
- X site; we do not want to send this message back to them, because they
- X will receive this message twice. Therefore, when this flag is on,
- X for every message received, its sender is checked against a list
- X of "restricted" mail addresses (a subset of the subscribers). If a
- X match is found, then mail is forwarded to the people listed in the
- X filename following this email address -- for the appropriate format
- X see below. If no match is found, then the message is forwarded to
- X to all of the subscribers. See also below.
- X -1: Execute only once; this is used when the program is running in
- X conjunction with listserv, in which case execution is interchanged
- X and controlled by the serverd program.
- X -e: Echo reports to the screen.
- X -s: Do not check for subscriptions.
- X -p: By default, replies to posted messages go to the list; this option
- X forces replies to be forwarded to the original author.
- X -m: Usually, each outgoing message has a single recipient. This switches
- X to multiple recipients -- the argument to it is the number of
- X multiple recipients to be included in this message.
- X -v: Display the version number of this package.
- X -f: Forward any message(s) from unsubscribed senders to MANAGER. This
- X way, any ordinary user account can be used as the list's address.
- X -L: The argument following is the list name to process.
- X -D: Turn debug on. A transaction of the last email sent out is kept
- X in the files /usr/server/sent and /usr/server/received. This assumes
- X use of the 'system' mail method.
- X
- X DISCLAIMER: If for any reason during the use of this program, implied
- X or not, you happen to die, or suffer any injury of any kind (physical
- X or mental), I, Mr. Anastasios Kotsikonas, AM NOT RESPONSIBLE at all.
- X In fact, I AM NOT RESPONSIBLE FOR ANYTHING that may happen to you, or
- X your computer and operating system.
- X
- X PLEASE: If you upgrade the code, send me a copy, and do not even attempt to
- X put your name for credit. Send to tasos@cs.bu.edu or tasos@bucsf.bu.edu.
- X
- X EXIT CODES:
- X 0: OK
- X 1: Could not open file
- X 2: Could not lock file
- X 3: Command line option error
- X 4: Syntax error in file
- X 5: Could not spawn
- X 6: Shutdown request
- X 7: Restart request
- X 8: Received system signal
- X 9: Too many multiple recipients
- X
- X ENJOY!!!
- X
- X Approximate algorithm:
- X {
- X Place a lock so that no other list program will access any files.
- X Read LIST_MAIL_FILE
- X If new message(s) have arrived then {
- X Append messages to MBOX
- X For each message do {
- X If the person is in the IGNORED file, go on to the next message.
- X If the person sending it is subscribed (listed in SUBSCRIBERS) then
- X If the person does not acknowledge his/her message, he/she
- X never receives his/her message back
- X If the -r flag is on then
- X check if the sender is listed in RESTRICTED
- X If so then
- X forward mail to all people listed in the file after the
- X restricted-sender's address
- X Else
- X distribute to all people in SUBSCRIBERS
- X Else
- X distribute to all people in SUBSCRIBERS, NEWSF (only to those
- X newsgroups that are supposed to received messages) and PEERS
- X according to the following:
- X Email from regular SUBSCRIBERS is sent to NEWS and PEERS as well
- X Email from news is sent to SUBSCRIBERS and PEERS
- X Email from peers is sent to SUBSCRIBERS and NEWS
- X Else if it news feed (listed in NEWSF)
- X distribute to SUBSCRIBERS
- X Else
- X if -f specified, forward it to MANAGER; otherwise return the
- X message to the sender.
- X }
- X Remove mail files.
- X }
- X Repeat process after IDLE_TIME, or die if -1 specified.
- X }
- X
- X Required files:
- X SUBSCRIBERS <-- The list of subscribed people
- X ALIASES <-- Aliases of email addresses of subscribers, news & peers
- X NEWSF <-- List of news groups
- X PEERS <-- List of peer lists
- X RESTRICTED <-- Addresses of senders whose messages
- X require special handling (usually
- X addresses of other lists): mail is
- X forwarded only to people found in the
- X file after the sender's address; see below
- X IGNORED <-- The list of undesired people
- X LIST_LOCK_FILE <-- Lock file
- X
- X Input files:
- X LIST_MAIL_FILE <-- File where new messages go
- X MAIL_COPY <-- Copy of this file (actual work file)
- X MSG_NO <-- Current message count
- X SUBSCRIBERS
- X RESTRICTED
- X IGNORED
- X
- X Output files:
- X MBOX <-- A log of all messages sent to date
- X REPORT_LIST <-- Progress report
- X HEADERS <-- A log of all emails sent (just the sender's address)
- X MSG <-- Body of message (no header)
- X MSG_NO <-- Write last message count
- X MAILFORWARD <-- Completed message (with header and a copy
- X of MSG) to be forwarded
- X
- X Format of the SUBSCRIBERS file:
- X One entry per line; each entry is the full email address of the subscriber
- X as it appears in the "From " field, followed by the word "ACK" (in which
- X case his/her message will be sent back to him/her as an acknowledgement)
- X "NOACK" (the opposite), or POSTPONE (no mail will be sent until the
- X user changes mode again), followed by the subscriber's name
- X -- this option may be
- X reset by the subscriber at any moment by sending a proper request to
- X listserv. Do not include any blank lines.
- X
- X Format of the RESTRICTED file:
- X One entry per line; each entry is the full email address of the
- X subscriber, followed by a file name where email addresses of recipients
- X are listed (just like in the SUBSCRIBERS file).When mail arrives from a
- X sender listed in the RESTRICTED file and the -r flag is on, then mail
- X will not be forwarded to SUBSCRIBERS, but instead to the people
- X listed in the file following the restricted-sender's address. Example:
- X tasos@bucsf.bu.edu /grad/tasos/.recipients
- X tasos@cs.bu.edu /grad/tasos/.otherrecipients
- X If the recipient file given is the word "NONE", then no one will receive
- X any messages. This is useful in the case that other distribution sites
- X are subscribers and do forward the message back to the sender,
- X in which case we protect ourselves from multiple reception of the same
- X messages.
- X For example, when two (or more) lists are mutual subscribers, and a
- X message originated by someone in our list, this message, after being
- X distributed locally, is sent to the other list; if the other site does
- X send messages back to the sender, this message will be forwarded to us
- X to be distributed again, something which is highly undesirable.
- X This precludes that the other site sends messages identified only by
- X their original senders, something which is unlikely but possible.
- X In this case, we would put our list as one of the entries in the
- X RESTRICTED file, with the word NONE next to it. Do not include
- X any blank lines.
- X
- X Format of the PEERS file:
- X One entry per line -- the email address of the peer list, followed
- X by its mail mode (NOACK), followed by the remote alias (how the peer list
- X is known in the remote host), followed by the email address of the
- X remote server that handles the remote peer list.
- X
- X Format of the NEWSF file:
- X One entry per line -- the email address of the news group, followed
- X by its mail mode (POSTPONE or NOACK), followed by the news group's name.
- X
- X Format of the IGNORED file:
- X One entry per line -- the email addresses of the people whose messages
- X are to be ignored. This is a good place to put root, sys and other
- X such undesired logins.
- X
- X Format of the ALIASES file:
- X One entry per line -- the new alias followed by the email address the
- X user is subscribed with.
- X
- X Recommended usage:
- X % list [-r] -L ALIAS &
- X or
- X % list [-r] -1 -L ALIAS
- X
- X*/
- X
- X#include <stdio.h>
- X#include <malloc.h>
- X#include <string.h>
- X#include <unistd.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X#include "defs.h"
- X#include "list.h"
- X#include "struct.h"
- X#include "global.h"
- X
- X/*
- X Function prototypes:
- X*/
- X
- X#ifdef __STDC__
- X#include <stdarg.h>
- extern int syscom (char *, ...);
- X#else
- X#include <varargs.h>
- extern int syscom ();
- X#endif
- extern int sys_config (FILE *, SYS *);
- extern void report_progress (FILE *, char *, int);
- extern void setup_string (char *, char *, char *);
- extern void init_signals (void);
- extern void catch_signals (void);
- extern void get_list_name (char *, char *);
- extern void extract_subscriber (FILE *, char *);
- extern void extract_origin (char *);
- extern int get_list_id (char *, SYS *, int);
- extern int getopt (int, char **, char *);
- extern char *upcase (char *);
- extern char *locase (char *);
- extern void shrink (char *);
- extern void distribute (FILE *, void (*)(char *, char *, unsigned short int),
- X FILE *, char *, char *, char *, char *);
- extern BOOLEAN sysmail (char *);
- extern BOOLEAN strinstr (char *, char *, char *);
- extern BOOLEAN ignore_sender (FILE *, char *, FILE *);
- X
- void main (int, char **, char **);
- void create_header (FILE **, char *, char *, char *, char *, char *);
- void create_multi_recipient_header (FILE **, char *, char *, char *, char *,
- X char *, int);
- void create_news_header (FILE **, char *, char *, char *, char *, char *);
- void create_gate_header (FILE **, char *, char *, char *, char *, char *,
- X char *);
- void process_message (char *, char *, BOOLEAN);
- void do_distribute (FILE *, char *, BOOLEAN, char *, char *, char *, char *,
- X char *, FILE *, BOOLEAN, BOOLEAN);
- BOOLEAN copy_msg (FILE *, BOOLEAN, char *);
- void sendmail (char *, BOOLEAN, BOOLEAN, int, int, char *);
- void usage (void);
- void list_config (char *);
- void version (void);
- void gexit (void);
- X
- X/*
- X The control structure of the mail-distributor. Check if mail has arrived.
- X If so, copy it to MAIL_COPY and proceed to lower level.
- X*/
- X
- void main (int argc, char **argv, char **envp)
- X{
- X struct stat stat_buf;
- X char command [MAX_LINE], *options = "1fvrL:em:spD";
- X int c;
- X char error [MAX_LINE];
- X int nlists;
- X FILE *f;
- X extern char *optarg;
- X extern int optopt;
- X
- X while ((c = getopt (argc, argv, options)) != EOF)
- X switch ((char) c) {
- X case '1': execute_once = TRUE; break;
- X case 'f': errors_to_manager = TRUE; break;
- X case 'r': send_to_subscribers = FALSE; break;
- X case 'L': list_alias = optarg; break;
- X case 'e': tty_echo = TRUE; break;
- X case 's': do_not_check_subscriptions = TRUE; break;
- X case 'p': article_replies_to_author = TRUE; break;
- X case 'v': version ();
- X case 'D': debug = TRUE; break;
- X case 'm':
- X multi_recip = TRUE;
- X if ((maxrecipients = atoi (optarg)) < 1)
- X fprintf (stderr, "-m %d -- yeah, right!\n", maxrecipients),
- X exit (3);
- X break;
- X case ':':
- X fprintf (stderr, "list: Option '%c' requires an argument.\n", optopt);
- X exit (3);
- X case '?':
- X default:
- X usage ();
- X }
- X#ifndef _MINIX
- X if (lockf (open (LIST_LOCK_FILE, O_RDWR), F_TLOCK, 0))
- X fprintf (stderr, "list: Unable to lock %s. Aborting.\n", LIST_LOCK_FILE),
- X exit (2);
- X#endif
- X init_signals();
- X catch_signals();
- X list_config (list_alias);
- X if ((report = fopen (report_listf, "a")) == NULL)
- X if ((report = fopen (REPORT_LIST, "a")) == NULL)
- X fprintf (stderr, "list: Could not open %s and %s\n", report_listf,
- X REPORT_LIST),
- X exit (1);
- X if (list_alias == NULL)
- X report_progress (report, "\nlist: No list to process", TRUE),
- X exit (3);
- X nlists = sys_config (report, &sys);
- X if ((listid = get_list_id (list_alias, &sys, nlists)) < 0)
- X sprintf (error, "\nlist: Unknown list %s", list_alias),
- X report_progress (report, error, TRUE),
- X exit (3);
- X if (!execute_once)
- X printf ("%s\n", VERSION);
- X if (sys.options & USE_ENV_VAR) {
- X if ((sys.mail.method = (char *) malloc (256 * sizeof (char))) == NULL)
- X report_progress (report, "\nmain(): malloc failed", TRUE),
- X exit (16);
- X sprintf (sys.mail.method, "env - %s=%s %s ", sys.mail.env_var,
- X sys.lists[listid].address, sys.mail.mail_prog);
- X }
- X if ((msg_no = fopen (msg_nof, "r")) != NULL)
- X fscanf (msg_no, "%d %d\n", &public_msg, &returned_msg),
- X fclose (msg_no);
- X
- X if (multi_recip)
- X if ((multi_recipients = (char **) malloc (maxrecipients * sizeof (char *)))
- X == NULL)
- X report_progress (report, "\nmain(): malloc failed", TRUE),
- X exit (16);
- X
- X if ((f = fopen (PID_LIST, "w")) != NULL)
- X fprintf (f, "%d", getpid()),
- X fclose (f);
- X signal (SIGINT, gexit);
- X
- X do {
- X if (!stat (list_mail_f, &stat_buf) && stat_buf.st_size > 0) {
- X syscom ("cp %s %s", list_mail_f, mail_copyf);
- X syscom ("cat %s >> %s", mail_copyf, mboxf);
- X syscom ("echo >> %s", mboxf);
- X syscom ("touch %s", list_moderated_f);
- X syscom ("chmod 666 %s", list_moderated_f);
- X if (!unlink (list_mail_f))
- X syscom ("touch %s", list_mail_f), /* rewrite file */
- X syscom ("chmod 666 %s", list_mail_f);
- X if ((mail = fopen (mail_copyf, "r")) == NULL)
- X sprintf (error, "\nlist: Could not open %s", mail_copyf),
- X report_progress (report, error, TRUE),
- X exit (1);
- X if ((subscribers = fopen (subscribersf, "r")) == NULL)
- X sprintf (error, "\nlist: Could not open %s", subscribersf),
- X report_progress (report, error, TRUE),
- X exit (1);
- X if ((news = fopen (newsf, "r")) == NULL)
- X sprintf (error, "\nlist: Could not open %s", newsf),
- X report_progress (report, error, TRUE),
- X exit (1);
- X if ((peers = fopen (peersf, "r")) == NULL)
- X sprintf (error, "\nlist: Could not open %s", peersf),
- X report_progress (report, error, TRUE),
- X exit (1);
- X if ((restricted = fopen (restrictedf, "r")) == NULL)
- X sprintf (error, "\nlist: Could not open %s", restrictedf),
- X report_progress (report, error, TRUE),
- X exit (1);
- X if ((ignored = fopen (ignoredf, "r")) == NULL)
- X sprintf (error, "\nlist: Could not open %s", ignoredf),
- X report_progress (report, error, TRUE),
- X exit (1);
- X if ((headers = fopen (headersf, "a")) == NULL)
- X sprintf (error, "\nlist: Could not open %s", headersf),
- X report_progress, (report, error, TRUE),
- X exit (1);
- X report_progress (report, NEW_ARRIVAL, FALSE);
- X distribute (mail, (void *) process_message, report, subscribersf, newsf,
- X peersf, aliasesf);
- X fclose (mail); /* Done */
- X fclose (subscribers);
- X fclose (news);
- X fclose (peers);
- X fclose (restricted);
- X fclose (ignored);
- X fclose (headers);
- X shrink (message_idsf);
- X unlink (mail_copyf); /* Done delivering */
- X }
- X else if (!execute_once) /* No mail to deliver */
- X if (sys.frequency > 0)
- X sleep (sys.frequency);
- X } while (!execute_once);
- X fclose (report);
- X free ((char *) sys.mail.method);
- X if (multi_recip)
- X free ((char **) multi_recipients);
- X gexit ();
- X}
- X
- X/*
- X Create a mail header.
- X*/
- X
- void create_header (FILE **f, char *filename, char *sender, char *originator,
- X char *recipient, char *subject)
- X{
- X char error [MAX_LINE];
- X char origin [MAX_LINE];
- X
- X strcpy (origin, originator);
- X locase (origin);
- X if ((*f = fopen (filename, "w")) == NULL)
- X RESET (error),
- X sprintf (error, "\ncreate_header(): Could not open %s", filename),
- X report_progress (report, error, TRUE),
- X exit (1);
- X locase (recipient);
- X if (sys.options & USE_TELNET)
- X fprintf (*f, "HELO\nMAIL From: <%s>\nRCPT To: <%s>\nDATA\n",
- X sys.lists[listid].address, recipient);
- X if (message_id[0] != EOS)
- X fprintf (*f, "Message-Id: %s\n", message_id);
- X fprintf (*f, "Comment: %s\nOriginator: %s\nErrors-To: %s\n\
- Reply-To: <%s>\nSender: %s\nVersion: %s\n\
- XFrom: %s\nTo: %s\nSubject: %s\n\n",
- X sys.lists[listid].comment, origin, sys.manager,
- X sys.lists[listid].address, sys.lists[listid].address,
- X VERSION, sender, recipient, subject);
- X}
- X
- X/*
- X Create a mail header with multiple recipients.
- X*/
- X
- void create_multi_recipient_header (FILE **f, char *filename, char *sender,
- X char *originator, char *recipient,
- X char *subject, int nrecipients)
- X{
- X char error [MAX_LINE];
- X char origin [MAX_LINE];
- X int i;
- X
- X strcpy (origin, originator);
- X locase (origin);
- X if ((*f = fopen (filename, "w")) == NULL)
- X RESET (error),
- X sprintf (error, "\ncreate_multi_recipient_header(): Could not open %s",
- X filename),
- X report_progress (report, error, TRUE),
- X exit (1);
- X if (sys.options & USE_TELNET) {
- X fprintf (*f, "HELO\nMAIL From: <%s>\n", sys.lists[listid].address);
- X for (i = 0; i < nrecipients; i++)
- X fprintf (*f, "RCPT To: <%s>\n", multi_recipients[i]),
- X free ((char *) multi_recipients[i]);
- X fprintf (*f, "DATA\n");
- X }
- X if (message_id[0] != EOS)
- X fprintf (*f, "Message-Id: %s\n", message_id);
- X fprintf (*f, "Comment: %s\nOriginator: %s\nErrors-To: %s\n\
- Reply-To: <%s>\nSender: %s\nVersion: %s\n\
- XFrom: %s\nTo: %s\nSubject: %s\n\n",
- X sys.lists[listid].comment, origin, sys.manager,
- X sys.lists[listid].address, sys.lists[listid].address,
- X VERSION, sender, recipient, subject);
- X}
- X
- X/*
- X Create a news header for a message to be posted.
- X*/
- X
- void create_news_header (FILE **f, char *filename, char *sender,
- X char *originator, char *group, char *subject)
- X{
- X char error [MAX_LINE];
- X char origin [MAX_LINE];
- X
- X strcpy (origin, originator);
- X locase (origin);
- X if ((*f = fopen (filename, "w")) == NULL)
- X RESET (error),
- X sprintf (error, "\ncreate_news_header(): Could not open %s", filename),
- X report_progress (report, error, TRUE),
- X exit (1);
- X locase (group);
- X if (message_id[0] != EOS)
- X fprintf (*f, "Message-Id: %s\n", message_id);
- X fprintf (*f, "Path: %s\nNewsgroups: %s\nDistribution: world\n\
- Organization: %s\n\
- Originator: %s\nReply-To: <%s>\nSender: %s\nFrom: %s\nSubject: %s\n\n",
- X (article_replies_to_author ? sender : sys.lists[listid].address),
- X group, sys.organization, origin,
- X (article_replies_to_author ? sender : sys.lists[listid].address),
- X sys.lists[listid].address,
- X sender, subject);
- X}
- X
- X/*
- X Create a gateway header.
- X*/
- X
- void create_gate_header (FILE **f, char *filename, char *sender,
- X char *originator, char *recipient,
- X char *group, char *subject)
- X{
- X char error [MAX_LINE];
- X char origin [MAX_LINE];
- X
- X strcpy (origin, originator);
- X locase (origin);
- X if ((*f = fopen (filename, "w")) == NULL)
- X RESET (error),
- X sprintf (error, "\ncreate_gate_header(): Could not open %s", filename),
- X report_progress (report, error, TRUE),
- X exit (1);
- X locase (group);
- X if (sys.options & USE_TELNET)
- X fprintf (*f, "HELO\nMAIL From: <%s>\nRCPT To: <%s>\nDATA\n",
- X sys.lists[listid].address, recipient);
- X if (message_id[0] != EOS)
- X fprintf (*f, "Message-Id: %s\n", message_id);
- X fprintf (*f, "Newsgroups: %s\nDistribution: world\nOrganization: %s\n\
- Originator: %s\nErrors-To: %s\nReply-To: <%s>\nSender: %s\n\
- XFrom: %s\nTo: %s\nSubject: %s\n\n",
- X group, sys.organization, origin, sys.manager,
- X (article_replies_to_author ? sender : sys.lists[listid].address),
- X sys.lists[listid].address, sender, recipient, subject);
- X}
- X
- X/*
- X The heart of the distribution. Since we are now at the beginning of the
- X message (as guaranteed by distribute ()), gather the rest of the message
- X -- that is until the beginning of the next message, or EOF. Note that
- X only the "From: ", "Originator: " and "Subject: " lines from the header
- X are saved.
- X The beginning of the next and every message is "From ". The actual
- X text of each message is separated from its header by a blank line (universal
- X format). The message is processed only if the sender is not listed in
- X IGNORED.
- X The entire message is stored in MSG. To distribute the message, prepare
- X a new header; the completed message is stored in MAILFORWARD. Actually,
- X for each subscriber we prepare a different header (different "To:" field)
- X and append MSG to MAILFORWARD. Distribute that mail to the members,
- X or, either return it to the sender if he/she is not subscribed, or
- X forward it to MANAGER if -f specified. Messages from MAILER_DAEMON are
- X always forwarded to MANAGER. A message from a mailer daemon is identified
- X by the presence of MAILER_DAEMON anywhere in the sender's email address,
- X to cover local and remote mailer daemon addresses. Please look at the
- X documentation for defs.h for the syntax of the MAILER_DAEMON string.
- X The parameter "sender" is used for report purposes and when we are sending
- X the sender's message back to him/her.
- X Messages from regular subscribers are sent to peer lists and news groups.
- X Messages from news groups are only distributed to local subscribers and
- X peer lists. Finally, messages from peer lists are distributed locally
- X and may be posted to news groups.
- X In the case of restricted mail, check if the sender is listed in
- X RESTRICTED; if so, forward the message to the people listed in the
- X filename found after the restricted-sender's address in RESTRICTED.
- X*/
- X
- void process_message (char *sender, char *linecopy, BOOLEAN sender_subscribed)
- X{
- X char line [MAX_LINE]; /* ... from the the current message */
- X char senders_subject [MAX_LINE]; /* the sender's subject */
- X char subject_copy [MAX_LINE]; /* a copy of the subject */
- X char report_msg [MAX_LINE]; /* place for report/error messages */
- X char original_sender [MAX_LINE]; /* as it appears in his message */
- X char originator [MAX_LINE]; /* Holds the Originator: address */
- X char reply_to [MAX_LINE]; /* Holds the Reply-To: address */
- X char id_copy [MAX_LINE]; /* Holds the Message-Id: */
- X FILE *forwardmail = NULL; /* completed message to be forwarded */
- X FILE *msg = NULL;
- X
- X line[0] =
- X senders_subject[0] =
- X subject_copy[0] =
- X originator[0] =
- X reply_to[0] =
- X message_id[0] =
- X id_copy[0]=
- X RESET (original_sender);
- X
- X /* Remove message header, but store the "From: " and "Subject: " fields to
- X be used later when sending the message to all subscribers. */
- X
- X while (!feof (mail) && line[0] != '\n') {
- X if (!strncmp (line, FROM, strlen (FROM)))
- X strcpy (original_sender, line + strlen (FROM)), /* Save From: */
- X original_sender [strlen (original_sender) - 1] = EOS; /* \n -> \0 */
- X if (!strncmp (line, SUBJECT, strlen (SUBJECT)))
- X strcpy (senders_subject, line + strlen (SUBJECT)), /* Save Subject: */
- X senders_subject [strlen (senders_subject) - 1] = EOS, /* \n -> \0 */
- X strcpy (subject_copy, senders_subject);
- X if (!strncmp (line, ORIGIN, strlen (ORIGIN)))
- X strcpy (originator, line + strlen (ORIGIN)), /* Remove "Originator: " */
- X extract_origin (originator),
- X upcase (originator);
- X if (!strncmp (line, REPLY_TO, strlen (REPLY_TO)))
- X strcpy (reply_to, line + strlen (REPLY_TO)), /* Remove "Reply-To: " */
- X extract_origin (reply_to),
- X upcase (reply_to);
- X if (!strncmp (line, MESSAGE_ID1, strlen (MESSAGE_ID1)) ||
- X !strncmp (line, MESSAGE_ID2, strlen (MESSAGE_ID2)) ||
- X !strncmp (line, MESSAGE_ID3, strlen (MESSAGE_ID3)))
- X strcpy (message_id, line + strlen ("Message-") + 4),
- X message_id [strlen (message_id) - 1] = EOS; /* \n -> \0 */
- X RESET (line);
- X fgets (line, MAX_LINE - 2, mail);
- X }
- X
- X /* Gather message into MSG; check if we have reached the next message,
- X or EOF */
- X if ((msg = fopen (msgf, "w")) == NULL)
- X sprintf (report_msg, "\nprocess_message(): Could not open %s", msgf),
- X report_progress (report, report_msg, TRUE),
- X exit (1);
- X RESET (line);
- X while (!feof (mail) &&
- X (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))) {
- X if (!strcmp (line, ".\n"))
- X PREPEND (".", line);
- X fprintf (msg, "%s", line);
- X fgets (line, MAX_LINE - 2, mail);
- X }
- X fclose (msg);
- X
- X strcpy (linecopy, line); /*** VERY IMPORTANT: we are now at the next msg ***/
- X /* Check the IGNORED file */
- X if (ignore_sender (ignored, sender, report))
- X return;
- X if (originator[0] != EOS) /* Check for mail loop using Originator: */
- X if (ignore_sender (ignored, originator, report))
- X return;
- X if (reply_to[0] != EOS) /* Check for mail loop using Reply-To: */
- X if (ignore_sender (ignored, reply_to, report))
- X return;
- X if (message_id[0] != EOS) { /* Check for mail loop using Message-Id: */
- X strcpy (id_copy, message_id);
- X upcase (id_copy);
- X if (message_ids = fopen (message_idsf, "r")) {
- X if (ignore_sender (message_ids, id_copy, report)) {
- X fclose (message_ids);
- X return;
- X }
- X fclose (message_ids);
- X }
- X if ((message_ids = fopen (message_idsf, "a")) == NULL)
- X sprintf (report_msg, "\nprocess_message(): Could not open %s",
- X message_idsf),
- X report_progress (report, report_msg, TRUE),
- X exit (1);
- X fprintf (message_ids, "%s %s\n", message_id, sender); /* Save new id */
- X fclose (message_ids);
- X }
- X if (sender_subscribed == NEWS)
- X if (ignore_sender (peers, originator, report))
- X return;
- X
- X if (originator[0] == EOS) /* Fresh message originating from this list */
- X sprintf (originator, "%s", sys.lists[listid].address);
- X upcase (originator);
- X
- X if (do_not_check_subscriptions)
- X sender_subscribed = SUBSCRIBED;
- X RESET (report_msg);
- X if (sender_subscribed == NOTSUBSCRIBED ||
- X strinstr (MAILER_DAEMON, sender, "|")) {/* Send error message to sender */
- X sprintf (report_msg, "Invalid message #%04d. Forwarding error message to \
- X%s.\n%s", ++returned_msg,
- X ((strinstr (MAILER_DAEMON, sender, "|") || errors_to_manager) ?
- X sys.manager : sender),
- X sender);
- X report_progress (report, report_msg, TRUE);
- X if ((msg_no = fopen (msg_nof, "w")) == NULL)
- X sprintf (report_msg, "\nprocess_message(): Could not open %s", msg_nof),
- X report_progress (report, report_msg, TRUE),
- X exit (1);
- X fprintf (msg_no, "%d %d\n", public_msg, returned_msg);
- X fclose (msg_no);
- X if ((msg = fopen (msgf, "r")) == NULL)
- X sprintf (report_msg, "\nprocess_message(): Could not open %s", msgf),
- X report_progress (report, report_msg, TRUE),
- X exit (1);
- X /* Prepare header */
- X create_header (&forwardmail, mailforwardf, sys.lists[listid].address,
- X originator,
- X ((strinstr (MAILER_DAEMON, sender, "|") || errors_to_manager) ?
- X sys.manager : sender),
- X senders_subject);
- X if (errors_to_manager || strinstr (MAILER_DAEMON, sender, "|"))
- X fprintf (forwardmail, "\nRejected message sent to %s by %s\n\
- follows.\n",
- X sys.lists[listid].address, sender);
- X else
- X fprintf (forwardmail, "\n%s: You are not subscribed to %s\n\
- Your message is returned to you unprocessed.\n", sender,
- sys.lists[listid].address);
- X fprintf (forwardmail, "-----------------------------------------------\
- X--------------------------------\n");
- X while (!feof (msg)) /* Copy actual message */
- X RESET (line),
- X fgets (line, MAX_LINE - 2, msg),
- X fprintf (forwardmail, "%s", line);
- X COMPLETE_TELNET (forwardmail);
- X fclose (msg);
- X fclose (forwardmail);
- X /* Form UNIX sendmail command */
- X if (sys.options & USE_SYSMAIL)
- X sysmail (mailforwardf);
- X else
- X syscom ("%s %s < %s", sys.mail.method,
- X (((sys.options & USE_TELNET) == 0) ?
- X ((strinstr (MAILER_DAEMON, sender, "|") || errors_to_manager) ?
- X sys.manager : locase (sender)) : ""),
- X mailforwardf);
- X return;
- X }
- X /* Distribute to all subscribers */
- X fprintf (headers, "%s\n", sender);
- X fflush (headers);
- X sprintf (report_msg, "Public message #%04d%s. Distributing to all \
- subscribers%s.\n%s",
- X ++public_msg, (sender_subscribed == NEWS ? " (news)" :
- X (sender_subscribed == PEER ? " (peer)" : "")),
- X (sender_subscribed == SUBSCRIBED ? ", news groups and peers" :
- X (sender_subscribed == NEWS ? ", peers" : ", news")),
- X sender);
- X report_progress (report, report_msg, TRUE);
- X if ((msg_no = fopen (msg_nof, "w")) == NULL)
- X sprintf (report_msg, "\nprocess_message(): Could not open %s", msg_no),
- X report_progress (report, report_msg, TRUE),
- X exit (1);
- X fprintf (msg_no, "%d %d\n", public_msg, returned_msg);
- X fclose (msg_no);
- X do_distribute (subscribers, subscribersf, send_to_subscribers, sender,
- X original_sender, senders_subject, subject_copy, originator,
- X report, FALSE, multi_recip);
- X if (sender_subscribed == SUBSCRIBED || sender_subscribed == PEER)
- X do_distribute (news, newsf, TRUE, sender, original_sender, senders_subject,
- X subject_copy, originator, report,
- X TRUE, FALSE); /* Send to news also */
- X if (sender_subscribed == SUBSCRIBED || sender_subscribed == NEWS)
- X do_distribute (peers, peersf, TRUE, sender, original_sender,
- X senders_subject, subject_copy, originator,
- X report, FALSE, FALSE); /* Send to peers also */
- X}
- X
- X/*
- X Do the distribution of the message to the specified list of subscribers.
- X The BOOLEAN argument 'posting' should be TRUE when posting AND gating to
- X news, and FALSE otherwise.
- X*/
- X
- void do_distribute (FILE *recipient_list, char *file,
- X BOOLEAN send_to_subscribers,
- X char *sender, char *original_sender, char *senders_subject,
- X char *subject_copy, char *originator, FILE *report,
- X BOOLEAN posting, BOOLEAN multi_recip)
- X{
- X char name [MAX_LINE]; /* holds each subscribers name */
- X char mailmode [MAX_LINE]; /* send message back to sender or not */
- X char subscriber [MAX_LINE]; /* holds each subscriber's address */
- X char report_msg [MAX_LINE]; /* place for report/error messages */
- X char recipient_file [MAX_LINE]; /* file of subscribers to use when -r */
- X char restricted_subscriber [MAX_LINE]; /* name of subscriber in RESTRICTED */
- X char line [MAX_LINE];
- X FILE *forwardmail;
- X BOOLEAN alternate_file = FALSE;
- X int nrecipients = 0;
- X
- X if (!send_to_subscribers) { /* -r: Check if restricted mail has arrived */
- X rewind (restricted);
- X while (!feof (restricted)) {
- X alternate_file = TRUE;
- X restricted_subscriber[0] = RESET (recipient_file);
- X fscanf (restricted, "%s %s", restricted_subscriber, recipient_file);
- X upcase (restricted_subscriber);
- X if (!strcmp (restricted_subscriber, sender)) {
- X if (!strcmp (recipient_file, NO_RECIPIENT_FILE)) {
- X /* Do not forward to anyone */
- X report_progress (report, "No alternate recipient file specified. \
- Message ignored.\n", FALSE);
- X return;
- X }
- X /* Restricted mail; forward message only to the people listed
- X in recipient_file */
- X if ((recipient_list = fopen (recipient_file, "r")) == NULL)
- X sprintf (report_msg, "\ndo_distribute(): Could not open alternate \
- recipient file %s", recipient_file),
- X report_progress (report, report_msg, TRUE),
- X exit (1);
- X RESET (report_msg);
- X sprintf (report_msg, "Restricted mail. Distributing only to \
- individuals listed in %s", recipient_file);
- X report_progress (report, report_msg, TRUE);
- X break;
- X }
- X }
- X }
- X rewind (recipient_list);
- X while (!feof (recipient_list)) { /* Send to all of them */
- X subscriber[0] = mailmode[0] = RESET (name);
- X extract_subscriber (recipient_list, subscriber);
- X fscanf (recipient_list, "%s ", mailmode);
- X if (subscriber[0] == EOS)
- X continue;
- X fgets (name, MAX_LINE - 2, recipient_list); /* Skip name */
- X name [strlen (name) - 1] = EOS;
- X upcase (mailmode);
- X if (!strcmp (mailmode, NOACK)) {
- X upcase (subscriber);
- X if (!strcmp (subscriber, sender) || !strcmp (subscriber, originator))
- X continue;
- X }
- X else if (!strcmp (mailmode, POSTPONE)) /* No email to this subscriber */
- X continue;
- X else if (mailmode[0] != EOS && strcmp (mailmode, ACK))
- X sprintf (report_msg, "\ndo_distribute(): Unrecognized mail mode %s in %s",
- X mailmode, file),
- X report_progress (report, report_msg, TRUE),
- X exit (4);
- X RESET (senders_subject);
- X strcpy (senders_subject, subject_copy);
- X if (multi_recip) {
- X if ((multi_recipients[nrecipients] =
- X (char *) malloc ((strlen (subscriber) + 1) * sizeof (char))) == NULL)
- X report_progress (report, "\ndo_distribute(): malloc failed", TRUE),
- X exit (16);
- X strcpy (multi_recipients[nrecipients++], locase (subscriber));
- X }
- X /* Prepare header */
- X if (posting) {
- X if (sys.options & POST_MAIL) /* Post to news group */
- X create_news_header (&forwardmail, mailforwardf, original_sender,
- X originator, name, senders_subject);
- X else if (sys.options & GATE_MAIL) /* Gate to news gateway */
- X create_gate_header (&forwardmail, mailforwardf, original_sender,
- X originator, subscriber, name, senders_subject),
- X posting = FALSE;
- X if (!copy_msg (forwardmail, posting, original_sender))
- X return;
- X }
- X else { /* Regular mail */
- X if (multi_recip) { /* Multi recipient header */
- X if (nrecipients == maxrecipients) {
- X sprintf (report_msg, "Multiple recipients of list <%s>",
- X sys.lists[listid].address);
- X create_multi_recipient_header (&forwardmail, mailforwardf,
- X original_sender, originator,
- X report_msg, senders_subject,
- X nrecipients);
- X if (!copy_msg (forwardmail, posting, original_sender))
- X return;
- X }
- X }
- X else { /* Single recipient header */
- X create_header (&forwardmail, mailforwardf, original_sender, originator,
- X subscriber, senders_subject);
- X if (!copy_msg (forwardmail, posting, original_sender))
- X return;
- X }
- X }
- X sendmail (subscriber, posting, multi_recip, nrecipients, maxrecipients,
- X mailforwardf);
- X if (nrecipients == maxrecipients)
- X nrecipients = 0;
- X }
- X if (alternate_file) /* Close alternate recipient file */
- X fclose (recipient_list);
- X
- X if (multi_recip && (nrecipients != 0)) { /* Left overs */
- X sprintf (report_msg, "Multiple recipients of list <%s>",
- X sys.lists[listid].address);
- X create_multi_recipient_header (&forwardmail, mailforwardf,
- X original_sender, originator,
- X report_msg, senders_subject,
- X nrecipients);
- X if (copy_msg (forwardmail, posting, original_sender))
- X sendmail (subscriber, posting, multi_recip, nrecipients, nrecipients,
- X mailforwardf);
- X }
- X}
- X
- X/*
- X Copy the original message to the outgoing message.
- X*/
- X
- BOOLEAN copy_msg (FILE *forwardmail, BOOLEAN posting, char *sender)
- X{
- X FILE *msg;
- X char line [MAX_LINE];
- X char report_msg [MAX_LINE];
- X int count = 0;
- X
- X if ((msg = fopen (msgf, "r")) == NULL)
- X sprintf (report_msg, "\ncopy_msg(): Could not open %s", msgf),
- X report_progress (report, report_msg, TRUE),
- X exit (1);
- X while (!feof (msg)) { /* Copy actual message */
- X RESET (line);
- X fgets (line, MAX_LINE - 2, msg);
- X fprintf (forwardmail, "%s", line);
- X count += strlen (line);
- X if ((sys.options & LIMIT_MSG) && (count > sys.limits.msg)) {
- X fclose (forwardmail);
- X rewind (msg);
- X create_header (&forwardmail, mailforwardf, sys.lists[listid].address,
- X sys.lists[listid].address, sender, "Posting rejected");
- X fprintf (forwardmail, "Your posting to list %s was rejected.\n\
- Reason: message size limit exceeded (maximum allowed: %ld bytes)\n\
- The first few lines of your message are included herein for reference:\n\n",
- sys.lists[listid].alias, sys.limits.msg);
- X report_progress (report, "Message rejected: maximum size exceeded",
- X TRUE);
- X count = 0;
- X while (!feof (msg) && count < 10)
- X RESET (line),
- X fgets (line, MAX_LINE - 2, msg),
- X fprintf (forwardmail, "%s", line),
- X ++count;
- X COMPLETE_TELNET (forwardmail);
- X fclose (forwardmail);
- X fclose (msg);
- X sendmail (sender, FALSE, FALSE, 0, 0, mailforwardf);
- X return FALSE;
- X }
- X }
- X if (!posting && (sys.options & USE_TELNET))
- X COMPLETE_FILE (forwardmail);
- X fclose (forwardmail);
- X fclose (msg);
- X return TRUE;
- X}
- X
- X/*
- X Send email (to subscribers/news/gateways/peers). It may send one single
- X copy to one recipient, or one copy to multiple recipients.
- X*/
- X
- void sendmail (char *subscriber, BOOLEAN posting, BOOLEAN multi_recip,
- X int nrecipients, int maxrecipients, char *mailforwardf)
- X{
- X char *buf;
- X int size, i;
- X
- X /* Form UNIX sendmail command */
- X if (posting && (sys.options & POST_MAIL)) /* Post to news */
- X syscom ("%s -h < %s", INEWS, mailforwardf);
- X else { /* Send email */
- X if (multi_recip) {
- X if (nrecipients == maxrecipients) {
- X if ((sys.options & USE_TELNET) == 0) { /* Line up recipients */
- X size = strlen (multi_recipients[0]) + 1;
- X if ((buf = (char *) malloc (size * sizeof (char))) == NULL)
- X report_progress (report, "\nsendmail(): malloc failed", TRUE),
- X exit (16);
- X strcpy (buf, multi_recipients[0]);
- X for (i = 1; i < nrecipients; i++)
- X size += strlen (multi_recipients[i]) + 2,
- X buf = (char *) realloc (buf, size * sizeof (char)),
- X sprintf (buf + strlen (buf), " %s", multi_recipients[i]);
- X if (strlen (buf) > 10000)
- X report_progress (report, "Too many multiple recipients", TRUE),
- X exit (9);
- X syscom ("%s %s < %s", sys.mail.method, buf, mailforwardf);
- X free ((char *) buf);
- X }
- X else if (sys.options & USE_SYSMAIL)
- X sysmail (mailforwardf);
- X else /* telnet */
- X syscom ("%s < %s", sys.mail.method, mailforwardf);
- X }
- X }
- X else /* Single recipient */
- X if (sys.options & USE_SYSMAIL)
- X sysmail (mailforwardf);
- X else
- X syscom ("%s %s < %s", sys.mail.method,
- X (((sys.options & USE_TELNET) == 0) ? locase (subscriber) : ""),
- X mailforwardf);
- X }
- X}
- X
- void usage ()
- X{
- X fprintf (stderr, "Usage: list <-L LIST_ALIAS> [-r] [-m #] [-1] [-f] [-e] \
- X[-s] [-p] [-v] [-D]\n\
- X-L: Process LIST_ALIAS (LIST_ALIAS has to be all in capital letters).\n\
- X-r: Restricted mail.\n\
- X-m: Specify number of multiple recipients in one outgoing message.\n\
- X-1: Execute only once.\n\
- X-f: Forward rejected messages to manager.\n\
- X-e: Echo reports to the screen.\n\
- X-s: Do not check for subscriptions.\n\
- X-p: Replies to posted messages will go to the author.\n\
- X-v: Version number.\n\
- X-D: Turn debug on.\n");
- X exit (3);
- X}
- X
- void list_config (char *alias)
- X{
- X if (alias == NULL)
- X return;
- X setup_string (subscribersf, alias, SUBSCRIBERS);
- X setup_string (headersf, alias, HEADERS);
- X setup_string (restrictedf, alias, RESTRICTED);
- X setup_string (newsf, alias, NEWSF);
- X setup_string (peersf, alias, PEERS);
- X setup_string (aliasesf, alias, ALIASES);
- X setup_string (ignoredf, alias, IGNORED);
- X setup_string (list_mail_f, alias, LIST_MAIL_FILE);
- X setup_string (list_moderated_f, alias, LIST_MODERATED_F);
- X setup_string (mboxf, alias, MBOX);
- X setup_string (msg_nof, alias, MSG_NO);
- X setup_string (mailforwardf, alias, MAILFORWARD);
- X setup_string (msgf, alias, MSG);
- X setup_string (mail_copyf, alias, MAIL_COPY);
- X setup_string (report_listf, alias, REPORT_LIST);
- X setup_string (message_idsf, alias, MESSAGE_IDS_F);
- X}
- X
- void version ()
- X{
- X fprintf (stderr, "%s\n", VERSION);
- X exit (0);
- X}
- X
- X/*
- X Graceful exit. Remove pid file.
- X*/
- X
- void gexit ()
- X{
- X unlink (PID_LIST);
- X exit (0);
- X}
- END_OF_FILE
- if test 42066 -ne `wc -c <'src/list.c'`; then
- echo shar: \"'src/list.c'\" unpacked with wrong size!
- fi
- # end of 'src/list.c'
- fi
- echo shar: End of archive 4 \(of 6\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-