|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 17401 (0x43f9)
Types: TextFile
Names: »rmail.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦3658e588a⟧ »EurOpenD3/mail/mh/mh-6.7.tar.Z«
└─⟦c75e36ecb⟧
└─⟦this⟧ »mh-6.7/zotnet/mf/mmdfI/src/uucp/rmail.c«
#define MFDEBUG /* temporarily */
#include "util.h"
#include "mmdf.h"
#include <pwd.h>
#include <signal.h>
#include "mf.h"
#include "tws.h"
/*
* R M A I L . C
*
* Developed from the Berkeley mail program of the same name
* by Mike Obrien at RAND to run with the MMDF mail system.
* Rewritten by Doug Kingston, US Army Ballistics Research Laboratory
* Hacked a lot by Steve Bellovin (smb@unc)
*
* This program runs SETUID to root so that it can set effective and
* real [ug]ids to mmdflogin.
*
* 27-Oct-82 Marshall T. Rose <mrose%uci@rand-relay>
* Support proper munging by using the UCI mail filtering
* routines (enabled by #ifdef MF)
* Also use ll_log() package (enabled by #ifdef LOG)
*
* 17-Oct-83 Marshall T. Rose <mrose%uci@rand-relay>
* New interfacing. Remove the #ifdef:s
*/
#define NAMESZ 64 /* Limit on component name size */
#define ADDROK 0
#define UUCP 1
#define RETURN 2
int Syscpy = 1;
int Tmpmode = 0600;
char *Fromtmp = "/tmp/rml.f.XXXXXX";
char *Msgtmp = "/tmp/rml.m.XXXXXX";
char *Errtmp = "/tmp/rml.e.XXXXXX";
char *Okhosts = "/usr/mmdf/table/rmail.ok";
char *Okdests = "/usr/mmdf/table/rmail.okdests";
extern char cmddfldir[];
extern char logdfldir[];
extern char mmdflogin[];
extern char pathsubmit[];
extern char sitesignature[];
extern char supportaddr[];
extern struct ll_struct chanlog;
char *dupfpath (), *index(), *rindex();
struct passwd *getpwnam(), *getpwuid();
FILE *popen();
/* \f
*/
struct ll_struct *logptr = &chanlog;
FILE *fromf; /* temporary out for colon-less UUCP "From" lines */
FILE *msgf; /* temporary out for message text */
FILE *mmdf; /* filtered mail file */
FILE *pipef; /* output to "submit" or "uux" */
char date[LINESIZE]; /* date of origination from uucp header */
char from[LINESIZE]; /* accumulated path of sender */
char origsys[NAMESZ]; /* originating system */
char origpath[LINESIZE];/* path from us to originating system */
char usrfrm[LINESIZE];
char Mailsys[LINESIZE];
int pbroke; /* broken-pipe flag */
int rtnflag; /* note was sent back */
int brpipe();
/* \f
*/
main(argc, argv)
char **argv;
{
char fromwhom[NAMESZ]; /* user on remote system */
char *fromptr;
char linebuf[LINESIZE]; /* scratchpad */
char sys[NAMESZ]; /* an element in the uucp path */
char *cp;
struct passwd *pw;
int error;
int cpyback;
if (argc < 2) {
fprintf(stderr, "Usage: rmail user [user ...]\n");
exit(1);
}
umask (0);
ll_hdinit (logptr, "RM");
logptr -> ll_file = dupfpath (logptr -> ll_file, logdfldir);
if ((pw = getpwnam (mmdflogin)) == NULL) {
fprintf (stderr, "Cannot find mmdflogin\n");
exit (99);
}
setgid (pw->pw_gid);
setuid (pw->pw_uid);
sprintf (Mailsys, "%s <%s@%s>",
sitesignature, mmdflogin, LocalName ());
/* \f
*/
{ /* BE VERY SURE... */
int i;
for (i = fileno (stdout); i <= HIGHFD; i++)
close (i);
}
/* create file to hold stderr output. We first open some */
/* null file to make sure stdout is taken. If stdin isn't */
/* open either, we've got so much trouble it isn't even worth */
/* worrying about a little more */
open("/dev/null", 0);
mktemp(Errtmp);
if (freopen(Errtmp, "w", stderr) == NULL) {
fprintf(stderr, "Can't create %s\n", Errtmp);
ll_log (logptr, LLOGFAT, "Unable to create '%s'",
Errtmp);
exit(1);
}
dup2 (fileno (stderr), fileno (stdout));
/* Create temp file for rest of message */
mktemp (Msgtmp);
if ((msgf=fdopen(creat(Msgtmp, Tmpmode), "w")) == NULL) {
fprintf(stderr, "Can't create %s\n", Msgtmp);
ll_log (logptr, LLOGFAT, "Unable to create '%s'",
Msgtmp);
exit(1);
}
/* create temp file for colon-less UUCP "From" lines */
mktemp (Fromtmp);
if ((fromf=fdopen(creat(Fromtmp, Tmpmode), "w")) == NULL) {
fprintf(stderr, "Can't create %s\n", Fromtmp);
ll_log (logptr, LLOGFAT, "Unable to create '%s'",
Fromtmp);
exit(1);
}
/* \f
*/
for (;;) {
if( fgets(linebuf, sizeof linebuf, stdin) == NULL )
break;
if( strncmp(linebuf, "From ", 5)
&& strncmp(linebuf, ">From ", 6) )
break;
if (linebuf[0] != '>')
fputs (">", fromf);
fputs(linebuf, fromf); /* Save, we may forward via UUCP */
cp = index (linebuf, ' '); /* start of name */
fromptr = ++cp;
cp = index (cp, ' '); /* cp at end of name */
*cp++ = 0; /* term. name, cp at date */
strcpy (fromwhom, fromptr);
strncpy (date, cp, 24); /* Mon Nov 10 23:12:09 1981 */
for (;;) {
cp = index(cp+1, 'r');
if (cp == NULL) {
cp = rindex(fromwhom, '!');
if (cp != NULL) {
char *p;
*cp = '\0';
p = rindex(fromwhom, '!');
if (p != NULL) strcpy(origsys, p+1);
else strcpy(origsys, fromwhom);
strcat(from, fromwhom);
strcat(from, "!");
strcpy(fromwhom, cp+1);
goto out;
}
strcpy (sys, SystemName ());
strcat (from, sys);
strcpy (origsys, sys);
strcat (from, "!");
goto out;
}
if (strncmp(cp, "remote from ", 12) == 0)
break;
}
sscanf(cp, "remote from %s", sys);
strcat(from, sys);
strcpy(origsys, sys); /* Save for quick ref. */
strcat(from, "!");
out:;
}
if( fromwhom[0] == '\0' ) /* No from line, illegal */
exit(99);
/* \f
*/
strcpy (origpath, from);
strcat (from, fromwhom);
mf_get_addr (from, usrfrm);
if ((cp = rindex (usrfrm, '<')) != NULL) {
strcpy (usrfrm, ++cp);/* sigh */
if ((cp = rindex (usrfrm, '>')) != NULL)
*cp = NULL;
}
if (usrfrm[0] == NULL)
sprintf (usrfrm, "%s!%s%%%s@%s",
SystemName (), from, UucpChan (), LocalName ());
ll_log (logptr, LLOGGEN, "Rmail from '%s' (%s)", from, usrfrm);
fputs (linebuf, msgf);
if (rp_isbad (txtcpy (stdin, msgf)))
fputs ("\n *** Problem during receipt from UUCP ***\n", msgf);
freopen (Msgtmp, "r", msgf);
freopen (Fromtmp, "r", fromf);
unlink (Msgtmp);
unlink (Fromtmp);
mmdf = NULL;
cpyback = 0;
for (argv++; --argc > 0; ) {
rewind (fromf);
rewind (msgf);
if (mmdf != NULL)
rewind (mmdf);
pbroke = 0;
rtnflag = 0;
signal(SIGPIPE, brpipe);
if (rp_isbad(deliver(*argv++)) && !rtnflag)
cpyback++;
}
/* Send back a copy if something nasty happened. For now, we use */
/* a real kludge -- we see if we noted some error, or if we find */
/* anything written to stderr.... */
fflush(stderr);
fflush (stdout);
if (cpyback) {rcpy();zcpy();}
unlink(Errtmp);
ll_close (logptr);
exit (0);
}
/* \f
*/
/*
* deliver() -- Handle all deliveries be they returns, automatic
* copies, or the real thing. Based on the address
* the letter is accepted or returned with a copy
* to the system administrators
*
* main() has set up the "from" string and the
* "date" string.
*/
char rtnend[] =
" --------------- End of Returned Mail ---------------\n";
deliver(to)
char *to;
{
int replyval;
int i;
char linebuf[LINESIZE];
char tmpbuf[LINESIZE];
switch (adrcheck (to)) {
case ADDROK:
ll_log (logptr, LLOGGEN, "Rmail to '%s' via MMDF", to);
if (rp_isbad (replyval =
xsubmit (NULL, usrfrm, NULL, NULL, to)))
break;
if (mmdf == NULL)
if (mf_get_msg () == NOTOK)
mmdf = msgf;
replyval = txtcpy (mmdf, pipef);
#ifndef RUNALON
i = (pclose(pipef) >> 8 ) & 0xff;
if (rp_isgood(replyval)) replyval = i;
#endif
break;
case UUCP:
ll_log (logptr, LLOGGEN, "Rmail to '%s' via UUCP", to);
if (rp_isbad (replyval = xuucp(from, to)))
break;
replyval = txtcpy(msgf, pipef);
#ifndef RUNALON
i = (pclose(pipef) >> 8 ) & 0xff;
if (rp_isgood(replyval)) replyval = (i == 0 ? RP_OK : RP_LIO);
#endif
break;
/* \f
*/
case RETURN:
rtnflag = 1;
ll_log (logptr, LLOGGEN, "Illegal Rmail to '%s'", to);
switch (adrcheck (from)) {
case ADDROK:
case RETURN:
replyval = xsubmit (dtimenow (), Mailsys,
from, supportaddr, from);
rtnmesg(to);
txtcpy(fromf, pipef);
txtcpy(msgf, pipef);
fputs (rtnend, pipef);
#ifndef RUNALON
i = (pclose(pipef) >> 8 ) & 0xff;
if (rp_isgood(replyval)) replyval = i;
#endif
break;
case UUCP:
replyval = xuucp (mmdflogin, from);
if (rp_isbad (replyval))
break;
fprintf (pipef, "To: %s\n", from);
fprintf (pipef, "Cc: %s\n", supportaddr);
rtnmesg(to);
txtcpy(fromf, pipef);
txtcpy(msgf, pipef);
fputs (rtnend, pipef);
#ifndef RUNALON
i = (pclose(pipef) >> 8 ) & 0xff;
if (rp_isgood(replyval))
replyval = (i == 0 ? RP_OK : RP_LIO);
#endif
break;
}
/* And now for the mail overseer's copy */
if (Syscpy) {
ll_log (logptr, LLOGGEN, "Notifying %s", supportaddr);
rewind (fromf);
rewind (msgf);
replyval = xsubmit (dtimenow (), Mailsys,
usrfrm, supportaddr, supportaddr);
if (rp_isbad (replyval))
break;
rtnmesg(to);
txtcpy (fromf, pipef);
txtcpy (msgf, pipef);
fputs (rtnend, pipef);
#ifndef RUNALON
i = (pclose(pipef) >> 8 ) & 0xff;
if (rp_isgood(replyval)) replyval = i;
#endif
}
}
return (replyval);
}
/* \f
*/
adrcheck (adr) /* Gateway to Arpanet? */
char *adr;
{
char *cp,
err[BUFSIZ],
host[BUFSIZ],
mbox[BUFSIZ];
struct adrx *adrxp;
if ((adrxp = seekadrx (adr)) == NULL)
return RETURN;
strcpy (err, adrxp -> err ? adrxp -> err : "");
strcpy (host, adrxp -> host ? adrxp -> host : "");
strcpy (mbox, adrxp -> mbox ? adrxp -> mbox : "");
while (seekadrx (NULL))
continue;
if (err[0] || mbox[0] == NULL)
return RETURN;
if (index (mbox, '!') || host[0] == NULL)
return UUCP;
if (rp_isgood (lookup (origsys, Okhosts)))
return ADDROK;
if (index (host, '@') || rp_isbad (okhost (host)))
return RETURN;
return ADDROK;
}
okhost(host) /* Host permitted to use mail facilities? */
char *host;
{
if (rp_isgood (lookup (origsys, Okhosts)))
return (RP_OK); /* Fully privledged originator */
if (rp_isgood (lookup (host, Okhosts)))
return (RP_OK); /* Fully privledged dest */
if (rp_isgood (lookup (host, Okdests)))
return (RP_OK); /* Unrestricted Dest. Host, OK */
return(RP_NO); /* Not permitted; must be bad */
}
/* \f
*/
/*
* lookup() -- This lookup function looks for strings which
* must be the first string on a line. Sorry Dave (dhc)
* but the MMDF channel functions are too specific
* to be easily used here without much kludging.
*/
/*****************************************
**** Can this be a call to a MMDF function??
**** Remember I have the RHOSTs table and the OKHOSTS table.
******************************************/
lookup (what, where)
char *what, *where;
{
FILE *lookf;
char entry[LINESIZE];
char *cp;
if ((lookf = fopen (where, "r")) == NULL)
return (RP_NO); /* Unknown problem */
while (fgets (entry, sizeof entry, lookf) != NULL) {
cp = entry;
while (*cp != '\n' && *cp != ' ' && *cp != '\t')
cp++;
*cp = 0;
if (lexequ (what, entry)) {
fclose (lookf);
return (RP_OK);
}
}
fclose (lookf);
return (RP_NO);
}
/* \f
*/
char *rtnmessage[] = {
" Your message has been intercepted trying to access\n",
"a restricted access host (e.g. an ARPANET host). A copy\n",
"of your message has been sent to the system administrators.\n",
"The text of your message follows.\n\n",
" --------------- Returned Mail Follows --------------\n",
0
};
rtnmesg (badadr)
char *badadr;
{
char **cpp;
fprintf (pipef, "Subject: Illegal Address (%s)\n\n", badadr);
for (cpp = rtnmessage; *cpp; cpp++)
fputs (*cpp, pipef);
}
txtcpy (frm, to)
FILE *frm, *to;
{
char buffer[BUFSIZ];
int nread;
while (!pbroke && (nread = fread (buffer, sizeof (*buffer), BUFSIZ, frm)) > 0)
fwrite (buffer, sizeof (*buffer), nread, to);
return (ferror (frm) ? RP_LIO : RP_OK );
}
/* \f
*/
xsubmit (date, from, to, cc, realto)
char *date, *from, *to, *cc, *realto;
{
char cmdstr[LINESIZE],
submit[LINESIZE];
getfpath (pathsubmit, cmddfldir, submit);
sprintf (cmdstr, "%s '-mlti%s*'", submit, UucpChan ());
#ifndef RUNALON
if ((pipef = popen (cmdstr, "w")) == NULL)
return (RP_NO);
#else
pipef = stdout;
printf ("%s\n", cmdstr);
#endif
fprintf (pipef, "%s\n%s\n!\n", from, realto);
if (date) {
fprintf (pipef, "Date: %s\n", date);
fprintf (pipef, "From: %s\n", from);
}
if (to) {
fprintf (pipef, "To: %s", to);
if (index (to, '@'))
fputc ('\n', pipef);/* Explicit host specified */
else
fprintf (pipef, "@%s\n", LocalName ());
}
if (cc) {
fprintf (pipef, "Cc: %s\n", cc);
}
return (RP_OK);
}
/* \f
*/
xuucp (from, to)
char *from, *to;
{
char cmdstr[LINESIZE];
sprintf (cmdstr, "/etc/delivermail -r%s -ep -m -s -i %s", from, to);
#ifndef RUNALON
if ((pipef = popen (cmdstr, "w")) == NULL)
return (RP_NO);
#else
pipef = stdout;
printf ("%s\n", cmdstr);
#endif
return (RP_OK);
}
/* \f
*/
brpipe() /* catch broken-pipe signals */
{
signal(SIGPIPE, SIG_IGN);
pbroke = 1;
}
char *oopsmessage[] = {
"\n\n\tThe system administrators (%s) have been informed of the\n",
"problem, but have not been given a copy of your message.\n",
NULL
};
/* \f
*/
rcpy () {
int i;
char buffer[BUFSIZ],
message[BUFSIZ];
FILE * fp;
ll_log (logptr, LLOGGEN, "Advising %s of failure as %s...", from, usrfrm);
sprintf (buffer, "Problems sending mail:\n\n");
if (ml_1adr (NO, NO, sitesignature, "Problems sending mail", usrfrm)
!= OK)
goto ml_err;
ml_txt (buffer);
if ((fp = fopen (Errtmp, "r")) != NULL) {
ml_file (fp);
if (ftell (fp) == 0L)
fprintf (pipef, "\tunknown problem\n");
fclose (fp);
}
else
ml_txt ("\tunknown problem\n");
for (i = 0; oopsmessage[i]; i++) {
sprintf (message, oopsmessage[i], supportaddr);
ml_txt (message);
}
fprintf (pipef, "\n\nReturned message follows:\n\n---------------\n\n");
rewind (fromf);
ml_file (fromf);
rewind (msgf);
ml_file (msgf);
if (ml_end (OK) != OK) {
char *cp;
ml_err: ;
if (cp = index (buffer, '\n'))
*cp = NULL;
ll_log (logptr, LLOGFAT, "Unable to post failure notice");
ll_log (logptr, LLOGFAT, "info: %s", buffer);
}
}
/* \f
*/
zcpy () {
char buffer[BUFSIZ];
FILE * fp;
ll_log (logptr, LLOGGEN, "Advising %s of failure...", supportaddr);
sprintf (buffer, "Problems sending mail for %s (aka %s):\n\n",
from, usrfrm);
if (ml_1adr (NO, NO, sitesignature, "Problems sending mail", supportaddr)
!= OK)
goto ml_err;
ml_txt (buffer);
if ((fp = fopen (Errtmp, "r")) != NULL) {
ml_file (fp);
if (ftell (fp) == 0L)
fprintf (pipef, "\tunknown problem\n");
fclose (fp);
}
else
ml_txt ("\tunable to open error file\n");
if (ml_end (OK) != OK) {
char *cp;
ml_err: ;
if (cp = index (buffer, '\n'))
*cp = NULL;
ll_log (logptr, LLOGFAT, "Unable to post failure notice");
ll_log (logptr, LLOGFAT, "info: %s", buffer);
}
}
/* \f
*/
mf_get_msg () {
int i,
fd,
md,
td;
char buffer[BUFSIZ],
tmpfil[LINESIZE],
mmdfil[LINESIZE];
#ifdef MFDEBUG
FILE * fp;
#endif MFDEBUG
FILE * out;
strcpy (tmpfil, "/tmp/rmailXXXXXX");
unlink (mktemp (tmpfil));
if ((fd = creat (tmpfil, Tmpmode)) == NOTOK)
return NOTOK;
close (fd);
if ((fd = open (tmpfil, 2)) == NOTOK)
return NOTOK;
if ((out = fdopen (fd, "w")) == NULL) {
close (fd);
return NOTOK;
}
if ((td = dup (fd)) == NOTOK) {
close (fd);
return NOTOK;
}
fprintf (out, "From %s %s\n", from, date);
if (rp_isbad (txtcpy (msgf, out))) {
close (fd);
close (td);
return NOTOK;
}
fclose (out);
lseek (td, 0L, 0);
strcpy (mmdfil, "/tmp/mmdfXXXXXX");
unlink (mktemp (mmdfil));
if ((fd = creat (mmdfil, Tmpmode)) == NOTOK) {
close (td);
unlink (tmpfil);
return NOTOK;
}
if ((fd = open (mmdfil, 2)) == NOTOK) {
close (td);
unlink (tmpfil);
return NOTOK;
}
if ((md = dup (fd)) == NOTOK) {
close (td);
unlink (tmpfil);
close (fd);
return NOTOK;
}
/* \f
*/
switch (i = uucp_to_mmdf (td, fd, TRUE)) {
case OK:
lseek (md, 0L, 0);
if ((mmdf = fdopen (md, "r")) != NULL)
break;
default:
close (md);
sprintf (buffer, "rmail(%d) filtering failed(%d)\n",
getpid (), i);
if (ml_1adr (NO, NO, sitesignature, "MF Failure", supportaddr)
!= OK)
goto ml_err;
ml_txt (buffer);
#ifdef MFDEBUG
lseek (td, 0L, 0);
if ((md = dup (td)) == NOTOK)
ml_txt ("unable to dup() descriptor for message copy\n");
else
if ((fp = fdopen (md, "r")) == NULL) {
ml_txt ("unable to fdopen() descriptor for message copy\n");
close (md);
}
else {
ml_txt ("\n --Message Follows--\n");
ml_file (fp);
fclose (fp);
}
#endif MFDEBUG
if (ml_end (OK) != OK) {
char *cp;
ml_err: ;
if (cp = index (buffer, '\n'))
*cp = NULL;
ll_log (logptr, LLOGFAT, "Unable to post failure notice");
ll_log (logptr, LLOGFAT, "info: %s", buffer);
}
md = NOTOK;
break;
}
close (td);
unlink (tmpfil);
close (fd);
unlink (mmdfil);
return md;
}
/* \f
*/
mf_get_addr (from, to)
char *from,
*to;
{
struct adrx *adrxp,
*seekadrx ();
*to = NULL;
if ((adrxp = seekadrx (from)) == NULL)
return;
addr_convert (adrxp, to, TRUE);
while (seekadrx (NULL))
continue;
return;
}