b584bc77ec0c800d2520684f869a6834c8ddc5a5
SCCSID(@
(#)envelope.c 3.1 %G%);
** NEWENVELOPE -- allocate a new envelope
** e -- the new envelope to fill in.
register ENVELOPE
*parent
;
extern putheader(), putbody();
extern ENVELOPE BlankEnvelope
;
clear((char *) e
, sizeof *e
);
bmove((char *) &CurEnv
->e_from
, (char *) &e
->e_from
, sizeof e
->e_from
);
bh
= BlankEnvelope
.e_header
;
*nhp
= (HDR
*) xalloc(sizeof *bh
);
bmove((char *) bh
, (char *) *nhp
, sizeof *bh
);
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",
e
->e_id
== NULL
? "(none)" : e
->e_id
,
/* 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
))
sendto(CurEnv
->e_receiptto
, (ADDRESS
*) NULL
, &rlist
);
(void) returntosender("Return receipt", rlist
, FALSE
);
** See if this message has timed out
if (bitset(EF_TIMEOUT
, e
->e_flags
) && queueit
)
** Arrange to send error messages if there are fatal errors.
if (bitset(EF_FATALERRS
, e
->e_flags
))
** 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
);
/* make sure that this envelope is marked unused */
e
->e_id
= e
->e_df
= NULL
;
e
->e_dfp
= e
->e_xfp
= NULL
;
** 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.
** Closes files associated with the envelope.
** Marks the envelope as unallocated.
/* clear out any file information */
e
->e_xfp
= e
->e_dfp
= NULL
;
/* now expunge names of objects */
e
->e_df
= e
->e_id
= NULL
;
/* and the flags which are now meaningless */
** UNLOCKQUEUE -- unlock the queue entry for a specified envelope
** e -- the envelope to unlock.
** unlocks the queue for `e'.
/* remove the transcript */
xunlink(queuename(e
, 'x'));
/* last but not least, remove the lock */
xunlink(queuename(e
, 'l'));
** 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 dbuf
[30]; /* holds ctime(tbuf) */
static char pbuf
[10]; /* holds pid */
static char tbuf
[20]; /* holds "current" time */
static char ybuf
[10]; /* holds tty id */
extern struct tm
*gmtime();
** Give this envelope a reality.
** I.e., an id, a transcript, and a creation time.
CurEnv
->e_ctime
= curtime();
** 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
)
OutChannel
= CurEnv
->e_xfp
;
** Set up some basic system macros.
(void) sprintf(pbuf
, "%d", getpid());
define('p', pbuf
, CurEnv
);
(void) sprintf(cbuf
, "%d", CurEnv
->e_hopcount
);
define('c', cbuf
, CurEnv
);
/* time as integer, unix time, arpa time */
(void) sprintf(tbuf
, "%02d%02d%02d%02d%02d", tm
->tm_year
, tm
->tm_mon
,
tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
);
define('t', tbuf
, CurEnv
);
(void) strcpy(dbuf
, ctime(&now
));
*index(dbuf
, '\n') = '\0';
if (macvalue('d', CurEnv
) == NULL
)
define('d', dbuf
, CurEnv
);
p
= newstr(arpadate(dbuf
));
if (macvalue('a', CurEnv
) == NULL
)
define('v', Version
, CurEnv
);
if (macvalue('y', CurEnv
) == NULL
)
if (rindex(p
, '/') != NULL
)
define('y', ybuf
, CurEnv
);
** QUEUENAME -- build a file name in the queue directory for this envelope.
** Assigns an id code if one does not already exist.
** This code is very careful to avoid trashing existing files
** under any circumstances.
** We first create an nf file that is only used when
** assigning an id. This file is always empty, so that
** we can never accidently truncate an lf file.
** e -- envelope to build it in/from.
** type -- the file type, used as the first character
** a pointer to the new file name (in a static buffer).
** Will create the lf and qf files if no id code is
** already assigned. This will cause the envelope
static char buf
[MAXNAME
];
/* new process -- start back at "AA" */
(void) sprintf(qf
, "qfAA%05d", pid
);
while (c1
< '~' || c2
< 'Z')
qf
[2] = lf
[2] = nf
[2] = c1
;
qf
[3] = lf
[3] = nf
[3] = ++c2
;
printf("queuename: trying \"%s\"\n", nf
);
if (access(lf
, 0) >= 0 || access(qf
, 0) >= 0)
(void) unlink(nf
); /* kernel bug */
if (c1
>= '~' && c2
>= 'Z')
syserr("queuename: Cannot create \"%s\" in \"%s\"",
e
->e_id
= newstr(&qf
[2]);
printf("queuename: assigned id %s, env=%x\n", e
->e_id
, e
);
(void) sprintf(buf
, "%cf%s", type
, e
->e_id
);
printf("queuename: %s\n", buf
);
** 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.
e
->e_xfp
= fopen(p
, "w");
syserr("Can't create %s", p
);
** 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.
** sets sendmail's notion of who the from person is.
register struct passwd
*pw
= NULL
;
printf("setsender(%s)\n", from
);
** Figure out the real user executing us.
** Username can return errno != 0 on non-errors.
if (QueueRun
|| OpMode
== MD_SMTP
|| OpMode
== MD_ARPAFTP
)
if (realname
== NULL
|| realname
[0] == '\0')
if (realname
== NULL
|| realname
[0] == '\0')
extern struct passwd
*getpwuid();
pw
= getpwuid(getruid());
if (realname
== NULL
|| realname
[0] == '\0')
** Determine if this real person is allowed to alias themselves.
extern bool trusteduser();
if (!trusteduser(realname
) &&
(!tTd(1, 9) || getuid() != geteuid()) &&
index(from
, '!') == NULL
&& getuid() != 0)
/* network sends -r regardless (why why why?) */
/* syserr("%s, you cannot use the -f flag", realname); */
if (from
== NULL
|| parse(from
, &CurEnv
->e_from
, 1) == NULL
)
(void) parse(from
, &CurEnv
->e_from
, 1);
CurEnv
->e_from
.q_flags
|= QDONTSEND
;
if (pw
== NULL
&& CurEnv
->e_from
.q_mailer
== LocalMailer
)
extern struct passwd
*getpwnam();
pw
= getpwnam(CurEnv
->e_from
.q_user
);
** Process passwd file entry.
/* extract home directory */
CurEnv
->e_from
.q_home
= newstr(pw
->pw_dir
);
/* run user's .mailcf file */
define('z', CurEnv
->e_from
.q_home
, CurEnv
);
expand("$z/.mailcf", buf
, &buf
[sizeof buf
- 1], CurEnv
);
if (safefile(buf
, getruid(), S_IREAD
))
/* if the user has given fullname already, don't redefine */
FullName
= macvalue('x', CurEnv
);
/* extract full name from passwd file */
if (FullName
== NULL
&& pw
->pw_gecos
!= NULL
)
buildfname(pw
->pw_gecos
, CurEnv
->e_from
.q_user
, buf
);
define('x', FullName
, CurEnv
);
if (CurEnv
->e_from
.q_home
== NULL
)
CurEnv
->e_from
.q_home
= getenv("HOME");
CurEnv
->e_from
.q_uid
= getuid();
CurEnv
->e_from
.q_gid
= getgid();
if (CurEnv
->e_from
.q_uid
!= 0)
DefUid
= CurEnv
->e_from
.q_uid
;
DefGid
= CurEnv
->e_from
.q_gid
;
** Rewrite the from person to dispose of possible implicit
pvp
= prescan(from
, '\0');
syserr("cannot prescan from (%s)", from
);
cataddr(pvp
, buf
, sizeof buf
);
define('f', newstr(buf
), CurEnv
);
/* save the domain spec if this mailer wants it */
if (bitset(M_CANONICAL
, CurEnv
->e_from
.q_mailer
->m_flags
))
extern char **copyplist();
while (*pvp
!= NULL
&& strcmp(*pvp
, "@") != 0)
CurEnv
->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)