a596cbb5adc589d9b093fbed104f2b733aae09de
* Copyright (c) 1983 Eric P. Allman
* Copyright (c) 1988 Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)envelope.c 6.10 (Berkeley) %G%";
** NEWENVELOPE -- allocate a new envelope
** e -- the new envelope to fill in.
register ENVELOPE
*parent
;
extern putheader(), putbody();
extern ENVELOPE BlankEnvelope
;
if (e
== CurEnv
&& e
->e_parent
!= NULL
)
bcopy((char *) &NullAddress
, (char *) &e
->e_from
, sizeof e
->e_from
);
bcopy((char *) &CurEnv
->e_from
, (char *) &e
->e_from
, sizeof e
->e_from
);
e
->e_msgpriority
= parent
->e_msgsize
;
if (CurEnv
->e_xfp
!= NULL
)
(void) fflush(CurEnv
->e_xfp
);
** DROPENVELOPE -- deallocate an envelope.
** e -- the envelope to deallocate.
** housekeeping necessary to dispose of an envelope.
** Unlocks this queue file.
printf("dropenvelope %x id=", e
);
printf(" flags=%o\n", e
->e_flags
);
syslog(LOG_DEBUG
, "dropenvelope, id=%s, flags=%o, pid=%d",
id
, e
->e_flags
, getpid());
/* we must have an id to remove disk files */
** Extract state information from dregs of send list.
for (q
= e
->e_sendqueue
; q
!= NULL
; q
= q
->q_next
)
if (bitset(QQUEUEUP
, q
->q_flags
))
** Send back return receipts as requested.
if (e
->e_receiptto
!= NULL
&& bitset(EF_SENDRECEIPT
, e
->e_flags
))
auto ADDRESS
*rlist
= NULL
;
(void) sendtolist(e
->e_receiptto
, (ADDRESS
*) NULL
, &rlist
, e
);
(void) returntosender("Return receipt", rlist
, FALSE
, e
);
** Arrange to send error messages if there are fatal errors.
if (bitset(EF_FATALERRS
|EF_TIMEOUT
, e
->e_flags
) && ErrorMode
!= EM_QUIET
)
** Instantiate or deinstantiate the queue.
if ((!queueit
&& !bitset(EF_KEEPQUEUE
, e
->e_flags
)) ||
bitset(EF_CLRQUEUE
, e
->e_flags
))
xunlink(queuename(e
, 'q'));
else if (queueit
|| !bitset(EF_INQUEUE
, e
->e_flags
))
queueup(e
, FALSE
, FALSE
);
syserr("dropenvelope: queueup");
/* make sure that this envelope is marked unused */
e
->e_id
= e
->e_df
= NULL
;
syslog(LOG_INFO
, "%s: done", id
);
** CLEARENVELOPE -- clear an envelope without unlocking
** This is normally used by a child process to get a clean
** envelope without disturbing the parent.
** e -- the envelope to clear.
** fullclear - if set, the current envelope is total
** garbage and should be ignored; otherwise,
** release any resources it may indicate.
** Closes files associated with the envelope.
** Marks the envelope as unallocated.
clearenvelope(e
, fullclear
)
extern ENVELOPE BlankEnvelope
;
/* clear out any file information */
/* now clear out the data */
STRUCTCOPY(BlankEnvelope
, *e
);
bh
= BlankEnvelope
.e_header
;
*nhp
= (HDR
*) xalloc(sizeof *bh
);
bcopy((char *) bh
, (char *) *nhp
, sizeof *bh
);
** INITSYS -- initialize instantiation of system
** In Daemon mode, this is done in the child.
** Initializes the system macros, some global variables,
** etc. In particular, the current time in various
static char cbuf
[5]; /* holds hop count */
static char pbuf
[10]; /* holds pid */
static char ybuf
[10]; /* holds tty id */
** Give this envelope a reality.
** I.e., an id, a transcript, and a creation time.
** Set OutChannel to something useful if stdout isn't it.
** This arranges that any extra stuff the mailer produces
** gets sent back to the user on error (because it is
** tucked away in the transcript).
if (OpMode
== MD_DAEMON
&& QueueRun
&& e
->e_xfp
!= NULL
)
** Set up some basic system macros.
(void) sprintf(pbuf
, "%d", getpid());
(void) sprintf(cbuf
, "%d", e
->e_hopcount
);
/* time as integer, unix time, arpa time */
if (macvalue('y', e
) == NULL
)
if (strrchr(p
, '/') != NULL
)
** SETTIME -- set the current time.
** Sets the various time macros -- $a, $b, $d, $t.
static char tbuf
[20]; /* holds "current" time */
static char dbuf
[30]; /* holds ctime(tbuf) */
extern struct tm
*gmtime();
(void) sprintf(tbuf
, "%04d%02d%02d%02d%02d", tm
->tm_year
+ 1900,
tm
->tm_mon
+1, tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
);
(void) strcpy(dbuf
, ctime(&now
));
*strchr(dbuf
, '\n') = '\0';
if (macvalue('d', e
) == NULL
)
p
= newstr(arpadate(dbuf
));
if (macvalue('a', e
) == NULL
)
** OPENXSCRIPT -- Open transcript file
** Creates a transcript file for possible eventual mailing or
** e -- the envelope to create the transcript in/for.
** Creates the transcript file.
fd
= open(p
, O_WRONLY
|O_CREAT
, 0644);
syserr("Can't create %s", p
);
e
->e_xfp
= fdopen(fd
, "w");
** CLOSEXSCRIPT -- close the transcript file.
** e -- the envelope containing the transcript to close.
** SETSENDER -- set the person who this message is from
** Under certain circumstances allow the user to say who
** s/he is (using -f or -r). These are:
** 1. The user's uid is zero (root).
** 2. The user's login name is in an approved list (typically
** from a network server).
** 3. The address the user is trying to claim has a
** "!" character in it (since #2 doesn't do it for
** us if we are dialing out for UUCP).
** A better check to replace #3 would be if the
** effective uid is "UUCP" -- this would require me
** to rewrite getpwent to "grab" uucp as it went by,
** make getname more nasty, do another passwd file
** scan, or compile the UID of "UUCP" into the code,
** all of which are reprehensible.
** Assuming all of these fail, we figure out something
** from -- the person we would like to believe this message
** is from, as specified on the command line.
** e -- the envelope in which we would like the sender set.
** sets sendmail's notion of who the from person is.
register struct passwd
*pw
;
extern struct passwd
*getpwnam();
printf("setsender(%s)\n", from
== NULL
? "" : from
);
** Figure out the real user executing us.
** Username can return errno != 0 on non-errors.
if (QueueRun
|| OpMode
== MD_SMTP
)
if (realname
== NULL
|| realname
[0] == '\0')
** Determine if this real person is allowed to alias themselves.
extern bool trusteduser();
if (!trusteduser(realname
) && getuid() != geteuid() &&
strchr(from
, '!') == NULL
&& getuid() != 0)
/* network sends -r regardless (why why why?) */
/* syserr("%s, you cannot use the -f flag", realname); */
if (from
== NULL
|| parseaddr(from
, &e
->e_from
, 1, '\0', e
) == NULL
)
/* log garbage addresses for traceback */
if (from
!= NULL
&& LogLevel
> 2)
char *host
= RealHostName
;
"from=%s unparseable, received from %s@%s",
parseaddr(from
= newstr(realname
), &e
->e_from
, 1, '\0', e
) == NULL
)
if (parseaddr("postmaster", &e
->e_from
, 1, '\0', e
) == NULL
)
syserr("setsender: can't even parse postmaster!");
e
->e_from
.q_flags
|= QDONTSEND
;
printf("setsender: QDONTSEND ");
printaddr(&e
->e_from
, FALSE
);
if (e
->e_from
.q_mailer
== LocalMailer
)
extern char *udbsender();
/* if the user has given fullname already, don't redefine */
FullName
= macvalue('x', e
);
if (FullName
!= NULL
&& FullName
[0] == '\0')
** We have an alternate address for the sender
pvp
= prescan(p
, '\0', pvpbuf
);
if ((pw
= getpwnam(e
->e_from
.q_user
)) != NULL
)
** Process passwd file entry.
/* extract home directory */
e
->e_from
.q_home
= newstr(pw
->pw_dir
);
define('z', e
->e_from
.q_home
, e
);
/* extract user and group id */
e
->e_from
.q_uid
= pw
->pw_uid
;
e
->e_from
.q_gid
= pw
->pw_gid
;
/* extract full name from passwd file */
if (FullName
== NULL
&& pw
->pw_gecos
!= NULL
&&
strcmp(pw
->pw_name
, e
->e_from
.q_user
) == 0)
buildfname(pw
->pw_gecos
, e
->e_from
.q_user
, buf
);
define('x', FullName
, e
);
if (e
->e_from
.q_home
== NULL
)
e
->e_from
.q_home
= getenv("HOME");
e
->e_from
.q_uid
= getuid();
e
->e_from
.q_gid
= getgid();
** Rewrite the from person to dispose of possible implicit
pvp
= prescan(from
, '\0', pvpbuf
);
syslog(LOG_NOTICE
, "cannot prescan from (%s)", from
);
usrerr("cannot prescan from (%s)", from
);
cataddr(pvp
, buf
, sizeof buf
, '\0');
e
->e_sender
= e
->e_returnpath
= newstr(buf
);
define('f', e
->e_sender
, e
);
/* save the domain spec if this mailer wants it */
if (e
->e_from
.q_mailer
!= NULL
&&
bitnset(M_CANONICAL
, e
->e_from
.q_mailer
->m_flags
))
extern char **copyplist();
while (*pvp
!= NULL
&& strcmp(*pvp
, "@") != 0)
e
->e_fromdomain
= copyplist(pvp
, TRUE
);
** TRUSTEDUSER -- tell us if this user is to be trusted.
** user -- the user to be checked.
** TRUE if the user is in an approved list.
extern char *TrustedUsers
[];
for (ulist
= TrustedUsers
; *ulist
!= NULL
; ulist
++)
if (strcmp(*ulist
, user
) == 0)