|
|
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 s
Length: 10979 (0x2ae3)
Types: TextFile
Names: »sendmail.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z«
└─⟦e5a54fb17⟧
└─⟦this⟧ »pp-5.0/Uip/sendmail/sendmail.c«
/* sendmail.c: A fake sendmail for those that really need it */
# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Uip/sendmail/RCS/sendmail.c,v 5.0 90/09/20 16:34:50 pp Exp Locker: pp $";
# endif
/*
* $Header: /cs/research/pp/hubris/pp-beta/Uip/sendmail/RCS/sendmail.c,v 5.0 90/09/20 16:34:50 pp Exp Locker: pp $
*
* $Log: sendmail.c,v $
* Revision 5.0 90/09/20 16:34:50 pp
* rcsforce : 5.0 public release
*
*/
#include <signal.h>
#include <pwd.h>
#include "util.h"
#include "prm.h"
#include "q.h"
#include "adr.h"
#include "retcode.h"
#include "ap.h"
#include <varargs.h>
extern char *loc_dom_site;
extern char *chndfldir;
extern char *hdr_822_bp;
extern char *ia5_bp;
extern char *local_822_chan;
extern UTC utclocalise();
extern struct passwd *getpwuid ();
extern char *getenv();
extern char *dupfpath();
static char *SMTPSRVR = "smtpsrvr";
static char *fullname; /* sender's full name */
static char *from; /* sender's mail address */
static int verify;
static int badaddrs;
static int rewritefrom;
static int watch;
static int extract_mode;
static char *eaddr[1024];
static int neaddr;
static char firstline[BUFSIZ];
static struct prm_vars prm;
static Q_struct qs;
static RP_Buf rps;
static RP_Buf *rp = &rps;
static SFD die();
static void adios ();
static char tbuf[BUFSIZ];
/*ARGSUSED*/
main(argc, argv)
int argc;
char **argv;
{
struct passwd *pwdptr;
register char *p;
register char **av;
char **oobto = NULL;
ADDR *adr;
uip_init(argv[0]);
pp_log_norm -> ll_stat |= LLOGTTY;
if ((pwdptr = getpwuid (getuid())) == (struct passwd *) NULL)
adios (NULLCP, "Unable to locate user's name");
(void) sprintf (tbuf, "%s@%s", pwdptr -> pw_name, loc_dom_site);
from = strdup (tbuf);
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
(void) signal(SIGINT, die);
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
(void) signal(SIGHUP, die);
(void) signal(SIGTERM, die);
(void) signal(SIGPIPE, die);
fullname = getenv("NAME");
av = argv;
while ((p = *++av) != NULL && p[0] == '-') {
switch (p[1]) {
case 'b': /* operations mode */
switch (p[2]) {
case 'a': /* smtp on stdin */
case 's': /* smtp on stdin */
smtp();
exit(98); /* should never happen */
case 'm': /* just send mail */
continue;
case 'v': /* verify mode */
verify++;
continue;
default:
adios (NULLCP, "Invalid operation mode %c", p[2]);
}
continue;
case 'f': /* from address */
case 'r': /* obsolete -f flag */
p += 2;
if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
{
p = *++av;
if (p == NULL || *p == '-') {
adios (NULLCP, "No \"from\" person");
av--;
continue;
}
}
if (rewritefrom) {
adios (NULLCP, "More than one \"from\" person");
continue;
}
from = p;
rewritefrom++;
continue;
case 'F': /* set full name */
p += 2;
if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
{
adios (NULLCP, "Bad -F flag");
av--;
continue;
}
fullname = p;
continue;
case 'h': /* hop count */
p += 2;
if (*p == '\0' && ((p = *++av) == NULL || !isdigit(*p)))
{
adios (NULLCP, "Bad hop count (%s)", p);
av--;
continue;
}
continue; /* Ignore */
case 't': /* read recipients from message */
extract_mode = 1;
continue;
case 'v': /* give blow-by-blow description */
watch++;
continue;
case 'T': /* set timeout interval */
case 'C': /* select configuration file (already done) */
case 'c': /* connect to non-local mailers */
case 'd': /* debug */
case 'e': /* error message disposition */
case 'i': /* don't let dot stop me */
case 'm': /* send to me too */
case 'n': /* don't alias */
case 'o': /* set option, handled in line */
case 's': /* save From lines in headers */
continue;
}
}
setuid(getuid());
prm_init (&prm);
prm.prm_opts = PRM_ACCEPTALL;
q_init (&qs);
qs.inbound = list_rchan_new (loc_dom_site, local_822_chan);
qs.encodedinfo.eit_types = list_bpt_new (hdr_822_bp);
list_bpt_add (&qs.encodedinfo.eit_types, list_bpt_new (ia5_bp));
if (rp_isbad (io_init (rp)) ||
rp_isbad (io_wprm (&prm, rp)) ||
rp_isbad (io_wrq (&qs, rp)))
adios (NULLCP, "Unable to submit mail at this time: %s",
rp -> rp_line);
adr = adr_new (from, AD_822_TYPE, 0);
adr -> ad_status = AD_STAT_DONE;
adr -> ad_resp = NO;
if (rp_isbad (io_wadr (adr, AD_ORIGINATOR, rp)))
adios (NULLCP, "Unable to submit mail from %s: %s",
from, rp -> rp_line);
adr_tfree (adr);
if (*av == NULL && !extract_mode) {
adios (NULLCP, "Usage: /usr/lib/sendmail [flags] addr...");
}
read_header ();
oobto = av;
while (*av)
send_address(*av++);
if (extract_mode) {
int i;
for (i = 0; i < neaddr; i++)
send_address (eaddr[i]);
}
if (rp_isbad (io_adend (rp)))
adios (NULLCP, "Problem with address list.");
if (verify) {
io_end(NOTOK);
exit(badaddrs ? 1 : 0);
}
if (rp_isbad (io_tinit (rp)) || rp_isbad (io_tpart (hdr_822_bp, 0, rp)))
adios (NULLCP, "Problem initialising for text: %s", rp -> rp_line);
doheader(oobto);
exit(dobody());
}
static struct qbuf *Header;
static struct qbuf *qbase;
static int nleft;
static char *qbptr;
static void qb_read_init (qp)
struct qbuf *qp;
{
char *cp;
qbase = qp;
cp = index (qp -> qb_data, ':');
if (cp == NULL)
adios (NULLCP, "Internal error - missing ':'");
cp ++;
nleft = qp -> qb_len - (cp - qp -> qb_data);
qbptr = cp;
}
int getqbchar ()
{
if (nleft > 0) {
nleft --;
return *qbptr++;
}
qbase = qbase -> qb_forw;
if (qbase == Header)
return EOF;
if (qbase -> qb_data[0] != ' ' && qbase -> qb_data[0] != '\t')
return EOF;
nleft = qbase -> qb_len;
qbptr = qbase -> qb_data;
return getqbchar ();
}
read_header ()
{
struct qbuf *qp;
char buffer[BUFSIZ];
AP_ptr ap;
Header = (struct qbuf *)malloc (sizeof *Header);
Header -> qb_forw = Header -> qb_back = Header;
while (fgets (buffer, sizeof buffer, stdin) != NULL) {
if (isheader (buffer)) {
qp = str2qb (buffer, strlen (buffer), 0);
insque (qp, Header -> qb_back);
}
else {
strcpy (firstline, buffer);
break;
}
}
if (!extract_mode)
return;
for (qp = Header -> qb_forw; qp != Header; qp = qp -> qb_forw) {
if (lexnequ (qp -> qb_data, "to:", 3) == 0 ||
lexnequ (qp -> qb_data, "cc:", 3) == 0 ||
lexnequ (qp -> qb_data, "bcc:", 4) == 0) {
qb_read_init (qp);
for (;;) {
ap_pinit (getqbchar);
switch (ap_1adr ()) {
case DONE:
break;
case NOTOK:
adios (NULLCP, "error in address");
break;
default:
ap = ap_t2s (ap_pstrt, &eaddr[neaddr++]);
ap_free (ap);
continue;
}
break;
}
}
}
}
send_address (addr)
char *addr;
{
int retval;
ADDR *adr;
if (watch) {
printf ("%s: ", addr);
(void) fflush (stdout);
}
adr = adr_new (addr, AD_822_TYPE, 0);
if (rp_isbad (retval = io_wadr (adr, AD_RECIPIENT, rp)))
adios (NULLCP, "Problem in send_address: [%s] %s.",
rp_valstr (retval),
rps.rp_line);
adr_tfree (adr);
switch (rp_gval (rp -> rp_val)) {
case RP_AOK:
if(watch) printf ("address ok\n");
break;
case RP_NO:
if(watch) printf ("not deliverable; unknown problem\n");
badaddrs = TRUE;
break;
case RP_USER:
if(watch) printf ("not deliverable; unknown address.\n");
badaddrs = TRUE;
break;
case RP_NDEL:
if(watch) printf ("not deliverable; permanent error.\n");
badaddrs = TRUE;
break;
case RP_AGN:
if(watch) printf ("failed, this attempt; try later\n");
badaddrs = TRUE;
break;
case RP_NOOP:
if(watch) printf ("not attempted, this time; perhaps try later.\n");
badaddrs = TRUE;
break;
default:
adios (NULLCP, "Unexpected address response: %s", rp -> rp_line);
}
(void) fflush (stdout);
}
doheader(oobto)
char **oobto;
{
int gotfrom, gotsender, gotdate, gotrecipient;
char line[LINESIZE];
char buf[LINESIZE];
struct qbuf *qp;
gotfrom = gotsender = gotdate = gotrecipient = 0;
for (qp = Header -> qb_forw; qp != Header; qp = qp -> qb_forw) {
if (qp -> qb_data[0] == '\n')
break;
if (prefix ("Date:", qp -> qb_data))
gotdate++;
if (prefix ("From:", qp -> qb_data)) {
gotfrom++;
if (rewritefrom) {
dofrom();
continue;
}
}
if (prefix ("Sender:", qp -> qb_data))
gotsender++;
if (prefix ("To:", qp -> qb_data)
|| prefix ("Cc:", qp -> qb_data)
|| prefix ("Bcc:", qp -> qb_data)
|| prefix ("Apparently-To:", qp -> qb_data) )
gotrecipient++;
if (rp_isbad (io_tdata (qp -> qb_data, qp -> qb_len)))
adios (NULLCP, "Data copy error");
}
if (!gotrecipient && oobto) {
while (*oobto) {
(void) sprintf (buf, "Apparently-To: %s\n", *oobto++);
if (rp_isbad (io_tdata (buf, strlen(buf))))
adios (NULLCP, "Data copy error");
}
}
if (!gotdate) {
UTC now, lut;
(void) strcpy (buf, "Date: ");
now = utcnow();
lut = utclocalise(now);
UTC2rfc (lut, buf + 6);
free ((char *) lut);
(void) strcat (buf, "\n");
if (rp_isbad (io_tdata (buf, strlen(buf))))
adios (NULLCP, "Data copy error");
}
if (!gotfrom)
dofrom();
if (!gotsender) {
(void) sprintf(buf, "Sender: %s\n", from);
if (rp_isbad (io_tdata (buf, strlen(buf))))
adios (NULLCP, "data copy error");
}
(void) sprintf (tbuf, "1.%s", ia5_bp);
if (rp_isbad (io_tdend (rp)) || rp_isbad (io_tpart (tbuf, 0, rp)))
adios (NULLCP, "Error seting up for body part: %s",
rp -> rp_line);
if (firstline[0] != '\n')
io_tdata (firstline, strlen(firstline));
}
/*
* Could this be an RFC822 header line?
*/
isheader(line)
char *line;
{
register char *cp = line;
while (*cp > ' ' && *cp != ':')
cp++;
return(cp > line && *cp == ':');
}
dofrom()
{
char line[128];
if (isstr(fullname))
(void) sprintf(line, "From: %s <%s>\n", fullname, from);
else
(void) sprintf(line, "From: %s\n", from);
io_tdata (line, strlen(line));
}
dobody()
{
char buffer[BUFSIZ];
register int i;
while (!feof (stdin) && !ferror (stdin) &&
(i = fread (buffer, sizeof (char), sizeof (buffer), stdin)) > 0)
if (rp_isbad (i = io_tdata (buffer, i)))
adios (NULLCP, "Problem writing body");
if (ferror (stdin))
adios (NULLCP, "Problem reading body");
if (rp_isbad (io_tdend (rp)) || rp_isbad (io_tend (rp)))
adios (NULLCP, "problem ending submission: %s", rp -> rp_line);
return(0); /* eventually the program exit value */
}
smtp()
{
char *smtpd = dupfpath(chndfldir, SMTPSRVR);
setuid(geteuid());
execl (smtpd, "sendmail-smtp", "smtp", (char *)0);
adios ("failed", "execl of %s", smtpd);
}
#ifndef lint
static void adios (va_alist)
va_dcl
{
va_list ap;
va_start (ap);
_ll_log (pp_log_norm, LLOG_FATAL, ap);
va_end (ap);
_exit (1);
}
#else
/* VARARGS2 */
static void adios (what, fmt)
char *what,
*fmt;
{
adios (what, fmt);
}
#endif
static SFD die(sig)
int sig;
{
io_end(NOTOK);
adios (NULLCP, "sendmail: dying from signal %d", sig);
}