Fix conflicts from merge of sendmail 8.11.0.

PR:		bin/11552 misc/18512 bin/15088
This commit is contained in:
Gregory Neil Shapiro 2000-08-12 22:19:16 +00:00
parent e8c96e01af
commit 3299c2f123
21 changed files with 6716 additions and 4521 deletions

View File

@ -1,5 +1,6 @@
#
# Copyright (c) 1998 Sendmail, Inc. All rights reserved.
# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
# All rights reserved.
# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved.
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
@ -8,6 +9,7 @@
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
# $FreeBSD$
#
######################################################################
@ -15,10 +17,11 @@
#####
##### SENDMAIL CONFIGURATION FILE
#####
define(`TEMPFILE', maketemp(/tmp/cfXXXXXX))dnl
ifdef(`unix', `dnl
ifdef(`TEMPFILE', `dnl', `define(`TEMPFILE', maketemp(/tmp/cfXXXXXX))dnl
syscmd(sh _CF_DIR_`'sh/makeinfo.sh _CF_DIR_ > TEMPFILE)dnl
include(TEMPFILE)dnl
syscmd(rm -f TEMPFILE)dnl
syscmd(rm -f TEMPFILE)dnl')', `dnl')
#####
######################################################################
######################################################################
@ -36,16 +39,85 @@ define(`PUSHDIVERT', `pushdef(`__D__', divnum)divert($1)')
define(`POPDIVERT', `divert(__D__)popdef(`__D__')')
define(`OSTYPE',
`PUSHDIVERT(-1)
ifdef(`__OSTYPE__', `errprint(`duplicate OSTYPE'($1))')
ifdef(`__OSTYPE__', `errprint(`duplicate OSTYPE'($1)
)')
define(`__OSTYPE__', $1)
define(`_ARG_', $2)
include(_CF_DIR_`'ostype/$1.m4)POPDIVERT`'')
## helpful functions
define(`lower', `translit(`$1', `ABCDEFGHIJKLMNOPQRSTUVWXYZ', `abcdefghijklmnopqrstuvwx')')
define(`strcasecmp', `ifelse(lower($1), lower($2), `1', `0')')
## new FEATUREs
define(`_DNSBL_R_',`')
## access to further arguments in FEATURE/HACK
define(`_ACC_ARG_1_',`$1')
define(`_ACC_ARG_2_',`$2')
define(`_ACC_ARG_3_',`$3')
define(`_ACC_ARG_4_',`$4')
define(`_ACC_ARG_5_',`$5')
define(`_ACC_ARG_6_',`$6')
define(`_ACC_ARG_7_',`$7')
define(`_ACC_ARG_8_',`$8')
define(`_ACC_ARG_9_',`$9')
define(`_ARG1_',`_ACC_ARG_1_(_ARGS_)')
define(`_ARG2_',`_ACC_ARG_2_(_ARGS_)')
define(`_ARG3_',`_ACC_ARG_3_(_ARGS_)')
define(`_ARG4_',`_ACC_ARG_4_(_ARGS_)')
define(`_ARG5_',`_ACC_ARG_5_(_ARGS_)')
define(`_ARG6_',`_ACC_ARG_6_(_ARGS_)')
define(`_ARG7_',`_ACC_ARG_7_(_ARGS_)')
define(`_ARG8_',`_ACC_ARG_8_(_ARGS_)')
define(`_ARG9_',`_ACC_ARG_9_(_ARGS_)')
dnl define if not yet defined: if `$1' is not defined it will be `$2'
define(`_DEFIFNOT',`ifdef(`$1',`',`define(`$1',`$2')')')
dnl ----------------------------------------
dnl add a char $2 to a string $1 if it is not there
define(`_ADDCHAR_',`define(`_I_',`eval(index(`$1',`$2') >= 0)')`'ifelse(_I_,`1',`$1',`$1$2')')
dnl ----
dnl delete a char $2 from a string $1 if it is there
define(`_DELCHAR_',`define(`_IDX_',`index(`$1',`$2')')`'define(`_I_',`eval(_IDX_ >= 0)')`'ifelse(_I_,`1',`substr(`$1',0,_IDX_)`'substr(`$1',eval(_IDX_+1))',`$1')')
dnl ----
dnl apply a macro to a whole string by recursion (one char at a time)
dnl $1: macro
dnl $2: first argument to macro
dnl $3: list that is split up into characters
define(`_AP_',`ifelse(`$3',`',`$2',`_AP_(`$1',$1(`$2',substr(`$3',0,1)),substr(`$3',1))')')
dnl ----
dnl MODIFY_MAILER_FLAGS: append tail of $2 to $1_MF_A/D_
dnl A if head($2) = +
dnl D if head($2) = -
dnl $1_MF_ is set otherwise; set _A/D_ to `'
define(`MODIFY_MAILER_FLAGS',`define(`_hd_',`substr(`$2',0,1)')define(`_tl_',`substr(`$2',1)')`'ifelse(_hd_,`+',`ifdef($1`'_MF_A_, `define($1`'_MF_A_,$1_MF_A_`'_tl_)', `define($1`'_MF_A_, _tl_)')',_hd_,`-',`ifdef($1`'_MF_D_, `define($1`'_MF_D_,$1_MF_D_`'_tl_)', `define($1`'_MF_D_,_tl_)')',`define($1`'_MF_,`$2')define($1`'_MF_A_,`')define($1`'_MF_D_,`')')')
dnl ----
dnl actually modify flags:
dnl $1: flags (strings) to modify
dnl $2: name of flags (just first part) to modify
dnl WARNING: the order might be important: if someone adds and delete the
dnl same characters, he does not deserve any better, does he?
dnl this could be coded more efficiently... (do not apply the macro if _MF_A/D_ is undefined)
define(`_MODMF_',`ifdef($2`'_MF_,`$2_MF_',`_AP_(`_ADDCHAR_',_AP_(`_DELCHAR_',$1,ifdef($2`'_MF_D_,`$2_MF_D_',`')),ifdef($2`'_MF_A_,`$2_MF_A_',`'))')')
dnl usage:
dnl MODIFY_MAILER_FLAGS(`LOCAL',`+FlaGs')dnl
dnl in MAILER.m4: _MODMF_(LMF,`LOCAL')
dnl ----------------------------------------
define(`MAILER',
`ifdef(`_MAILER_$1_', `dnl`'',
`define(`_MAILER_$1_', `')PUSHDIVERT(7)include(_CF_DIR_`'mailer/$1.m4)POPDIVERT`'')')
define(`DOMAIN', `PUSHDIVERT(-1)define(`_ARG_', $2)include(_CF_DIR_`'domain/$1.m4)POPDIVERT`'')
define(`FEATURE', `PUSHDIVERT(-1)define(`_ARG_', $2)include(_CF_DIR_`'feature/$1.m4)POPDIVERT`'')
define(`HACK', `PUSHDIVERT(-1)define(`_ARG_', $2)include(_CF_DIR_`'hack/$1.m4)POPDIVERT`'')
`define(`_M_N_', `ifelse(`$2', `', `$1', `$2')')dnl
ifdef(_MAILER_`'_M_N_`'_, `dnl`'',
`define(_MAILER_`'_M_N_`'_, `')define(`_ARG_', `$2')define(`_ARGS_', `shift($@)')PUSHDIVERT(7)include(_CF_DIR_`'mailer/$1.m4)POPDIVERT`'')')
define(`DOMAIN', `PUSHDIVERT(-1)define(`_ARG_', `$2')include(_CF_DIR_`'domain/$1.m4)POPDIVERT`'')
define(`FEATURE', `PUSHDIVERT(-1)define(`_ARG_', `$2')define(`_ARGS_', `shift($@)')include(_CF_DIR_`'feature/$1.m4)POPDIVERT`'')
define(`HACK', `PUSHDIVERT(-1)define(`_ARG_', `$2')define(`_ARGS_', `shift($@)')include(_CF_DIR_`'hack/$1.m4)POPDIVERT`'')
define(`_DPO_',`')
define(`DAEMON_OPTIONS', `define(`_DPO_', defn(`_DPO_')
O DaemonPortOptions=`$1')')
define(`_MAIL_FILTERS_', `')
define(`MAIL_FILTER', `define(`_MAIL_FILTERS_', defn(`_MAIL_FILTERS_')
X`'$1`, '`$2')')
define(`INPUT_MAIL_FILTER', `MAIL_FILTER(`$1', `$2')
ifelse(defn(`confINPUT_MAIL_FILTERS')X, `X',
`define(`confINPUT_MAIL_FILTERS', $1)',
`define(`confINPUT_MAIL_FILTERS', defn(`confINPUT_MAIL_FILTERS')`, '`$1')')')
define(`CF_LEVEL', `9')dnl
define(`VERSIONID', ``##### $1 #####'')
define(`LOCAL_RULE_0', `divert(3)')
define(`LOCAL_RULE_1',
@ -54,7 +126,7 @@ define(`LOCAL_RULE_1',
### Ruleset 1 -- Sender Rewriting ###
#######################################
S1
Ssender=1
')
define(`LOCAL_RULE_2',
`divert(9)dnl
@ -62,7 +134,7 @@ define(`LOCAL_RULE_2',
### Ruleset 2 -- Recipient Rewriting ###
##########################################
S2
Srecipient=2
')
define(`LOCAL_RULESETS',
`divert(9)
@ -90,31 +162,66 @@ POPDIVERT`'dnl`'')
define(`MASQUERADE_AS', `define(`MASQUERADE_NAME', $1)')
define(`MASQUERADE_DOMAIN', `PUSHDIVERT(5)CM$1
POPDIVERT`'dnl`'')
define(`MASQUERADE_EXCEPTION', `PUSHDIVERT(5)CN$1
POPDIVERT`'dnl`'')
define(`MASQUERADE_DOMAIN_FILE', `PUSHDIVERT(5)FM$1
POPDIVERT`'dnl`'')
define(`LOCAL_DOMAIN', `PUSHDIVERT(5)Cw$1
POPDIVERT`'dnl`'')
define(`CANONIFY_DOMAIN', `PUSHDIVERT(5)C{Canonify}$1
POPDIVERT`'dnl`'')
define(`CANONIFY_DOMAIN_FILE', `PUSHDIVERT(5)F{Canonify}$1
POPDIVERT`'dnl`'')
define(`GENERICS_DOMAIN', `PUSHDIVERT(5)CG$1
POPDIVERT`'dnl`'')
define(`GENERICS_DOMAIN_FILE', `PUSHDIVERT(5)FG$1
POPDIVERT`'dnl`'')
define(`LDAPROUTE_DOMAIN', `PUSHDIVERT(5)C{LDAPRoute}$1
POPDIVERT`'dnl`'')
define(`LDAPROUTE_DOMAIN_FILE', `PUSHDIVERT(5)F{LDAPRoute}$1
POPDIVERT`'dnl`'')
define(`VIRTUSER_DOMAIN', `PUSHDIVERT(5)C{VirtHost}$1
define(`_VIRTHOSTS_')
POPDIVERT`'dnl`'')
define(`VIRTUSER_DOMAIN_FILE', `PUSHDIVERT(5)F{VirtHost}$1
define(`_VIRTHOSTS_')
POPDIVERT`'dnl`'')
define(`RELAY_DOMAIN', `PUSHDIVERT(5)CR$1
POPDIVERT`'dnl`'')
define(`RELAY_DOMAIN_FILE', `PUSHDIVERT(5)FR$1
POPDIVERT`'dnl`'')
define(`TRUST_AUTH_MECH', `PUSHDIVERT(5)C{TrustAuthMech}$1
POPDIVERT`'dnl`'')
define(`_OPTINS', `ifdef(`$1', `$2$1$3')')
m4wrap(`include(_CF_DIR_`m4/proto.m4')')
# default location for files
ifdef(`MAIL_SETTINGS_DIR', , `define(`MAIL_SETTINGS_DIR', `/etc/mail/')')
# set our default hashed database type
define(`DATABASE_MAP_TYPE', `hash')
# set up default values for options
define(`ALIAS_FILE', ifdef(`_USE_ETC_MAIL_', `/etc/mail/aliases', `/etc/aliases'))
define(`ALIAS_FILE', `MAIL_SETTINGS_DIR`'aliases')
define(`confMAILER_NAME', ``MAILER-DAEMON'')
define(`confFROM_LINE', `From $g $d')
define(`confFROM_LINE', `From $g $d')
define(`confOPERATORS', `.:%@!^/[]+')
define(`confSMTP_LOGIN_MSG', `$j Sendmail $v/$Z; $b')
define(`confRECEIVED_HEADER', `$?sfrom $s $.$?_($?s$|from $.$_)
$.by $j ($v/$Z)$?r with $r$. id $i$?u
for $u; $|;
$.$b$?g
(envelope-from $g)$.')')
define(`_REC_AUTH_', `$.$?{auth_type}(authenticated')
define(`_REC_FULL_AUTH_', `$.$?{auth_type}(authenticated as ${auth_authen} $?{auth_author}for ${auth_author} $.with ${auth_type}')
define(`_REC_HDR_', `$?sfrom $s $.$?_($?s$|from $.$_)')
define(`_REC_END_', `for $u; $|;
$.$b?g
(envelope-from $g)$.')
define(`_REC_TLS_', `(using ${tls_version} with cipher ${cipher} (${cipher_bits} bits) verified ${verify})$.$?u')
define(`_REC_BY_', `$.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version}')
define(`confRECEIVED_HEADER', `_REC_HDR_
_REC_AUTH_$?{auth_ssf} (${auth_ssf} bits)$.)
_REC_BY_
_REC_TLS_
_REC_END_')
define(`confSEVEN_BIT_INPUT', `False')
define(`confEIGHT_BIT_HANDLING', `pass8')
define(`confALIAS_WAIT', `10')
@ -134,10 +241,15 @@ define(`confSAFE_QUEUE', `True')
define(`confTO_QUEUERETURN', `5d')
define(`confTO_QUEUEWARN', `4h')
define(`confTIME_ZONE', `USE_SYSTEM')
define(`confCW_FILE', ifdef(`_USE_ETC_MAIL_', `/etc/mail/local-host-names', `/etc/sendmail.cw'))
define(`confCW_FILE', `MAIL_SETTINGS_DIR`'local-host-names')
define(`confMIME_FORMAT_ERRORS', `True')
define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward')
define(`confCR_FILE', `-o /etc/mail/relay-domains')
define(`confCR_FILE', `-o MAIL_SETTINGS_DIR`'relay-domains')
define(`confMILTER_MACROS_CONNECT', ``j, _, {daemon_name}, {if_name}, {if_addr}'')
define(`confMILTER_MACROS_HELO', ``{tls_version}, {cipher}, {cipher_bits}, {cert_subject}, {cert_issuer}'')
define(`confMILTER_MACROS_ENVFROM', ``i, {auth_type}, {auth_authen}, {auth_ssf}, {auth_author}, {mail_mailer}, {mail_host}, {mail_addr}'')
define(`confMILTER_MACROS_ENVRCPT', ``{rcpt_mailer}, {rcpt_host}, {rcpt_addr}'')
divert(0)dnl
VERSIONID(`@(#)cfhead.m4 8.23 (Berkeley) 10/6/1998')
VERSIONID(`$Id: cfhead.m4,v 8.76.4.9 2000/07/11 23:50:30 geir Exp $')

View File

@ -1,6 +1,7 @@
divert(-1)
#
# Copyright (c) 1998 Sendmail, Inc. All rights reserved.
# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
# All rights reserved.
# Copyright (c) 1983 Eric P. Allman. All rights reserved.
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
@ -9,13 +10,12 @@ divert(-1)
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#
# $FreeBSD$
#
divert(0)
VERSIONID(`@(#)bsd4.4.m4 8.10 (Berkeley) 10/6/1998')
ifdef(`HELP_FILE',, `define(`HELP_FILE', ifdef(`_USE_ETC_MAIL_', `/etc/mail/helpfile', `/usr/share/misc/sendmail.hf'))')dnl
ifdef(`STATUS_FILE',, `define(`STATUS_FILE', ifdef(`_USE_ETC_MAIL_', `/etc/mail/statistics', `/var/log/sendmail.st'))')dnl
VERSIONID(`$Id: bsd4.4.m4,v 8.14 1999/04/24 05:37:40 gshapiro Exp $')
ifdef(`STATUS_FILE',, `define(`STATUS_FILE', `/var/log/sendmail.st')')dnl
ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /usr/libexec/mail.local)')dnl
ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail $u')')dnl
ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -z -a$g $h!rmail ($u)')')dnl

View File

@ -1,6 +1,7 @@
#!/bin/sh
#
# Copyright (c) 1998 Sendmail, Inc. All rights reserved.
# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
# All rights reserved.
# Copyright (c) 1983 Eric P. Allman. All rights reserved.
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
@ -10,7 +11,9 @@
# the sendmail distribution.
#
#
# @(#)makeinfo.sh 8.11 (Berkeley) 5/19/1998
# $Id: makeinfo.sh,v 8.14 1999/02/07 07:26:25 gshapiro Exp $
#
# $FreeBSD$
#
usewhoami=0

View File

@ -9,15 +9,17 @@
* Change directory to "netinfo" and get the file internet.listing
* The file is updated monthly.
*
* Feed the output of this program to "makemap hash /etc/bitdomain.db"
* Feed the output of this program to "makemap hash /etc/mail/bitdomain.db"
* to create the table used by the "FEATURE(bitdomain)" config file macro.
* If your sendmail does not have the db library compiled in, you can instead
* use "makemap dbm /etc/bitdomain" and
* "FEATURE(bitdomain,`dbm -o /etc/bitdomain')"
* use "makemap dbm /etc/mail/bitdomain" and
* "FEATURE(bitdomain,`dbm -o /etc/mail/bitdomain')"
*
* The bitdomain table should be rebuilt monthly.
*/
/* $FreeBSD$ */
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
@ -187,7 +189,7 @@ char *domainlen;
case NO_DATA:
err = "registered in DNS, but not mailable";
break;
default:
err = "unknown nameserver error";
break;
@ -210,7 +212,7 @@ valhost(host, hbsize)
int hbsize;
{
register u_char *eom, *ap;
register int n;
register int n;
HEADER *hp;
querybuf answer;
int ancount, qdcount;
@ -406,4 +408,4 @@ finish()
}
}
}

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 1998 Sendmail, Inc. All rights reserved.
.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
.\" All rights reserved.
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@ -7,46 +8,60 @@
.\" the sendmail distribution.
.\"
.\"
.\" @(#)mail.local.8 8.7 (Berkeley) 5/19/1998
.\" $Id: mail.local.8,v 8.14 1999/08/26 15:49:20 ca Exp $
.\"
.Dd May 19, 1998
.Dt MAIL.LOCAL 8
.Os
.Sh NAME
.Nm mail.local
.Nd store mail in a mailbox
.Sh SYNOPSIS
.Nm mail.local
.Op Fl f Ar from
.Op Fl b
.Op Fl s
.Ar user ...
.Sh DESCRIPTION
.Nm Mail.local
.\" $FreeBSD$
.\"
.TH MAIL.LOCAL 8 "$Date: 1999/08/26 15:49:20 $"
.SH NAME
.B mail.local
\- store mail in a mailbox
.SH SYNOPSIS
.B mail.local
.RB [ \-7 "] [" \-B "] [" \-d "] [" \-l "] [" \-s "] [" \-f
.IR from "] " "user ..."
.SH DESCRIPTION
.B Mail.local
reads the standard input up to an end-of-file and appends it to each
.Ar user's
.Pa mail
file.
The
.Ar user
.I user's
.B mail
file. The
.I user
must be a valid user name.
.Pp
.PP
The options are as follows:
.Bl -tag -width xxxfrom
.It Fl f Ar from
Specify the sender's name.
.It Fl b
.TP 1i
.B \-7
Do not advertise 8BITMIME support in LMTP mode.
.TP
.B \-B
Turn off the attempts to notify the
.Dq biff
service.
.It Fl s
.TP
.B \-b
Return a permanent error instead of a temporary error
if a mailbox exceeds quota.
.TP
.B \-d
Specify this is a delivery (for backward compatibility).
.TP
.BI \-f " from"
Specify the sender's name.
.TP
.B \-l
Turn on LMTP mode.
.TP
.B \-s
Turn off the
.Xr fsync 2
call that forces the mailbox to be committed to disk before returning a
.Dq success
status.
.El
.Pp
.TP
.BI \-r " from"
Specify the sender's name (for backward compatibility).
.PP
Individual mail messages in the mailbox are delimited by an empty
line followed by a line beginning with the string ``From ''.
A line containing the string ``From '', the sender's name and a time stamp
@ -57,47 +72,48 @@ which could be mistaken for a ``From '' delimiter line
(that is,
a line beginning with the five characters
``From '' following a blank line).
.Pp
.PP
The mail files are exclusively locked with
.Xr flock 2
while mail is appended,
flock(2)
while mail is appended,
and a
.Pa user.lock
file also is created while the mailbox is locked
.B user.lock
file also is created while the mailbox is locked
for compatibility with older MUAs.
.Pp
If the ``biff'' service is returned by
.Xr getservbyname 3 ,
.PP
If the ``biff'' service is returned by
getservbyname(3),
the biff server is notified of delivered mail.
.Pp
.PP
The
.Nm mail.local
.B mail.local
utility exits 0 on success, and >0 if an error occurs.
.Sh ENVIRONMENT
.Bl -tag -width indent
.It Ev TZ
.SH ENVIRONMENT
.IP TZ
Used to set the appropriate time zone on the timestamp.
.El
.Sh FILES
.Bl -tag -width /tmp/local.XXXXXX -compact
.It Pa /tmp/local.XXXXXX
.SH FILES
.PD 0.2v
.TP 2.2i
/tmp/local.XXXXXX
temporary files
.It Pa /var/mail/user
.TP
/var/mail/user
user's mailbox directory
.It Pa /var/mail/user.lock
.TP
/var/mail/user.lock
lock file for a user's mailbox
.El
.Sh SEE ALSO
.Xr mail 1 ,
.Xr flock 2 ,
.Xr getservbyname 3 ,
.Xr comsat 8 ,
.Xr sendmail 8
.Sh HISTORY
.PD
.SH SEE ALSO
mail(1),
flock(2),
getservbyname(3),
comsat(8),
sendmail(8)
.SH HISTORY
A superset of
.Nm mail.local
.B mail.local
(handling mailbox reading as well as mail delivery)
appeared in
.At v7 .
appeared in
Version 7 AT&T UNIX
as the program
.Nm mail .
.BR mail .

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
@ -13,33 +14,45 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1988, 1993\n\
"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\
All rights reserved.\n\
Copyright (c) 1988, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#endif /* ! lint */
#ifndef lint
static char sccsid[] = "@(#)mailstats.c 8.29 (Berkeley) 1/25/1999";
#endif /* not lint */
static char id[] = "@(#)$Id: mailstats.c,v 8.53.16.10 2000/07/18 05:51:15 gshapiro Exp $";
#endif /* ! lint */
/* $FreeBSD$ */
#include <unistd.h>
#include <stddef.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#ifdef EX_OK
# undef EX_OK /* unistd.h may have another use for this */
#endif /* EX_OK */
#include <sysexits.h>
#include <sendmail/sendmail.h>
#include <sendmail/mailstats.h>
#include <sendmail/pathnames.h>
#ifndef NOT_SENDMAIL
# define NOT_SENDMAIL
#endif
#include <sendmail.h>
#include <mailstats.h>
#include <pathnames.h>
#define MNAMELEN 20 /* max length of mailer name */
int
main(argc, argv)
int argc;
char **argv;
{
extern char *optarg;
extern int optind;
struct statistics stat;
register int i;
int mno;
int save_errno;
int ch, fd;
char *sfile;
char *cfile;
@ -48,11 +61,15 @@ main(argc, argv)
bool progmode;
long frmsgs = 0, frbytes = 0, tomsgs = 0, tobytes = 0, rejmsgs = 0;
long dismsgs = 0;
char mtable[MAXMAILERS][MNAMELEN+1];
time_t now;
char mtable[MAXMAILERS][MNAMELEN + 1];
char sfilebuf[MAXLINE];
char buf[MAXLINE];
time_t now;
struct statistics stats;
extern char *ctime();
extern char *optarg;
extern int optind;
cfile = _PATH_SENDMAILCF;
sfile = NULL;
@ -74,22 +91,15 @@ main(argc, argv)
mnames = FALSE;
break;
#if _FFR_MAILSTATS_PROGMODE
case 'p':
progmode = TRUE;
break;
#endif
case '?':
default:
usage:
#if _FFR_MAILSTATS_PROGMODE
fputs("usage: mailstats [-o] [-C cffile] [-f stfile] -o -p\n",
stderr);
#else
fputs("usage: mailstats [-o] [-C cffile] [-f stfile] -o \n",
stderr);
#endif
(void) fputs("usage: mailstats [-C cffile] [-f stfile] [-o] [-p]\n",
stderr);
exit(EX_USAGE);
}
}
@ -101,15 +111,17 @@ main(argc, argv)
if ((cfp = fopen(cfile, "r")) == NULL)
{
save_errno = errno;
fprintf(stderr, "mailstats: ");
errno = save_errno;
perror(cfile);
exit(EX_NOINPUT);
}
mno = 0;
(void) strcpy(mtable[mno++], "prog");
(void) strcpy(mtable[mno++], "*file*");
(void) strcpy(mtable[mno++], "*include*");
(void) strlcpy(mtable[mno++], "prog", MNAMELEN + 1);
(void) strlcpy(mtable[mno++], "*file*", MNAMELEN + 1);
(void) strlcpy(mtable[mno++], "*include*", MNAMELEN + 1);
while (fgets(buf, sizeof(buf), cfp) != NULL)
{
@ -141,14 +153,14 @@ main(argc, argv)
}
/* this is the S or StatusFile option -- save it */
if (strlen(b) >= sizeof sfilebuf)
if (strlcpy(sfilebuf, b, sizeof sfilebuf) >=
sizeof sfilebuf)
{
fprintf(stderr,
"StatusFile filename too long: %.30s...\n",
b);
exit(EX_CONFIG);
}
strcpy(sfilebuf, b);
b = strchr(sfilebuf, '#');
if (b == NULL)
b = strchr(sfilebuf, '\n');
@ -172,7 +184,7 @@ main(argc, argv)
exit(EX_SOFTWARE);
}
m = mtable[mno];
s = m + MNAMELEN; /* is [MNAMELEN+1] */
s = m + MNAMELEN; /* is [MNAMELEN + 1] */
while (*b != ',' && !(isascii(*b) && isspace(*b)) &&
*b != '\0' && m < s)
*m++ = *b++;
@ -195,66 +207,70 @@ main(argc, argv)
exit (EX_OSFILE);
}
if ((fd = open(sfile, O_RDONLY)) < 0 ||
(i = read(fd, &stat, sizeof stat)) < 0)
fd = open(sfile, O_RDONLY);
if ((fd < 0) || (i = read(fd, &stats, sizeof stats)) < 0)
{
fputs("mailstats: ", stderr);
save_errno = errno;
(void) fputs("mailstats: ", stderr);
errno = save_errno;
perror(sfile);
exit(EX_NOINPUT);
}
if (i == 0)
{
sleep(1);
if ((i = read(fd, &stat, sizeof stat)) < 0)
(void) sleep(1);
if ((i = read(fd, &stats, sizeof stats)) < 0)
{
fputs("mailstats: ", stderr);
save_errno = errno;
(void) fputs("mailstats: ", stderr);
errno = save_errno;
perror(sfile);
exit(EX_NOINPUT);
}
else if (i == 0)
{
bzero((ARBPTR_T) &stat, sizeof stat);
(void) time(&stat.stat_itime);
memset((ARBPTR_T) &stats, '\0', sizeof stats);
(void) time(&stats.stat_itime);
}
}
if (i != 0)
{
if (stat.stat_magic != STAT_MAGIC)
if (stats.stat_magic != STAT_MAGIC)
{
fprintf(stderr,
"mailstats: incorrect magic number in %s\n",
sfile);
exit(EX_OSERR);
}
else if (stat.stat_version != STAT_VERSION)
else if (stats.stat_version != STAT_VERSION)
{
fprintf(stderr,
"mailstats version (%d) incompatible with %s version(%d)\n",
STAT_VERSION, sfile, stat.stat_version);
"mailstats version (%d) incompatible with %s version (%d)\n",
STAT_VERSION, sfile, stats.stat_version);
exit(EX_OSERR);
}
else if (i != sizeof stat || stat.stat_size != sizeof(stat))
else if (i != sizeof stats || stats.stat_size != sizeof(stats))
{
fputs("mailstats: file size changed.\n", stderr);
(void) fputs("mailstats: file size changed.\n", stderr);
exit(EX_OSERR);
}
}
if (progmode)
{
time(&now);
printf("%ld %ld\n", (long) stat.stat_itime, (long) now);
(void) time(&now);
printf("%ld %ld\n", (long) stats.stat_itime, (long) now);
}
else
{
printf("Statistics from %s", ctime(&stat.stat_itime));
printf("Statistics from %s", ctime(&stats.stat_itime));
printf(" M msgsfr bytes_from msgsto bytes_to msgsrej msgsdis%s\n",
mnames ? " Mailer" : "");
}
for (i = 0; i < MAXMAILERS; i++)
{
if (stat.stat_nf[i] || stat.stat_nt[i] ||
stat.stat_nr[i] || stat.stat_nd[i])
if (stats.stat_nf[i] || stats.stat_nt[i] ||
stats.stat_nr[i] || stats.stat_nd[i])
{
char *format;
@ -263,34 +279,40 @@ main(argc, argv)
else
format = "%2d %8ld %10ldK %8ld %10ldK %6ld %6ld";
printf(format, i,
stat.stat_nf[i], stat.stat_bf[i],
stat.stat_nt[i], stat.stat_bt[i],
stat.stat_nr[i], stat.stat_nd[i]);
stats.stat_nf[i], stats.stat_bf[i],
stats.stat_nt[i], stats.stat_bt[i],
stats.stat_nr[i], stats.stat_nd[i]);
if (mnames)
printf(" %s", mtable[i]);
printf("\n");
frmsgs += stat.stat_nf[i];
frbytes += stat.stat_bf[i];
tomsgs += stat.stat_nt[i];
tobytes += stat.stat_bt[i];
rejmsgs += stat.stat_nr[i];
dismsgs += stat.stat_nd[i];
frmsgs += stats.stat_nf[i];
frbytes += stats.stat_bf[i];
tomsgs += stats.stat_nt[i];
tobytes += stats.stat_bt[i];
rejmsgs += stats.stat_nr[i];
dismsgs += stats.stat_nd[i];
}
}
if (progmode)
{
printf(" T %8ld %10ld %8ld %10ld %6ld %6ld\n",
frmsgs, frbytes, tomsgs, tobytes, rejmsgs, dismsgs);
close(fd);
printf(" C %8ld %8ld %6ld\n",
stats.stat_cf, stats.stat_ct, stats.stat_cr);
(void) close(fd);
fd = open(sfile, O_RDWR | O_TRUNC);
if (fd >= 0)
close(fd);
(void) close(fd);
}
else
{
printf("=============================================================\n");
printf(" T %8ld %10ldK %8ld %10ldK %6ld %6ld\n",
frmsgs, frbytes, tomsgs, tobytes, rejmsgs, dismsgs);
printf(" C %8ld %10s %8ld %10s %6ld\n",
stats.stat_cf, "", stats.stat_ct, "", stats.stat_cr);
}
exit(EX_OK);
/* NOTREACHED */
return EX_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
@ -12,74 +13,86 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1988, 1993\n\
"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\
All rights reserved.\n\
Copyright (c) 1983 Eric P. Allman. All rights reserved.\n\
Copyright (c) 1988, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#endif /* ! lint */
#ifndef lint
static char sccsid[] = "@(#)praliases.c 8.21 (Berkeley) 12/27/1998";
#endif /* not lint */
static char id[] = "@(#)$Id: praliases.c,v 8.59.4.10 2000/07/18 05:41:39 gshapiro Exp $";
#endif /* ! lint */
/* $FreeBSD$ */
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef EX_OK
# undef EX_OK /* unistd.h may have another use for this */
#endif /* EX_OK */
#include <sysexits.h>
#if !defined(NDBM) && !defined(NEWDB)
ERROR README: You must define one of NDBM or NEWDB in order to compile
ERROR README: praliases.
#endif
#ifdef NDBM
# include <ndbm.h>
#endif
#ifndef NOT_SENDMAIL
# define NOT_SENDMAIL
#endif
#include <sendmail.h>
#include <pathnames.h>
#ifdef NEWDB
# include <db.h>
# ifndef DB_VERSION_MAJOR
# define DB_VERSION_MAJOR 1
# endif
#endif
#if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) || \
defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__)
# ifndef HASSTRERROR
# define HASSTRERROR 1 /* has strerror(3) */
# endif
#endif
#if !HASSTRERROR
extern char *strerror __P((int));
#endif
#endif /* ! NOT_SENDMAIL */
#include <sendmail/sendmail.h>
#include <sendmail/pathnames.h>
#include <libsmdb/smdb.h>
static void praliases __P((char *, int, char **));
#ifdef NDBM
static void praliases_dbm __P((char *, int, char **));
#endif
uid_t RealUid;
gid_t RealGid;
char *RealUserName;
uid_t RunAsUid;
uid_t RunAsGid;
char *RunAsUserName;
int Verbose = 2;
bool DontInitGroups = FALSE;
uid_t TrustedUid = 0;
BITMAP256 DontBlameSendmail;
extern void syserr __P((const char *, ...));
int
main(argc, argv)
int argc;
char **argv;
{
extern char *optarg;
extern int optind;
char *cfile;
#if _FFR_GRAB_ALIASFILE_OPTION
char *filename = NULL;
#else
char *filename = "/etc/aliases";
#endif
FILE *cfp;
int ch;
char afilebuf[MAXLINE];
char buf[MAXLINE];
struct passwd *pw;
static char rnamebuf[MAXNAME];
extern char *optarg;
extern int optind;
clrbitmap(DontBlameSendmail);
RunAsUid = RealUid = getuid();
RunAsGid = RealGid = getgid();
pw = getpwuid(RealUid);
if (pw != NULL)
{
if (strlen(pw->pw_name) > MAXNAME - 1)
pw->pw_name[MAXNAME] = 0;
snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name);
}
else
(void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d",
(int) RealUid);
RunAsUserName = RealUserName = rnamebuf;
cfile = _PATH_SENDMAILCF;
#if _FFR_GRAB_ALIASFILE_OPTION
while ((ch = getopt(argc, argv, "C:f:")) != -1)
#else
while ((ch = getopt(argc, argv, "f:")) != -1)
#endif
{
switch ((char)ch) {
case 'C':
@ -91,11 +104,7 @@ main(argc, argv)
case '?':
default:
(void)fprintf(stderr,
#if _FFR_GRAB_ALIASFILE_OPTION
"usage: praliases [-C cffile] [-f aliasfile]\n");
#else
"usage: praliases [-f aliasfile]\n");
#endif
"usage: praliases [-C cffile] [-f aliasfile]\n");
exit(EX_USAGE);
}
}
@ -110,8 +119,8 @@ main(argc, argv)
if ((cfp = fopen(cfile, "r")) == NULL)
{
fprintf(stderr, "praliases: ");
perror(cfile);
fprintf(stderr, "praliases: %s: %s\n",
cfile, errstring(errno));
exit(EX_NOINPUT);
}
@ -119,6 +128,10 @@ main(argc, argv)
{
register char *b, *p;
b = strchr(buf, '\n');
if (b != NULL)
*b = '\0';
b = buf;
switch (*b++)
{
@ -140,15 +153,15 @@ main(argc, argv)
}
/* this is the A or AliasFile option -- save it */
if (strlen(b) >= sizeof afilebuf)
if (strlcpy(afilebuf, b, sizeof afilebuf) >=
sizeof afilebuf)
{
fprintf(stderr,
"AliasFile filename too long: %.30s...\n",
"praliases: AliasFile filename too long: %.30s\n",
b);
(void) fclose(cfp);
exit(EX_CONFIG);
}
strcpy(afilebuf, b);
b = afilebuf;
for (p = b; p != NULL; )
@ -160,12 +173,50 @@ main(argc, argv)
b = p;
p = strpbrk(p, " ,/");
/* find end of spec */
if (p != NULL)
p = strpbrk(p, ",\n");
if (p != NULL)
*p++ = '\0';
{
bool quoted = FALSE;
for (; *p != '\0'; p++)
{
/*
** Don't break into a quoted
** string.
*/
if (*p == '"')
quoted = !quoted;
else if (*p == ',' && !quoted)
break;
}
/* No more alias specs follow */
if (*p == '\0')
{
/* chop trailing whitespace */
while (isascii(*p) &&
isspace(*p) &&
p > b)
p--;
*p = '\0';
p = NULL;
}
}
if (p != NULL)
{
char *e = p - 1;
/* chop trailing whitespace */
while (isascii(*e) &&
isspace(*e) &&
e > b)
e--;
*++e = '\0';
*p++ = '\0';
}
praliases(b, argc, argv);
}
@ -175,196 +226,192 @@ main(argc, argv)
}
(void) fclose(cfp);
exit(EX_OK);
/* NOTREACHED */
return EX_OK;
}
static void
praliases(filename, argc, argv)
char *filename;
int argc;
int argc;
char **argv;
{
#ifdef NEWDB
DB *db;
DBT newdbkey, newdbcontent;
char buf[MAXNAME];
#endif
char *class;
int result;
char *colon;
char *db_name;
char *db_type;
SMDB_DATABASE *database = NULL;
SMDB_CURSOR *cursor = NULL;
SMDB_DBENT db_key, db_value;
SMDB_DBPARAMS params;
SMDB_USER_INFO user_info;
class = strchr(filename, ':');
if (class != NULL)
colon = strchr(filename, ':');
if (colon == NULL)
{
if (strncasecmp(filename, "dbm:", 4) == 0)
{
#ifdef NDBM
praliases_dbm(class + 1, argc, argv);
return;
#else
fprintf(stderr, "class dbm not available\n");
exit(EX_DATAERR);
#endif
}
filename = class + 1;
}
#ifdef NEWDB
if (strlen(filename) + 4 >= sizeof buf)
{
fprintf(stderr, "Alias filename too long: %.30s...\n", filename);
exit(EX_USAGE);
}
(void) strcpy(buf, filename);
(void) strcat(buf, ".db");
# if DB_VERSION_MAJOR < 2
db = dbopen(buf, O_RDONLY, 0444, DB_HASH, NULL);
# else
db = NULL;
errno = db_open(buf, DB_HASH, DB_RDONLY, 0444, NULL, NULL, &db);
# endif
if (db != NULL)
{
if (!argc)
{
# if DB_VERSION_MAJOR > 1
DBC *dbc;
# endif
bzero(&newdbkey, sizeof newdbkey);
bzero(&newdbcontent, sizeof newdbcontent);
# if DB_VERSION_MAJOR < 2
while(!db->seq(db, &newdbkey, &newdbcontent, R_NEXT))
# else
# if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >=6
if ((errno = db->cursor(db, NULL, &dbc, 0)) == 0)
# else
if ((errno = db->cursor(db, NULL, &dbc)) == 0)
# endif
{
while ((errno = dbc->c_get(dbc, &newdbkey,
&newdbcontent,
DB_NEXT)) == 0)
# endif
printf("%.*s:%.*s\n",
(int) newdbkey.size,
(char *) newdbkey.data,
(int) newdbcontent.size,
(char *) newdbcontent.data);
# if DB_VERSION_MAJOR > 1
(void) dbc->c_close(dbc);
}
else
{
fprintf(stderr,
"praliases: %s: Could not set cursor: %s\n",
buf, strerror(errno));
errno = db->close(db, 0);
exit(EX_DATAERR);
}
# endif
}
else for (; *argv; ++argv)
{
bzero(&newdbkey, sizeof newdbkey);
bzero(&newdbcontent, sizeof newdbcontent);
newdbkey.data = *argv;
newdbkey.size = strlen(*argv) + 1;
# if DB_VERSION_MAJOR < 2
if (!db->get(db, &newdbkey, &newdbcontent, 0))
# else
if ((errno = db->get(db, NULL, &newdbkey,
&newdbcontent, 0)) == 0)
# endif
printf("%s:%.*s\n", (char *) newdbkey.data,
(int) newdbcontent.size,
(char *) newdbcontent.data);
else
printf("%s: No such key\n",
(char *) newdbkey.data);
}
# if DB_VERSION_MAJOR < 2
(void)db->close(db);
# else
errno = db->close(db, 0);
# endif
db_name = filename;
db_type = SMDB_TYPE_DEFAULT;
}
else
{
#endif
#ifdef NDBM
praliases_dbm(filename, argc, argv);
#endif
#ifdef NEWDB
*colon = '\0';
db_name = colon + 1;
db_type = filename;
}
#endif
}
#ifdef NDBM
static void
praliases_dbm(filename, argc, argv)
char *filename;
int argc;
char **argv;
{
DBM *dbp;
datum content, key;
if ((dbp = dbm_open(filename, O_RDONLY, 0)) == NULL)
/* clean off arguments */
for (;;)
{
(void)fprintf(stderr,
"praliases: %s: %s\n", filename, strerror(errno));
exit(EX_OSFILE);
while (isascii(*db_name) && isspace(*db_name))
db_name++;
if (*db_name != '-')
break;
while (*db_name != '\0' &&
!(isascii(*db_name) && isspace(*db_name)))
db_name++;
}
if (!argc)
if (*db_name == '\0' || (db_type != NULL && *db_type == '\0'))
{
for (key = dbm_firstkey(dbp);
key.dptr != NULL; key = dbm_nextkey(dbp))
if (colon != NULL)
*colon = ':';
fprintf(stderr, "praliases: illegal alias specification: %s\n",
filename);
goto fatal;
}
memset(&params, '\0', sizeof params);
params.smdbp_cache_size = 1024 * 1024;
user_info.smdbu_id = RunAsUid;
user_info.smdbu_group_id = RunAsGid;
strlcpy(user_info.smdbu_name, RunAsUserName, SMDB_MAX_USER_NAME_LEN);
result = smdb_open_database(&database, db_name, O_RDONLY, 0,
SFF_ROOTOK, db_type, &user_info, &params);
if (result != SMDBE_OK)
{
fprintf(stderr, "praliases: %s: open: %s\n",
db_name, errstring(result));
goto fatal;
}
if (argc == 0)
{
memset(&db_key, '\0', sizeof db_key);
memset(&db_value, '\0', sizeof db_value);
result = database->smdb_cursor(database, &cursor, 0);
if (result != SMDBE_OK)
{
content = dbm_fetch(dbp, key);
(void)printf("%.*s:%.*s\n",
(int) key.dsize, key.dptr,
(int) content.dsize, content.dptr);
fprintf(stderr, "praliases: %s: set cursor: %s\n",
db_name, errstring(result));
goto fatal;
}
while ((result = cursor->smdbc_get(cursor, &db_key, &db_value,
SMDB_CURSOR_GET_NEXT)) ==
SMDBE_OK)
{
#if 0
/* skip magic @:@ entry */
if (db_key.data.size == 2 &&
db_key.data.data[0] == '@' &&
db_key.data.data[1] == '\0' &&
db_value.data.size == 2 &&
db_value.data.data[0] == '@' &&
db_value.data.data[1] == '\0')
continue;
#endif /* 0 */
printf("%.*s:%.*s\n",
(int) db_key.data.size,
(char *) db_key.data.data,
(int) db_value.data.size,
(char *) db_value.data.data);
}
if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY)
{
fprintf(stderr,
"praliases: %s: get value at cursor: %s\n",
db_name, errstring(result));
goto fatal;
}
}
else
else for (; *argv != NULL; ++argv)
{
for (; *argv; ++argv)
memset(&db_key, '\0', sizeof db_key);
memset(&db_value, '\0', sizeof db_value);
db_key.data.data = *argv;
db_key.data.size = strlen(*argv) + 1;
if (database->smdb_get(database, &db_key,
&db_value, 0) == SMDBE_OK)
{
/*
** Use the sendmail adaptive algorithm of trying
** the key first without, then if needed with,
** the terminating NULL byte.
*/
key.dptr = *argv;
key.dsize = strlen(*argv);
content = dbm_fetch(dbp, key);
if (content.dptr == NULL)
{
key.dsize++;
content = dbm_fetch(dbp, key);
}
if (content.dptr != NULL)
(void)printf("%s:%.*s\n", key.dptr,
(int) content.dsize, content.dptr);
else
(void)printf("%s: No such key\n", key.dptr);
printf("%.*s:%.*s\n",
(int) db_key.data.size,
(char *) db_key.data.data,
(int) db_value.data.size,
(char *) db_value.data.data);
}
else
printf("%s: No such key\n", (char *) db_key.data.data);
}
dbm_close(dbp);
fatal:
if (cursor != NULL)
(void) cursor->smdbc_close(cursor);
if (database != NULL)
(void) database->smdb_close(database);
if (colon != NULL)
*colon = ':';
return;
}
#endif
#if !HASSTRERROR
char *
strerror(eno)
int eno;
/*VARARGS1*/
void
#ifdef __STDC__
message(const char *msg, ...)
#else /* __STDC__ */
message(msg, va_alist)
const char *msg;
va_dcl
#endif /* __STDC__ */
{
extern int sys_nerr;
extern char *sys_errlist[];
static char ebuf[60];
const char *m;
VA_LOCAL_DECL
if (eno >= 0 && eno < sys_nerr)
return sys_errlist[eno];
(void) sprintf(ebuf, "Error %d", eno);
return ebuf;
m = msg;
if (isascii(m[0]) && isdigit(m[0]) &&
isascii(m[1]) && isdigit(m[1]) &&
isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
m += 4;
VA_START(msg);
(void) vfprintf(stderr, m, ap);
VA_END;
(void) fprintf(stderr, "\n");
}
#endif /* !HASSTRERROR */
/*VARARGS1*/
void
#ifdef __STDC__
syserr(const char *msg, ...)
#else /* __STDC__ */
syserr(msg, va_alist)
const char *msg;
va_dcl
#endif /* __STDC__ */
{
const char *m;
VA_LOCAL_DECL
m = msg;
if (isascii(m[0]) && isdigit(m[0]) &&
isascii(m[1]) && isdigit(m[1]) &&
isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
m += 4;
VA_START(msg);
(void) vfprintf(stderr, m, ap);
VA_END;
(void) fprintf(stderr, "\n");
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -11,20 +12,24 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1988, 1993\n\
"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\
All rights reserved.\n\
Copyright (c) 1988, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#endif /* ! lint */
#ifndef lint
static char sccsid[] = "@(#)rmail.c 8.18 (Berkeley) 10/23/1998";
#endif /* not lint */
static char id[] = "@(#)$Id: rmail.c,v 8.39.4.5 2000/07/18 05:55:29 gshapiro Exp $";
#endif /* ! lint */
/* $FreeBSD$ */
/*
* RMAIL -- UUCP mail server.
*
* This program reads the >From ... remote from ... lines that UUCP is so
* fond of and turns them into something reasonable. It then execs sendmail
* with various options built from these lines.
* with various options built from these lines.
*
* The expected syntax is:
*
@ -43,6 +48,8 @@ static char sccsid[] = "@(#)rmail.c 8.18 (Berkeley) 10/23/1998";
* The err(3) routine is included here deliberately to make this code
* a bit more portable.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/wait.h>
@ -52,66 +59,74 @@ static char sccsid[] = "@(#)rmail.c 8.18 (Berkeley) 10/23/1998";
#ifdef BSD4_4
# define FORK vfork
# include <paths.h>
#else
#else /* BSD4_4 */
# define FORK fork
# ifndef _PATH_SENDMAIL
# define _PATH_SENDMAIL "/usr/lib/sendmail"
# endif
#endif
# endif /* ! _PATH_SENDMAIL */
#endif /* BSD4_4 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef EX_OK
# undef EX_OK /* unistd.h may have another use for this */
#endif
#endif /* EX_OK */
#include <sysexits.h>
#ifndef MAX
# define MAX(a, b) ((a) < (b) ? (b) : (a))
#endif
#endif /* ! MAX */
#ifndef __P
# ifdef __STDC__
# define __P(protos) protos
# else
# else /* __STDC__ */
# define __P(protos) ()
# define const
# endif
#endif
# endif /* __STDC__ */
#endif /* ! __P */
#if defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206)
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif /* ! STDIN_FILENO */
#if defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) || _AIX4 >= 40300
# define HASSNPRINTF 1
#endif
#if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) || \
defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__)
# ifndef HASSTRERROR
# define HASSTRERROR 1 /* has strerror(3) */
# endif
#endif
#if !HASSTRERROR
extern char *strerror __P((int));
#endif
#endif /* defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) || _AIX4 >= 40300 */
#if defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4)
# define memmove(d, s, l) (bcopy((s), (d), (l)))
#endif
# define memmove(d, s, l) (bcopy((s), (d), (l)))
#endif /* defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4) */
#if !HASSNPRINTF
extern int snprintf __P((char *, size_t, const char *, ...));
#endif /* !HASSNPRINTF */
u_char tTdvect[100];
#if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6)
# ifndef HASSTRERROR
# define HASSTRERROR 1
# endif /* ! HASSTRERROR */
#endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) ||
defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */
void err __P((int, const char *, ...));
void usage __P((void));
char *xalloc __P((int));
#if defined(SUNOS403) || defined(NeXT) || (defined(MACH) && defined(i386) && !defined(__GNU__)) || defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) || defined(ALTOS_SYSTEM_V) || defined(RISCOS) || defined(_AUX_SOURCE) || defined(UMAXV) || defined(titan) || defined(UNIXWARE) || defined(sony_news) || defined(luna) || defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(__MAXION__)
# undef WIFEXITED
# undef WEXITSTATUS
# define WIFEXITED(st) (((st) & 0377) == 0)
# define WEXITSTATUS(st) (((st) >> 8) & 0377)
#endif /* defined(SUNOS403) || defined(NeXT) || (defined(MACH) && defined(i386) && !defined(__GNU__)) || defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) || defined(ALTOS_SYSTEM_V) || defined(RISCOS) || defined(_AUX_SOURCE) || defined(UMAXV) || defined(titan) || defined(UNIXWARE) || defined(sony_news) || defined(luna) || defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(__MAXION__) */
#include "sendmail/errstring.h"
static void err __P((int, const char *, ...));
static void usage __P((void));
static char *xalloc __P((int));
#define newstr(s) strcpy(xalloc(strlen(s) + 1), s)
char *
static char *
xalloc(sz)
register int sz;
{
@ -132,45 +147,49 @@ main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int errno, optind;
FILE *fp;
struct stat sb;
int ch, debug, i, pdes[2], pid, status;
size_t fplen = 0, fptlen = 0, len;
off_t offset;
int ch, debug, i, pdes[2], pid, status;
FILE *fp;
char *addrp = NULL, *domain, *p, *t;
char *from_path, *from_sys, *from_user;
char *args[100], buf[2048], lbuf[2048];
struct stat sb;
extern char *optarg;
extern int optind;
debug = 0;
domain = "UUCP"; /* Default "domain". */
while ((ch = getopt(argc, argv, "D:T")) != -1)
switch (ch) {
case 'T':
{
switch (ch)
{
case 'T':
debug = 1;
break;
case 'D':
case 'D':
domain = optarg;
break;
case '?':
default:
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc < 1)
usage();
fplen = fptlen = 0;
addrp = "";
from_path = from_sys = from_user = NULL;
for (offset = 0;;) {
for (offset = 0; ; )
{
/* Get and nul-terminate the line. */
if (fgets(lbuf, sizeof(lbuf), stdin) == NULL)
exit (EX_DATAERR);
exit(EX_DATAERR);
if ((p = strchr(lbuf, '\n')) == NULL)
err(EX_DATAERR, "line too long");
*p = '\0';
@ -183,32 +202,40 @@ main(argc, argv)
else if (offset == 0)
err(EX_DATAERR,
"missing or empty From line: %s", lbuf);
else {
else
{
*p = '\n';
break;
}
if (*addrp == '\0')
if (addrp == NULL || *addrp == '\0')
err(EX_DATAERR, "corrupted From line: %s", lbuf);
/* Use the "remote from" if it exists. */
for (p = addrp; (p = strchr(p + 1, 'r')) != NULL;)
if (!strncmp(p, "remote from ", 12)) {
for (t = p += 12;
*t && !(isascii(*t) && isspace(*t)); ++t);
for (p = addrp; (p = strchr(p + 1, 'r')) != NULL; )
{
if (!strncmp(p, "remote from ", 12))
{
for (t = p += 12; *t != '\0'; ++t)
{
if (isascii(*t) && isspace(*t))
break;
}
*t = '\0';
if (debug)
(void)fprintf(stderr,
"remote from: %s\n", p);
fprintf(stderr, "remote from: %s\n", p);
break;
}
}
/* Else use the string up to the last bang. */
if (p == NULL) {
if (p == NULL)
{
if (*addrp == '!')
err(EX_DATAERR,
"bang starts address: %s", addrp);
else if ((t = strrchr(addrp, '!')) != NULL) {
err(EX_DATAERR, "bang starts address: %s",
addrp);
else if ((t = strrchr(addrp, '!')) != NULL)
{
*t = '\0';
p = addrp;
addrp = t + 1;
@ -216,34 +243,43 @@ main(argc, argv)
err(EX_DATAERR,
"corrupted From line: %s", lbuf);
if (debug)
(void)fprintf(stderr, "bang: %s\n", p);
fprintf(stderr, "bang: %s\n", p);
}
}
/* 'p' now points to any system string from this line. */
if (p != NULL) {
if (p != NULL)
{
/* Nul terminate it as necessary. */
for (t = p; *t && !(isascii(*t) && isspace(*t)); ++t);
for (t = p; *t != '\0'; ++t)
{
if (isascii(*t) && isspace(*t))
break;
}
*t = '\0';
/* If the first system, copy to the from_sys string. */
if (from_sys == NULL) {
if (from_sys == NULL)
{
from_sys = newstr(p);
if (debug)
(void)fprintf(stderr,
"from_sys: %s\n", from_sys);
fprintf(stderr, "from_sys: %s\n",
from_sys);
}
/* Concatenate to the path string. */
len = t - p;
if (from_path == NULL) {
if (from_path == NULL)
{
fplen = 0;
if ((from_path = malloc(fptlen = 256)) == NULL)
err(EX_TEMPFAIL, NULL);
}
if (fplen + len + 2 > fptlen) {
if (fplen + len + 2 > fptlen)
{
fptlen += MAX(fplen + len + 2, 256);
if ((from_path =
realloc(from_path, fptlen)) == NULL)
if ((from_path = realloc(from_path,
fptlen)) == NULL)
err(EX_TEMPFAIL, NULL);
}
memmove(from_path + fplen, p, len);
@ -253,7 +289,11 @@ main(argc, argv)
}
/* Save off from user's address; the last one wins. */
for (p = addrp; *p && !(isascii(*p) && isspace(*p)); ++p);
for (p = addrp; *p != '\0'; ++p)
{
if (isascii(*p) && isspace(*p))
break;
}
*p = '\0';
if (*addrp == '\0')
addrp = "<>";
@ -261,11 +301,11 @@ main(argc, argv)
free(from_user);
from_user = newstr(addrp);
if (debug) {
if (debug)
{
if (from_path != NULL)
(void)fprintf(stderr,
"from_path: %s\n", from_path);
(void)fprintf(stderr, "from_user: %s\n", from_user);
fprintf(stderr, "from_path: %s\n", from_path);
fprintf(stderr, "from_user: %s\n", from_user);
}
if (offset != -1)
@ -284,86 +324,99 @@ main(argc, argv)
/* set from system and protocol used */
if (from_sys == NULL)
(void)snprintf(buf, sizeof(buf), "-p%s", domain);
snprintf(buf, sizeof(buf), "-p%s", domain);
else if (strchr(from_sys, '.') == NULL)
(void)snprintf(buf, sizeof(buf), "-p%s:%s.%s",
snprintf(buf, sizeof(buf), "-p%s:%s.%s",
domain, from_sys, domain);
else
(void)snprintf(buf, sizeof(buf), "-p%s:%s", domain, from_sys);
snprintf(buf, sizeof(buf), "-p%s:%s", domain, from_sys);
args[i++] = newstr(buf);
/* Set name of ``from'' person. */
(void)snprintf(buf, sizeof(buf), "-f%s%s",
from_path ? from_path : "", from_user);
/* Set name of ``from'' person. */
snprintf(buf, sizeof(buf), "-f%s%s",
from_path ? from_path : "", from_user);
args[i++] = newstr(buf);
/*
* Don't copy arguments beginning with - as they will be
* passed to sendmail and could be interpreted as flags.
* To prevent confusion of sendmail wrap < and > around
* the address (helps to pass addrs like @gw1,@gw2:aa@bb)
*/
while (*argv) {
** Don't copy arguments beginning with - as they will be
** passed to sendmail and could be interpreted as flags.
** To prevent confusion of sendmail wrap < and > around
** the address (helps to pass addrs like @gw1,@gw2:aa@bb)
*/
while (*argv)
{
if (**argv == '-')
err(EX_USAGE, "dash precedes argument: %s", *argv);
if (strchr(*argv, ',') == NULL || strchr(*argv, '<') != NULL)
args[i++] = *argv;
else {
if ((args[i] = malloc(strlen(*argv) + 3)) == NULL)
else
{
len = strlen(*argv) + 3;
if ((args[i] = malloc(len)) == NULL)
err(EX_TEMPFAIL, "Cannot malloc");
sprintf (args [i++], "<%s>", *argv);
snprintf(args[i++], len, "<%s>", *argv);
}
argv++;
}
}
args[i] = 0;
if (debug) {
(void)fprintf(stderr, "Sendmail arguments:\n");
if (debug)
{
fprintf(stderr, "Sendmail arguments:\n");
for (i = 0; args[i]; i++)
(void)fprintf(stderr, "\t%s\n", args[i]);
fprintf(stderr, "\t%s\n", args[i]);
}
/*
* If called with a regular file as standard input, seek to the right
* position in the file and just exec sendmail. Could probably skip
* skip the stat, but it's not unreasonable to believe that a failed
* seek will cause future reads to fail.
*/
if (!fstat(STDIN_FILENO, &sb) && S_ISREG(sb.st_mode)) {
** If called with a regular file as standard input, seek to the right
** position in the file and just exec sendmail. Could probably skip
** skip the stat, but it's not unreasonable to believe that a failed
** seek will cause future reads to fail.
*/
if (!fstat(STDIN_FILENO, &sb) && S_ISREG(sb.st_mode))
{
if (lseek(STDIN_FILENO, offset, SEEK_SET) != offset)
err(EX_TEMPFAIL, "stdin seek");
execv(_PATH_SENDMAIL, args);
(void) execv(_PATH_SENDMAIL, args);
err(EX_OSERR, "%s", _PATH_SENDMAIL);
}
if (pipe(pdes) < 0)
err(EX_OSERR, NULL);
switch (pid = FORK()) {
case -1: /* Err. */
switch (pid = FORK())
{
case -1: /* Err. */
err(EX_OSERR, NULL);
case 0: /* Child. */
if (pdes[0] != STDIN_FILENO) {
(void)dup2(pdes[0], STDIN_FILENO);
(void)close(pdes[0]);
/* NOTREACHED */
case 0: /* Child. */
if (pdes[0] != STDIN_FILENO)
{
(void) dup2(pdes[0], STDIN_FILENO);
(void) close(pdes[0]);
}
(void)close(pdes[1]);
execv(_PATH_SENDMAIL, args);
(void) close(pdes[1]);
(void) execv(_PATH_SENDMAIL, args);
_exit(127);
/* NOTREACHED */
}
if ((fp = fdopen(pdes[1], "w")) == NULL)
err(EX_OSERR, NULL);
(void)close(pdes[0]);
(void) close(pdes[0]);
/* Copy the file down the pipe. */
do {
(void)fprintf(fp, "%s", lbuf);
do
{
(void) fprintf(fp, "%s", lbuf);
} while (fgets(lbuf, sizeof(lbuf), stdin) != NULL);
if (ferror(stdin))
err(EX_TEMPFAIL, "stdin: %s", strerror(errno));
err(EX_TEMPFAIL, "stdin: %s", errstring(errno));
if (fclose(fp))
err(EX_OSERR, NULL);
@ -372,65 +425,48 @@ main(argc, argv)
err(EX_OSERR, "%s", _PATH_SENDMAIL);
if (!WIFEXITED(status))
err(EX_OSERR,
"%s: did not terminate normally", _PATH_SENDMAIL);
err(EX_OSERR, "%s: did not terminate normally", _PATH_SENDMAIL);
if (WEXITSTATUS(status))
err(status, "%s: terminated with %d (non-zero) status",
_PATH_SENDMAIL, WEXITSTATUS(status));
exit(EX_OK);
/* NOTREACHED */
return EX_OK;
}
void
static void
usage()
{
(void)fprintf(stderr, "usage: rmail [-T] [-D domain] user ...\n");
(void) fprintf(stderr, "usage: rmail [-T] [-D domain] user ...\n");
exit(EX_USAGE);
}
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
# include <stdarg.h>
#else /* __STDC__ */
# include <varargs.h>
#endif /* __STDC__ */
void
static void
#ifdef __STDC__
err(int eval, const char *fmt, ...)
#else
#else /* __STDC__ */
err(eval, fmt, va_alist)
int eval;
const char *fmt;
va_dcl
#endif
#endif /* __STDC__ */
{
va_list ap;
#if __STDC__
#ifdef __STDC__
va_start(ap, fmt);
#else
#else /* __STDC__ */
va_start(ap);
#endif
(void)fprintf(stderr, "rmail: ");
(void)vfprintf(stderr, fmt, ap);
#endif /* __STDC__ */
(void) fprintf(stderr, "rmail: ");
(void) vfprintf(stderr, fmt, ap);
va_end(ap);
(void)fprintf(stderr, "\n");
(void) fprintf(stderr, "\n");
exit(eval);
}
#if !HASSTRERROR
char *
strerror(eno)
int eno;
{
extern int sys_nerr;
extern char *sys_errlist[];
static char ebuf[60];
if (eno >= 0 && eno < sys_nerr)
return sys_errlist[eno];
(void) sprintf(ebuf, "Error %d", eno);
return ebuf;
}
#endif /* !HASSTRERROR */

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 1998 Sendmail, Inc. All rights reserved.
.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
.\" All rights reserved.
.\" Copyright (c) 1993 Eric P. Allman. All rights reserved.
.\" Copyright (c) 1993
.\" The Regents of the University of California. All rights reserved.
@ -8,7 +9,9 @@
.\" the sendmail distribution.
.\"
.\"
.\" @(#)smrsh.8 8.7 (Berkeley) 5/19/1998
.\" $Id: smrsh.8,v 8.11 1999/06/09 16:51:07 ca Exp $
.\"
.\" $FreeBSD$
.\"
.TH SMRSH 8 11/02/93
.SH NAME
@ -38,11 +41,14 @@ Briefly,
.I smrsh
limits programs to be in the directory
/usr/libexec/sm.bin,
allowing the system administrator to choose the set of acceptable commands.
allowing the system administrator to choose the set of acceptable commands,
and to the shell builtin commands ``exec'', ``exit'', and ``echo''.
It also rejects any commands with the characters
`\`', `<', `>', `|', `;', `&', `$', `(', `)', `\er' (carriage return),
`\`', `<', `>', `;', `$', `(', `)', `\er' (carriage return),
or `\en' (newline)
on the command line to prevent ``end run'' attacks.
It allows ``||'' and ``&&'' to enable commands like:
``"|exec /usr/local/bin/procmail -f- /etc/procmailrcs/user || exit 75"''
.PP
Initial pathnames on programs are stripped,
so forwarding to ``/usr/bin/vacation'',

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1993 Eric P. Allman. All rights reserved.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@ -11,8 +12,19 @@
*/
#ifndef lint
static char sccsid[] = "@(#)smrsh.c 8.11 (Berkeley) 5/19/1998";
#endif /* not lint */
static char copyright[] =
"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\
All rights reserved.\n\
Copyright (c) 1993 Eric P. Allman. All rights reserved.\n\
Copyright (c) 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* ! lint */
#ifndef lint
static char id[] = "@(#)$Id: smrsh.c,v 8.31.4.4 2000/05/25 21:44:29 gshapiro Exp $";
#endif /* ! lint */
/* $FreeBSD$ */
/*
** SMRSH -- sendmail restricted shell
@ -32,12 +44,12 @@ static char sccsid[] = "@(#)smrsh.c 8.11 (Berkeley) 5/19/1998";
** "/usr/bin/vacation" will continue to work.
**
** The following characters are completely illegal:
** < > | ^ ; & $ ` ( ) \n \r
** < > ^ & ` ( ) \n \r
** The following characters are sometimes illegal:
** | &
** This is more restrictive than strictly necessary.
**
** To use this, edit /etc/sendmail.cf, search for ^Mprog, and
** change P=/bin/sh to P=/usr/libexec/smrsh, where this compiled
** binary is installed /usr/libexec/smrsh.
** To use this, add FEATURE(`smrsh') to your .mc file.
**
** This can be used on any version of sendmail.
**
@ -49,17 +61,23 @@ static char sccsid[] = "@(#)smrsh.c 8.11 (Berkeley) 5/19/1998";
#include <sys/file.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef EX_OK
# undef EX_OK
#endif
#endif /* EX_OK */
#include <sysexits.h>
#include <syslog.h>
#include <stdlib.h>
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif /* ! TRUE */
/* directory in which all commands must reside */
#ifndef CMDDIR
# define CMDDIR "/usr/libexec/sm.bin"
#endif
#endif /* ! CMDDIR */
/* characters disallowed in the shell "-c" argument */
#define SPECIALS "<|>^();&`$\r\n"
@ -67,7 +85,56 @@ static char sccsid[] = "@(#)smrsh.c 8.11 (Berkeley) 5/19/1998";
/* default search path */
#ifndef PATH
# define PATH "/bin:/usr/bin"
#endif
#endif /* ! PATH */
#ifndef __P
# include "sendmail/cdefs.h"
#endif /* ! __P */
extern size_t strlcpy __P((char *, const char *, size_t));
extern size_t strlcat __P((char *, const char *, size_t));
char newcmdbuf[1000];
char *prg, *par;
/*
** ADDCMD -- add a string to newcmdbuf, check for overflow
**
** Parameters:
** s -- string to add
** cmd -- it's a command: prepend CMDDIR/
** len -- length of string to add
**
** Side Effects:
** changes newcmdbuf or exits with a failure.
**
*/
void
addcmd(s, cmd, len)
char *s;
int cmd;
int len;
{
if (s == NULL || *s == '\0')
return;
if (sizeof newcmdbuf - strlen(newcmdbuf) <=
len + (cmd ? (strlen(CMDDIR) + 1) : 0))
{
fprintf(stderr, "%s: command too long: %s\n", prg, par);
#ifndef DEBUG
syslog(LOG_WARNING, "command too long: %.40s", par);
#endif /* ! DEBUG */
exit(EX_UNAVAILABLE);
}
if (cmd)
{
(void) strlcat(newcmdbuf, CMDDIR, sizeof newcmdbuf);
(void) strlcat(newcmdbuf, "/", sizeof newcmdbuf);
}
(void) strlcat(newcmdbuf, s, sizeof newcmdbuf);
}
int
main(argc, argv)
@ -76,20 +143,26 @@ main(argc, argv)
{
register char *p;
register char *q;
register char *r;
register char *cmd;
int i;
int isexec;
int save_errno;
char *newenv[2];
char cmdbuf[1000];
char pathbuf[1000];
char specialbuf[32];
#ifndef LOG_MAIL
#ifndef DEBUG
# ifndef LOG_MAIL
openlog("smrsh", 0);
#else
# else /* ! LOG_MAIL */
openlog("smrsh", LOG_ODELAY|LOG_CONS, LOG_MAIL);
#endif
# endif /* ! LOG_MAIL */
#endif /* ! DEBUG */
strcpy(pathbuf, "PATH=");
strcat(pathbuf, PATH);
(void) strlcpy(pathbuf, "PATH=", sizeof pathbuf);
(void) strlcat(pathbuf, PATH, sizeof pathbuf);
newenv[0] = pathbuf;
newenv[1] = NULL;
@ -97,10 +170,15 @@ main(argc, argv)
** Do basic argv usage checking
*/
prg = argv[0];
par = argv[2];
if (argc != 3 || strcmp(argv[1], "-c") != 0)
{
fprintf(stderr, "Usage: %s -c command\n", argv[0]);
fprintf(stderr, "Usage: %s -c command\n", prg);
#ifndef DEBUG
syslog(LOG_ERR, "usage");
#endif /* ! DEBUG */
exit(EX_USAGE);
}
@ -111,103 +189,193 @@ main(argc, argv)
** the address to 7 bits before checking.
*/
strcpy(cmdbuf, SPECIALS);
for (p = cmdbuf; *p != '\0'; p++)
*p |= '\200';
strcat(cmdbuf, SPECIALS);
p = strpbrk(argv[2], cmdbuf);
if (p != NULL)
if (strlen(SPECIALS) * 2 >= sizeof specialbuf)
{
fprintf(stderr, "%s: cannot use %c in command\n",
argv[0], *p);
syslog(LOG_CRIT, "uid %d: attempt to use %c in command: %s",
getuid(), *p, argv[2]);
#ifndef DEBUG
syslog(LOG_ERR, "too many specials: %.40s", SPECIALS);
#endif /* ! DEBUG */
exit(EX_UNAVAILABLE);
}
(void) strlcpy(specialbuf, SPECIALS, sizeof specialbuf);
for (p = specialbuf; *p != '\0'; p++)
*p |= '\200';
(void) strlcat(specialbuf, SPECIALS, sizeof specialbuf);
/*
** Do a quick sanity check on command line length.
*/
i = strlen(argv[2]);
if (i > (sizeof cmdbuf - sizeof CMDDIR - 2))
i = strlen(par);
if (i > (sizeof newcmdbuf - sizeof CMDDIR - 2))
{
fprintf(stderr, "%s: command too long: %s\n", argv[0], argv[2]);
syslog(LOG_WARNING, "command too long: %.40s", argv[2]);
fprintf(stderr, "%s: command too long: %s\n", prg, par);
#ifndef DEBUG
syslog(LOG_WARNING, "command too long: %.40s", par);
#endif /* ! DEBUG */
exit(EX_UNAVAILABLE);
}
/*
** Strip off a leading pathname on the command name. For
** example, change /usr/ucb/vacation to vacation.
*/
q = par;
newcmdbuf[0] = '\0';
isexec = FALSE;
/* strip leading spaces */
for (q = argv[2]; *q != '\0' && isascii(*q) && isspace(*q); )
q++;
/* find the end of the command name */
p = strpbrk(q, " \t");
if (p == NULL)
cmd = &q[strlen(q)];
else
while (*q)
{
*p = '\0';
cmd = p;
}
/*
** Strip off a leading pathname on the command name. For
** example, change /usr/ucb/vacation to vacation.
*/
/* search backwards for last / (allow for 0200 bit) */
while (cmd > q)
{
if ((*--cmd & 0177) == '/')
/* strip leading spaces */
while (*q != '\0' && isascii(*q) && isspace(*q))
q++;
if (*q == '\0')
{
cmd++;
if (isexec)
{
fprintf(stderr, "%s: missing command to exec\n",
prg);
#ifndef DEBUG
syslog(LOG_CRIT, "uid %d: missing command to exec", getuid());
#endif /* ! DEBUG */
exit(EX_UNAVAILABLE);
}
break;
}
}
/* cmd now points at final component of path name */
/* find the end of the command name */
p = strpbrk(q, " \t");
if (p == NULL)
cmd = &q[strlen(q)];
else
{
*p = '\0';
cmd = p;
}
/* search backwards for last / (allow for 0200 bit) */
while (cmd > q)
{
if ((*--cmd & 0177) == '/')
{
cmd++;
break;
}
}
/* cmd now points at final component of path name */
/*
** Check to see if the command name is legal.
*/
(void) strcpy(cmdbuf, CMDDIR);
(void) strcat(cmdbuf, "/");
(void) strcat(cmdbuf, cmd);
/* allow a few shell builtins */
if (strcmp(q, "exec") == 0 && p != NULL)
{
addcmd("exec ", FALSE, strlen("exec "));
/* test _next_ arg */
q = ++p;
isexec = TRUE;
continue;
}
else if (strcmp(q, "exit") == 0 || strcmp(q, "echo") == 0)
{
addcmd(cmd, FALSE, strlen(cmd));
/* test following chars */
}
else
{
/*
** Check to see if the command name is legal.
*/
(void) strlcpy(cmdbuf, CMDDIR, sizeof cmdbuf);
(void) strlcat(cmdbuf, "/", sizeof cmdbuf);
(void) strlcat(cmdbuf, cmd, sizeof cmdbuf);
#ifdef DEBUG
printf("Trying %s\n", cmdbuf);
#endif
if (access(cmdbuf, X_OK) < 0)
{
/* oops.... crack attack possiblity */
fprintf(stderr, "%s: %s not available for sendmail programs\n",
argv[0], cmd);
printf("Trying %s\n", cmdbuf);
#endif /* DEBUG */
if (access(cmdbuf, X_OK) < 0)
{
/* oops.... crack attack possiblity */
fprintf(stderr,
"%s: %s not available for sendmail programs\n",
prg, cmd);
if (p != NULL)
*p = ' ';
#ifndef DEBUG
syslog(LOG_CRIT, "uid %d: attempt to use %s",
getuid(), cmd);
#endif /* ! DEBUG */
exit(EX_UNAVAILABLE);
}
/*
** Create the actual shell input.
*/
addcmd(cmd, TRUE, strlen(cmd));
}
isexec = FALSE;
if (p != NULL)
*p = ' ';
syslog(LOG_CRIT, "uid %d: attempt to use %s", getuid(), cmd);
else
break;
r = strpbrk(p, specialbuf);
if (r == NULL) {
addcmd(p, FALSE, strlen(p));
break;
}
#if ALLOWSEMI
if (*r == ';') {
addcmd(p, FALSE, r - p + 1);
q = r + 1;
continue;
}
#endif /* ALLOWSEMI */
if ((*r == '&' && *(r + 1) == '&') ||
(*r == '|' && *(r + 1) == '|'))
{
addcmd(p, FALSE, r - p + 2);
q = r + 2;
continue;
}
fprintf(stderr, "%s: cannot use %c in command\n", prg, *r);
#ifndef DEBUG
syslog(LOG_CRIT, "uid %d: attempt to use %c in command: %s",
getuid(), *r, par);
#endif /* ! DEBUG */
exit(EX_UNAVAILABLE);
} /* end of while *q */
if (isexec)
{
fprintf(stderr, "%s: missing command to exec\n", prg);
#ifndef DEBUG
syslog(LOG_CRIT, "uid %d: missing command to exec", getuid());
#endif /* ! DEBUG */
exit(EX_UNAVAILABLE);
}
if (p != NULL)
*p = ' ';
/*
** Create the actual shell input.
*/
strcpy(cmdbuf, CMDDIR);
strcat(cmdbuf, "/");
strcat(cmdbuf, cmd);
/* make sure we created something */
if (newcmdbuf[0] == '\0')
{
fprintf(stderr, "Usage: %s -c command\n", prg);
#ifndef DEBUG
syslog(LOG_ERR, "usage");
#endif /* ! DEBUG */
exit(EX_USAGE);
}
/*
** Now invoke the shell
*/
#ifdef DEBUG
printf("%s\n", cmdbuf);
#endif
execle("/bin/sh", "/bin/sh", "-c", cmdbuf, NULL, newenv);
printf("%s\n", newcmdbuf);
#endif /* DEBUG */
(void) execle("/bin/sh", "/bin/sh", "-c", newcmdbuf, NULL, newenv);
save_errno = errno;
#ifndef DEBUG
syslog(LOG_CRIT, "Cannot exec /bin/sh: %m");
#endif /* ! DEBUG */
errno = save_errno;
perror("/bin/sh");
exit(EX_OSFILE);
/* NOTREACHED */
return EX_OSFILE;
}

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 1998 Sendmail, Inc. All rights reserved.
.\" Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
.\" All rights reserved.
.\" Copyright (c) 1983, 1997 Eric P. Allman. All rights reserved.
.\" Copyright (c) 1985, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -8,78 +9,114 @@
.\" the sendmail distribution.
.\"
.\"
.\" @(#)aliases.5 8.8 (Berkeley) 5/19/1998
.\" $Id: aliases.5,v 8.15.4.1 2000/07/18 07:23:02 gshapiro Exp $
.\"
.Dd May 19, 1998
.Dt ALIASES 5
.Os BSD 4
.Sh NAME
.Nm aliases
.Nd aliases file for sendmail
.Sh SYNOPSIS
.Nm aliases
.Sh DESCRIPTION
This file describes user
.Tn ID
aliases used by
.Pa /usr/sbin/sendmail .
The file resides in
.Pa /etc
and
.\" $FreeBSD$
.\"
.TH ALIASES 5 "$Date: 2000/07/18 07:23:02 $"
.SH NAME
.B aliases
\- aliases file for sendmail
.SH SYNOPSIS
.B aliases
.SH DESCRIPTION
This file describes user
ID
aliases used by
sendmail.
The file resides in
/etc/mail
and
is formatted as a series of lines of the form
.Bd -filled -offset indent
name: name_1, name_2, name_3, . . .
.Ed
.Pp
.IP
name: addr_1, addr_2, addr_3, . . .
.PP
The
.Em name
.I name
is the name to alias, and the
.Em name_n
are the aliases for that name.
Lines beginning with white space are continuation lines.
Lines beginning with
.Ql #
.I addr_n
are the aliases for that name.
.I addr_n
can be another alias, a local username, a local filename,
a command,
an include file,
or an external address.
.TP
.B Local Username
username
.IP
The username must be available via getpwnam(3).
.TP
.B Local Filename
/path/name
.IP
Messages are appended to the file specified by the full pathname
(starting with a slash (/))
.TP
.B Command
|command
.IP
A command starts with a pipe symbol (|),
it receives messages via standard input.
.TP
.B Include File
:include: /path/name
.IP
The aliases in pathname are added to the aliases for
.I name.
.TP
.B E-Mail Address
user@domain
.IP
An e-mail address in RFC 822 format.
.PP
Lines beginning with white space are continuation lines.
Another way to continue lines is by placing a backslash
directly before a newline.
Lines beginning with
#
are comments.
.Pp
Aliasing occurs only on local names.
.PP
Aliasing occurs only on local names.
Loops can not occur, since no message will be sent to any person more than once.
.Pp
After aliasing has been done, local and valid recipients who have a
.Dq Pa .forward
file in their home directory have messages forwarded to the
.PP
After aliasing has been done, local and valid recipients who have a
``.forward''
file in their home directory have messages forwarded to the
list of users defined in that file.
.Pp
.PP
This is only the raw data file; the actual aliasing information is
placed into a binary format in the file
.Pa /etc/aliases.db
using the program
.Xr newaliases 1 .
A
.Xr newaliases
command should be executed each time the aliases file is changed for the
placed into a binary format in the file
/etc/mail/aliases.db
using the program
newaliases(1).
A
newaliases
command should be executed each time the aliases file is changed for the
change to take effect.
.Sh SEE ALSO
.Xr newaliases 1 ,
.Xr dbm 3 ,
.Xr dbopen 3 ,
.Xr sendmail 8
.Rs
.%T "SENDMAIL Installation and Operation Guide"
.Re
.Rs
.%T "SENDMAIL An Internetwork Mail Router"
.Re
.Sh BUGS
If you have compiled
.Xr sendmail
.SH SEE ALSO
newaliases(1),
dbm(3),
dbopen(3),
db_open(3),
sendmail(8)
.PP
.I
SENDMAIL Installation and Operation Guide.
.PP
.I
SENDMAIL An Internetwork Mail Router.
.SH BUGS
If you have compiled
sendmail
with DBM support instead of NEWDB,
you may have encountered problems in
.Xr dbm 3
restricting a single alias to about 1000 bytes of information.
You can get longer aliases by ``chaining''; that is, make the last name in
you may have encountered problems in
dbm(3)
restricting a single alias to about 1000 bytes of information.
You can get longer aliases by ``chaining''; that is, make the last name in
the alias be a dummy name which is a continuation alias.
.Sh HISTORY
.SH HISTORY
The
.Nm
file format appeared in
.Bx 4.0 .
.B aliases
file format appeared in
4.0BSD.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
@ -11,11 +12,22 @@
*/
#ifndef lint
static char sccsid[] = "@(#)err.c 8.74 (Berkeley) 6/4/1998";
#endif /* not lint */
static char id[] = "@(#)$Id: err.c,v 8.120.4.1 2000/05/25 18:56:15 gshapiro Exp $";
#endif /* ! lint */
# include "sendmail.h"
# include <errno.h>
/* $FreeBSD$ */
#include <sendmail.h>
#ifdef LDAPMAP
# include <lber.h>
# include <ldap.h> /* for LDAP error codes */
#endif /* LDAPMAP */
static void putoutmsg __P((char *, bool, bool));
static void puterrmsg __P((char *));
static char *fmtmsg __P((char *, const char *, const char *, const char *,
int, const char *, va_list));
/*
** SYSERR -- Print error message.
@ -43,31 +55,29 @@ static char sccsid[] = "@(#)err.c 8.74 (Berkeley) 6/4/1998";
** sets ExitStat.
*/
char MsgBuf[BUFSIZ*2]; /* text of most recent message */
char HeldMessageBuf[sizeof MsgBuf]; /* for held messages */
extern void putoutmsg __P((char *, bool, bool));
extern void puterrmsg __P((char *));
static void fmtmsg __P((char *, const char *, const char *, int, const char *, va_list));
char MsgBuf[BUFSIZ*2]; /* text of most recent message */
static char HeldMessageBuf[sizeof MsgBuf]; /* for held messages */
#if NAMED_BIND && !defined(NO_DATA)
# define NO_DATA NO_ADDRESS
#endif
#endif /* NAMED_BIND && !defined(NO_DATA) */
void
/*VARARGS1*/
#ifdef __STDC__
syserr(const char *fmt, ...)
#else
#else /* __STDC__ */
syserr(fmt, va_alist)
const char *fmt;
va_dcl
#endif
#endif /* __STDC__ */
{
register char *p;
int olderrno = errno;
int save_errno = errno;
bool panic;
char *uname;
char *user;
char *enhsc;
char *errtxt;
struct passwd *pw;
char ubuf[80];
VA_LOCAL_DECL
@ -80,12 +90,18 @@ syserr(fmt, va_alist)
}
/* format and output the error message */
if (olderrno == 0)
if (save_errno == 0)
{
p = "554";
enhsc = "5.0.0";
}
else
{
p = "451";
enhsc = "4.0.0";
}
VA_START(fmt);
fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
errtxt = fmtmsg(MsgBuf, (char *) NULL, p, enhsc, save_errno, fmt, ap);
VA_END;
puterrmsg(MsgBuf);
@ -94,35 +110,35 @@ syserr(fmt, va_alist)
{
if (CurEnv->e_message != NULL)
free(CurEnv->e_message);
CurEnv->e_message = newstr(MsgBuf + 4);
CurEnv->e_message = newstr(errtxt);
}
/* determine exit status if not already set */
if (ExitStat == EX_OK)
{
if (olderrno == 0)
if (save_errno == 0)
ExitStat = EX_SOFTWARE;
else
ExitStat = EX_OSERR;
if (tTd(54, 1))
printf("syserr: ExitStat = %d\n", ExitStat);
dprintf("syserr: ExitStat = %d\n", ExitStat);
}
pw = sm_getpwuid(getuid());
if (pw != NULL)
uname = pw->pw_name;
user = pw->pw_name;
else
{
uname = ubuf;
snprintf(ubuf, sizeof ubuf, "UID%d", getuid());
user = ubuf;
snprintf(ubuf, sizeof ubuf, "UID%d", (int) getuid());
}
if (LogLevel > 0)
sm_syslog(panic ? LOG_ALERT : LOG_CRIT,
CurEnv == NULL ? NOQID : CurEnv->e_id,
"SYSERR(%s): %.900s",
uname, &MsgBuf[4]);
switch (olderrno)
user, errtxt);
switch (save_errno)
{
case EBADF:
case ENFILE:
@ -130,19 +146,21 @@ syserr(fmt, va_alist)
case ENOTTY:
#ifdef EFBIG
case EFBIG:
#endif
#endif /* EFBIG */
#ifdef ESPIPE
case ESPIPE:
#endif
#endif /* ESPIPE */
#ifdef EPIPE
case EPIPE:
#endif
#endif /* EPIPE */
#ifdef ENOBUFS
case ENOBUFS:
#endif
#endif /* ENOBUFS */
#ifdef ESTALE
case ESTALE:
#endif
#endif /* ESTALE */
printopenfds(TRUE);
mci_dump_all(TRUE);
break;
@ -151,7 +169,8 @@ syserr(fmt, va_alist)
{
#ifdef XLA
xla_all_end();
#endif
#endif /* XLA */
sync_queue_time();
if (tTd(0, 1))
abort();
exit(EX_OSERR);
@ -182,21 +201,31 @@ syserr(fmt, va_alist)
void
#ifdef __STDC__
usrerr(const char *fmt, ...)
#else
#else /* __STDC__ */
usrerr(fmt, va_alist)
const char *fmt;
va_dcl
#endif
#endif /* __STDC__ */
{
char *enhsc;
char *errtxt;
VA_LOCAL_DECL
if (fmt[0] == '5' || fmt[0] == '6')
enhsc = "5.0.0";
else if (fmt[0] == '4' || fmt[0] == '8')
enhsc = "4.0.0";
else if (fmt[0] == '2')
enhsc = "2.0.0";
else
enhsc = NULL;
VA_START(fmt);
errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "501", enhsc, 0, fmt, ap);
VA_END;
if (SuprErrs)
return;
VA_START(fmt);
fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
VA_END;
/* save this message for mailq printing */
switch (MsgBuf[0])
{
@ -205,7 +234,7 @@ usrerr(fmt, va_alist)
if (CurEnv->e_message != NULL)
break;
/* fall through.... */
/* FALLTHROUGH */
case '5':
case '6':
@ -216,12 +245,12 @@ usrerr(fmt, va_alist)
char buf[MAXLINE];
snprintf(buf, sizeof buf, "Postmaster warning: %.*s",
(int)sizeof buf - 22, MsgBuf + 4);
(int) sizeof buf - 22, errtxt);
CurEnv->e_message = newstr(buf);
}
else
{
CurEnv->e_message = newstr(MsgBuf + 4);
CurEnv->e_message = newstr(errtxt);
}
break;
}
@ -229,9 +258,93 @@ usrerr(fmt, va_alist)
puterrmsg(MsgBuf);
if (LogLevel > 3 && LogUsrErrs)
sm_syslog(LOG_NOTICE, CurEnv->e_id,
"%.900s",
&MsgBuf[4]);
sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt);
if (QuickAbort)
longjmp(TopFrame, 1);
}
/*
** USRERRENH -- Signal user error.
**
** Same as usrerr but with enhanced status code.
**
** Parameters:
** enhsc -- the enhanced status code.
** fmt -- the format string. If it does not begin with
** a three-digit SMTP reply code, 501 is assumed.
** (others) -- printf strings
**
** Returns:
** none
** Through TopFrame if QuickAbort is set.
**
** Side Effects:
** increments Errors.
*/
/*VARARGS1*/
void
#ifdef __STDC__
usrerrenh(char *enhsc, const char *fmt, ...)
#else /* __STDC__ */
usrerrenh(enhsc, fmt, va_alist)
char *enhsc;
const char *fmt;
va_dcl
#endif /* __STDC__ */
{
char *errtxt;
VA_LOCAL_DECL
if (enhsc == NULL || *enhsc == '\0')
{
if (fmt[0] == '5' || fmt[0] == '6')
enhsc = "5.0.0";
else if (fmt[0] == '4' || fmt[0] == '8')
enhsc = "4.0.0";
else if (fmt[0] == '2')
enhsc = "2.0.0";
}
VA_START(fmt);
errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "501", enhsc, 0, fmt, ap);
VA_END;
if (SuprErrs)
return;
/* save this message for mailq printing */
switch (MsgBuf[0])
{
case '4':
case '8':
if (CurEnv->e_message != NULL)
break;
/* FALLTHROUGH */
case '5':
case '6':
if (CurEnv->e_message != NULL)
free(CurEnv->e_message);
if (MsgBuf[0] == '6')
{
char buf[MAXLINE];
snprintf(buf, sizeof buf, "Postmaster warning: %.*s",
(int) sizeof buf - 22, errtxt);
CurEnv->e_message = newstr(buf);
}
else
{
CurEnv->e_message = newstr(errtxt);
}
break;
}
puterrmsg(MsgBuf);
if (LogLevel > 3 && LogUsrErrs)
sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt);
if (QuickAbort)
longjmp(TopFrame, 1);
@ -255,17 +368,18 @@ usrerr(fmt, va_alist)
void
#ifdef __STDC__
message(const char *msg, ...)
#else
#else /* __STDC__ */
message(msg, va_alist)
const char *msg;
va_dcl
#endif
#endif /* __STDC__ */
{
char *errtxt;
VA_LOCAL_DECL
errno = 0;
VA_START(msg);
fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "050", (char *) NULL, 0, msg, ap);
VA_END;
putoutmsg(MsgBuf, FALSE, FALSE);
@ -276,12 +390,12 @@ message(msg, va_alist)
case '8':
if (CurEnv->e_message != NULL)
break;
/* fall through.... */
/* FALLTHROUGH */
case '5':
if (CurEnv->e_message != NULL)
free(CurEnv->e_message);
CurEnv->e_message = newstr(MsgBuf + 4);
CurEnv->e_message = newstr(errtxt);
break;
}
}
@ -307,17 +421,19 @@ message(msg, va_alist)
void
#ifdef __STDC__
nmessage(const char *msg, ...)
#else
#else /* __STDC__ */
nmessage(msg, va_alist)
const char *msg;
va_dcl
#endif
#endif /* __STDC__ */
{
char *errtxt;
VA_LOCAL_DECL
errno = 0;
VA_START(msg);
fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
errtxt = fmtmsg(MsgBuf, (char *) NULL, "050",
(char *) NULL, 0, msg, ap);
VA_END;
putoutmsg(MsgBuf, FALSE, FALSE);
@ -328,12 +444,12 @@ nmessage(msg, va_alist)
case '8':
if (CurEnv->e_message != NULL)
break;
/* fall through.... */
/* FALLTHROUGH */
case '5':
if (CurEnv->e_message != NULL)
free(CurEnv->e_message);
CurEnv->e_message = newstr(MsgBuf + 4);
CurEnv->e_message = newstr(errtxt);
break;
}
}
@ -356,17 +472,18 @@ nmessage(msg, va_alist)
** Deletes SMTP reply code number as appropriate.
*/
void
static void
putoutmsg(msg, holdmsg, heldmsg)
char *msg;
bool holdmsg;
bool heldmsg;
{
char *errtxt = msg;
char msgcode = msg[0];
/* display for debugging */
if (tTd(54, 8))
printf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
dprintf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
heldmsg ? " (held)" : "");
/* map warnings to something SMTP can handle */
@ -382,8 +499,8 @@ putoutmsg(msg, holdmsg, heldmsg)
if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
sm_syslog(LOG_INFO, CurEnv->e_id,
"--> %s%s",
msg, holdmsg ? " (held)" : "");
"--> %s%s",
msg, holdmsg ? " (held)" : "");
if (msgcode == '8')
msg[0] = '0';
@ -395,6 +512,8 @@ putoutmsg(msg, holdmsg, heldmsg)
{
/* save for possible future display */
msg[0] = msgcode;
if (HeldMessageBuf[0] == '5' && msgcode == '4')
return;
snprintf(HeldMessageBuf, sizeof HeldMessageBuf, "%s", msg);
return;
}
@ -403,16 +522,29 @@ putoutmsg(msg, holdmsg, heldmsg)
if (OutChannel == NULL)
return;
/* find actual text of error (after SMTP status codes) */
if (ISSMTPREPLY(errtxt))
{
int l;
errtxt += 4;
l = isenhsc(errtxt, ' ');
if (l <= 0)
l = isenhsc(errtxt, '\0');
if (l > 0)
errtxt += l + 1;
}
/* if DisConnected, OutChannel now points to the transcript */
if (!DisConnected &&
(OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
fprintf(OutChannel, "%s\r\n", msg);
else
fprintf(OutChannel, "%s\n", &msg[4]);
fprintf(OutChannel, "%s\n", errtxt);
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%05d >>> %s\n", (int) getpid(),
(OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : &msg[4]);
(OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : errtxt);
if (msg[3] == ' ')
(void) fflush(OutChannel);
if (!ferror(OutChannel) || DisConnected)
@ -432,9 +564,9 @@ putoutmsg(msg, holdmsg, heldmsg)
HoldErrs = TRUE;
if (LogLevel > 0)
sm_syslog(LOG_CRIT, CurEnv->e_id,
"SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
CurHostName == NULL ? "NO-HOST" : CurHostName,
shortenstring(msg, MAXSHORTSTR), errstring(errno));
"SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
CurHostName == NULL ? "NO-HOST" : CurHostName,
shortenstring(msg, MAXSHORTSTR), errstring(errno));
}
/*
** PUTERRMSG -- like putoutmsg, but does special processing for error messages
@ -449,7 +581,7 @@ putoutmsg(msg, holdmsg, heldmsg)
** Sets the fatal error bit in the envelope as appropriate.
*/
void
static void
puterrmsg(msg)
char *msg;
{
@ -467,7 +599,7 @@ puterrmsg(msg)
if (CurEnv == NULL)
return;
if (msgcode == '6')
{
/* notify the postmaster */
@ -480,28 +612,122 @@ puterrmsg(msg)
}
}
/*
** ISENHSC -- check whether a string contains an enhanced status code
**
** Parameters:
** s -- string with possible enhanced status code.
** delim -- delim for enhanced status code.
**
** Returns:
** 0 -- no enhanced status code.
** >4 -- length of enhanced status code.
**
** Side Effects:
** none.
*/
int
isenhsc(s, delim)
const char *s;
int delim;
{
int l, h;
if (s == NULL)
return 0;
if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.'))
return 0;
h = 0;
l = 2;
while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
++h;
if (h == 0 || s[l + h] != '.')
return 0;
l += h + 1;
h = 0;
while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
++h;
if (h == 0 || s[l + h] != delim)
return 0;
return l + h;
}
/*
** EXTENHSC -- check and extract an enhanced status code
**
** Parameters:
** s -- string with possible enhanced status code.
** delim -- delim for enhanced status code.
** e -- pointer to storage for enhanced status code.
** must be != NULL and have space for at least
** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3})
**
** Returns:
** 0 -- no enhanced status code.
** >4 -- length of enhanced status code.
**
** Side Effects:
** fills e with enhanced status code.
*/
int
extenhsc(s, delim, e)
const char *s;
int delim;
char *e;
{
int l, h;
if (s == NULL)
return 0;
if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.'))
return 0;
h = 0;
l = 2;
e[0] = s[0];
e[1] = '.';
while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
{
e[l + h] = s[l + h];
++h;
}
if (h == 0 || s[l + h] != '.')
return 0;
e[l + h] = '.';
l += h + 1;
h = 0;
while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
{
e[l + h] = s[l + h];
++h;
}
if (h == 0 || s[l + h] != delim)
return 0;
e[l + h] = '\0';
return l + h;
}
/*
** FMTMSG -- format a message into buffer.
**
** Parameters:
** eb -- error buffer to get result.
** eb -- error buffer to get result -- MUST BE MsgBuf.
** to -- the recipient tag for this message.
** num -- arpanet error number.
** num -- default three digit SMTP reply code.
** enhsc -- enhanced status code.
** en -- the error number to display.
** fmt -- format of string.
** a, b, c, d, e -- arguments.
** ap -- arguments for fmt.
**
** Returns:
** none.
** pointer to error text beyond status codes.
**
** Side Effects:
** none.
*/
static void
fmtmsg(eb, to, num, eno, fmt, ap)
static char *
fmtmsg(eb, to, num, enhsc, eno, fmt, ap)
register char *eb;
const char *to;
const char *num;
const char *enhsc;
int eno;
const char *fmt;
va_list ap;
@ -509,11 +735,10 @@ fmtmsg(eb, to, num, eno, fmt, ap)
char del;
int l;
int spaceleft = sizeof MsgBuf;
char *errtxt;
/* output the reply code */
if (isascii(fmt[0]) && isdigit(fmt[0]) &&
isascii(fmt[1]) && isdigit(fmt[1]) &&
isascii(fmt[2]) && isdigit(fmt[2]))
if (ISSMTPCODE(fmt))
{
num = fmt;
fmt += 4;
@ -526,6 +751,26 @@ fmtmsg(eb, to, num, eno, fmt, ap)
eb += 4;
spaceleft -= 4;
if ((l = isenhsc(fmt, ' ' )) > 0 && l < spaceleft - 4)
{
/* copy enh.status code including trailing blank */
l++;
(void) strlcpy(eb, fmt, l + 1);
eb += l;
spaceleft -= l;
fmt += l;
}
else if ((l = isenhsc(enhsc, '\0')) > 0 && l < spaceleft - 4)
{
/* copy enh.status code */
(void) strlcpy(eb, enhsc, l + 1);
eb[l] = ' ';
eb[++l] = '\0';
eb += l;
spaceleft -= l;
}
errtxt = eb;
/* output the file name and line number */
if (FileName != NULL)
{
@ -556,6 +801,8 @@ fmtmsg(eb, to, num, eno, fmt, ap)
/* output the error code, if any */
if (eno != 0)
(void) snprintf(eb, spaceleft, ": %s", errstring(eno));
return errtxt;
}
/*
** BUFFER_ERRORS -- arrange to buffer future error messages
@ -613,13 +860,10 @@ errstring(errnum)
char *dnsmsg;
char *bp;
static char buf[MAXLINE];
# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
extern char *sys_errlist[];
extern int sys_nerr;
# endif
# if SMTP
extern char *SmtpPhase;
# endif /* SMTP */
#endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */
/*
** Handle special network error codes.
@ -630,18 +874,18 @@ errstring(errnum)
dnsmsg = NULL;
switch (errnum)
{
# if defined(DAEMON) && defined(ETIMEDOUT)
#if defined(DAEMON) && defined(ETIMEDOUT)
case ETIMEDOUT:
case ECONNRESET:
bp = buf;
#if HASSTRERROR
# if HASSTRERROR
snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum));
#else
# else /* HASSTRERROR */
if (errnum >= 0 && errnum < sys_nerr)
snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]);
else
snprintf(bp, SPACELEFT(buf, bp), "Error %d", errnum);
#endif
# endif /* HASSTRERROR */
bp += strlen(bp);
if (CurHostName != NULL)
{
@ -666,24 +910,24 @@ errstring(errnum)
snprintf(bp, SPACELEFT(buf, bp), " during %s",
SmtpPhase);
}
return (buf);
return buf;
case EHOSTDOWN:
if (CurHostName == NULL)
break;
(void) snprintf(buf, sizeof buf, "Host %s is down",
shortenstring(CurHostName, MAXSHORTSTR));
return (buf);
return buf;
case ECONNREFUSED:
if (CurHostName == NULL)
break;
(void) snprintf(buf, sizeof buf, "Connection refused by %s",
shortenstring(CurHostName, MAXSHORTSTR));
return (buf);
# endif
return buf;
#endif /* defined(DAEMON) && defined(ETIMEDOUT) */
# if NAMED_BIND
#if NAMED_BIND
case HOST_NOT_FOUND + E_DNSBASE:
dnsmsg = "host not found";
break;
@ -699,7 +943,7 @@ errstring(errnum)
case NO_DATA + E_DNSBASE:
dnsmsg = "no data known";
break;
# endif
#endif /* NAMED_BIND */
case EPERM:
/* SunOS gives "Not owner" -- this is the POSIX message */
@ -738,13 +982,18 @@ errstring(errnum)
case E_SM_GWFILE:
return "Group writable file";
case E_SM_GRFILE:
return "Group readable file";
case E_SM_WRFILE:
return "World readable file";
}
if (dnsmsg != NULL)
{
bp = buf;
strcpy(bp, "Name server: ");
bp += strlen(bp);
bp += strlcpy(bp, "Name server: ", sizeof buf);
if (CurHostName != NULL)
{
snprintf(bp, SPACELEFT(buf, bp), "%s: ",
@ -755,13 +1004,18 @@ errstring(errnum)
return buf;
}
#ifdef LDAPMAP
if (errnum >= E_LDAPBASE)
return ldap_err2string(errnum - E_LDAPBASE);
#endif /* LDAPMAP */
#if HASSTRERROR
return strerror(errnum);
#else
#else /* HASSTRERROR */
if (errnum > 0 && errnum < sys_nerr)
return (sys_errlist[errnum]);
return sys_errlist[errnum];
(void) snprintf(buf, sizeof buf, "Error %d", errnum);
return (buf);
#endif
return buf;
#endif /* HASSTRERROR */
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 1998 Sendmail, Inc. All rights reserved.
.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
.\" All rights reserved.
.\" Copyright (c) 1983, 1997 Eric P. Allman. All rights reserved.
.\" Copyright (c) 1985, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -8,53 +9,59 @@
.\" the sendmail distribution.
.\"
.\"
.\" @(#)mailq.1 8.10 (Berkeley) 5/19/1998
.\" $Id: mailq.1,v 8.14.28.1 2000/07/14 05:07:01 gshapiro Exp $
.\"
.Dd May 19, 1998
.Dt MAILQ 1
.Os BSD 4
.Sh NAME
.Nm mailq
.Nd print the mail queue
.Sh SYNOPSIS
.Nm mailq
.Op Fl v
.Sh DESCRIPTION
.Nm Mailq
.\" $FreeBSD$
.\"
.TH MAILQ 1 "$Date: 2000/07/14 05:07:01 $"
.SH NAME
.B mailq
\- print the mail queue
.SH SYNOPSIS
.B mailq
.RB [ \-v ]
.SH DESCRIPTION
.B Mailq
prints a summary of the mail messages queued for future delivery.
.Pp
The first line printed for each message
shows the internal identifier used on this host
for the message,
.PP
The first line printed for each message
shows the internal identifier used on this host
for the message with a possible status character,
the size of the message in bytes,
the date and time the message was accepted into the queue,
and the envelope sender of the message.
The second line shows the error message that caused this message
to be retained in the queue;
it will not be present if the message is being processed
for the first time.
The following lines show message recipients,
the date and time the message was accepted into the queue,
and the envelope sender of the message.
The second line shows the error message that caused this message
to be retained in the queue;
it will not be present if the message is being processed
for the first time.
The status characters are either
.B *
to indicate the job is being processed;
.B X
to indicate that the load is too high to process the job; and
.B -
to indicate that the job is too young to process.
The following lines show message recipients,
one per line.
.Pp
.PP
The options are as follows:
.Bl -tag -width Ds
.It Fl v
Print verbose information.
This adds the priority of the message and
a single character indicator (``+'' or blank)
indicating whether a warning message has been sent
.TP
.B \-v
Print verbose information.
This adds the priority of the message and
a single character indicator (``+'' or blank)
indicating whether a warning message has been sent
on the first line of the message.
Additionally, extra lines may be intermixed with the recipients
indicating the ``controlling user'' information;
this shows who will own any programs that are executed
on behalf of this message
indicating the ``controlling user'' information;
this shows who will own any programs that are executed
on behalf of this message
and the name of the alias this command expanded from, if any.
.El
.Pp
.PP
The
.Nm mailq
.B mailq
utility exits 0 on success, and >0 if an error occurs.
.Sh NOTES
.SH NOTES
.Nm Mailq
is identical to
.Dq Li "sendmail -bp" .
@ -62,10 +69,10 @@ Most of the options which apply to
.Xr sendmail 8
also apply to
.Nm mailq .
.Sh SEE ALSO
.Xr sendmail 8
.Sh HISTORY
.SH SEE ALSO
sendmail(8)
.SH HISTORY
The
.Nm mailq
command appeared in
.Bx 4.0 .
.B mailq
command appeared in
4.0BSD.

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
@ -11,13 +12,27 @@
*/
#ifndef lint
static char sccsid[] = "@(#)mci.c 8.83 (Berkeley) 10/13/1998";
#endif /* not lint */
static char id[] = "@(#)$Id: mci.c,v 8.133.10.3 2000/06/23 16:17:06 ca Exp $";
#endif /* ! lint */
/* $FreeBSD$ */
#include <sendmail.h>
#if NETINET || NETINET6
# include <arpa/inet.h>
#endif /* NETINET || NETINET6 */
#include "sendmail.h"
#include <arpa/inet.h>
#include <dirent.h>
static int mci_generate_persistent_path __P((const char *, char *,
int, bool));
static bool mci_load_persistent __P((MCI *));
static void mci_uncache __P((MCI **, bool));
static int mci_lock_host_statfile __P((MCI *));
static int mci_read_persistent __P((FILE *, MCI *));
/*
** Mail Connection Information (MCI) Caching Module.
**
@ -49,11 +64,8 @@ static char sccsid[] = "@(#)mci.c 8.83 (Berkeley) 10/13/1998";
** MCI structure.
*/
MCI **MciCache; /* the open connection cache */
static MCI **MciCache; /* the open connection cache */
extern int mci_generate_persistent_path __P((const char *, char *, int, bool));
extern bool mci_load_persistent __P((MCI *));
extern void mci_uncache __P((MCI **, bool));
/*
** MCI_CACHE -- enter a connection structure into the open connection cache
**
@ -96,12 +108,13 @@ mci_cache(mci)
mci_uncache(mcislot, TRUE);
if (tTd(42, 5))
printf("mci_cache: caching %lx (%s) in slot %d\n",
(u_long) mci, mci->mci_host, (int)(mcislot - MciCache));
dprintf("mci_cache: caching %lx (%s) in slot %d\n",
(u_long) mci, mci->mci_host,
(int)(mcislot - MciCache));
if (tTd(91, 100))
sm_syslog(LOG_DEBUG, CurEnv->e_id,
"mci_cache: caching %x (%.100s) in slot %d",
mci, mci->mci_host, mcislot - MciCache);
"mci_cache: caching %lx (%.100s) in slot %d",
(u_long) mci, mci->mci_host, mcislot - MciCache);
*mcislot = mci;
mci->mci_flags |= MCIF_CACHED;
@ -135,8 +148,8 @@ mci_scan(savemci)
{
/* first call */
MciCache = (MCI **) xalloc(MaxMciCache * sizeof *MciCache);
bzero((char *) MciCache, MaxMciCache * sizeof *MciCache);
return (&MciCache[0]);
memset((char *) MciCache, '\0', MaxMciCache * sizeof *MciCache);
return &MciCache[0];
}
now = curtime();
@ -149,10 +162,16 @@ mci_scan(savemci)
bestmci = &MciCache[i];
continue;
}
if (mci->mci_lastuse + MciCacheTimeout < now && mci != savemci)
if ((mci->mci_lastuse + MciCacheTimeout < now ||
(mci->mci_mailer != NULL &&
mci->mci_mailer->m_maxdeliveries > 0 &&
mci->mci_deliveries + 1 >= mci->mci_mailer->m_maxdeliveries))&&
mci != savemci)
{
/* connection idle too long -- close it */
/* connection idle too long or too many deliveries */
bestmci = &MciCache[i];
/* close it */
mci_uncache(bestmci, TRUE);
continue;
}
@ -178,7 +197,7 @@ mci_scan(savemci)
** none.
*/
void
static void
mci_uncache(mcislot, doquit)
register MCI **mcislot;
bool doquit;
@ -196,14 +215,16 @@ mci_uncache(mcislot, doquit)
mci_unlock_host(mci);
if (tTd(42, 5))
printf("mci_uncache: uncaching %lx (%s) from slot %d (%d)\n",
dprintf("mci_uncache: uncaching %lx (%s) from slot %d (%d)\n",
(u_long) mci, mci->mci_host,
(int)(mcislot - MciCache), doquit);
if (tTd(91, 100))
sm_syslog(LOG_DEBUG, CurEnv->e_id,
"mci_uncache: uncaching %x (%.100s) from slot %d (%d)",
mci, mci->mci_host, mcislot - MciCache, doquit);
"mci_uncache: uncaching %lx (%.100s) from slot %d (%d)",
(u_long) mci, mci->mci_host,
mcislot - MciCache, doquit);
mci->mci_deliveries = 0;
#if SMTP
if (doquit)
{
@ -214,17 +235,17 @@ mci_uncache(mcislot, doquit)
/* only uses the envelope to flush the transcript file */
if (mci->mci_state != MCIS_CLOSED)
smtpquit(mci->mci_mailer, mci, &BlankEnvelope);
#ifdef XLA
# ifdef XLA
xla_host_end(mci->mci_host);
#endif
# endif /* XLA */
}
else
#endif
#endif /* SMTP */
{
if (mci->mci_in != NULL)
xfclose(mci->mci_in, "mci_uncache", "mci_in");
(void) fclose(mci->mci_in);
if (mci->mci_out != NULL)
xfclose(mci->mci_out, "mci_uncache", "mci_out");
(void) fclose(mci->mci_out);
mci->mci_in = mci->mci_out = NULL;
mci->mci_state = MCIS_CLOSED;
mci->mci_exitstat = EX_OK;
@ -274,22 +295,30 @@ mci_get(host, m)
extern SOCKADDR CurHostAddr;
/* clear CurHostAddr so we don't get a bogus address with this name */
bzero(&CurHostAddr, sizeof CurHostAddr);
#endif
memset(&CurHostAddr, '\0', sizeof CurHostAddr);
#endif /* DAEMON */
/* clear out any expired connections */
(void) mci_scan(NULL);
if (m->m_mno < 0)
syserr("negative mno %d (%s)", m->m_mno, m->m_name);
s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
mci = &s->s_mci;
mci->mci_host = s->s_name;
if (!mci_load_persistent(mci))
/*
** We don't need to load the peristent data if we have data
** already loaded in the cache.
*/
if (mci->mci_host == NULL &&
(mci->mci_host = s->s_name) != NULL &&
!mci_load_persistent(mci))
{
if (tTd(42, 2))
printf("mci_get(%s %s): lock failed\n", host, m->m_name);
dprintf("mci_get(%s %s): lock failed\n",
host, m->m_name);
mci->mci_exitstat = EX_TEMPFAIL;
mci->mci_state = MCIS_CLOSED;
mci->mci_statfile = NULL;
@ -298,7 +327,7 @@ mci_get(host, m)
if (tTd(42, 2))
{
printf("mci_get(%s %s): mci_state=%d, _flags=%x, _exitstat=%d, _errno=%d\n",
dprintf("mci_get(%s %s): mci_state=%d, _flags=%lx, _exitstat=%d, _errno=%d\n",
host, m->m_name, mci->mci_state, mci->mci_flags,
mci->mci_exitstat, mci->mci_errno);
}
@ -306,8 +335,6 @@ mci_get(host, m)
#if SMTP
if (mci->mci_state == MCIS_OPEN)
{
extern int smtpprobe __P((MCI *));
/* poke the connection to see if it's still alive */
(void) smtpprobe(mci);
@ -328,9 +355,9 @@ mci_get(host, m)
(void) getpeername(fileno(mci->mci_in),
(struct sockaddr *) &CurHostAddr, &socklen);
}
# endif
# endif /* DAEMON */
}
#endif
#endif /* SMTP */
if (mci->mci_state == MCIS_CLOSED)
{
time_t now = curtime();
@ -347,6 +374,29 @@ mci_get(host, m)
return mci;
}
/*
** MCI_MATCH -- check connection cache for a particular host
*/
bool
mci_match(host, m)
char *host;
MAILER *m;
{
register MCI *mci;
register STAB *s;
if (m->m_mno < 0)
return FALSE;
s = stab(host, ST_MCI + m->m_mno, ST_FIND);
if (s == NULL)
return FALSE;
mci = &s->s_mci;
if (mci->mci_state == MCIS_OPEN)
return TRUE;
return FALSE;
}
/*
** MCI_SETSTAT -- set status codes in MCI structure.
**
** Parameters:
@ -395,7 +445,7 @@ struct mcifbits
int mcif_bit; /* flag bit */
char *mcif_name; /* flag name */
};
struct mcifbits MciFlags[] =
static struct mcifbits MciFlags[] =
{
{ MCIF_VALID, "VALID" },
{ MCIF_TEMP, "TEMP" },
@ -424,7 +474,6 @@ mci_dump(mci, logit)
register char *p;
char *sep;
char buf[4000];
extern char *ctime();
sep = logit ? " " : "\n\t";
p = buf;
@ -437,7 +486,7 @@ mci_dump(mci, logit)
snprintf(p, SPACELEFT(buf, p), "NULL");
goto printit;
}
snprintf(p, SPACELEFT(buf, p), "flags=%x", mci->mci_flags);
snprintf(p, SPACELEFT(buf, p), "flags=%lx", mci->mci_flags);
p += strlen(p);
if (mci->mci_flags != 0)
{
@ -456,7 +505,7 @@ mci_dump(mci, logit)
snprintf(p, SPACELEFT(buf, p),
",%serrno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,%s",
sep, mci->mci_errno, mci->mci_herrno,
mci->mci_exitstat, mci->mci_state, mci->mci_pid, sep);
mci->mci_exitstat, mci->mci_state, (int) mci->mci_pid, sep);
p += strlen(p);
snprintf(p, SPACELEFT(buf, p),
"maxsize=%ld, phase=%s, mailer=%s,%s",
@ -519,7 +568,7 @@ mci_dump_all(logit)
** mci -- containing the host we want to lock.
**
** Returns:
** EX_OK -- got the lock.
** EX_OK -- got the lock.
** EX_TEMPFAIL -- didn't get the lock.
*/
@ -530,7 +579,7 @@ mci_lock_host(mci)
if (mci == NULL)
{
if (tTd(56, 1))
printf("mci_lock_host: NULL mci\n");
dprintf("mci_lock_host: NULL mci\n");
return EX_OK;
}
@ -540,34 +589,34 @@ mci_lock_host(mci)
return mci_lock_host_statfile(mci);
}
int
static int
mci_lock_host_statfile(mci)
MCI *mci;
{
int savedErrno = errno;
int save_errno = errno;
int retVal = EX_OK;
char fname[MAXPATHLEN+1];
char fname[MAXPATHLEN + 1];
if (HostStatDir == NULL || mci->mci_host == NULL)
return EX_OK;
if (tTd(56, 2))
printf("mci_lock_host: attempting to lock %s\n",
dprintf("mci_lock_host: attempting to lock %s\n",
mci->mci_host);
if (mci_generate_persistent_path(mci->mci_host, fname, sizeof fname, TRUE) < 0)
{
/* of course this should never happen */
if (tTd(56, 2))
printf("mci_lock_host: Failed to generate host path for %s\n",
mci->mci_host);
dprintf("mci_lock_host: Failed to generate host path for %s\n",
mci->mci_host);
retVal = EX_TEMPFAIL;
goto cleanup;
}
mci->mci_statfile = safefopen(fname, O_RDWR, FileMode,
SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_SAFEDIRPATH|SFF_CREAT);
SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_SAFEDIRPATH|SFF_CREAT);
if (mci->mci_statfile == NULL)
{
@ -579,19 +628,19 @@ mci_lock_host_statfile(mci)
if (!lockfile(fileno(mci->mci_statfile), fname, "", LOCK_EX|LOCK_NB))
{
if (tTd(56, 2))
printf("mci_lock_host: couldn't get lock on %s\n",
fname);
fclose(mci->mci_statfile);
dprintf("mci_lock_host: couldn't get lock on %s\n",
fname);
(void) fclose(mci->mci_statfile);
mci->mci_statfile = NULL;
retVal = EX_TEMPFAIL;
goto cleanup;
}
if (tTd(56, 12) && mci->mci_statfile != NULL)
printf("mci_lock_host: Sanity check -- lock is good\n");
dprintf("mci_lock_host: Sanity check -- lock is good\n");
cleanup:
errno = savedErrno;
errno = save_errno;
return retVal;
}
/*
@ -611,12 +660,12 @@ void
mci_unlock_host(mci)
MCI *mci;
{
int saveErrno = errno;
int save_errno = errno;
if (mci == NULL)
{
if (tTd(56, 1))
printf("mci_unlock_host: NULL mci\n");
dprintf("mci_unlock_host: NULL mci\n");
return;
}
@ -626,23 +675,23 @@ mci_unlock_host(mci)
if (!SingleThreadDelivery && mci_lock_host_statfile(mci) == EX_TEMPFAIL)
{
if (tTd(56, 1))
printf("mci_unlock_host: stat file already locked\n");
dprintf("mci_unlock_host: stat file already locked\n");
}
else
{
if (tTd(56, 2))
printf("mci_unlock_host: store prior to unlock\n");
dprintf("mci_unlock_host: store prior to unlock\n");
mci_store_persistent(mci);
}
if (mci->mci_statfile != NULL)
{
fclose(mci->mci_statfile);
(void) fclose(mci->mci_statfile);
mci->mci_statfile = NULL;
}
errno = saveErrno;
errno = save_errno;
}
/*
** MCI_LOAD_PERSISTENT -- load persistent host info
@ -659,38 +708,38 @@ mci_unlock_host(mci)
** FALSE -- lock failed
*/
bool
static bool
mci_load_persistent(mci)
MCI *mci;
{
int saveErrno = errno;
int save_errno = errno;
bool locked = TRUE;
FILE *fp;
char fname[MAXPATHLEN+1];
char fname[MAXPATHLEN + 1];
if (mci == NULL)
{
if (tTd(56, 1))
printf("mci_load_persistent: NULL mci\n");
dprintf("mci_load_persistent: NULL mci\n");
return TRUE;
}
if (IgnoreHostStatus || HostStatDir == NULL || mci->mci_host == NULL)
return TRUE;
/* Already have the persistent information in memory */
if (SingleThreadDelivery && mci->mci_statfile != NULL)
return TRUE;
if (tTd(56, 1))
printf("mci_load_persistent: Attempting to load persistent information for %s\n",
mci->mci_host);
dprintf("mci_load_persistent: Attempting to load persistent information for %s\n",
mci->mci_host);
if (mci_generate_persistent_path(mci->mci_host, fname, sizeof fname, FALSE) < 0)
{
/* Not much we can do if the file isn't there... */
if (tTd(56, 1))
printf("mci_load_persistent: Couldn't generate host path\n");
dprintf("mci_load_persistent: Couldn't generate host path\n");
goto cleanup;
}
@ -700,21 +749,23 @@ mci_load_persistent(mci)
{
/* I can't think of any reason this should ever happen */
if (tTd(56, 1))
printf("mci_load_persistent: open(%s): %s\n",
dprintf("mci_load_persistent: open(%s): %s\n",
fname, errstring(errno));
goto cleanup;
}
FileName = fname;
locked = lockfile(fileno(fp), fname, "", LOCK_SH|LOCK_NB);
(void) mci_read_persistent(fp, mci);
FileName = NULL;
if (locked)
lockfile(fileno(fp), fname, "", LOCK_UN);
fclose(fp);
{
(void) mci_read_persistent(fp, mci);
(void) lockfile(fileno(fp), fname, "", LOCK_UN);
}
FileName = NULL;
(void) fclose(fp);
cleanup:
errno = saveErrno;
errno = save_errno;
return locked;
}
/*
@ -736,7 +787,7 @@ cleanup:
** perfectly safe due to underlying stdio buffering.
*/
int
static int
mci_read_persistent(fp, mci)
FILE *fp;
register MCI *mci;
@ -752,7 +803,7 @@ mci_read_persistent(fp, mci)
syserr("mci_read_persistent: NULL mci");
if (tTd(56, 93))
{
printf("mci_read_persistent: fp=%lx, mci=", (u_long) fp);
dprintf("mci_read_persistent: fp=%lx, mci=", (u_long) fp);
mci_dump(mci, FALSE);
}
@ -837,12 +888,12 @@ void
mci_store_persistent(mci)
MCI *mci;
{
int saveErrno = errno;
int save_errno = errno;
if (mci == NULL)
{
if (tTd(56, 1))
printf("mci_store_persistent: NULL mci\n");
dprintf("mci_store_persistent: NULL mci\n");
return;
}
@ -850,20 +901,20 @@ mci_store_persistent(mci)
return;
if (tTd(56, 1))
printf("mci_store_persistent: Storing information for %s\n",
mci->mci_host);
dprintf("mci_store_persistent: Storing information for %s\n",
mci->mci_host);
if (mci->mci_statfile == NULL)
{
if (tTd(56, 1))
printf("mci_store_persistent: no statfile\n");
dprintf("mci_store_persistent: no statfile\n");
return;
}
rewind(mci->mci_statfile);
#if !NOFTRUNCATE
(void) ftruncate(fileno(mci->mci_statfile), (off_t) 0);
#endif
#endif /* !NOFTRUNCATE */
fprintf(mci->mci_statfile, "V0\n");
fprintf(mci->mci_statfile, "E%d\n", mci->mci_errno);
@ -878,9 +929,9 @@ mci_store_persistent(mci)
fprintf(mci->mci_statfile, "U%ld\n", (long)(mci->mci_lastuse));
fprintf(mci->mci_statfile, ".\n");
fflush(mci->mci_statfile);
(void) fflush(mci->mci_statfile);
errno = saveErrno;
errno = save_errno;
return;
}
/*
@ -905,6 +956,7 @@ mci_store_persistent(mci)
** < 0 -- if any action routine returns a negative value, that
** value is returned.
** 0 -- if we successfully went to completion.
** > 0 -- return status from action()
*/
int
@ -922,13 +974,13 @@ mci_traverse_persistent(action, pathname)
return -1;
if (tTd(56, 1))
printf("mci_traverse: pathname is %s\n", pathname);
dprintf("mci_traverse: pathname is %s\n", pathname);
ret = stat(pathname, &statbuf);
if (ret < 0)
{
if (tTd(56, 2))
printf("mci_traverse: Failed to stat %s: %s\n",
dprintf("mci_traverse: Failed to stat %s: %s\n",
pathname, errstring(errno));
return ret;
}
@ -936,12 +988,13 @@ mci_traverse_persistent(action, pathname)
{
struct dirent *e;
char *newptr;
char newpath[MAXPATHLEN+1];
char newpath[MAXPATHLEN + 1];
bool leftone, removedone;
if ((d = opendir(pathname)) == NULL)
{
if (tTd(56, 2))
printf("mci_traverse: opendir %s: %s\n",
dprintf("mci_traverse: opendir %s: %s\n",
pathname, errstring(errno));
return -1;
}
@ -949,41 +1002,62 @@ mci_traverse_persistent(action, pathname)
if (strlen(pathname) >= sizeof newpath - MAXNAMLEN - 3)
{
if (tTd(56, 2))
printf("mci_traverse: path \"%s\" too long",
dprintf("mci_traverse: path \"%s\" too long",
pathname);
return -1;
}
strcpy(newpath, pathname);
(void) strlcpy(newpath, pathname, sizeof newpath);
newptr = newpath + strlen(newpath);
*newptr++ = '/';
while ((e = readdir(d)) != NULL)
/*
** repeat until no file has been removed
** this may become ugly when several files "expire"
** during these loops, but it's better than doing
** a rewinddir() inside the inner loop
*/
do
{
if (e->d_name[0] == '.')
continue;
leftone = removedone = FALSE;
while ((e = readdir(d)) != NULL)
{
if (e->d_name[0] == '.')
continue;
strncpy(newptr, e->d_name,
sizeof newpath - (newptr - newpath) - 1);
newpath[sizeof newpath - 1] = '\0';
(void) strlcpy(newptr, e->d_name,
sizeof newpath -
(newptr - newpath));
ret = mci_traverse_persistent(action, newpath);
ret = mci_traverse_persistent(action, newpath);
if (ret < 0)
break;
if (ret == 1)
leftone = TRUE;
if (!removedone && ret == 0 &&
action == mci_purge_persistent)
removedone = TRUE;
}
if (ret < 0)
break;
/*
** The following appears to be
** necessary during purges, since
** we modify the directory structure
*/
if (action == mci_purge_persistent)
if (removedone)
rewinddir(d);
}
if (tTd(56, 40))
dprintf("mci_traverse: path %s: ret %d removed %d left %d\n",
pathname, ret, removedone, leftone);
} while (removedone);
/* purge (or whatever) the directory proper */
*--newptr = '\0';
ret = (*action)(newpath, NULL);
closedir(d);
if (!leftone)
{
*--newptr = '\0';
ret = (*action)(newpath, NULL);
}
(void) closedir(d);
}
else if (S_ISREG(statbuf.st_mode))
{
@ -992,7 +1066,7 @@ mci_traverse_persistent(action, pathname)
char *scan;
char host[MAXHOSTNAMELEN];
char *hostptr = host;
/*
** Reconstruct the host name from the path to the
** persistent information.
@ -1027,7 +1101,7 @@ mci_traverse_persistent(action, pathname)
return ret;
}
/*
** MCI_PRINT_PERSISTENT -- print persisten info
** MCI_PRINT_PERSISTENT -- print persistent info
**
** Dump the persistent information in the file 'pathname'
**
@ -1066,23 +1140,23 @@ mci_print_persistent(pathname, hostname)
if (fp == NULL)
{
if (tTd(56, 1))
printf("mci_print_persistent: cannot open %s: %s\n",
dprintf("mci_print_persistent: cannot open %s: %s\n",
pathname, errstring(errno));
return 0;
}
FileName = pathname;
bzero(&mcib, sizeof mcib);
memset(&mcib, '\0', sizeof mcib);
if (mci_read_persistent(fp, &mcib) < 0)
{
syserr("%s: could not read status file", pathname);
fclose(fp);
(void) fclose(fp);
FileName = NULL;
return 0;
}
locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB);
fclose(fp);
(void) fclose(fp);
FileName = NULL;
printf("%c%-39s %12s ",
@ -1125,7 +1199,9 @@ mci_print_persistent(pathname, hostname)
** NULL if this is a directory (domain).
**
** Returns:
** 0
** 0 -- ok
** 1 -- file not deleted (too young, incorrect format)
** < 0 -- some error occurred
*/
int
@ -1133,18 +1209,30 @@ mci_purge_persistent(pathname, hostname)
char *pathname;
char *hostname;
{
struct stat statbuf;
char *end = pathname + strlen(pathname) - 1;
int ret;
if (tTd(56, 1))
printf("mci_purge_persistent: purging %s\n", pathname);
dprintf("mci_purge_persistent: purging %s\n", pathname);
ret = stat(pathname, &statbuf);
if (ret < 0)
{
if (tTd(56, 2))
dprintf("mci_purge_persistent: Failed to stat %s: %s\n",
pathname, errstring(errno));
return ret;
}
if (curtime() - statbuf.st_mtime < MciInfoTimeout)
return 1;
if (hostname != NULL)
{
/* remove the file */
if (unlink(pathname) < 0)
{
if (tTd(56, 2))
printf("mci_purge_persistent: failed to unlink %s: %s\n",
dprintf("mci_purge_persistent: failed to unlink %s: %s\n",
pathname, errstring(errno));
}
}
@ -1152,18 +1240,18 @@ mci_purge_persistent(pathname, hostname)
{
/* remove the directory */
if (*end != '.')
return 0;
return 1;
if (tTd(56, 1))
printf("mci_purge_persistent: dpurge %s\n", pathname);
dprintf("mci_purge_persistent: dpurge %s\n", pathname);
if (rmdir(pathname) < 0)
{
if (tTd(56, 2))
printf("mci_purge_persistent: rmdir %s: %s\n",
dprintf("mci_purge_persistent: rmdir %s: %s\n",
pathname, errstring(errno));
}
}
return 0;
@ -1187,7 +1275,7 @@ mci_purge_persistent(pathname, hostname)
** -1 -- failure
*/
int
static int
mci_generate_persistent_path(host, path, pathlen, createflag)
const char *host;
char *path;
@ -1198,6 +1286,9 @@ mci_generate_persistent_path(host, path, pathlen, createflag)
int ret = 0;
int len;
char t_host[MAXHOSTNAMELEN];
#if NETINET6
struct in6_addr in6_addr;
#endif /* NETINET6 */
/*
** Rationality check the arguments.
@ -1215,7 +1306,7 @@ mci_generate_persistent_path(host, path, pathlen, createflag)
}
if (tTd(56, 80))
printf("mci_generate_persistent_path(%s): ", host);
dprintf("mci_generate_persistent_path(%s): ", host);
if (*host == '\0' || *host == '.')
return -1;
@ -1224,9 +1315,9 @@ mci_generate_persistent_path(host, path, pathlen, createflag)
if (strlen(host) > sizeof t_host - 1)
return -1;
if (host[0] == '[')
strcpy(t_host, host + 1);
else
strcpy(t_host, host);
(void) strlcpy(t_host, host + 1, sizeof t_host);
else
(void) strlcpy(t_host, host, sizeof t_host);
/*
** Delete any trailing dots from the hostname.
@ -1238,9 +1329,18 @@ mci_generate_persistent_path(host, path, pathlen, createflag)
(elem[-1] == '.' || (host[0] == '[' && elem[-1] == ']')))
*--elem = '\0';
#if NETINET || NETINET6
/* check for bogus bracketed address */
if (host[0] == '[' && inet_addr(t_host) == INADDR_NONE)
if (host[0] == '[' &&
# if NETINET6
inet_pton(AF_INET6, t_host, &in6_addr) != 1 &&
# endif /* NETINET6 */
# if NETINET
inet_addr(t_host) == INADDR_NONE
# endif /* NETINET */
)
return -1;
#endif /* NETINET || NETINET6 */
/* check for what will be the final length of the path */
len = strlen(HostStatDir) + 2;
@ -1255,7 +1355,7 @@ mci_generate_persistent_path(host, path, pathlen, createflag)
if (len > pathlen || len < 1)
return -1;
strcpy(path, HostStatDir);
(void) strlcpy(path, HostStatDir, pathlen);
p = path + strlen(path);
while (elem > t_host)
@ -1286,10 +1386,10 @@ mci_generate_persistent_path(host, path, pathlen, createflag)
if (tTd(56, 80))
{
if (ret < 0)
printf("FAILURE %d\n", ret);
dprintf("FAILURE %d\n", ret);
else
printf("SUCCESS %s\n", path);
dprintf("SUCCESS %s\n", path);
}
return (ret);
return ret;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff