static char SccsId
[] = "@(#)arpa.c 2.2 1/11/81";
char Version
[] = "@(#)Arpa-mailer version 2.2 of 1/11/81";
** ARPA MAILER -- Queue ARPANET mail for eventual delivery
** The standard input is stuck away in the outgoing arpanet
** mail queue for delivery by the true arpanet mailer.
** /usr/lib/mailers/arpa from host user
** Positional Parameters:
** from -- the person sending the mail.
** host -- the host to send the mail to.
** user -- the user to send the mail to.
** /usr/spool/netmail/* -- the queue file.
** 0 -- all messages successfully mailed.
** 2 -- user or host unknown.
** 3 -- service unavailable, probably temporary
** file system condition.
** 4 -- syntax error in address.
** SPOOLDIR -- the spool directory
** Compilation Instructions:
** cc -n -O -s arpa-mailer.c -o arpa-mailer -lX
** mv arpa-mailer /usr/lib/mailers/arpa
** Eric Allman, UCB/INGRES (eric@berkeley)
# define SPOOLDIR "/usr/spool/netmail"
char *From
; /* person sending this mail */
char *To
; /* current "To:" person */
int State
; /* the current state (for exit codes) */
bool Tflag
; /* -T given */
char FromHost
[200]; /* string to prepend to addresses */
** MAIN -- Main program for arpa mailer
** Processes arguments, and calls sendmail successively on
** Catch interrupt signals.
** Collect input file name and from person.
** If more than one person in the to list, and
** if the input file is not a real file,
** collect input into a temp file.
** For each person in the to list
** Eric Allman UCB/INGRES.
if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
if (strcmp(argv
[1], "-T") == 0)
lastmark
= &FromHost
[-1];
for (p
= From
, q
= FromHost
; (*q
= *p
) != '\0'; p
++, q
++)
if (*q
== '.' || *q
== '!' || *q
== '@')
State
= sendmail(argv
[2], argv
[3]);
** FINIS -- Finish up, remove temp files, etc.
** This does basic cleanup on interrupt, error, or
** normal termination. It uses "State" to tell which
** REXIT -- exit, reporting error code if -T given
** e -- error code to exit with; see sysexits.h
fprintf(stderr
, "arpa-mail: return code %d\n", e
);
** SENDMAIL -- Queue up mail for the arpanet mailer.
** The mail is inserted with proper headers into the
** arpanet queue directory.
** create a spool file name.
** output the header information to spool file,
** separate names in To:, CC: fields with commas.
** copy the mail to the spool file.
** host -- the host to send to.
** user -- the user to send to.
** the mail is copied into a file in the network
** queue directory (/usr/spool/netmail).
char spoolfile
[50]; /* gets the spool file name */
static int callnum
; /* for the final letter on spoolfile */
register FILE *sfp
; /* spool file */
/* verify that the host exists */
strcpy(buf
, "/dev/net/");
if (host
[0] == '\0' || access(buf
, 0) < 0)
** Create spool file name.
** Format is "username000nnX", where username is
** padded on the right with zeros and nn (the process
** id) is padded on the left with zeros; X is a unique
strcpy(spoolfile
, "test.out");
sprintf(spoolfile
, "%s/arpamail%05d%c", SPOOLDIR
, getpid(), 'a' + callnum
++);
sfp
= fopen(spoolfile
, "w");
** Output mailer control lines.
** These lines are as follows:
** /dev/net/<hostname> {target host}
** user-name {at target host}
** /mnt/eric {pathname of sender; not used}
** eric {name of user who is sending}
** Check the first line for the date. If not found,
** assume the message is not in arpanet standard format
** and output a "Date:" and "From:" header.
if (fgets(buf
, sizeof buf
, stdin
) == NULL
)
if (strncmp("From ", buf
, 5) == 0)
/* strip Unix "From" line */
/* should save the date here */
fgets(buf
, sizeof buf
, stdin
);
if (matchhdr(buf
, "date") == NULL
)
** At this point, we have a message with REAL headers.
** We look at each head line and insert commas if it
** is a To: or Cc: field.
if (!matchhdr(buf
, "to") && !matchhdr(buf
, "cc"))
while (isspace(c
= peekc(stdin
)) && c
!= '\n')
fgets(buf
, BUFSIZ
, stdin
);
} while (fgets(buf
, BUFSIZ
, stdin
) != NULL
);
/* output the rest of the header & the body of the letter */
} while (fgets(buf
, sizeof buf
, stdin
) != NULL
);
** REWRITE -- Output header line with needed commas.
** first -- true if this is not a continuation
** The contents of buf is copied onto the spool file with
** with the right commas interlaced
char word
[BUFSIZ
], word2
[BUFSIZ
];
static char wsep
[] = ", ";
while (*cp
!= ':' && *cp
)
while (*cp
&& isspace(*cp
))
if (strcmp(word2
, "%") == 0)
if (strcmp(word2
, "@") && strcmp(word2
, "at"))
if (isspace(c
) && c
!= '\n')
** PUTADDR -- output address onto file
** Putaddr prepends the network header onto the address
** unless one already exists.
** name -- the name to output.
** fp -- the file to put it on.
for (p
= name
; *p
!= '\0' && *p
!= ':' && *p
!= '.' && *p
!= '@' &&
*p
!= '!' && *p
!= '^'; p
++)
** PEEKC -- peek at next character in input file
** fp -- stdio file buffer
** the next character in the input or EOF
** GWORD -- get the next liberal word from a string
** buf -- place to put scanned word
** p -- place to start looking for word
** updated value of p or 0 if no more left after this
** buf gets the liberal word scanned.
** buf will be length 0 if there is no more input,
** or if p was passed as 0
while (*sp
&& (isspace(*sp
) || *sp
== ','))
if (*sp
!= '%' && *sp
!= '@')
while (*sp
&& !isspace(*sp
) && *sp
!= ',' && *sp
!= '%' && *sp
!= '@')
** ISHDR -- see if the passed line is a ARPA style header line
** non-zero if the line is a header line, else zero
while (*p
!= ':' && !isspace(*p
))
** PUTDATE -- Put the date & from field into the message.
** fp -- file to put them onto.
fputs(" at Berkeley\n", fp
);