diff options
author | gshapiro <gshapiro@FreeBSD.org> | 2000-08-12 22:19:16 +0000 |
---|---|---|
committer | gshapiro <gshapiro@FreeBSD.org> | 2000-08-12 22:19:16 +0000 |
commit | 74c280481f7b3087059573dc63b94ac093b17466 (patch) | |
tree | 7f1b2dddabe7373f19a658433a351ef5464ef883 /contrib/sendmail | |
parent | c3cd75415d60bc002b20182ffd3383ea9e901a80 (diff) | |
download | FreeBSD-src-74c280481f7b3087059573dc63b94ac093b17466.zip FreeBSD-src-74c280481f7b3087059573dc63b94ac093b17466.tar.gz |
Fix conflicts from merge of sendmail 8.11.0.
PR: bin/11552 misc/18512 bin/15088
Diffstat (limited to 'contrib/sendmail')
-rw-r--r-- | contrib/sendmail/cf/m4/cfhead.m4 | 154 | ||||
-rw-r--r-- | contrib/sendmail/cf/ostype/bsd4.4.m4 | 10 | ||||
-rw-r--r-- | contrib/sendmail/cf/sh/makeinfo.sh | 7 | ||||
-rw-r--r-- | contrib/sendmail/contrib/bitdomain.c | 14 | ||||
-rw-r--r-- | contrib/sendmail/mail.local/mail.local.8 | 136 | ||||
-rw-r--r-- | contrib/sendmail/mail.local/mail.local.c | 1556 | ||||
-rw-r--r-- | contrib/sendmail/mailstats/mailstats.c | 144 | ||||
-rw-r--r-- | contrib/sendmail/makemap/makemap.c | 1034 | ||||
-rw-r--r-- | contrib/sendmail/praliases/praliases.c | 483 | ||||
-rw-r--r-- | contrib/sendmail/rmail/rmail.c | 334 | ||||
-rw-r--r-- | contrib/sendmail/smrsh/smrsh.8 | 14 | ||||
-rw-r--r-- | contrib/sendmail/smrsh/smrsh.c | 330 | ||||
-rw-r--r-- | contrib/sendmail/src/aliases.5 | 165 | ||||
-rw-r--r-- | contrib/sendmail/src/conf.c | 2630 | ||||
-rw-r--r-- | contrib/sendmail/src/conf.h | 1372 | ||||
-rw-r--r-- | contrib/sendmail/src/err.c | 440 | ||||
-rw-r--r-- | contrib/sendmail/src/headers.c | 496 | ||||
-rw-r--r-- | contrib/sendmail/src/mailq.1 | 95 | ||||
-rw-r--r-- | contrib/sendmail/src/mci.c | 360 | ||||
-rw-r--r-- | contrib/sendmail/src/savemail.c | 486 | ||||
-rw-r--r-- | contrib/sendmail/src/sendmail.8 | 939 |
21 files changed, 6697 insertions, 4502 deletions
diff --git a/contrib/sendmail/cf/m4/cfhead.m4 b/contrib/sendmail/cf/m4/cfhead.m4 index abd390e..c229e70 100644 --- a/contrib/sendmail/cf/m4/cfhead.m4 +++ b/contrib/sendmail/cf/m4/cfhead.m4 @@ -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 $') diff --git a/contrib/sendmail/cf/ostype/bsd4.4.m4 b/contrib/sendmail/cf/ostype/bsd4.4.m4 index f94e653..65309b9 100644 --- a/contrib/sendmail/cf/ostype/bsd4.4.m4 +++ b/contrib/sendmail/cf/ostype/bsd4.4.m4 @@ -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 diff --git a/contrib/sendmail/cf/sh/makeinfo.sh b/contrib/sendmail/cf/sh/makeinfo.sh index 91de99b..8fb371c 100644 --- a/contrib/sendmail/cf/sh/makeinfo.sh +++ b/contrib/sendmail/cf/sh/makeinfo.sh @@ -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 diff --git a/contrib/sendmail/contrib/bitdomain.c b/contrib/sendmail/contrib/bitdomain.c index ec79b95..b864d65 100644 --- a/contrib/sendmail/contrib/bitdomain.c +++ b/contrib/sendmail/contrib/bitdomain.c @@ -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() } } } - + diff --git a/contrib/sendmail/mail.local/mail.local.8 b/contrib/sendmail/mail.local/mail.local.8 index 541a7ee..246a952 100644 --- a/contrib/sendmail/mail.local/mail.local.8 +++ b/contrib/sendmail/mail.local/mail.local.8 @@ -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 . diff --git a/contrib/sendmail/mail.local/mail.local.c b/contrib/sendmail/mail.local/mail.local.c index 2a405c5e..03fe02c 100644 --- a/contrib/sendmail/mail.local/mail.local.c +++ b/contrib/sendmail/mail.local/mail.local.c @@ -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) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * @@ -11,31 +12,37 @@ #ifndef lint static char copyright[] = -"@(#) Copyright (c) 1990, 1993, 1994\n\ +"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ +#endif /* ! lint */ #ifndef lint -static char sccsid[] = "@(#)mail.local.c 8.83 (Berkeley) 12/17/1998"; -#endif /* not lint */ +static char id[] = "@(#)$Id: mail.local.c,v 8.143.4.13 2000/07/18 05:41:38 gshapiro Exp $"; +#endif /* ! lint */ + +/* $FreeBSD$ */ /* - * This is not intended to work on System V derived systems - * such as Solaris or HP-UX, since they use a totally different - * approach to mailboxes (essentially, they have a setgid program - * rather than setuid, and they rely on the ability to "give away" - * files to do their work). IT IS NOT A BUG that this doesn't - * work on such architectures. - */ +** This is not intended to work on System V derived systems +** such as Solaris or HP-UX, since they use a totally different +** approach to mailboxes (essentially, they have a setgid program +** rather than setuid, and they rely on the ability to "give away" +** files to do their work). IT IS NOT A BUG that this doesn't +** work on such architectures. +*/ + +#include <sys/types.h> #include <sys/param.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/file.h> #include <netinet/in.h> +#include <arpa/nameser.h> -#include <errno.h> #include <fcntl.h> #include <netdb.h> #include <pwd.h> @@ -47,73 +54,100 @@ static char sccsid[] = "@(#)mail.local.c 8.83 (Berkeley) 12/17/1998"; #include <unistd.h> #ifdef EX_OK # undef EX_OK /* unistd.h may have another use for this */ -#endif +#endif /* EX_OK */ #include <sysexits.h> #include <ctype.h> +#ifndef __P +# include "sendmail/cdefs.h" +#endif /* ! __P */ +#include "sendmail/useful.h" + +extern size_t strlcpy __P((char *, const char *, size_t)); +extern size_t strlcat __P((char *, const char *, size_t)); + +#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) */ + +#include "sendmail/errstring.h" + + +#ifndef LOCKTO_RM +# define LOCKTO_RM 300 /* timeout for stale lockfile removal */ +#endif /* LOCKTO_RM */ +#ifndef LOCKTO_GLOB +# define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ +#endif /* LOCKTO_GLOB */ + #ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif +# include <stdarg.h> +# define REALLOC(ptr, size) realloc(ptr, size) +#else /* __STDC__ */ +# include <varargs.h> +/* define a realloc() which works for NULL pointers */ +# define REALLOC(ptr, size) (((ptr) == NULL) ? malloc(size) : realloc(ptr, size)) +#endif /* __STDC__ */ #if (defined(sun) && defined(__svr4__)) || defined(__SVR4) # define USE_LOCKF 1 # define USE_SETEUID 1 -# define _PATH_MAILDIR "/var/mail" -#endif +# define _PATH_MAILDIR "/var/mail" +#endif /* (defined(sun) && defined(__svr4__)) || defined(__SVR4) */ -#if (defined(sun) && !defined(__svr4__)) && !defined(__SVR4) -# ifdef __dead -# undef __dead -# define __dead -# endif -#endif +#ifdef NCR_MP_RAS3 +# define USE_LOCKF 1 +# define HASSNPRINTF 1 +# define _PATH_MAILDIR "/var/mail" +#endif /* NCR_MP_RAS3 */ #if defined(_AIX) # define USE_LOCKF 1 # define USE_SETEUID 1 # define USE_VSYSLOG 0 -#endif +#endif /* defined(_AIX) */ #if defined(__hpux) # define USE_LOCKF 1 # define USE_SETRESUID 1 # define USE_VSYSLOG 0 -# ifdef __dead -# undef __dead -# define __dead -# endif -#endif +#endif /* defined(__hpux) */ + +#ifdef DGUX +# define HASSNPRINTF 1 +# define USE_LOCKF 1 +# define USE_VSYSLOG 0 +#endif /* DGUX */ #if defined(_CRAY) # if !defined(MAXPATHLEN) # define MAXPATHLEN PATHSIZE -# endif +# endif /* !defined(MAXPATHLEN) */ # define USE_VSYSLOG 0 -# define _PATH_MAILDIR "/usr/spool/mail" -#endif +# define _PATH_MAILDIR "/usr/spool/mail" +#endif /* defined(_CRAY) */ #if defined(ultrix) # define USE_VSYSLOG 0 -#endif +#endif /* defined(ultrix) */ #if defined(__osf__) # define USE_VSYSLOG 0 -#endif +#endif /* defined(__osf__) */ #if defined(NeXT) && !defined(__APPLE__) # include <libc.h> -# define _PATH_MAILDIR "/usr/spool/mail" -# define __dead /* empty */ +# define _PATH_MAILDIR "/usr/spool/mail" # define S_IRUSR S_IREAD # define S_IWUSR S_IWRITE -#endif +#endif /* defined(NeXT) && !defined(__APPLE__) */ #if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) -# include <paths.h> -# define HASSTRERROR 1 /* has strerror(3) */ -#endif +# include <paths.h> +#endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ /* * If you don't have flock, you could try using lockf instead. @@ -121,119 +155,126 @@ static char sccsid[] = "@(#)mail.local.c 8.83 (Berkeley) 12/17/1998"; #ifdef USE_LOCKF # define flock(a, b) lockf(a, b, 0) +# ifdef LOCK_EX +# undef LOCK_EX +# endif /* LOCK_EX */ # define LOCK_EX F_LOCK -#endif +#endif /* USE_LOCKF */ #ifndef USE_VSYSLOG # define USE_VSYSLOG 1 -#endif +#endif /* ! USE_VSYSLOG */ #ifndef LOCK_EX # include <sys/file.h> -#endif +#endif /* ! LOCK_EX */ #if defined(BSD4_4) || defined(__GLIBC__) -# include "pathnames.h" -#endif - -#ifndef __P -# ifdef __STDC__ -# define __P(protos) protos -# else -# define __P(protos) () -# define const -# endif -#endif -#ifndef __dead -# if defined(__GNUC__) && (__GNUC__ < 2 || __GNUC_MINOR__ < 5) && !defined(__STRICT_ANSI__) -# define __dead __volatile -# else -# define __dead -# endif -#endif +# include <paths.h> +# define _PATH_LOCTMP "/var/tmp/local.XXXXXX" +#endif /* defined(BSD4_4) || defined(__GLIBC__) */ #ifdef BSD4_4 # define HAS_ST_GEN 1 -#else +#else /* BSD4_4 */ # ifndef _BSD_VA_LIST_ # define _BSD_VA_LIST_ va_list -# endif -#endif +# endif /* ! _BSD_VA_LIST_ */ +#endif /* BSD4_4 */ #if defined(BSD4_4) || defined(linux) # define HASSNPRINTF 1 -#else +#else /* defined(BSD4_4) || defined(linux) */ # ifndef ultrix extern FILE *fdopen __P((int, const char *)); -# endif -#endif +# endif /* ! ultrix */ +#endif /* defined(BSD4_4) || defined(linux) */ + +#if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) +# define CONTENTLENGTH 1 /* Needs the Content-Length header */ +#endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ #if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) # define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ -#endif +#endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ + +#ifdef HPUX11 +# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ +#endif /* HPUX11 */ + +#if _AIX4 >= 40300 +# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */ +#endif /* _AIX4 >= 40300 */ #if !HASSNPRINTF extern int snprintf __P((char *, size_t, const char *, ...)); # ifndef _CRAY extern int vsnprintf __P((char *, size_t, const char *, ...)); -# endif -#endif - -#if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) -# ifndef HASSTRERROR -# define HASSTRERROR 1 -# endif -#endif - -#if !HASSTRERROR -extern char *strerror __P((int)); -#endif +# endif /* ! _CRAY */ +#endif /* !HASSNPRINTF */ /* - * If you don't have setreuid, and you have saved uids, and you have - * a seteuid() call that doesn't try to emulate using setuid(), then - * you can try defining USE_SETEUID. - */ +** If you don't have setreuid, and you have saved uids, and you have +** a seteuid() call that doesn't try to emulate using setuid(), then +** you can try defining USE_SETEUID. +*/ #ifdef USE_SETEUID # define setreuid(r, e) seteuid(e) -#endif +#endif /* USE_SETEUID */ /* - * And of course on hpux you have setresuid() - */ +** And of course on hpux you have setresuid() +*/ #ifdef USE_SETRESUID # define setreuid(r, e) setresuid(-1, e, -1) -#endif +#endif /* USE_SETRESUID */ #ifndef _PATH_LOCTMP -# define _PATH_LOCTMP "/tmp/local.XXXXXX" -#endif -#ifndef _PATH_MAILDIR -# define _PATH_MAILDIR "/var/spool/mail" -#endif +# define _PATH_LOCTMP "/var/tmp/local.XXXXXX" +#endif /* ! _PATH_LOCTMP */ +# ifndef _PATH_MAILDIR +# define _PATH_MAILDIR "/var/spool/mail" +# endif /* ! _PATH_MAILDIR */ #ifndef S_ISREG # define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG) -#endif +#endif /* ! S_ISREG */ + +#ifdef MAILLOCK +# include <maillock.h> +#endif /* MAILLOCK */ + +#ifndef INADDRSZ +# define INADDRSZ 4 /* size of an IPv4 address in bytes */ +#endif /* ! INADDRSZ */ #ifndef MAILER_DAEMON # define MAILER_DAEMON "MAILER-DAEMON" -#endif - -int eval = EX_OK; /* sysexits.h error value. */ -int lmtpmode = 0; -u_char tTdvect[100]; - -void deliver __P((int, char *, int, int)); -void e_to_sys __P((int)); -void notifybiff __P((char *)); -int store __P((char *, int)); -void usage __P((void)); -void vwarn __P((const char *, _BSD_VA_LIST_)); -void lockmbox __P((char *)); -void unlockmbox __P((void)); -void mailerr __P((const char *, const char *, ...)); -void dolmtp __P((int, int)); +#endif /* ! MAILER_DAEMON */ + +#ifdef CONTENTLENGTH +char ContentHdr[40] = "Content-Length: "; +off_t HeaderLength; +off_t BodyLength; +#endif /* CONTENTLENGTH */ + +bool EightBitMime = TRUE; /* advertise 8BITMIME in LMTP */ +int ExitVal = EX_OK; /* sysexits.h error value. */ +bool LMTPMode = FALSE; +bool bouncequota = FALSE; /* permanent error when over quota */ +bool nobiff = FALSE; +bool nofsync = FALSE; + +void deliver __P((int, char *, bool)); +int e_to_sys __P((int)); +void notifybiff __P((char *)); +int store __P((char *, int)); +void usage __P((void)); +void vwarn __P((const char *, _BSD_VA_LIST_)); +int lockmbox __P((char *)); +void unlockmbox __P((void)); +void mailerr __P((const char *, const char *, ...)); + int main(argc, argv) @@ -241,11 +282,13 @@ main(argc, argv) char *argv[]; { struct passwd *pw; - int ch, fd, nobiff, nofsync; + int ch, fd; uid_t uid; char *from; extern char *optarg; extern int optind; + extern void dolmtp __P((bool)); + /* make sure we have some open file descriptors */ for (fd = 10; fd < 30; fd++) @@ -254,79 +297,103 @@ main(argc, argv) /* use a reasonable umask */ (void) umask(0077); -#ifdef LOG_MAIL +# ifdef LOG_MAIL openlog("mail.local", 0, LOG_MAIL); -#else +# else /* LOG_MAIL */ openlog("mail.local", 0); -#endif +# endif /* LOG_MAIL */ from = NULL; - nobiff = 0; - nofsync = 0; - while ((ch = getopt(argc, argv, "bdf:r:ls")) != -1) - switch(ch) { - case 'b': - nobiff++; + while ((ch = getopt(argc, argv, "7bdf:r:l")) != -1) + { + switch(ch) + { + case '7': /* Do not advertise 8BITMIME */ + EightBitMime = FALSE; + break; + + case 'B': + nobiff = TRUE; + break; + + case 'b': /* bounce mail when over quota. */ + bouncequota = TRUE; break; - case 'd': /* Backward compatible. */ + + case 'd': /* Backward compatible. */ break; - case 'f': - case 'r': /* Backward compatible. */ - if (from != NULL) { + + case 'f': + case 'r': /* Backward compatible. */ + if (from != NULL) + { mailerr(NULL, "multiple -f options"); usage(); } from = optarg; break; - case 'l': - lmtpmode++; + + case 'l': + LMTPMode = TRUE; break; - case 's': + + case 's': nofsync++; break; - case '?': - default: + + case '?': + default: usage(); } + } argc -= optind; argv += optind; - if (lmtpmode) - dolmtp(nobiff, nofsync); + /* initialize biff structures */ + if (!nobiff) + notifybiff(NULL); + + if (LMTPMode) + dolmtp(bouncequota); - if (!*argv) + if (*argv == '\0') usage(); /* - * If from not specified, use the name from getlogin() if the - * uid matches, otherwise, use the name from the password file - * corresponding to the uid. - */ + ** If from not specified, use the name from getlogin() if the + ** uid matches, otherwise, use the name from the password file + ** corresponding to the uid. + */ uid = getuid(); - if (!from && (!(from = getlogin()) || - !(pw = getpwnam(from)) || pw->pw_uid != uid)) - from = (pw = getpwuid(uid)) ? pw->pw_name : "???"; + + if (from == NULL && ((from = getlogin()) == NULL || + (pw = getpwnam(from)) == NULL || + pw->pw_uid != uid)) + from = (pw = getpwuid(uid)) != NULL ? pw->pw_name : "???"; /* - * There is no way to distinguish the error status of one delivery - * from the rest of the deliveries. So, if we failed hard on one - * or more deliveries, but had no failures on any of the others, we - * return a hard failure. If we failed temporarily on one or more - * deliveries, we return a temporary failure regardless of the other - * failures. This results in the delivery being reattempted later - * at the expense of repeated failures and multiple deliveries. - */ + ** There is no way to distinguish the error status of one delivery + ** from the rest of the deliveries. So, if we failed hard on one + ** or more deliveries, but had no failures on any of the others, we + ** return a hard failure. If we failed temporarily on one or more + ** deliveries, we return a temporary failure regardless of the other + ** failures. This results in the delivery being reattempted later + ** at the expense of repeated failures and multiple deliveries. + */ for (fd = store(from, 0); *argv; ++argv) - deliver(fd, *argv, nobiff, nofsync); - exit(eval); + deliver(fd, *argv, bouncequota); + exit(ExitVal); + /* NOTREACHED */ + return ExitVal; } char * -parseaddr(s) +parseaddr(s, rcpt) char *s; + bool rcpt; { char *p; - int len; + int l; if (*s++ != '<') return NULL; @@ -334,94 +401,79 @@ parseaddr(s) p = s; /* at-domain-list */ - while (*p == '@') { + while (*p == '@') + { p++; - if (*p == '[') { + while (*p != ',' && *p != ':' && *p != '\0') p++; - while (isascii(*p) && - (isalnum(*p) || *p == '.' || - *p == '-' || *p == ':')) - p++; - if (*p++ != ']') - return NULL; - } else { - while ((isascii(*p) && isalnum(*p)) || - strchr(".-_", *p)) - p++; - } - if (*p == ',' && p[1] == '@') - p++; - else if (*p == ':' && p[1] != '@') - p++; - else + if (*p == '\0') return NULL; + + /* Skip over , or : */ + p++; } s = p; /* local-part */ - if (*p == '\"') { - p++; - while (*p && *p != '\"') { - if (*p == '\\') { - if (!*++p) - return NULL; - } - p++; - } - if (!*p++) - return NULL; - } else { - while (*p && *p != '@' && *p != '>') { - if (*p == '\\') { - if (!*++p) - return NULL; - } else { - if (*p <= ' ' || (*p & 128) || - strchr("<>()[]\\,;:\"", *p)) + while (*p != '\0' && *p != '@' && *p != '>') + { + if (*p == '\\') + { + if (*++p == '\0') return NULL; - } + } + else if (*p == '\"') + { p++; + while (*p != '\0' && *p != '\"') + { + if (*p == '\\') + { + if (*++p == '\0') + return NULL; + } + p++; + } + if (*p == '\0' || *(p + 1) == '\0') + return NULL; } + /* +detail ? */ + if (*p == '+' && rcpt) + *p = '\0'; + p++; } /* @domain */ - if (*p == '@') { - p++; - if (*p == '[') { + if (*p == '@') + { + if (rcpt) + *p++ = '\0'; + while (*p != '\0' && *p != '>') p++; - while (isascii(*p) && - (isalnum(*p) || *p == '.' || - *p == '-' || *p == ':')) - p++; - if (*p++ != ']') - return NULL; - } else { - while ((isascii(*p) && isalnum(*p)) || - strchr(".-_", *p)) - p++; - } } - if (*p++ != '>') + if (*p != '>') return NULL; - if (*p && *p != ' ') + else + *p = '\0'; + p++; + + if (*p != '\0' && *p != ' ') return NULL; - len = p - s - 1; - if (*s == '\0' || len <= 0) - { + + if (*s == '\0') s = MAILER_DAEMON; - len = strlen(s); - } - p = malloc(len + 1); - if (p == NULL) { + l = strlen(s) + 1; + p = malloc(l); + if (p == NULL) + { printf("421 4.3.0 memory exhausted\r\n"); exit(EX_TEMPFAIL); } - strncpy(p, s, len); - p[len] = '\0'; + (void) strlcpy(p, s, l); return p; } @@ -429,51 +481,51 @@ char * process_recipient(addr) char *addr; { - if (getpwnam(addr) == NULL) { + if (getpwnam(addr) == NULL) return "550 5.1.1 user unknown"; - } - return NULL; } - #define RCPT_GROW 30 void -dolmtp(nobiff, nofsync) - int nobiff, nofsync; +dolmtp(bouncequota) + bool bouncequota; { char *return_path = NULL; char **rcpt_addr = NULL; int rcpt_num = 0; int rcpt_alloc = 0; - char myhostname[1024]; - char buf[4096]; + bool gotlhlo = FALSE; char *err; int msgfd; char *p; int i; + char myhostname[1024]; + char buf[4096]; - gethostname(myhostname, sizeof myhostname - 1); + (void) gethostname(myhostname, sizeof myhostname - 1); printf("220 %s LMTP ready\r\n", myhostname); - for (;;) { - fflush(stdout); - if (fgets(buf, sizeof(buf)-1, stdin) == NULL) { + for (;;) + { + (void) fflush(stdout); + if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) exit(EX_OK); - } p = buf + strlen(buf) - 1; if (p >= buf && *p == '\n') *p-- = '\0'; if (p >= buf && *p == '\r') *p-- = '\0'; - switch (buf[0]) { - - case 'd': - case 'D': - if (strcasecmp(buf, "data") == 0) { - if (rcpt_num == 0) { + switch (buf[0]) + { + case 'd': + case 'D': + if (strcasecmp(buf, "data") == 0) + { + if (rcpt_num == 0) + { printf("503 5.5.1 No recipients\r\n"); continue; } @@ -481,36 +533,56 @@ dolmtp(nobiff, nofsync) if (msgfd == -1) continue; - for (i = 0; i < rcpt_num; i++) { + for (i = 0; i < rcpt_num; i++) + { p = strchr(rcpt_addr[i], '+'); if (p != NULL) *p++ = '\0'; - deliver(msgfd, rcpt_addr[i], nobiff, - nofsync); + deliver(msgfd, rcpt_addr[i], bouncequota); } - close(msgfd); + (void) close(msgfd); goto rset; } goto syntaxerr; + /* NOTREACHED */ + break; - case 'l': - case 'L': - if (strncasecmp(buf, "lhlo ", 5) == 0) { - printf("250-%s\r\n250-8BITMIME\r\n250-ENHANCEDSTATUSCODES\r\n250 PIPELINING\r\n", - myhostname); + case 'l': + case 'L': + if (strncasecmp(buf, "lhlo ", 5) == 0) + { + /* check for duplicate per RFC 1651 4.2 */ + if (gotlhlo) + { + printf("503 %s Duplicate LHLO\r\n", + myhostname); + continue; + } + gotlhlo = TRUE; + printf("250-%s\r\n", myhostname); + if (EightBitMime) + printf("250-8BITMIME\r\n"); + printf("250-ENHANCEDSTATUSCODES\r\n"); + printf("250 PIPELINING\r\n"); continue; } goto syntaxerr; + /* NOTREACHED */ + break; - case 'm': - case 'M': - if (strncasecmp(buf, "mail ", 5) == 0) { - if (return_path != NULL) { + case 'm': + case 'M': + if (strncasecmp(buf, "mail ", 5) == 0) + { + if (return_path != NULL) + { printf("503 5.5.1 Nested MAIL command\r\n"); continue; } if (strncasecmp(buf+5, "from:", 5) != 0 || - ((return_path = parseaddr(buf+10)) == NULL)) { + ((return_path = parseaddr(buf + 10, + FALSE)) == NULL)) + { printf("501 5.5.4 Syntax error in parameters\r\n"); continue; } @@ -518,46 +590,62 @@ dolmtp(nobiff, nofsync) continue; } goto syntaxerr; + /* NOTREACHED */ + break; - case 'n': - case 'N': - if (strcasecmp(buf, "noop") == 0) { + case 'n': + case 'N': + if (strcasecmp(buf, "noop") == 0) + { printf("250 2.0.0 ok\r\n"); continue; } goto syntaxerr; + /* NOTREACHED */ + break; - case 'q': - case 'Q': - if (strcasecmp(buf, "quit") == 0) { + case 'q': + case 'Q': + if (strcasecmp(buf, "quit") == 0) + { printf("221 2.0.0 bye\r\n"); exit(EX_OK); } goto syntaxerr; + /* NOTREACHED */ + break; - case 'r': - case 'R': - if (strncasecmp(buf, "rcpt ", 5) == 0) { - if (return_path == NULL) { + case 'r': + case 'R': + if (strncasecmp(buf, "rcpt ", 5) == 0) + { + if (return_path == NULL) + { printf("503 5.5.1 Need MAIL command\r\n"); continue; } - if (rcpt_num >= rcpt_alloc) { + if (rcpt_num >= rcpt_alloc) + { rcpt_alloc += RCPT_GROW; rcpt_addr = (char **) - realloc((char *)rcpt_addr, - rcpt_alloc * sizeof(char **)); - if (rcpt_addr == NULL) { + REALLOC((char *)rcpt_addr, + rcpt_alloc * + sizeof(char **)); + if (rcpt_addr == NULL) + { printf("421 4.3.0 memory exhausted\r\n"); exit(EX_TEMPFAIL); } } - if (strncasecmp(buf+5, "to:", 3) != 0 || - ((rcpt_addr[rcpt_num] = parseaddr(buf+8)) == NULL)) { + if (strncasecmp(buf + 5, "to:", 3) != 0 || + ((rcpt_addr[rcpt_num] = parseaddr(buf + 8, + TRUE)) == NULL)) + { printf("501 5.5.4 Syntax error in parameters\r\n"); continue; } - if ((err = process_recipient(rcpt_addr[rcpt_num])) != NULL) { + if ((err = process_recipient(rcpt_addr[rcpt_num])) != NULL) + { printf("%s\r\n", err); continue; } @@ -565,32 +653,39 @@ dolmtp(nobiff, nofsync) printf("250 2.1.5 ok\r\n"); continue; } - else if (strcasecmp(buf, "rset") == 0) { + else if (strcasecmp(buf, "rset") == 0) + { printf("250 2.0.0 ok\r\n"); - rset: - while (rcpt_num) { +rset: + while (rcpt_num) free(rcpt_addr[--rcpt_num]); - } if (return_path != NULL) free(return_path); return_path = NULL; continue; } goto syntaxerr; + /* NOTREACHED */ + break; - case 'v': - case 'V': - if (strncasecmp(buf, "vrfy ", 5) == 0) { + case 'v': + case 'V': + if (strncasecmp(buf, "vrfy ", 5) == 0) + { printf("252 2.3.3 try RCPT to attempt delivery\r\n"); continue; } goto syntaxerr; + /* NOTREACHED */ + break; - default: + default: syntaxerr: printf("500 5.5.2 Syntax error\r\n"); continue; + /* NOTREACHED */ + break; } } } @@ -602,135 +697,258 @@ store(from, lmtprcpts) { FILE *fp = NULL; time_t tval; - int fd, eline; + bool eline; + bool fullline = TRUE; /* current line is terminated */ + bool prevfl; /* previous line was terminated */ char line[2048]; + int fd; char tmpbuf[sizeof _PATH_LOCTMP + 1]; - strcpy(tmpbuf, _PATH_LOCTMP); - if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL) { - if (lmtprcpts) { + (void) umask(0077); + (void) strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf); + if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL) + { + if (lmtprcpts) + { printf("451 4.3.0 unable to open temporary file\r\n"); return -1; - } else { + } + else + { mailerr("451 4.3.0", "unable to open temporary file"); - exit(eval); + exit(ExitVal); } } - (void)unlink(tmpbuf); + (void) unlink(tmpbuf); - if (lmtpmode) { + if (LMTPMode) + { printf("354 go ahead\r\n"); - fflush(stdout); + (void) fflush(stdout); } - (void)time(&tval); - (void)fprintf(fp, "From %s %s", from, ctime(&tval)); + (void) time(&tval); + (void) fprintf(fp, "From %s %s", from, ctime(&tval)); + +#ifdef CONTENTLENGTH + HeaderLength = 0; + BodyLength = -1; +#endif /* CONTENTLENGTH */ line[0] = '\0'; - for (eline = 1; fgets(line, sizeof(line), stdin);) { - size_t line_len = strlen(line); + eline = TRUE; + while (fgets(line, sizeof(line), stdin) != (char *)NULL) + { + size_t line_len = 0; + int peek; - if (line_len >= 2 && - line[line_len - 2] == '\r' && - line[line_len - 1] == '\n') { - strcpy(line + line_len - 2, "\n"); - } - if (lmtprcpts && line[0] == '.') { - char *src = line + 1, *dest = line; + prevfl = fullline; /* preserve state of previous line */ + while (line[line_len] != '\n' && line_len < sizeof(line) - 2) + line_len++; + line_len++; - if (line[1] == '\n') + /* Check for dot-stuffing */ + if (prevfl && lmtprcpts && line[0] == '.') + { + if (line[1] == '\n' || + (line[1] == '\r' && line[2] == '\n')) goto lmtpdot; - while (*src != '\0') - *dest++ = *src++; - *dest = '\0'; + memcpy(line, line + 1, line_len); + line_len--; } - if (line[0] == '\n') - eline = 1; - else { + + /* Check to see if we have the full line from fgets() */ + fullline = FALSE; + if (line_len > 0) + { + if (line[line_len - 1] == '\n') + { + if (line_len >= 2 && + line[line_len - 2] == '\r') + { + line[line_len - 2] = '\n'; + line[line_len - 1] = '\0'; + line_len--; + } + fullline = TRUE; + } + else if (line[line_len - 1] == '\r') + { + /* Did we just miss the CRLF? */ + peek = fgetc(stdin); + if (peek == '\n') + { + line[line_len - 1] = '\n'; + fullline = TRUE; + } + else + (void) ungetc(peek, stdin); + } + } + else + fullline = TRUE; + +#ifdef CONTENTLENGTH + if (prevfl && line[0] == '\n' && HeaderLength == 0) + { + eline = FALSE; + HeaderLength = ftell(fp); + if (HeaderLength <= 0) + { + /* + ** shouldn't happen, unless ftell() is + ** badly broken + */ + + HeaderLength = -1; + } + } +#else /* CONTENTLENGTH */ + if (prevfl && line[0] == '\n') + eline = TRUE; +#endif /* CONTENTLENGTH */ + else + { if (eline && line[0] == 'F' && !memcmp(line, "From ", 5)) (void)putc('>', fp); - eline = 0; + eline = FALSE; +#ifdef CONTENTLENGTH + /* discard existing "Content-Length:" headers */ + if (prevfl && HeaderLength == 0 && + (line[0] == 'C' || line[0] == 'c') && + strncasecmp(line, ContentHdr, 15) == 0) + { + /* + ** be paranoid: clear the line + ** so no "wrong matches" may occur later + */ + line[0] = '\0'; + continue; + } +#endif /* CONTENTLENGTH */ + } - (void)fprintf(fp, "%s", line); - if (ferror(fp)) { - if (lmtprcpts) { - while (lmtprcpts--) { + (void) fwrite(line, sizeof(char), line_len, fp); + if (ferror(fp)) + { + if (lmtprcpts) + { + while (lmtprcpts--) printf("451 4.3.0 temporary file write error\r\n"); - } - fclose(fp); + (void) fclose(fp); return -1; - } else { + } + else + { mailerr("451 4.3.0", "temporary file write error"); - fclose(fp); - exit(eval); + (void) fclose(fp); + exit(ExitVal); } } } - if (lmtprcpts) { + if (lmtprcpts) + { /* Got a premature EOF -- toss message and exit */ exit(EX_OK); } /* If message not newline terminated, need an extra. */ if (strchr(line, '\n') == NULL) - (void)putc('\n', fp); + (void) putc('\n', fp); lmtpdot: +#ifdef CONTENTLENGTH + BodyLength = ftell(fp); + if (HeaderLength == 0 && BodyLength > 0) /* empty body */ + { + HeaderLength = BodyLength; + BodyLength = 0; + } + else + BodyLength = BodyLength - HeaderLength - 1 ; + + if (HeaderLength > 0 && BodyLength >= 0) + { + extern char *quad_to_string(); + + if (sizeof BodyLength > sizeof(long)) + snprintf(line, sizeof line, "%s\n", + quad_to_string(BodyLength)); + else + snprintf(line, sizeof line, "%ld\n", (long) BodyLength); + strlcpy(&ContentHdr[16], line, sizeof(ContentHdr) - 16); + } + else + BodyLength = -1; /* Something is wrong here */ +#endif /* CONTENTLENGTH */ + /* Output a newline; note, empty messages are allowed. */ - (void)putc('\n', fp); + (void) putc('\n', fp); - if (fflush(fp) == EOF || ferror(fp)) { - if (lmtprcpts) { - while (lmtprcpts--) { + if (fflush(fp) == EOF || ferror(fp) != 0) + { + if (lmtprcpts) + { + while (lmtprcpts--) printf("451 4.3.0 temporary file write error\r\n"); - } - fclose(fp); + (void) fclose(fp); return -1; - } else { + } + else + { mailerr("451 4.3.0", "temporary file write error"); - fclose(fp); - exit(eval); + (void) fclose(fp); + exit(ExitVal); } } - return (fd); + return fd; } void -deliver(fd, name, nobiff, nofsync) +deliver(fd, name, bouncequota) int fd; char *name; - int nobiff, nofsync; + bool bouncequota; { - struct stat fsb, sb; + struct stat fsb; + struct stat sb; struct passwd *pw; - int mbfd, nr, nw, off; + char path[MAXPATHLEN]; + int mbfd, nr = 0, nw, off; char *p; - char biffmsg[100], buf[8*1024], path[MAXPATHLEN]; off_t curoff; +#ifdef CONTENTLENGTH + off_t headerbytes; + int readamount; +#endif /* CONTENTLENGTH */ + char biffmsg[100], buf[8*1024]; extern char *quad_to_string(); + /* - * Disallow delivery to unknown names -- special mailboxes can be - * handled in the sendmail aliases file. - */ - if ((pw = getpwnam(name)) == NULL) { - if (eval != EX_TEMPFAIL) - eval = EX_UNAVAILABLE; - if (lmtpmode) { - if (eval == EX_TEMPFAIL) { + ** Disallow delivery to unknown names -- special mailboxes can be + ** handled in the sendmail aliases file. + */ + if ((pw = getpwnam(name)) == NULL) + { + if (ExitVal != EX_TEMPFAIL) + ExitVal = EX_UNAVAILABLE; + if (LMTPMode) + { + if (ExitVal == EX_TEMPFAIL) printf("451 4.3.0 cannot lookup name: %s\r\n", name); - } else { + else printf("550 5.1.1 unknown name: %s\r\n", name); - } } - else { + else + { char *errcode = NULL; - if (eval == EX_TEMPFAIL) + if (ExitVal == EX_TEMPFAIL) errcode = "451 4.3.0"; else errcode = "550 5.1.1"; @@ -741,12 +959,12 @@ deliver(fd, name, nobiff, nofsync) endpwent(); /* - * Keep name reasonably short to avoid buffer overruns. - * This isn't necessary on BSD because of the proper - * definition of snprintf(), but it can cause problems - * on other systems. - * Also, clear out any bogus characters. - */ + ** Keep name reasonably short to avoid buffer overruns. + ** This isn't necessary on BSD because of the proper + ** definition of snprintf(), but it can cause problems + ** on other systems. + ** Also, clear out any bogus characters. + */ if (strlen(name) > 40) name[40] = '\0'; @@ -758,89 +976,140 @@ deliver(fd, name, nobiff, nofsync) *p = '.'; } - (void)snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name); + + (void) snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name); + /* - * If the mailbox is linked or a symlink, fail. There's an obvious - * race here, that the file was replaced with a symbolic link after - * the lstat returned, but before the open. We attempt to detect - * this by comparing the original stat information and information - * returned by an fstat of the file descriptor returned by the open. - * - * NB: this is a symptom of a larger problem, that the mail spooling - * directory is writeable by the wrong users. If that directory is - * writeable, system security is compromised for other reasons, and - * it cannot be fixed here. - * - * If we created the mailbox, set the owner/group. If that fails, - * just return. Another process may have already opened it, so we - * can't unlink it. Historically, binmail set the owner/group at - * each mail delivery. We no longer do this, assuming that if the - * ownership or permissions were changed there was a reason. - * - * XXX - * open(2) should support flock'ing the file. - */ + ** If the mailbox is linked or a symlink, fail. There's an obvious + ** race here, that the file was replaced with a symbolic link after + ** the lstat returned, but before the open. We attempt to detect + ** this by comparing the original stat information and information + ** returned by an fstat of the file descriptor returned by the open. + ** + ** NB: this is a symptom of a larger problem, that the mail spooling + ** directory is writeable by the wrong users. If that directory is + ** writeable, system security is compromised for other reasons, and + ** it cannot be fixed here. + ** + ** If we created the mailbox, set the owner/group. If that fails, + ** just return. Another process may have already opened it, so we + ** can't unlink it. Historically, binmail set the owner/group at + ** each mail delivery. We no longer do this, assuming that if the + ** ownership or permissions were changed there was a reason. + ** + ** XXX + ** open(2) should support flock'ing the file. + */ + tryagain: - lockmbox(path); - if (lstat(path, &sb) < 0) { - mbfd = open(path, - O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); +#ifdef MAILLOCK + p = name; +#else /* MAILLOCK */ + p = path; +#endif /* MAILLOCK */ + if ((off = lockmbox(p)) != 0) + { + if (off == EX_TEMPFAIL || e_to_sys(off) == EX_TEMPFAIL) + { + ExitVal = EX_TEMPFAIL; + mailerr("451 4.3.0", + "lockmailbox %s failed; error code %d %s", + p, off, errno > 0 ? errstring(errno) : ""); + } + else + { + mailerr("551 5.3.0", + "lockmailbox %s failed; error code %d %s", + p, off, errno > 0 ? errstring(errno) : ""); + } + return; + } + + if (lstat(path, &sb) < 0) + { + int save_errno; + int mode = S_IRUSR|S_IWUSR; + gid_t gid = pw->pw_gid; + +#ifdef MAILGID + (void) umask(0007); + gid = MAILGID; + mode |= S_IRGRP|S_IWGRP; +#endif /* MAILGID */ + + mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY, mode); + + save_errno = errno; + if (lstat(path, &sb) < 0) { - eval = EX_CANTCREAT; + ExitVal = EX_CANTCREAT; mailerr("550 5.2.0", "%s: lstat: file changed after open", path); goto err1; } else sb.st_uid = pw->pw_uid; - if (mbfd == -1) { - if (errno == EEXIST) + if (mbfd == -1) + { + if (save_errno == EEXIST) goto tryagain; - } else if (fchown(mbfd, pw->pw_uid, pw->pw_gid)) { + } + else if (fchown(mbfd, pw->pw_uid, gid) < 0) + { mailerr("451 4.3.0", "chown %u.%u: %s", - pw->pw_uid, pw->pw_gid, name); + pw->pw_uid, gid, name); goto err1; } - } else if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) { + } + else if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) + { mailerr("550 5.2.0", "%s: irregular file", path); goto err0; - } else if (sb.st_uid != pw->pw_uid) { - eval = EX_CANTCREAT; + } + else if (sb.st_uid != pw->pw_uid) + { + ExitVal = EX_CANTCREAT; mailerr("550 5.2.0", "%s: wrong ownership (%d)", - path, sb.st_uid); + path, sb.st_uid); goto err0; - } else { - mbfd = open(path, O_APPEND|O_WRONLY, 0); } + else + mbfd = open(path, O_APPEND|O_WRONLY, 0); - if (mbfd == -1) { - mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); + if (mbfd == -1) + { + mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); goto err0; - } else if (fstat(mbfd, &fsb) < 0 || - fsb.st_nlink != 1 || - sb.st_nlink != 1 || - !S_ISREG(fsb.st_mode) || - sb.st_dev != fsb.st_dev || - sb.st_ino != fsb.st_ino || + } + else if (fstat(mbfd, &fsb) < 0 || + fsb.st_nlink != 1 || + sb.st_nlink != 1 || + !S_ISREG(fsb.st_mode) || + sb.st_dev != fsb.st_dev || + sb.st_ino != fsb.st_ino || #if HAS_ST_GEN && 0 /* AFS returns random values for st_gen */ - sb.st_gen != fsb.st_gen || -#endif - sb.st_uid != fsb.st_uid) { - eval = EX_TEMPFAIL; + sb.st_gen != fsb.st_gen || +#endif /* HAS_ST_GEN && 0 */ + sb.st_uid != fsb.st_uid) + { + ExitVal = EX_TEMPFAIL; mailerr("550 5.2.0", "%s: fstat: file changed after open", path); goto err1; } + /* Wait until we can get a lock on the file. */ - if (flock(mbfd, LOCK_EX)) { - mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); + if (flock(mbfd, LOCK_EX) < 0) + { + mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); goto err1; } - if (!nobiff) { + if (!nobiff) + { /* Get the starting offset of the new message for biff. */ curoff = lseek(mbfd, (off_t)0, SEEK_END); if (sizeof curoff > sizeof(long)) @@ -852,193 +1121,314 @@ tryagain: } /* Copy the message into the file. */ - if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { + if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) + { mailerr("450 4.2.0", "temporary file: %s", - strerror(errno)); + errstring(errno)); goto err1; } - if (setreuid(0, pw->pw_uid) < 0) { + if (setreuid(0, pw->pw_uid) < 0) + { mailerr("450 4.2.0", "setreuid(0, %d): %s (r=%d, e=%d)", - pw->pw_uid, strerror(errno), getuid(), geteuid()); + pw->pw_uid, errstring(errno), getuid(), geteuid()); goto err1; } #ifdef DEBUG - printf("new euid = %d\n", geteuid()); -#endif + fprintf(stderr, "new euid = %d\n", geteuid()); +#endif /* DEBUG */ +#ifdef CONTENTLENGTH + headerbytes = (BodyLength >= 0) ? HeaderLength : -1 ; + for (;;) + { + if (headerbytes == 0) + { + snprintf(buf, sizeof buf, "%s", ContentHdr); + nr = strlen(buf); + headerbytes = -1; + readamount = 0; + } + else if (headerbytes > sizeof(buf) || headerbytes < 0) + readamount = sizeof(buf); + else + readamount = headerbytes; + if (readamount != 0) + nr = read(fd, buf, readamount); + if (nr <= 0) + break; + if (headerbytes > 0) + headerbytes -= nr ; + +#else /* CONTENTLENGTH */ while ((nr = read(fd, buf, sizeof(buf))) > 0) + { +#endif /* CONTENTLENGTH */ for (off = 0; off < nr; off += nw) - if ((nw = write(mbfd, buf + off, nr - off)) < 0) { + { + if ((nw = write(mbfd, buf + off, nr - off)) < 0) + { +#ifdef EDQUOT + if (errno == EDQUOT && bouncequota) + mailerr("552 5.2.2", "%s: %s", + path, errstring(errno)); + else +#endif /* EDQUOT */ mailerr("450 4.2.0", "%s: %s", - path, strerror(errno)); + path, errstring(errno)); goto err3; } - if (nr < 0) { + } + } + if (nr < 0) + { mailerr("450 4.2.0", "temporary file: %s", - strerror(errno)); + errstring(errno)); goto err3; } /* Flush to disk, don't wait for update. */ - if (!nofsync && fsync(mbfd)) { - mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); + if (!nofsync && fsync(mbfd) < 0) + { + mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); err3: - if (setreuid(0, 0) < 0) { + if (setreuid(0, 0) < 0) + { #if 0 /* already printed an error above for this recipient */ - e_to_sys(errno); + (void) e_to_sys(errno); mailerr("450 4.2.0", "setreuid(0, 0): %s", - strerror(errno)); -#endif + errstring(errno)); +#endif /* 0 */ } #ifdef DEBUG - printf("reset euid = %d\n", geteuid()); -#endif - (void)ftruncate(mbfd, curoff); -err1: (void)close(mbfd); + fprintf(stderr, "reset euid = %d\n", geteuid()); +#endif /* DEBUG */ + (void) ftruncate(mbfd, curoff); +err1: (void) close(mbfd); err0: unlockmbox(); return; } /* Close and check -- NFS doesn't write until the close. */ - if (close(mbfd)) { - mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); - truncate(path, curoff); - } else if (!nobiff) + if (close(mbfd)) + { +#ifdef EDQUOT + if (errno == EDQUOT && bouncequota) + mailerr("552 5.2.2", "%s: %s", path, errstring(errno)); + else +#endif /* EDQUOT */ + mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); + (void) truncate(path, curoff); + } + else if (!nobiff) notifybiff(biffmsg); - if (setreuid(0, 0) < 0) { + if (setreuid(0, 0) < 0) + { mailerr("450 4.2.0", "setreuid(0, 0): %s", - strerror(errno)); + errstring(errno)); goto err0; } #ifdef DEBUG - printf("reset euid = %d\n", geteuid()); -#endif + fprintf(stderr, "reset euid = %d\n", geteuid()); +#endif /* DEBUG */ unlockmbox(); - if (lmtpmode) { + if (LMTPMode) printf("250 2.1.5 %s OK\r\n", name); - } } /* - * user.lock files are necessary for compatibility with other - * systems, e.g., when the mail spool file is NFS exported. - * Alas, mailbox locking is more than just a local matter. - * EPA 11/94. - */ +** user.lock files are necessary for compatibility with other +** systems, e.g., when the mail spool file is NFS exported. +** Alas, mailbox locking is more than just a local matter. +** EPA 11/94. +*/ -char lockname[MAXPATHLEN]; -int locked = 0; +bool Locked = FALSE; + +#ifdef MAILLOCK +int +lockmbox(name) + char *name; +{ + int r; + + if (Locked) + return 0; + if ((r = maillock(name, 15)) == L_SUCCESS) + { + Locked = TRUE; + return 0; + } + switch (r) + { + case L_TMPLOCK: /* Can't create tmp file */ + case L_TMPWRITE: /* Can't write pid into lockfile */ + case L_MAXTRYS: /* Failed after retrycnt attempts */ + errno = 0; + r = EX_TEMPFAIL; + break; + case L_ERROR: /* Check errno for reason */ + r = errno; + break; + default: /* other permanent errors */ + errno = 0; + r = EX_UNAVAILABLE; + break; + } + return r; +} void +unlockmbox() +{ + if (Locked) + mailunlock(); + Locked = FALSE; +} +#else /* MAILLOCK */ + +char LockName[MAXPATHLEN]; + +int lockmbox(path) char *path; { int statfailed = 0; - - if (locked) - return; - if (strlen(path) + 6 > sizeof lockname) - return; - snprintf(lockname, sizeof lockname, "%s.lock", path); - for (;; sleep(5)) { + time_t start; + + if (Locked) + return 0; + if (strlen(path) + 6 > sizeof LockName) + return EX_SOFTWARE; + (void) snprintf(LockName, sizeof LockName, "%s.lock", path); + (void) time(&start); + for (; ; sleep(5)) + { int fd; struct stat st; time_t now; - fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT, 0); - if (fd >= 0) { + /* global timeout */ + (void) time(&now); + if (now > start + LOCKTO_GLOB) + { + errno = 0; + return EX_TEMPFAIL; + } + fd = open(LockName, O_WRONLY|O_EXCL|O_CREAT, 0); + if (fd >= 0) + { /* defeat lock checking programs which test pid */ - write(fd, "0", 2); - locked = 1; - close(fd); - return; + (void) write(fd, "0", 2); + Locked = TRUE; + (void) close(fd); + return 0; } - if (stat(lockname, &st) < 0) { + if (stat(LockName, &st) < 0) + { if (statfailed++ > 5) - return; + { + errno = 0; + return EX_TEMPFAIL; + } continue; } statfailed = 0; - time(&now); - if (now < st.st_ctime + 300) + (void) time(&now); + if (now < st.st_ctime + LOCKTO_RM) continue; - unlink(lockname); + + /* try to remove stale lockfile */ + if (unlink(LockName) < 0) + return errno; } } void unlockmbox() { - if (!locked) + if (!Locked) return; - unlink(lockname); - locked = 0; + (void) unlink(LockName); + Locked = FALSE; } +#endif /* MAILLOCK */ void notifybiff(msg) char *msg; { - static struct sockaddr_in addr; + static bool initialized = FALSE; static int f = -1; struct hostent *hp; struct servent *sp; int len; + static struct sockaddr_in addr; + + if (!initialized) + { + initialized = TRUE; - if (addr.sin_family == 0) { /* Be silent if biff service not available. */ - if ((sp = getservbyname("biff", "udp")) == NULL) - return; - if ((hp = gethostbyname("localhost")) == NULL) { + if ((sp = getservbyname("biff", "udp")) == NULL || + (hp = gethostbyname("localhost")) == NULL || + hp->h_length != INADDRSZ) return; - } + addr.sin_family = hp->h_addrtype; - memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); + memcpy(&addr.sin_addr, hp->h_addr, INADDRSZ); addr.sin_port = sp->s_port; } - if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + + /* No message, just return */ + if (msg == NULL) + return; + + /* Couldn't initialize addr struct */ + if (addr.sin_family == AF_UNSPEC) + return; + + if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return; - } len = strlen(msg) + 1; - (void) sendto(f, msg, len, 0, (struct sockaddr *)&addr, sizeof(addr)); + (void) sendto(f, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr)); } void usage() { - eval = EX_USAGE; - mailerr(NULL, "usage: mail.local [-b] [-l] [-f from] [-s] user ..."); - exit(eval); + ExitVal = EX_USAGE; + mailerr(NULL, "usage: mail.local [-B] [-l] [-f from] [-s] user ..."); + exit(ExitVal); } void #ifdef __STDC__ mailerr(const char *hdr, const char *fmt, ...) -#else +#else /* __STDC__ */ mailerr(hdr, fmt, va_alist) const char *hdr; const char *fmt; va_dcl -#endif +#endif /* __STDC__ */ { va_list ap; #ifdef __STDC__ va_start(ap, fmt); -#else +#else /* __STDC__ */ va_start(ap); -#endif - if (lmtpmode) +#endif /* __STDC__ */ + if (LMTPMode) { if (hdr != NULL) printf("%s ", hdr); - vprintf(fmt, ap); - printf("\r\n"); + (void) vprintf(fmt, ap); + (void) printf("\r\n"); } else { - e_to_sys(errno); + (void) e_to_sys(errno); vwarn(fmt, ap); } } @@ -1049,142 +1439,133 @@ vwarn(fmt, ap) _BSD_VA_LIST_ ap; { /* - * Log the message to stderr. - * - * Don't use LOG_PERROR as an openlog() flag to do this, - * it's not portable enough. - */ - if (eval != EX_USAGE) - (void)fprintf(stderr, "mail.local: "); - (void)vfprintf(stderr, fmt, ap); - (void)fprintf(stderr, "\n"); + ** Log the message to stderr. + ** + ** Don't use LOG_PERROR as an openlog() flag to do this, + ** it's not portable enough. + */ + + if (ExitVal != EX_USAGE) + (void) fprintf(stderr, "mail.local: "); + (void) vfprintf(stderr, fmt, ap); + (void) fprintf(stderr, "\n"); #if USE_VSYSLOG /* Log the message to syslog. */ vsyslog(LOG_ERR, fmt, ap); -#else +#else /* USE_VSYSLOG */ { char fmtbuf[10240]; (void) vsnprintf(fmtbuf, sizeof fmtbuf, fmt, ap); syslog(LOG_ERR, "%s", fmtbuf); } -#endif +#endif /* USE_VSYSLOG */ } /* * e_to_sys -- * Guess which errno's are temporary. Gag me. */ -void +int e_to_sys(num) int num; { /* Temporary failures override hard errors. */ - if (eval == EX_TEMPFAIL) - return; + if (ExitVal == EX_TEMPFAIL) + return ExitVal; - switch(num) { /* Hopefully temporary errors. */ -#ifdef EAGAIN - case EAGAIN: /* Resource temporarily unavailable */ -#endif + switch (num) /* Hopefully temporary errors. */ + { #ifdef EDQUOT - case EDQUOT: /* Disc quota exceeded */ -#endif + case EDQUOT: /* Disc quota exceeded */ + if (bouncequota) + { + ExitVal = EX_UNAVAILABLE; + break; + } + /* FALLTHROUGH */ +#endif /* EDQUOT */ +#ifdef EAGAIN + case EAGAIN: /* Resource temporarily unavailable */ +#endif /* EAGAIN */ #ifdef EBUSY - case EBUSY: /* Device busy */ -#endif + case EBUSY: /* Device busy */ +#endif /* EBUSY */ #ifdef EPROCLIM - case EPROCLIM: /* Too many processes */ -#endif + case EPROCLIM: /* Too many processes */ +#endif /* EPROCLIM */ #ifdef EUSERS - case EUSERS: /* Too many users */ -#endif + case EUSERS: /* Too many users */ +#endif /* EUSERS */ #ifdef ECONNABORTED - case ECONNABORTED: /* Software caused connection abort */ -#endif + case ECONNABORTED: /* Software caused connection abort */ +#endif /* ECONNABORTED */ #ifdef ECONNREFUSED - case ECONNREFUSED: /* Connection refused */ -#endif + case ECONNREFUSED: /* Connection refused */ +#endif /* ECONNREFUSED */ #ifdef ECONNRESET - case ECONNRESET: /* Connection reset by peer */ -#endif + case ECONNRESET: /* Connection reset by peer */ +#endif /* ECONNRESET */ #ifdef EDEADLK - case EDEADLK: /* Resource deadlock avoided */ -#endif + case EDEADLK: /* Resource deadlock avoided */ +#endif /* EDEADLK */ #ifdef EFBIG - case EFBIG: /* File too large */ -#endif + case EFBIG: /* File too large */ +#endif /* EFBIG */ #ifdef EHOSTDOWN - case EHOSTDOWN: /* Host is down */ -#endif + case EHOSTDOWN: /* Host is down */ +#endif /* EHOSTDOWN */ #ifdef EHOSTUNREACH - case EHOSTUNREACH: /* No route to host */ -#endif + case EHOSTUNREACH: /* No route to host */ +#endif /* EHOSTUNREACH */ #ifdef EMFILE - case EMFILE: /* Too many open files */ -#endif + case EMFILE: /* Too many open files */ +#endif /* EMFILE */ #ifdef ENETDOWN - case ENETDOWN: /* Network is down */ -#endif + case ENETDOWN: /* Network is down */ +#endif /* ENETDOWN */ #ifdef ENETRESET - case ENETRESET: /* Network dropped connection on reset */ -#endif + case ENETRESET: /* Network dropped connection on reset */ +#endif /* ENETRESET */ #ifdef ENETUNREACH - case ENETUNREACH: /* Network is unreachable */ -#endif + case ENETUNREACH: /* Network is unreachable */ +#endif /* ENETUNREACH */ #ifdef ENFILE - case ENFILE: /* Too many open files in system */ -#endif + case ENFILE: /* Too many open files in system */ +#endif /* ENFILE */ #ifdef ENOBUFS - case ENOBUFS: /* No buffer space available */ -#endif + case ENOBUFS: /* No buffer space available */ +#endif /* ENOBUFS */ #ifdef ENOMEM - case ENOMEM: /* Cannot allocate memory */ -#endif + case ENOMEM: /* Cannot allocate memory */ +#endif /* ENOMEM */ #ifdef ENOSPC - case ENOSPC: /* No space left on device */ -#endif + case ENOSPC: /* No space left on device */ +#endif /* ENOSPC */ #ifdef EROFS - case EROFS: /* Read-only file system */ -#endif + case EROFS: /* Read-only file system */ +#endif /* EROFS */ #ifdef ESTALE - case ESTALE: /* Stale NFS file handle */ -#endif + case ESTALE: /* Stale NFS file handle */ +#endif /* ESTALE */ #ifdef ETIMEDOUT - case ETIMEDOUT: /* Connection timed out */ -#endif + case ETIMEDOUT: /* Connection timed out */ +#endif /* ETIMEDOUT */ #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN && EWOULDBLOCK != EDEADLK - case EWOULDBLOCK: /* Operation would block. */ -#endif - eval = EX_TEMPFAIL; + case EWOULDBLOCK: /* Operation would block. */ +#endif /* defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN && EWOULDBLOCK != EDEADLK */ + ExitVal = EX_TEMPFAIL; break; - default: - eval = EX_UNAVAILABLE; + + default: + ExitVal = EX_UNAVAILABLE; break; } + return ExitVal; } -#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 */ - #if defined(ultrix) || defined(_CRAY) - /* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. @@ -1218,16 +1599,16 @@ strerror(eno) * SUCH DAMAGE. */ -#if defined(LIBC_SCCS) && !defined(lint) +# if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ +# endif /* defined(LIBC_SCCS) && !defined(lint) */ -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <ctype.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <fcntl.h> +# include <errno.h> +# include <stdio.h> +# include <ctype.h> static int _gettemp(); @@ -1239,14 +1620,14 @@ mkstemp(path) return (_gettemp(path, &fd) ? fd : -1); } -/* +# if 0 char * mktemp(path) char *path; { return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); } -*/ +# endif /* 0 */ static _gettemp(path, doopen) @@ -1260,7 +1641,8 @@ _gettemp(path, doopen) pid = getpid(); for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ - while (*--trv == 'X') { + while (*--trv == 'X') + { *trv = (pid % 10) + '0'; pid /= 10; } @@ -1269,14 +1651,17 @@ _gettemp(path, doopen) * check the target directory; if you have six X's and it * doesn't exist this runs for a *very* long time. */ - for (start = trv + 1;; --trv) { + for (start = trv + 1;; --trv) + { if (trv <= path) break; - if (*trv == '/') { + if (*trv == '/') + { *trv = '\0'; if (stat(path, &sbuf) < 0) return(0); - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_mode)) + { errno = ENOTDIR; return(0); } @@ -1285,8 +1670,10 @@ _gettemp(path, doopen) } } - for (;;) { - if (doopen) { + for (;;) + { + if (doopen) + { if ((*doopen = open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) return(1); @@ -1297,12 +1684,14 @@ _gettemp(path, doopen) return(errno == ENOENT ? 1 : 0); /* tricky little algorithm for backward compatibility */ - for (trv = start;;) { + for (trv = start;;) + { if (!*trv) return(0); if (*trv == 'z') *trv++ = 'a'; - else { + else + { if (isascii(*trv) && isdigit(*trv)) *trv = 'a'; else @@ -1311,7 +1700,6 @@ _gettemp(path, doopen) } } } - /*NOTREACHED*/ + /* NOTREACHED */ } - -#endif /* ultrix */ +#endif /* defined(ultrix) || defined(_CRAY) */ diff --git a/contrib/sendmail/mailstats/mailstats.c b/contrib/sendmail/mailstats/mailstats.c index 303b0a3..6bd918e 100644 --- a/contrib/sendmail/mailstats/mailstats.c +++ b/contrib/sendmail/mailstats/mailstats.c @@ -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; } diff --git a/contrib/sendmail/makemap/makemap.c b/contrib/sendmail/makemap/makemap.c index 9717a43..33acfb8 100644 --- a/contrib/sendmail/makemap/makemap.c +++ b/contrib/sendmail/makemap/makemap.c @@ -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) 1992 Eric P. Allman. All rights reserved. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -11,44 +12,34 @@ */ #ifndef lint -static char sccsid[] = "@(#)makemap.c 8.71 (Berkeley) 11/29/1998"; -#endif /* not lint */ +static char copyright[] = +"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1992 Eric P. Allman. All rights reserved.\n\ + Copyright (c) 1992, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Id: makemap.c,v 8.135.4.10 2000/07/18 05:41:39 gshapiro Exp $"; +#endif /* ! lint */ + +/* $FreeBSD$ */ #include <sys/types.h> -#include <sys/errno.h> #ifndef ISC_UNIX # include <sys/file.h> -#endif -#include "sendmail.h" -#include "pathnames.h" - -#ifdef NDBM -# include <ndbm.h> -#endif - -#ifdef NEWDB -# include <db.h> -# ifndef DB_VERSION_MAJOR -# define DB_VERSION_MAJOR 1 -# endif -#endif - -enum type { T_DBM, T_BTREE, T_HASH, T_ERR, T_UNKNOWN }; - -union dbent -{ -#ifdef NDBM - datum dbm; -#endif -#ifdef NEWDB - DBT db; -#endif - struct - { - char *data; - size_t size; - } xx; -}; +#endif /* ! ISC_UNIX */ +#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> +#include <sendmail/sendmail.h> +#include <sendmail/pathnames.h> +#include <libsmdb/smdb.h> uid_t RealUid; gid_t RealGid; @@ -58,11 +49,32 @@ uid_t RunAsGid; char *RunAsUserName; int Verbose = 2; bool DontInitGroups = FALSE; -long DontBlameSendmail = DBS_SAFE; -u_char tTdvect[100]; uid_t TrustedUid = 0; +BITMAP256 DontBlameSendmail; #define BUFSIZE 1024 +#if _FFR_DELIM +# define ISSEP(c) ((sep == '\0' && isascii(c) && isspace(c)) || (c) == sep) +#else /* _FFR_DELIM */ +# define ISSEP(c) (isascii(c) && isspace(c)) +#endif /* _FFR_DELIM */ + + +static void +usage(progname) + char *progname; +{ + fprintf(stderr, + "Usage: %s [-C cffile] [-N] [-c cachesize] [-d] [-e] [-f] [-l] [-o] [-r] [-s] %s[-u] [-v] type mapname\n", + progname, +#if _FFR_DELIM + "[-t delimiter] " +#else /* _FFR_DELIM */ + "" +#endif /* _FFR_DELIM */ + ); + exit(EX_USAGE); +} int main(argc, argv) @@ -74,85 +86,65 @@ main(argc, argv) bool inclnull = FALSE; bool notrunc = FALSE; bool allowreplace = FALSE; - bool allowdups = FALSE; + bool allowempty = FALSE; bool verbose = FALSE; bool foldcase = TRUE; + bool unmake = FALSE; +#if _FFR_DELIM + char sep = '\0'; +#endif /* _FFR_DELIM */ int exitstat; int opt; char *typename = NULL; char *mapname = NULL; - char *ext = NULL; int lineno; int st; int mode; + int smode; int putflags = 0; -#ifdef NEWDB - long dbcachesize = 1024 * 1024; -#endif - enum type type; -#if !O_EXLOCK - int fd; -#endif - int sff = SFF_ROOTOK|SFF_REGONLY; + long sff = SFF_ROOTOK|SFF_REGONLY; struct passwd *pw; - union - { -#ifdef NDBM - DBM *dbm; -#endif -#ifdef NEWDB - DB *db; -#endif - void *dbx; - } dbp; - union dbent key, val; -#ifdef NEWDB -# if DB_VERSION_MAJOR < 2 - BTREEINFO bti; - HASHINFO hinfo; -# else - DB_INFO dbinfo; -# endif -#endif + SMDB_DATABASE *database; + SMDB_CURSOR *cursor; + SMDB_DBENT db_key, db_val; + SMDB_DBPARAMS params; + SMDB_USER_INFO user_info; char ibuf[BUFSIZE]; - char fbuf[MAXNAME]; - char dbuf[MAXNAME]; -#ifdef NDBM - char pbuf[MAXNAME]; -#endif -#if _FFR_TRUSTED_USER +#if HASFCHOWN FILE *cfp; char buf[MAXLINE]; -#endif +#endif /* HASFCHOWN */ static char rnamebuf[MAXNAME]; /* holds RealUserName */ - struct stat std; -#ifdef NDBM - struct stat stp; -#endif extern char *optarg; extern int optind; - progname = argv[0]; + memset(¶ms, '\0', sizeof params); + params.smdbp_cache_size = 1024 * 1024; + + progname = strrchr(argv[0], '/'); + if (progname != NULL) + progname++; + else + progname = argv[0]; cfile = _PATH_SENDMAILCF; + 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; - sprintf(rnamebuf, "%s", pw->pw_name); - } + (void) strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf); else - sprintf(rnamebuf, "Unknown UID %d", (int) RealUid); + (void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d", + (int) RealUid); RunAsUserName = RealUserName = rnamebuf; + user_info.smdbu_id = RunAsUid; + user_info.smdbu_group_id = RunAsGid; + (void) strlcpy(user_info.smdbu_name, RunAsUserName, + SMDB_MAX_USER_NAME_LEN); -#if _FFR_NEW_MAKEMAP_FLAGS -#define OPTIONS "C:Nc:dflorsv" -#else -#define OPTIONS "C:Ndforsv" -#endif + +#define OPTIONS "C:Nc:t:deflorsuv" while ((opt = getopt(argc, argv, OPTIONS)) != -1) { switch (opt) @@ -165,34 +157,26 @@ main(argc, argv) inclnull = TRUE; break; -#if _FFR_NEW_MAKEMAP_FLAGS case 'c': -# ifdef NEWDB - dbcachesize = atol(optarg); -# endif + params.smdbp_cache_size = atol(optarg); break; -#endif case 'd': - allowdups = TRUE; + params.smdbp_allow_dup = TRUE; + break; + + case 'e': + allowempty = TRUE; break; case 'f': foldcase = FALSE; break; -#if _FFR_NEW_MAKEMAP_FLAGS case 'l': -# ifdef NDBM - printf("dbm\n"); -# endif -# ifdef NEWDB - printf("hash\n"); - printf("btree\n"); -# endif + smdb_print_available_types(); exit(EX_OK); break; -#endif case 'o': notrunc = TRUE; @@ -203,7 +187,25 @@ main(argc, argv) break; case 's': - DontBlameSendmail |= DBS_MAPINUNSAFEDIRPATH|DBS_WRITEMAPTOHARDLINK|DBS_WRITEMAPTOSYMLINK|DBS_LINKEDMAPINWRITABLEDIR; + setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail); + setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail); + setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail); + setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail); + break; + +#if _FFR_DELIM + case 't': + if (optarg == NULL || *optarg == '\0') + { + fprintf(stderr, "Invalid separator\n"); + break; + } + sep = *optarg; + break; +#endif /* _FFR_DELIM */ + + case 'u': + unmake = TRUE; break; case 'v': @@ -211,51 +213,36 @@ main(argc, argv) break; default: - type = T_ERR; - break; + usage(progname); + /* NOTREACHED */ } } - if (!bitset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) + if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) sff |= SFF_NOSLINK; - if (!bitset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) + if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) sff |= SFF_NOHLINK; - if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) + if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) sff |= SFF_NOWLINK; argc -= optind; argv += optind; if (argc != 2) - type = T_ERR; + { + usage(progname); + /* NOTREACHED */ + } else { typename = argv[0]; mapname = argv[1]; - ext = NULL; - - if (strcmp(typename, "dbm") == 0) - { - type = T_DBM; - } - else if (strcmp(typename, "btree") == 0) - { - type = T_BTREE; - ext = ".db"; - } - else if (strcmp(typename, "hash") == 0) - { - type = T_HASH; - ext = ".db"; - } - else - type = T_UNKNOWN; } -#if _FFR_TRUSTED_USER +#if HASFCHOWN + /* Find TrustedUser value in sendmail.cf */ if ((cfp = fopen(cfile, "r")) == NULL) { - fprintf(stderr, "mailstats: "); - perror(cfile); + fprintf(stderr, "makemap: %s: %s", cfile, errstring(errno)); exit(EX_NOINPUT); } while (fgets(buf, sizeof(buf), cfp) != NULL) @@ -281,8 +268,6 @@ main(argc, argv) TrustedUid = atoi(b); else { - register struct passwd *pw; - TrustedUid = 0; pw = getpwnam(b); if (pw == NULL) @@ -291,15 +276,17 @@ main(argc, argv) else TrustedUid = pw->pw_uid; } - + # ifdef UID_MAX if (TrustedUid > UID_MAX) { - syserr("TrustedUser: uid value (%ld) > UID_MAX (%ld)", - TrustedUid, UID_MAX); + fprintf(stderr, + "TrustedUser: uid value (%ld) > UID_MAX (%ld)", + (long) TrustedUid, + (long) UID_MAX); TrustedUid = 0; } -# endif +# endif /* UID_MAX */ break; } @@ -309,470 +296,187 @@ main(argc, argv) } } (void) fclose(cfp); -#endif - switch (type) +#endif /* HASFCHOWN */ + + if (!params.smdbp_allow_dup && !allowreplace) + putflags = SMDBF_NO_OVERWRITE; + + if (unmake) { - case T_ERR: -#if _FFR_NEW_MAKEMAP_FLAGS - fprintf(stderr, - "Usage: %s [-N] [-c cachesize] [-d] [-f] [-l] [-o] [-r] [-s] [-v] type mapname\n", - progname); -#else - fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-s] [-v] type mapname\n", progname); -#endif - exit(EX_USAGE); - - case T_UNKNOWN: - fprintf(stderr, "%s: Unknown database type %s\n", - progname, typename); - exit(EX_USAGE); - -#ifndef NDBM - case T_DBM: -#endif -#ifndef NEWDB - case T_BTREE: - case T_HASH: -#endif - fprintf(stderr, "%s: Type %s not supported in this version\n", - progname, typename); - exit(EX_UNAVAILABLE); - -#ifdef NEWDB - case T_BTREE: -# if DB_VERSION_MAJOR < 2 - bzero(&bti, sizeof bti); -# else - bzero(&dbinfo, sizeof dbinfo); -# endif - if (allowdups) - { -# if DB_VERSION_MAJOR < 2 - bti.flags |= R_DUP; -# else - dbinfo.flags |= DB_DUP; -# endif - } - if (allowdups || allowreplace) - putflags = 0; - else - { -# if DB_VERSION_MAJOR < 2 - putflags = R_NOOVERWRITE; -# else - putflags = DB_NOOVERWRITE; -# endif - } - break; - - case T_HASH: -# if DB_VERSION_MAJOR < 2 - bzero(&hinfo, sizeof hinfo); -# else - bzero(&dbinfo, sizeof dbinfo); -# endif - if (allowreplace) - putflags = 0; - else - { -# if DB_VERSION_MAJOR < 2 - putflags = R_NOOVERWRITE; -# else - putflags = DB_NOOVERWRITE; -# endif - } - break; -#endif -#ifdef NDBM - case T_DBM: - if (allowdups) + mode = O_RDONLY; + smode = S_IRUSR; + } + else + { + mode = O_RDWR; + if (!notrunc) { - fprintf(stderr, "%s: Type %s does not support -d (allow dups)\n", - progname, typename); - exit(EX_UNAVAILABLE); + mode |= O_CREAT|O_TRUNC; + sff |= SFF_CREAT; } - if (allowreplace) - putflags = DBM_REPLACE; - else - putflags = DBM_INSERT; - break; -#endif + smode = S_IWUSR; } - /* - ** Adjust file names. - */ + params.smdbp_num_elements = 4096; - if (ext != NULL) + errno = smdb_open_database(&database, mapname, mode, smode, sff, + typename, &user_info, ¶ms); + if (errno != SMDBE_OK) { - int el, fl; + char *hint; - el = strlen(ext); - fl = strlen(mapname); - if (el + fl + 1 >= sizeof fbuf) - { - fprintf(stderr, "%s: file name too long", mapname); - exit(EX_USAGE); - } - if (fl < el || strcmp(&mapname[fl - el], ext) != 0) - { - strcpy(fbuf, mapname); - strcat(fbuf, ext); - mapname = fbuf; - } + if (errno == SMDBE_UNSUPPORTED_DB_TYPE && + (hint = smdb_db_definition(typename)) != NULL) + fprintf(stderr, + "%s: Need to recompile with -D%s for %s support\n", + progname, hint, typename); + else + fprintf(stderr, + "%s: error opening type %s map %s: %s\n", + progname, typename, mapname, errstring(errno)); + exit(EX_CANTCREAT); } - if (!notrunc) - sff |= SFF_CREAT; - switch (type) + (void) database->smdb_sync(database, 0); + + if (geteuid() == 0 && TrustedUid != 0) { -#ifdef NEWDB - case T_BTREE: - case T_HASH: - if (strlen(mapname) >= sizeof dbuf) - { - fprintf(stderr, - "%s: map name too long\n", mapname); - exit(EX_USAGE); - } - strcpy(dbuf, mapname); - if ((st = safefile(dbuf, RealUid, RealGid, RealUserName, - sff, S_IWUSR, &std)) != 0) - { - fprintf(stderr, - "%s: could not create: %s\n", - dbuf, errstring(st)); - exit(EX_CANTCREAT); - } - break; -#endif -#ifdef NDBM - case T_DBM: - if (strlen(mapname) + 5 > sizeof dbuf) - { - fprintf(stderr, - "%s: map name too long\n", mapname); - exit(EX_USAGE); - } - sprintf(dbuf, "%s.dir", mapname); - if ((st = safefile(dbuf, RealUid, RealGid, RealUserName, - sff, S_IWUSR, &std)) != 0) - { - fprintf(stderr, - "%s: could not create: %s\n", - dbuf, errstring(st)); - exit(EX_CANTCREAT); - } - sprintf(pbuf, "%s.pag", mapname); - if ((st = safefile(pbuf, RealUid, RealGid, RealUserName, - sff, S_IWUSR, &stp)) != 0) + errno = database->smdb_set_owner(database, TrustedUid, -1); + if (errno != SMDBE_OK) { fprintf(stderr, - "%s: could not create: %s\n", - pbuf, errstring(st)); - exit(EX_CANTCREAT); + "WARNING: ownership change on %s failed %s", + mapname, errstring(errno)); } - break; -#endif - default: - fprintf(stderr, - "%s: internal error: type %d\n", - progname, - type); - exit(EX_SOFTWARE); } /* - ** Create the database. + ** Copy the data */ - mode = O_RDWR; - if (!notrunc) - mode |= O_CREAT|O_TRUNC; -#if O_EXLOCK - mode |= O_EXLOCK; -#else - /* pre-lock the database */ - fd = safeopen(dbuf, mode & ~O_TRUNC, 0644, sff); - if (fd < 0) - { - fprintf(stderr, "%s: cannot create type %s map %s\n", - progname, typename, mapname); - exit(EX_CANTCREAT); - } -#endif - switch (type) + exitstat = EX_OK; + if (unmake) { -#ifdef NDBM - case T_DBM: - dbp.dbm = dbm_open(mapname, mode, 0644); - if (dbp.dbm != NULL && - dbm_dirfno(dbp.dbm) == dbm_pagfno(dbp.dbm)) - { - fprintf(stderr, "dbm map %s: cannot run with GDBM\n", - mapname); - dbm_close(dbp.dbm); - exit(EX_CONFIG); - } - if (dbp.dbm != NULL && - (filechanged(dbuf, dbm_dirfno(dbp.dbm), &std) || - filechanged(pbuf, dbm_pagfno(dbp.dbm), &stp))) + bool stop; + errno = database->smdb_cursor(database, &cursor, 0); + if (errno != SMDBE_OK) { + fprintf(stderr, - "dbm map %s: file changed after open\n", - mapname); - dbm_close(dbp.dbm); - exit(EX_CANTCREAT); + "%s: cannot make cursor for type %s map %s\n", + progname, typename, mapname); + exit(EX_SOFTWARE); } -#if _FFR_TRUSTED_USER - if (geteuid() == 0 && TrustedUid != 0) + + memset(&db_key, '\0', sizeof db_key); + memset(&db_val, '\0', sizeof db_val); + + for (stop = FALSE, lineno = 0; !stop; lineno++) { - if (fchown(dbm_dirfno(dbp.dbm), TrustedUid, -1) < 0 || - fchown(dbm_pagfno(dbp.dbm), TrustedUid, -1) < 0) + errno = cursor->smdbc_get(cursor, &db_key, &db_val, + SMDB_CURSOR_GET_NEXT); + if (errno != SMDBE_OK) { - fprintf(stderr, - "WARNING: ownership change on %s failed: %s", - mapname, errstring(errno)); + stop = TRUE; } + if (!stop) + printf("%.*s\t%.*s\n", + (int) db_key.data.size, + (char *) db_key.data.data, + (int) db_val.data.size, + (char *)db_val.data.data); + } -#endif - - break; -#endif - -#ifdef NEWDB - case T_HASH: - /* tweak some parameters for performance */ -# if DB_VERSION_MAJOR < 2 - hinfo.nelem = 4096; - hinfo.cachesize = dbcachesize; -# else - dbinfo.h_nelem = 4096; - dbinfo.db_cachesize = dbcachesize; -# endif - -# if DB_VERSION_MAJOR < 2 - dbp.db = dbopen(mapname, mode, 0644, DB_HASH, &hinfo); -# else - { - int flags = 0; - - if (bitset(O_CREAT, mode)) - flags |= DB_CREATE; - if (bitset(O_TRUNC, mode)) - flags |= DB_TRUNCATE; - - dbp.db = NULL; - errno = db_open(mapname, DB_HASH, flags, 0644, - NULL, &dbinfo, &dbp.db); - } -# endif - if (dbp.db != NULL) + (void) cursor->smdbc_close(cursor); + } + else + { + lineno = 0; + while (fgets(ibuf, sizeof ibuf, stdin) != NULL) { - int fd; - -# if DB_VERSION_MAJOR < 2 - fd = dbp.db->fd(dbp.db); -# else - fd = -1; - errno = dbp.db->fd(dbp.db, &fd); -# endif - if (filechanged(dbuf, fd, &std)) + register char *p; + + lineno++; + + /* + ** Parse the line. + */ + + p = strchr(ibuf, '\n'); + if (p != NULL) + *p = '\0'; + else if (!feof(stdin)) { fprintf(stderr, - "db map %s: file changed after open\n", - mapname); -# if DB_VERSION_MAJOR < 2 - dbp.db->close(dbp.db); -# else - errno = dbp.db->close(dbp.db, 0); -# endif - exit(EX_CANTCREAT); + "%s: %s: line %d: line too long (%ld bytes max)\n", + progname, mapname, lineno, (long) sizeof ibuf); + exitstat = EX_DATAERR; + continue; } - (void) (*dbp.db->sync)(dbp.db, 0); -#if _FFR_TRUSTED_USER - if (geteuid() == 0 && TrustedUid != 0) + + if (ibuf[0] == '\0' || ibuf[0] == '#') + continue; + if ( +#if _FFR_DELIM + sep == '\0' && +#endif /* _FFR_DELIM */ + isascii(ibuf[0]) && isspace(ibuf[0])) { - if (fchown(fd, TrustedUid, -1) < 0) - { - fprintf(stderr, - "WARNING: ownership change on %s failed: %s", - mapname, errstring(errno)); - } + fprintf(stderr, + "%s: %s: line %d: syntax error (leading space)\n", + progname, mapname, lineno); + exitstat = EX_DATAERR; + continue; } -#endif - } - break; - - case T_BTREE: - /* tweak some parameters for performance */ -# if DB_VERSION_MAJOR < 2 - bti.cachesize = dbcachesize; -# else - dbinfo.db_cachesize = dbcachesize; -# endif - -# if DB_VERSION_MAJOR < 2 - dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti); -# else - { - int flags = 0; - - if (bitset(O_CREAT, mode)) - flags |= DB_CREATE; - if (bitset(O_TRUNC, mode)) - flags |= DB_TRUNCATE; - - dbp.db = NULL; - errno = db_open(mapname, DB_BTREE, flags, 0644, - NULL, &dbinfo, &dbp.db); - } -# endif - if (dbp.db != NULL) - { - int fd; - -# if DB_VERSION_MAJOR < 2 - fd = dbp.db->fd(dbp.db); -# else - fd = -1; - errno = dbp.db->fd(dbp.db, &fd); -# endif - if (filechanged(dbuf, fd, &std)) + + memset(&db_key, '\0', sizeof db_key); + memset(&db_val, '\0', sizeof db_val); + db_key.data.data = ibuf; + + for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++) { - fprintf(stderr, - "db map %s: file changed after open\n", - mapname); -# if DB_VERSION_MAJOR < 2 - dbp.db->close(dbp.db); -# else - errno = dbp.db->close(dbp.db, 0); -# endif - exit(EX_CANTCREAT); + if (foldcase && isascii(*p) && isupper(*p)) + *p = tolower(*p); } - (void) (*dbp.db->sync)(dbp.db, 0); -#if _FFR_TRUSTED_USER - if (geteuid() == 0 && TrustedUid != 0) + db_key.data.size = p - ibuf; + if (inclnull) + db_key.data.size++; + + if (*p != '\0') + *p++ = '\0'; + while (ISSEP(*p)) + p++; + if (!allowempty && *p == '\0') { - if (fchown(fd, TrustedUid, -1) < 0) - { - fprintf(stderr, - "WARNING: ownership change on %s failed: %s", - mapname, errstring(errno)); - } + fprintf(stderr, + "%s: %s: line %d: no RHS for LHS %s\n", + progname, mapname, lineno, + (char *) db_key.data.data); + exitstat = EX_DATAERR; + continue; } -#endif - } - break; -#endif - - default: - fprintf(stderr, "%s: internal error: type %d\n", - progname, type); - exit(EX_SOFTWARE); - } - - if (dbp.dbx == NULL) - { - fprintf(stderr, "%s: cannot open type %s map %s\n", - progname, typename, mapname); - exit(EX_CANTCREAT); - } - - /* - ** Copy the data - */ - - lineno = 0; - exitstat = EX_OK; - while (fgets(ibuf, sizeof ibuf, stdin) != NULL) - { - register char *p; - lineno++; + db_val.data.data = p; + db_val.data.size = strlen(p); + if (inclnull) + db_val.data.size++; - /* - ** Parse the line. - */ + /* + ** Do the database insert. + */ - p = strchr(ibuf, '\n'); - if (p != NULL) - *p = '\0'; - else if (!feof(stdin)) - { - fprintf(stderr, "%s: %s: line %d: line too long (%ld bytes max)\n", - progname, mapname, lineno, (long) sizeof ibuf); - continue; - } - - if (ibuf[0] == '\0' || ibuf[0] == '#') - continue; - if (isascii(ibuf[0]) && isspace(ibuf[0])) - { - fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", - progname, mapname, lineno); - continue; - } -#ifdef NEWDB - if (type == T_HASH || type == T_BTREE) - { - bzero(&key.db, sizeof key.db); - bzero(&val.db, sizeof val.db); - } -#endif - - key.xx.data = ibuf; - for (p = ibuf; *p != '\0' && !(isascii(*p) && isspace(*p)); p++) - { - if (foldcase && isascii(*p) && isupper(*p)) - *p = tolower(*p); - } - key.xx.size = p - key.xx.data; - if (inclnull) - key.xx.size++; - if (*p != '\0') - *p++ = '\0'; - while (isascii(*p) && isspace(*p)) - p++; - if (*p == '\0') - { - fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", - progname, mapname, lineno, key.xx.data); - continue; - } - val.xx.data = p; - val.xx.size = strlen(p); - if (inclnull) - val.xx.size++; - - /* - ** Do the database insert. - */ - - if (verbose) - { - printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); - } + if (verbose) + { + printf("key=`%s', val=`%s'\n", + (char *) db_key.data.data, + (char *) db_val.data.data); + } - switch (type) - { -#ifdef NDBM - case T_DBM: - st = dbm_store(dbp.dbm, key.dbm, val.dbm, putflags); - break; -#endif - -#ifdef NEWDB - case T_BTREE: - case T_HASH: -# if DB_VERSION_MAJOR < 2 - st = (*dbp.db->put)(dbp.db, &key.db, &val.db, putflags); -# else - errno = (*dbp.db->put)(dbp.db, NULL, &key.db, - &val.db, putflags); + errno = database->smdb_put(database, &db_key, &db_val, + putflags); switch (errno) { - case DB_KEYEXIST: + case SMDBE_KEY_EXIST: st = 1; break; @@ -784,25 +488,24 @@ main(argc, argv) st = -1; break; } -# endif - break; -#endif - default: - break; - } - if (st < 0) - { - fprintf(stderr, "%s: %s: line %d: key %s: put error\n", - progname, mapname, lineno, key.xx.data); - perror(mapname); - exitstat = EX_IOERR; - } - else if (st > 0) - { - fprintf(stderr, - "%s: %s: line %d: key %s: duplicate key\n", - progname, mapname, lineno, key.xx.data); + if (st < 0) + { + fprintf(stderr, + "%s: %s: line %d: key %s: put error: %s\n", + progname, mapname, lineno, + (char *) db_key.data.data, + errstring(errno)); + exitstat = EX_IOERR; + } + else if (st > 0) + { + fprintf(stderr, + "%s: %s: line %d: key %s: duplicate key\n", + progname, mapname, + lineno, (char *) db_key.data.data); + exitstat = EX_DATAERR; + } } } @@ -810,114 +513,29 @@ main(argc, argv) ** Now close the database. */ - switch (type) + errno = database->smdb_close(database); + if (errno != SMDBE_OK) { -#ifdef NDBM - case T_DBM: - dbm_close(dbp.dbm); - break; -#endif - -#ifdef NEWDB - case T_HASH: - case T_BTREE: -# if DB_VERSION_MAJOR < 2 - if ((*dbp.db->close)(dbp.db) < 0) -# else - if ((errno = (*dbp.db->close)(dbp.db, 0)) != 0) -# endif - { - fprintf(stderr, "%s: %s: error on close\n", - progname, mapname); - perror(mapname); - exitstat = EX_IOERR; - } -#endif - default: - break; + fprintf(stderr, "%s: close(%s): %s\n", + progname, mapname, errstring(errno)); + exitstat = EX_IOERR; } + smdb_free_database(database); -#if !O_EXLOCK - /* release locks */ - close(fd); -#endif - - exit (exitstat); -} -/* -** LOCKFILE -- lock a file using flock or (shudder) fcntl locking -** -** Parameters: -** fd -- the file descriptor of the file. -** filename -- the file name (for error messages). -** ext -- the filename extension. -** type -- type of the lock. Bits can be: -** LOCK_EX -- exclusive lock. -** LOCK_NB -- non-blocking. -** -** Returns: -** TRUE if the lock was acquired. -** FALSE otherwise. -*/ - -bool -lockfile(fd, filename, ext, type) - int fd; - char *filename; - char *ext; - int type; -{ -# if !HASFLOCK - int action; - struct flock lfd; - extern int errno; - - bzero(&lfd, sizeof lfd); - if (bitset(LOCK_UN, type)) - lfd.l_type = F_UNLCK; - else if (bitset(LOCK_EX, type)) - lfd.l_type = F_WRLCK; - else - lfd.l_type = F_RDLCK; - if (bitset(LOCK_NB, type)) - action = F_SETLK; - else - action = F_SETLKW; - - if (fcntl(fd, action, &lfd) >= 0) - return TRUE; - - /* - ** On SunOS, if you are testing using -oQ/tmp/mqueue or - ** -oA/tmp/aliases or anything like that, and /tmp is mounted - ** as type "tmp" (that is, served from swap space), the - ** previous fcntl will fail with "Invalid argument" errors. - ** Since this is fairly common during testing, we will assume - ** that this indicates that the lock is successfully grabbed. - */ - - if (errno == EINVAL) - return TRUE; - -# else /* HASFLOCK */ - - if (flock(fd, type) >= 0) - return TRUE; - -# endif - - return FALSE; + exit(exitstat); + /* NOTREACHED */ + return exitstat; } /*VARARGS1*/ void #ifdef __STDC__ message(const char *msg, ...) -#else +#else /* __STDC__ */ message(msg, va_alist) const char *msg; va_dcl -#endif +#endif /* __STDC__ */ { const char *m; VA_LOCAL_DECL @@ -928,20 +546,20 @@ message(msg, va_alist) isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') m += 4; VA_START(msg); - vfprintf(stderr, m, ap); + (void) vfprintf(stderr, m, ap); VA_END; - fprintf(stderr, "\n"); + (void) fprintf(stderr, "\n"); } /*VARARGS1*/ void #ifdef __STDC__ syserr(const char *msg, ...) -#else +#else /* __STDC__ */ syserr(msg, va_alist) const char *msg; va_dcl -#endif +#endif /* __STDC__ */ { const char *m; VA_LOCAL_DECL @@ -952,65 +570,7 @@ syserr(msg, va_alist) isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') m += 4; VA_START(msg); - vfprintf(stderr, m, ap); + (void) vfprintf(stderr, m, ap); VA_END; - fprintf(stderr, "\n"); -} - -const char * -errstring(err) - int err; -{ -#if !HASSTRERROR - static char errstr[64]; -# if !defined(ERRLIST_PREDEFINED) - extern char *sys_errlist[]; - extern int sys_nerr; -# endif -#endif - - /* handle pseudo-errors internal to sendmail */ - switch (err) - { - case E_SM_OPENTIMEOUT: - return "Timeout on file open"; - - case E_SM_NOSLINK: - return "Symbolic links not allowed"; - - case E_SM_NOHLINK: - return "Hard links not allowed"; - - case E_SM_REGONLY: - return "Regular files only"; - - case E_SM_ISEXEC: - return "Executable files not allowed"; - - case E_SM_WWDIR: - return "World writable directory"; - - case E_SM_GWDIR: - return "Group writable directory"; - - case E_SM_FILECHANGE: - return "File changed after open"; - - case E_SM_WWFILE: - return "World writable file"; - - case E_SM_GWFILE: - return "Group writable file"; - } - -#if HASSTRERROR - return strerror(err); -#else - if (err < 0 || err >= sys_nerr) - { - sprintf(errstr, "Error %d", err); - return errstr; - } - return sys_errlist[err]; -#endif + (void) fprintf(stderr, "\n"); } diff --git a/contrib/sendmail/praliases/praliases.c b/contrib/sendmail/praliases/praliases.c index 8b0057a..59a3c00 100644 --- a/contrib/sendmail/praliases/praliases.c +++ b/contrib/sendmail/praliases/praliases.c @@ -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"); + { + 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) - *p++ = '\0'; + { + 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; - - class = strchr(filename, ':'); - if (class != NULL) + 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; + + 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; + db_name = filename; + db_type = SMDB_TYPE_DEFAULT; } -#ifdef NEWDB - if (strlen(filename) + 4 >= sizeof buf) + else { - fprintf(stderr, "Alias filename too long: %.30s...\n", filename); - exit(EX_USAGE); + *colon = '\0'; + db_name = colon + 1; + db_type = filename; } - (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) + + /* clean off arguments */ + for (;;) { - 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 + 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++; } - else + + if (*db_name == '\0' || (db_type != NULL && *db_type == '\0')) { -#endif -#ifdef NDBM - praliases_dbm(filename, argc, argv); -#endif -#ifdef NEWDB + if (colon != NULL) + *colon = ':'; + fprintf(stderr, "praliases: illegal alias specification: %s\n", + filename); + goto fatal; } -#endif -} -#ifdef NDBM -static void -praliases_dbm(filename, argc, argv) - char *filename; - int argc; - char **argv; -{ - DBM *dbp; - datum content, key; + memset(¶ms, '\0', sizeof params); + params.smdbp_cache_size = 1024 * 1024; - if ((dbp = dbm_open(filename, O_RDONLY, 0)) == NULL) + 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, ¶ms); + if (result != SMDBE_OK) { - (void)fprintf(stderr, - "praliases: %s: %s\n", filename, strerror(errno)); - exit(EX_OSFILE); + fprintf(stderr, "praliases: %s: open: %s\n", + db_name, errstring(result)); + goto fatal; } - if (!argc) + + if (argc == 0) { - for (key = dbm_firstkey(dbp); - key.dptr != NULL; key = dbm_nextkey(dbp)) + 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) + { + 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) { - content = dbm_fetch(dbp, key); - (void)printf("%.*s:%.*s\n", - (int) key.dsize, key.dptr, - (int) content.dsize, content.dptr); + 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); -} -#endif -#if !HASSTRERROR + fatal: + if (cursor != NULL) + (void) cursor->smdbc_close(cursor); + if (database != NULL) + (void) database->smdb_close(database); + if (colon != NULL) + *colon = ':'; + return; +} -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]; - - if (eno >= 0 && eno < sys_nerr) - return sys_errlist[eno]; - (void) sprintf(ebuf, "Error %d", eno); - return ebuf; + 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"); } -#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"); +} diff --git a/contrib/sendmail/rmail/rmail.c b/contrib/sendmail/rmail/rmail.c index 3c268ab..bd21b7c 100644 --- a/contrib/sendmail/rmail/rmail.c +++ b/contrib/sendmail/rmail/rmail.c @@ -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) -# define HASSNPRINTF 1 -#endif +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif /* ! STDIN_FILENO */ -#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 +#if defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) || _AIX4 >= 40300 +# define HASSNPRINTF 1 +#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) */ + +#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__) */ + -void err __P((int, const char *, ...)); -void usage __P((void)); -char *xalloc __P((int)); +#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 */ diff --git a/contrib/sendmail/smrsh/smrsh.8 b/contrib/sendmail/smrsh/smrsh.8 index bd0fb69..6d58ce0 100644 --- a/contrib/sendmail/smrsh/smrsh.8 +++ b/contrib/sendmail/smrsh/smrsh.8 @@ -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'', diff --git a/contrib/sendmail/smrsh/smrsh.c b/contrib/sendmail/smrsh/smrsh.c index cf7768f..0b8ecef 100644 --- a/contrib/sendmail/smrsh/smrsh.c +++ b/contrib/sendmail/smrsh/smrsh.c @@ -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 */ - - /* - ** Check to see if the command name is legal. - */ + /* 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 */ - (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); - exit(EX_UNAVAILABLE); - } - if (p != NULL) - *p = ' '; + else + break; - /* - ** Create the actual shell input. - */ + 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; + } - strcpy(cmdbuf, CMDDIR); - strcat(cmdbuf, "/"); - strcat(cmdbuf, cmd); + 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); + } + /* 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; } diff --git a/contrib/sendmail/src/aliases.5 b/contrib/sendmail/src/aliases.5 index 513bf49..7b274e7 100644 --- a/contrib/sendmail/src/aliases.5 +++ b/contrib/sendmail/src/aliases.5 @@ -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. diff --git a/contrib/sendmail/src/conf.c b/contrib/sendmail/src/conf.c index cc6c968..85668b8 100644 --- a/contrib/sendmail/src/conf.c +++ b/contrib/sendmail/src/conf.c @@ -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,14 +12,30 @@ */ #ifndef lint -static char sccsid[] = "@(#)conf.c 8.452 (Berkeley) 1/26/1999"; -#endif /* not lint */ +static char id[] = "@(#)$Id: conf.c,v 8.646.2.2.2.23 2000/07/15 17:35:18 gshapiro Exp $"; +#endif /* ! lint */ + +/* $FreeBSD$ */ + +#include <sendmail.h> +#include <sendmail/pathnames.h> -# include "sendmail.h" -# include "pathnames.h" # include <sys/ioctl.h> # include <sys/param.h> -# include <limits.h> + +#include <limits.h> +#if NETINET || NETINET6 +# include <arpa/inet.h> +#endif /* NETINET || NETINET6 */ +#if HASULIMIT && defined(HPUX11) +# include <ulimit.h> +#endif /* HASULIMIT && defined(HPUX11) */ + + +static void setupmaps __P((void)); +static void setupmailers __P((void)); +static int get_num_procs_online __P((void)); + /* ** CONF.C -- Sendmail Configuration Tables. @@ -54,51 +71,52 @@ static char sccsid[] = "@(#)conf.c 8.452 (Berkeley) 1/26/1999"; struct hdrinfo HdrInfo[] = { - /* originator fields, most to least significant */ - { "resent-sender", H_FROM|H_RESENT }, - { "resent-from", H_FROM|H_RESENT }, - { "resent-reply-to", H_FROM|H_RESENT }, - { "sender", H_FROM }, - { "from", H_FROM }, - { "reply-to", H_FROM }, - { "errors-to", H_FROM|H_ERRORSTO }, - { "full-name", H_ACHECK }, - { "return-receipt-to", H_RECEIPTTO }, + /* originator fields, most to least significant */ + { "resent-sender", H_FROM|H_RESENT, NULL }, + { "resent-from", H_FROM|H_RESENT, NULL }, + { "resent-reply-to", H_FROM|H_RESENT, NULL }, + { "sender", H_FROM, NULL }, + { "from", H_FROM, NULL }, + { "reply-to", H_FROM, NULL }, + { "errors-to", H_FROM|H_ERRORSTO, NULL }, + { "full-name", H_ACHECK, NULL }, + { "return-receipt-to", H_RECEIPTTO, NULL }, /* destination fields */ - { "to", H_RCPT }, - { "resent-to", H_RCPT|H_RESENT }, - { "cc", H_RCPT }, - { "resent-cc", H_RCPT|H_RESENT }, - { "bcc", H_RCPT|H_BCC }, - { "resent-bcc", H_RCPT|H_BCC|H_RESENT }, - { "apparently-to", H_RCPT }, + { "to", H_RCPT, NULL }, + { "resent-to", H_RCPT|H_RESENT, NULL }, + { "cc", H_RCPT, NULL }, + { "resent-cc", H_RCPT|H_RESENT, NULL }, + { "bcc", H_RCPT|H_BCC, NULL }, + { "resent-bcc", H_RCPT|H_BCC|H_RESENT, NULL }, + { "apparently-to", H_RCPT, NULL }, /* message identification and control */ - { "message-id", 0 }, - { "resent-message-id", H_RESENT }, - { "message", H_EOH }, - { "text", H_EOH }, + { "message-id", 0, NULL }, + { "resent-message-id", H_RESENT, NULL }, + { "message", H_EOH, NULL }, + { "text", H_EOH, NULL }, /* date fields */ - { "date", 0 }, - { "resent-date", H_RESENT }, + { "date", 0, NULL }, + { "resent-date", H_RESENT, NULL }, /* trace fields */ - { "received", H_TRACE|H_FORCE }, - { "x400-received", H_TRACE|H_FORCE }, - { "via", H_TRACE|H_FORCE }, - { "mail-from", H_TRACE|H_FORCE }, + { "received", H_TRACE|H_FORCE, NULL }, + { "x400-received", H_TRACE|H_FORCE, NULL }, + { "via", H_TRACE|H_FORCE, NULL }, + { "mail-from", H_TRACE|H_FORCE, NULL }, /* miscellaneous fields */ - { "comments", H_FORCE|H_ENCODABLE }, - { "return-path", H_FORCE|H_ACHECK }, - { "content-transfer-encoding", H_CTE }, - { "content-type", H_CTYPE }, - { "content-length", H_ACHECK }, - { "subject", H_ENCODABLE }, - - { NULL, 0 } + { "comments", H_FORCE|H_ENCODABLE, NULL }, + { "return-path", H_FORCE|H_ACHECK|H_BINDLATE, NULL }, + { "content-transfer-encoding", H_CTE, NULL }, + { "content-type", H_CTYPE, NULL }, + { "content-length", H_ACHECK, NULL }, + { "subject", H_ENCODABLE, NULL }, + { "x-authentication-warning", H_FORCE, NULL }, + + { NULL, 0, NULL } }; @@ -121,6 +139,7 @@ struct prival PrivacyValues[] = { "noverb", PRIV_NOVERB }, { "authwarnings", PRIV_AUTHWARNINGS }, { "noreceipts", PRIV_NORECEIPTS }, + { "nobodyreturn", PRIV_NOBODYRETN }, { "goaway", PRIV_GOAWAY }, { NULL, 0 } }; @@ -172,6 +191,14 @@ struct dbsval DontBlameSendmailValues[] = DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE }, { "runprograminunsafedirpath", DBS_RUNPROGRAMINUNSAFEDIRPATH }, { "runwritableprogram", DBS_RUNWRITABLEPROGRAM }, + { "nonrootsafeaddr", DBS_NONROOTSAFEADDR }, + { "truststickybit", DBS_TRUSTSTICKYBIT }, + { "dontwarnforwardfileinunsafedirpath", + DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH }, + { "insufficiententropy", DBS_INSUFFICIENTENTROPY }, +#if _FFR_UNSAFE_SASL + { "groupreadablesaslfile", DBS_GROUPREADABLESASLFILE }, +#endif /* _FFR_UNSAFE_SASL */ { NULL, 0 } }; @@ -202,39 +229,36 @@ int DtableSize = 50; /* max open files; reset in 4.2bsd */ #define HOURS * 60 MINUTES #define DAYS * 24 HOURS -#ifndef _PATH_VARTMP -# define _PATH_VARTMP "/usr/tmp/" -#endif - #ifndef MAXRULERECURSION # define MAXRULERECURSION 50 /* max ruleset recursion depth */ -#endif +#endif /* ! MAXRULERECURSION */ void setdefaults(e) register ENVELOPE *e; { int i; + int numprocs; struct passwd *pw; - char buf[MAXNAME]; - extern void setdefuser __P((void)); - extern void setupmaps __P((void)); - extern void setupmailers __P((void)); - extern void setupheaders __P((void)); + numprocs = get_num_procs_online(); SpaceSub = ' '; /* option B */ - QueueLA = 8; /* option x */ - RefuseLA = 12; /* option X */ + QueueLA = 8 * numprocs; /* option x */ + RefuseLA = 12 * numprocs; /* option X */ WkRecipFact = 30000L; /* option y */ WkClassFact = 1800L; /* option z */ WkTimeFact = 90000L; /* option Z */ QueueFactor = WkRecipFact * 20; /* option q */ FileMode = (RealUid != geteuid()) ? 0644 : 0600; /* option F */ - - if (((pw = getpwnam("mailnull")) != NULL && pw->pw_uid != 0) || - ((pw = getpwnam("sendmail")) != NULL && pw->pw_uid != 0) || - ((pw = getpwnam("daemon")) != NULL && pw->pw_uid != 0)) +#if _FFR_QUEUE_FILE_MODE + QueueFileMode = (RealUid != geteuid()) ? 0644 : 0600; + /* option QueueFileMode */ +#endif /* _FFR_QUEUE_FILE_MODE */ + + if (((pw = sm_getpwnam("mailnull")) != NULL && pw->pw_uid != 0) || + ((pw = sm_getpwnam("sendmail")) != NULL && pw->pw_uid != 0) || + ((pw = sm_getpwnam("daemon")) != NULL && pw->pw_uid != 0)) { DefUid = pw->pw_uid; /* option u */ DefGid = pw->pw_gid; /* option g */ @@ -248,31 +272,36 @@ setdefaults(e) } TrustedUid = 0; if (tTd(37, 4)) - printf("setdefaults: DefUser=%s, DefUid=%d, DefGid=%d\n", - DefUser != NULL ? DefUser : "<1:1>", - (int) DefUid, (int) DefGid); + dprintf("setdefaults: DefUser=%s, DefUid=%d, DefGid=%d\n", + DefUser != NULL ? DefUser : "<1:1>", + (int) DefUid, (int) DefGid); CheckpointInterval = 10; /* option C */ MaxHopCount = 25; /* option h */ - e->e_sendmode = SM_FORK; /* option d */ + set_delivery_mode(SM_FORK, e); /* option d */ e->e_errormode = EM_PRINT; /* option e */ + e->e_queuedir = NOQDIR; + e->e_ctime = curtime(); SevenBitInput = FALSE; /* option 7 */ MaxMciCache = 1; /* option k */ MciCacheTimeout = 5 MINUTES; /* option K */ LogLevel = 9; /* option L */ - inittimeouts(NULL); /* option r */ + inittimeouts(NULL, FALSE); /* option r */ PrivacyFlags = PRIV_PUBLIC; /* option p */ - DontBlameSendmail = DBS_SAFE; /* DontBlameSendmail option */ + MeToo = TRUE; /* option m */ + SendMIMEErrors = TRUE; /* option f */ + SuperSafe = TRUE; /* option s */ + clrbitmap(DontBlameSendmail); /* DontBlameSendmail option */ #if MIME8TO7 MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */ -#else +#else /* MIME8TO7 */ MimeMode = MM_PASS8BIT; -#endif +#endif /* MIME8TO7 */ for (i = 0; i < MAXTOCLASS; i++) { TimeOuts.to_q_return[i] = 5 DAYS; /* option T */ TimeOuts.to_q_warning[i] = 0; /* option T */ } - ServiceSwitchFile = "/etc/service.switch"; + ServiceSwitchFile = "/etc/mail/service.switch"; ServiceCacheMaxAge = (time_t) 10; HostsFile = _PATH_HOSTS; PidFile = newstr(_PATH_SENDMAILPID); @@ -285,14 +314,35 @@ setdefaults(e) DontLockReadFiles = TRUE; DoubleBounceAddr = "postmaster"; MaxHeadersLength = MAXHDRSLEN; - snprintf(buf, sizeof buf, "%s%sdead.letter", - _PATH_VARTMP, - _PATH_VARTMP[sizeof _PATH_VARTMP - 2] == '/' ? "" : "/"); - DeadLetterDrop = newstr(buf); + MaxForwardEntries = 0; +#if SASL + AuthMechanisms = newstr(AUTH_MECHANISMS); +#endif /* SASL */ #ifdef HESIOD_INIT HesiodContext = NULL; -#endif +#endif /* HESIOD_INIT */ +#if NETINET6 + /* Detect if IPv6 is available at run time */ + i = socket(AF_INET6, SOCK_STREAM, 0); + if (i >= 0) + { + InetMode = AF_INET6; + (void) close(i); + } + else + InetMode = AF_INET; +#else /* NETINET6 */ + InetMode = AF_INET; +#endif /* NETINET6 */ ControlSocketName = NULL; + memset(&ConnectOnlyTo, '\0', sizeof ConnectOnlyTo); + DataFileBufferSize = 4096; + XscriptFileBufferSize = 4096; + for (i = 0; i < MAXRWSETS; i++) + RuleSetNames[i] = NULL; +#if _FFR_MILTER + InputFilters[0] = NULL; +#endif /* _FFR_MILTER */ setupmaps(); setupmailers(); setupheaders(); @@ -314,26 +364,30 @@ setdefuser() snprintf(defuserbuf, sizeof defuserbuf, "%s", defpwent == NULL ? "nobody" : defpwent->pw_name); if (tTd(37, 4)) - printf("setdefuser: DefUid=%d, DefUser=%s\n", + dprintf("setdefuser: DefUid=%d, DefUser=%s\n", (int) DefUid, DefUser); } /* ** SETUPMAILERS -- initialize default mailers */ -void +static void setupmailers() { char buf[100]; - strcpy(buf, "prog, P=/bin/sh, F=lsoDq9, T=DNS/RFC822/X-Unix, A=sh -c \201u"); + (void) strlcpy(buf, "prog, P=/bin/sh, F=lsoDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u", + sizeof buf); makemailer(buf); - strcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=DNS/RFC822/X-Unix, A=FILE \201u"); + (void) strlcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=X-Unix/X-Unix/X-Unix, A=FILE \201u", + sizeof buf); makemailer(buf); - strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u"); + (void) strlcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u", + sizeof buf); makemailer(buf); + initerrmailers(); } /* ** SETUPMAPS -- set up map classes @@ -357,7 +411,7 @@ setupmailers() s->s_mapclass.map_store = store; \ } -void +static void setupmaps() { register STAB *s; @@ -370,55 +424,74 @@ setupmaps() MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE, map_parseargs, bt_map_open, db_map_close, db_map_lookup, db_map_store); -#endif +#endif /* NEWDB */ #ifdef NDBM MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE, map_parseargs, ndbm_map_open, ndbm_map_close, ndbm_map_lookup, ndbm_map_store); -#endif +#endif /* NDBM */ #ifdef NIS MAPDEF("nis", NULL, MCF_ALIASOK, map_parseargs, nis_map_open, null_map_close, nis_map_lookup, null_map_store); -#endif +#endif /* NIS */ #ifdef NISPLUS MAPDEF("nisplus", NULL, MCF_ALIASOK, map_parseargs, nisplus_map_open, null_map_close, nisplus_map_lookup, null_map_store); -#endif +#endif /* NISPLUS */ + #ifdef LDAPMAP - MAPDEF("ldapx", NULL, 0, - ldap_map_parseargs, ldap_map_open, ldap_map_close, - ldap_map_lookup, null_map_store); -#endif + MAPDEF("ldap", NULL, MCF_ALIASOK, + ldapmap_parseargs, ldapmap_open, ldapmap_close, + ldapmap_lookup, null_map_store); + + /* Deprecated */ + MAPDEF("ldapx", NULL, MCF_ALIASOK, + ldapx_map_parseargs, ldapmap_open, ldapmap_close, + ldapmap_lookup, null_map_store); +#endif /* LDAPMAP */ + +#ifdef PH_MAP + MAPDEF("ph", NULL, 0, + ph_map_parseargs, ph_map_open, ph_map_close, + ph_map_lookup, null_map_store); +#endif /* PH_MAP */ + +#if MAP_NSD + /* IRIX 6.5 nsd support */ + MAPDEF("nsd", NULL, MCF_ALIASOK, + map_parseargs, null_map_open, null_map_close, + nsd_map_lookup, null_map_store); +#endif /* MAP_NSD */ #ifdef HESIOD MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY, map_parseargs, hes_map_open, null_map_close, hes_map_lookup, null_map_store); -#endif +#endif /* HESIOD */ #if NETINFO MAPDEF("netinfo", NULL, MCF_ALIASOK, map_parseargs, ni_map_open, null_map_close, ni_map_lookup, null_map_store); -#endif +#endif /* NETINFO */ #if 0 MAPDEF("dns", NULL, 0, dns_map_init, null_map_open, null_map_close, dns_map_lookup, null_map_store); -#endif +#endif /* 0 */ #if NAMED_BIND /* best MX DNS lookup */ MAPDEF("bestmx", NULL, MCF_OPTFILE, map_parseargs, null_map_open, null_map_close, bestmx_map_lookup, null_map_store); -#endif +#endif /* NAMED_BIND */ MAPDEF("host", NULL, 0, host_map_init, null_map_open, null_map_close, @@ -450,14 +523,14 @@ setupmaps() MAPDEF("regex", NULL, 0, regex_map_init, null_map_open, null_map_close, regex_map_lookup, null_map_store); -#endif +#endif /* MAP_REGEX */ #if USERDB /* user database */ MAPDEF("userdb", ".db", 0, map_parseargs, null_map_open, null_map_close, udb_map_lookup, null_map_store); -#endif +#endif /* USERDB */ /* arbitrary programs */ MAPDEF("program", NULL, MCF_ALIASOK, @@ -479,12 +552,28 @@ setupmaps() map_parseargs, null_map_open, null_map_close, null_map_lookup, null_map_store); -#if _FFR_MAP_SYSLOG /* syslog map -- logs information to syslog */ MAPDEF("syslog", NULL, 0, - syslog_map_parseargs, null_map_open, null_map_close, - syslog_map_lookup, null_map_store); -#endif + syslog_map_parseargs, null_map_open, null_map_close, + syslog_map_lookup, null_map_store); + + /* macro storage map -- rulesets can set macros */ + MAPDEF("macro", NULL, 0, + dequote_init, null_map_open, null_map_close, + macro_map_lookup, null_map_store); + + /* arithmetic map -- add/subtract/compare */ + MAPDEF("arith", NULL, 0, + dequote_init, null_map_open, null_map_close, + arith_map_lookup, null_map_store); + + if (tTd(38, 2)) + { + /* bogus map -- always return tempfail */ + MAPDEF("bogus", NULL, MCF_ALIASOK|MCF_OPTFILE, + map_parseargs, null_map_open, null_map_close, + bogus_map_lookup, null_map_store); + } } #undef MAPDEF @@ -528,43 +617,47 @@ inithostmaps() if (strcmp(maptype[i], "files") == 0 && stab("hosts.files", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts"); + (void) strlcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts", + sizeof buf); (void) makemapentry(buf); } -#if NAMED_BIND +# if NAMED_BIND else if (strcmp(maptype[i], "dns") == 0 && stab("hosts.dns", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "hosts.dns dns A"); + (void) strlcpy(buf, "hosts.dns dns A", sizeof buf); (void) makemapentry(buf); } -#endif -#ifdef NISPLUS +# endif /* NAMED_BIND */ +# ifdef NISPLUS else if (strcmp(maptype[i], "nisplus") == 0 && stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "hosts.nisplus nisplus -k name -v address -d hosts.org_dir"); + (void) strlcpy(buf, "hosts.nisplus nisplus -k name -v address hosts.org_dir", + sizeof buf); (void) makemapentry(buf); } -#endif -#ifdef NIS +# endif /* NISPLUS */ +# ifdef NIS else if (strcmp(maptype[i], "nis") == 0 && stab("hosts.nis", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "hosts.nis nis -d -k 0 -v 1 hosts.byname"); + (void) strlcpy(buf, "hosts.nis nis -k 0 -v 1 hosts.byname", + sizeof buf); (void) makemapentry(buf); } -#endif -#if NETINFO +# endif /* NIS */ +# if NETINFO else if (strcmp(maptype[i], "netinfo") == 0) && stab("hosts.netinfo", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "hosts.netinfo netinfo -v name /machines"); + (void) strlcpy(buf, "hosts.netinfo netinfo -v name /machines", + sizeof buf); (void) makemapentry(buf); } -#endif +# endif /* NETINFO */ } -#endif +#endif /* 0 */ /* ** Make sure we have a host map. @@ -573,11 +666,11 @@ inithostmaps() if (stab("host", ST_MAP, ST_FIND) == NULL) { /* user didn't initialize: set up host map */ - strcpy(buf, "host host"); + (void) strlcpy(buf, "host host", sizeof buf); #if NAMED_BIND if (ConfigLevel >= 2) - strcat(buf, " -a."); -#endif + (void) strlcat(buf, " -a. -D", sizeof buf); +#endif /* NAMED_BIND */ (void) makemapentry(buf); } @@ -591,45 +684,49 @@ inithostmaps() if (strcmp(maptype[i], "files") == 0 && stab("aliases.files", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "aliases.files null"); + (void) strlcpy(buf, "aliases.files null", sizeof buf); (void) makemapentry(buf); } #ifdef NISPLUS else if (strcmp(maptype[i], "nisplus") == 0 && stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion -d mail_aliases.org_dir"); + (void) strlcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion mail_aliases.org_dir", + sizeof buf); (void) makemapentry(buf); } -#endif +#endif /* NISPLUS */ #ifdef NIS else if (strcmp(maptype[i], "nis") == 0 && stab("aliases.nis", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "aliases.nis nis -d mail.aliases"); + (void) strlcpy(buf, "aliases.nis nis mail.aliases", + sizeof buf); (void) makemapentry(buf); } -#endif -#ifdef NETINFO +#endif /* NIS */ +#if NETINFO else if (strcmp(maptype[i], "netinfo") == 0 && stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "aliases.netinfo netinfo -z, /aliases"); + (void) strlcpy(buf, "aliases.netinfo netinfo -z, /aliases", + sizeof buf); (void) makemapentry(buf); } -#endif +#endif /* NETINFO */ #ifdef HESIOD else if (strcmp(maptype[i], "hesiod") == 0 && stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "aliases.hesiod hesiod aliases"); + (void) strlcpy(buf, "aliases.hesiod hesiod aliases", + sizeof buf); (void) makemapentry(buf); } -#endif +#endif /* HESIOD */ } if (stab("aliases", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "aliases switch aliases"); + (void) strlcpy(buf, "aliases switch aliases", sizeof buf); (void) makemapentry(buf); } @@ -644,40 +741,43 @@ inithostmaps() if (strcmp(maptype[i], "files") == 0 && stab("users.files", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd"); + (void) strlcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd", + sizeof buf); (void) makemapentry(buf); } -#ifdef NISPLUS +# ifdef NISPLUS else if (strcmp(maptype[i], "nisplus") == 0 && stab("users.nisplus", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "users.nisplus nisplus -m -kname -vhome -d passwd.org_dir"); + (void) strlcpy(buf, "users.nisplus nisplus -m -kname -vhome passwd.org_dir", + sizeof buf); (void) makemapentry(buf); } -#endif -#ifdef NIS +# endif /* NISPLUS */ +# ifdef NIS else if (strcmp(maptype[i], "nis") == 0 && stab("users.nis", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "users.nis nis -m -d passwd.byname"); + (void) strlcpy(buf, "users.nis nis -m passwd.byname", + sizeof buf); (void) makemapentry(buf); } -#endif -#ifdef HESIOD +# endif /* NIS */ +# ifdef HESIOD else if (strcmp(maptype[i], "hesiod") == 0) && stab("users.hesiod", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "users.hesiod hesiod"); + (void) strlcpy(buf, "users.hesiod hesiod", sizeof buf); (void) makemapentry(buf); } -#endif +# endif /* HESIOD */ } if (stab("users", ST_MAP, ST_FIND) == NULL) { - strcpy(buf, "users switch -m passwd"); + (void) strlcpy(buf, "users switch -m passwd", sizeof buf); (void) makemapentry(buf); } -#endif +#endif /* 0 */ } /* ** SWITCH_MAP_FIND -- find the list of types associated with a map @@ -694,23 +794,26 @@ inithostmaps() ** ** Returns: ** The number of map types filled in, or -1 for failure. +** +** Side effects: +** Preserves errno so nothing in the routine clobbers it. */ #if defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) # define _USE_SUN_NSSWITCH_ -#endif +#endif /* defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) */ #ifdef _USE_SUN_NSSWITCH_ # include <nsswitch.h> -#endif +#endif /* _USE_SUN_NSSWITCH_ */ #if defined(ultrix) || (defined(__osf__) && defined(__alpha)) # define _USE_DEC_SVC_CONF_ -#endif +#endif /* defined(ultrix) || (defined(__osf__) && defined(__alpha)) */ #ifdef _USE_DEC_SVC_CONF_ # include <sys/svcinfo.h> -#endif +#endif /* _USE_DEC_SVC_CONF_ */ int switch_map_find(service, maptype, mapreturn) @@ -719,6 +822,7 @@ switch_map_find(service, maptype, mapreturn) short mapreturn[MAXMAPACTIONS]; { int svcno; + int save_errno = errno; #ifdef _USE_SUN_NSSWITCH_ struct __nsw_switchconfig *nsw_conf; @@ -749,8 +853,9 @@ switch_map_find(service, maptype, mapreturn) svcno++; lk = lk->next; } + errno = save_errno; return svcno; -#endif +#endif /* _USE_SUN_NSSWITCH_ */ #ifdef _USE_DEC_SVC_CONF_ struct svcinfo *svcinfo; @@ -769,7 +874,10 @@ switch_map_find(service, maptype, mapreturn) else if (strcmp(service, "passwd") == 0) svc = SVC_PASSWD; else + { + errno = save_errno; return -1; + } for (svcno = 0; svcno < SVC_PATHSIZE; svcno++) { switch (svcinfo->svcpath[svc][svcno]) @@ -786,18 +894,20 @@ switch_map_find(service, maptype, mapreturn) maptype[svcno] = "dns"; break; -#ifdef SVC_HESIOD +# ifdef SVC_HESIOD case SVC_HESIOD: maptype[svcno] = "hesiod"; break; -#endif +# endif /* SVC_HESIOD */ case SVC_LAST: + errno = save_errno; return svcno; } } + errno = save_errno; return svcno; -#endif +#endif /* _USE_DEC_SVC_CONF_ */ #if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) /* @@ -814,9 +924,10 @@ switch_map_find(service, maptype, mapreturn) { /* (re)read service switch */ register FILE *fp; - int sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK; + long sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK; - if (!bitset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR, DontBlameSendmail)) + if (!bitnset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR, + DontBlameSendmail)) sff |= SFF_NOWLINK; if (ConfigFileRead) @@ -878,7 +989,7 @@ switch_map_find(service, maptype, mapreturn) if (svcno < MAXMAPSTACK) st->s_service[svcno] = NULL; } - fclose(fp); + (void) fclose(fp); } } @@ -894,46 +1005,56 @@ switch_map_find(service, maptype, mapreturn) if (maptype[svcno++] == NULL) break; } + errno = save_errno; return --svcno; } -#endif +#endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */ #if !defined(_USE_SUN_NSSWITCH_) /* if the service file doesn't work, use an absolute fallback */ # ifdef _USE_DEC_SVC_CONF_ punt: -# endif +# endif /* _USE_DEC_SVC_CONF_ */ for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) mapreturn[svcno] = 0; svcno = 0; if (strcmp(service, "aliases") == 0) { maptype[svcno++] = "files"; +# if defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) + maptype[svcno++] = "netinfo"; +# endif /* defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) */ # ifdef AUTO_NIS_ALIASES # ifdef NISPLUS maptype[svcno++] = "nisplus"; -# endif +# endif /* NISPLUS */ # ifdef NIS maptype[svcno++] = "nis"; -# endif -# endif +# endif /* NIS */ +# endif /* AUTO_NIS_ALIASES */ + errno = save_errno; return svcno; } if (strcmp(service, "hosts") == 0) { -# if NAMED_BIND +# if NAMED_BIND maptype[svcno++] = "dns"; -# else -# if defined(sun) && !defined(BSD) +# else /* NAMED_BIND */ +# if defined(sun) && !defined(BSD) /* SunOS */ maptype[svcno++] = "nis"; -# endif -# endif +# endif /* defined(sun) && !defined(BSD) */ +# endif /* NAMED_BIND */ +# if defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) + maptype[svcno++] = "netinfo"; +# endif /* defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) */ maptype[svcno++] = "files"; + errno = save_errno; return svcno; } + errno = save_errno; return -1; -#endif +#endif /* !defined(_USE_SUN_NSSWITCH_) */ } /* ** USERNAME -- return the user id of the logged in user. @@ -983,12 +1104,12 @@ username() } if (myname == NULL || myname[0] == '\0') { - syserr("554 Who are you?"); + syserr("554 5.3.0 Who are you?"); myname = "postmaster"; } } - return (myname); + return myname; } /* ** TTYPATH -- Get the path of the user's tty @@ -1027,22 +1148,22 @@ ttypath() (pathn = ttyname(0)) == NULL) { errno = 0; - return (NULL); + return NULL; } /* see if we have write permission */ if (stat(pathn, &stbuf) < 0 || !bitset(S_IWOTH, stbuf.st_mode)) { errno = 0; - return (NULL); + return NULL; } /* see if the user is logged in */ if (getlogin() == NULL) - return (NULL); + return NULL; /* looks good */ - return (pathn); + return pathn; } /* ** CHECKCOMPAT -- check for From and To person compatible. @@ -1077,16 +1198,11 @@ checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { -# ifdef lint - if (to == NULL) - to++; -# endif /* lint */ - if (tTd(49, 1)) - printf("checkcompat(to=%s, from=%s)\n", + dprintf("checkcompat(to=%s, from=%s)\n", to->q_paddr, e->e_from.q_paddr); -# ifdef EXAMPLE_CODE +#ifdef EXAMPLE_CODE /* this code is intended as an example only */ register STAB *s; @@ -1095,12 +1211,12 @@ checkcompat(to, e) to->q_mailer == s->s_mailer) { usrerr("553 No ARPA mail through this machine: see your system administration"); - /* e->e_flags |= EF_NO_BODY_RETN; to supress body on return */ + /* e->e_flags |= EF_NO_BODY_RETN; to suppress body on return */ to->q_status = "5.7.1"; - return (EX_UNAVAILABLE); + return EX_UNAVAILABLE; } -# endif /* EXAMPLE_CODE */ - return (EX_OK); +#endif /* EXAMPLE_CODE */ + return EX_OK; } /* ** SETSIGNAL -- set a signal handler @@ -1113,29 +1229,54 @@ setsignal(sig, handler) int sig; sigfunc_t handler; { -#if defined(SYS5SIGNALS) || defined(BSD4_3) -# ifdef BSD4_3 - return signal(sig, handler); -# else - return sigset(sig, handler); -# endif -#else + /* + ** First, try for modern signal calls + ** and restartable syscalls + */ + +# ifdef SA_RESTART struct sigaction n, o; - bzero(&n, sizeof n); -# if USE_SA_SIGACTION + memset(&n, '\0', sizeof n); +# if USE_SA_SIGACTION n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler; n.sa_flags = SA_RESTART|SA_SIGINFO; -# else +# else /* USE_SA_SIGACTION */ n.sa_handler = handler; -# ifdef SA_RESTART n.sa_flags = SA_RESTART; -# endif -# endif +# endif /* USE_SA_SIGACTION */ if (sigaction(sig, &n, &o) < 0) return SIG_ERR; return o.sa_handler; -#endif +# else /* SA_RESTART */ + + /* + ** Else check for SYS5SIGNALS or + ** BSD4_3 signals + */ + +# if defined(SYS5SIGNALS) || defined(BSD4_3) +# ifdef BSD4_3 + return signal(sig, handler); +# else /* BSD4_3 */ + return sigset(sig, handler); +# endif /* BSD4_3 */ +# else /* defined(SYS5SIGNALS) || defined(BSD4_3) */ + + /* + ** Finally, if nothing else is available, + ** go for a default + */ + + struct sigaction n, o; + + memset(&n, '\0', sizeof n); + n.sa_handler = handler; + if (sigaction(sig, &n, &o) < 0) + return SIG_ERR; + return o.sa_handler; +# endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */ +# endif /* SA_RESTART */ } /* ** BLOCKSIGNAL -- hold a signal to prevent delivery @@ -1153,13 +1294,13 @@ int blocksignal(sig) int sig; { -#ifdef BSD4_3 -# ifndef sigmask -# define sigmask(s) (1 << ((s) - 1)) -# endif +# ifdef BSD4_3 +# ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +# endif /* ! sigmask */ return (sigblock(sigmask(sig)) & sigmask(sig)) != 0; -#else -# ifdef ALTOS_SYSTEM_V +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V sigfunc_t handler; handler = sigset(sig, SIG_HOLD); @@ -1167,17 +1308,17 @@ blocksignal(sig) return -1; else return handler == SIG_HOLD; -# else +# else /* ALTOS_SYSTEM_V */ sigset_t sset, oset; - sigemptyset(&sset); - sigaddset(&sset, sig); + (void) sigemptyset(&sset); + (void) sigaddset(&sset, sig); if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0) return -1; else return sigismember(&oset, sig); -# endif -#endif +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ } /* ** RELEASESIGNAL -- release a held signal @@ -1195,10 +1336,10 @@ int releasesignal(sig) int sig; { -#ifdef BSD4_3 +# ifdef BSD4_3 return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0; -#else -# ifdef ALTOS_SYSTEM_V +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V sigfunc_t handler; handler = sigset(sig, SIG_HOLD); @@ -1206,17 +1347,17 @@ releasesignal(sig) return -1; else return handler == SIG_HOLD; -# else +# else /* ALTOS_SYSTEM_V */ sigset_t sset, oset; - sigemptyset(&sset); - sigaddset(&sset, sig); + (void) sigemptyset(&sset); + (void) sigaddset(&sset, sig); if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0) return -1; else return sigismember(&oset, sig); -# endif -#endif +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ } /* ** HOLDSIGS -- arrange to hold all signals @@ -1263,11 +1404,11 @@ rlsesigs() #ifdef _AUX_SOURCE # include <compat.h> -#endif +#endif /* _AUX_SOURCE */ #if SHARE_V1 # include <shares.h> -#endif +#endif /* SHARE_V1 */ void init_md(argc, argv) @@ -1276,16 +1417,16 @@ init_md(argc, argv) { #ifdef _AUX_SOURCE setcompat(getcompat() | COMPAT_BSDPROT); -#endif +#endif /* _AUX_SOURCE */ #ifdef SUN_EXTENSIONS init_md_sun(); -#endif +#endif /* SUN_EXTENSIONS */ #if _CONVEX_SOURCE /* keep gethostby*() from stripping the local domain name */ set_domain_trim_off(); -#endif +#endif /* _CONVEX_SOURCE */ #ifdef __QNX__ /* ** Due to QNX's network distributed nature, you can target a tcpip @@ -1294,7 +1435,7 @@ init_md(argc, argv) ** environment is clear. */ __sock_locate(); -#endif +#endif /* __QNX__ */ #if SECUREWARE || defined(_SCO_unix_) set_auth_parameters(argc, argv); @@ -1307,14 +1448,15 @@ init_md(argc, argv) if (getluid() == -1) setluid(0); -# endif -#endif +# endif /* _SCO_unix_ */ +#endif /* SECUREWARE || defined(_SCO_unix_) */ + #ifdef VENDOR_DEFAULT VendorCode = VENDOR_DEFAULT; -#else +#else /* VENDOR_DEFAULT */ VendorCode = VENDOR_BERKELEY; -#endif +#endif /* VENDOR_DEFAULT */ } /* ** INIT_VENDOR_MACROS -- vendor-dependent macro initializations @@ -1370,167 +1512,171 @@ init_vendor_macros(e) /* do guesses based on general OS type */ #ifndef LA_TYPE # define LA_TYPE LA_ZERO -#endif +#endif /* ! LA_TYPE */ #ifndef FSHIFT # if defined(unixpc) # define FSHIFT 5 -# endif +# endif /* defined(unixpc) */ # if defined(__alpha) || defined(IRIX) # define FSHIFT 10 -# endif +# endif /* defined(__alpha) || defined(IRIX) */ -#endif +#endif /* ! FSHIFT */ #ifndef FSHIFT # define FSHIFT 8 -#endif +#endif /* ! FSHIFT */ #ifndef FSCALE # define FSCALE (1 << FSHIFT) -#endif +#endif /* ! FSCALE */ #ifndef LA_AVENRUN # ifdef SYSTEM5 # define LA_AVENRUN "avenrun" -# else +# else /* SYSTEM5 */ # define LA_AVENRUN "_avenrun" -# endif -#endif +# endif /* SYSTEM5 */ +#endif /* ! LA_AVENRUN */ /* _PATH_KMEM should be defined in <paths.h> */ #ifndef _PATH_KMEM # define _PATH_KMEM "/dev/kmem" -#endif +#endif /* ! _PATH_KMEM */ #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) -#include <nlist.h> +# include <nlist.h> /* _PATH_UNIX should be defined in <paths.h> */ -#ifndef _PATH_UNIX -# if defined(SYSTEM5) -# define _PATH_UNIX "/unix" -# else -# define _PATH_UNIX "/vmunix" -# endif -#endif - -#ifdef _AUX_SOURCE +# ifndef _PATH_UNIX +# if defined(SYSTEM5) +# define _PATH_UNIX "/unix" +# else /* defined(SYSTEM5) */ +# define _PATH_UNIX "/vmunix" +# endif /* defined(SYSTEM5) */ +# endif /* ! _PATH_UNIX */ + +# ifdef _AUX_SOURCE struct nlist Nl[2]; -#else +# else /* _AUX_SOURCE */ struct nlist Nl[] = { { LA_AVENRUN }, { 0 }, }; -#endif -#define X_AVENRUN 0 +# endif /* _AUX_SOURCE */ +# define X_AVENRUN 0 -int +static int getla() { static int kmem = -1; -#if LA_TYPE == LA_INT +# if LA_TYPE == LA_INT long avenrun[3]; -#else -# if LA_TYPE == LA_SHORT +# else /* LA_TYPE == LA_INT */ +# if LA_TYPE == LA_SHORT short avenrun[3]; -# else +# else /* LA_TYPE == LA_SHORT */ double avenrun[3]; -# endif -#endif +# endif /* LA_TYPE == LA_SHORT */ +# endif /* LA_TYPE == LA_INT */ extern int errno; extern off_t lseek(); if (kmem < 0) { -#ifdef _AUX_SOURCE - strcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN); +# ifdef _AUX_SOURCE + (void) strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN, + sizeof Nl[X_AVENRUN].n_name); Nl[1].n_name[0] = '\0'; -#endif +# endif /* _AUX_SOURCE */ -#if defined(_AIX3) || defined(_AIX4) +# if defined(_AIX3) || defined(_AIX4) if (knlist(Nl, 1, sizeof Nl[0]) < 0) -#else +# else /* defined(_AIX3) || defined(_AIX4) */ if (nlist(_PATH_UNIX, Nl) < 0) -#endif +# endif /* defined(_AIX3) || defined(_AIX4) */ { if (tTd(3, 1)) - printf("getla: nlist(%s): %s\n", _PATH_UNIX, + dprintf("getla: nlist(%s): %s\n", _PATH_UNIX, errstring(errno)); - return (-1); + return -1; } if (Nl[X_AVENRUN].n_value == 0) { if (tTd(3, 1)) - printf("getla: nlist(%s, %s) ==> 0\n", + dprintf("getla: nlist(%s, %s) ==> 0\n", _PATH_UNIX, LA_AVENRUN); - return (-1); + return -1; } -#ifdef NAMELISTMASK +# ifdef NAMELISTMASK Nl[X_AVENRUN].n_value &= NAMELISTMASK; -#endif +# endif /* NAMELISTMASK */ kmem = open(_PATH_KMEM, 0, 0); if (kmem < 0) { if (tTd(3, 1)) - printf("getla: open(/dev/kmem): %s\n", + dprintf("getla: open(/dev/kmem): %s\n", errstring(errno)); - return (-1); + return -1; } - (void) fcntl(kmem, F_SETFD, 1); + (void) fcntl(kmem, F_SETFD, FD_CLOEXEC); } if (tTd(3, 20)) - printf("getla: symbol address = %#lx\n", + dprintf("getla: symbol address = %#lx\n", (u_long) Nl[X_AVENRUN].n_value); if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 || read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) { /* thank you Ian */ if (tTd(3, 1)) - printf("getla: lseek or read: %s\n", errstring(errno)); - return (-1); + dprintf("getla: lseek or read: %s\n", + errstring(errno)); + return -1; } # if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) if (tTd(3, 5)) { # if LA_TYPE == LA_SHORT - printf("getla: avenrun = %d", avenrun[0]); + dprintf("getla: avenrun = %d", avenrun[0]); if (tTd(3, 15)) - printf(", %d, %d", avenrun[1], avenrun[2]); -# else - printf("getla: avenrun = %ld", avenrun[0]); + dprintf(", %d, %d", avenrun[1], avenrun[2]); +# else /* LA_TYPE == LA_SHORT */ + dprintf("getla: avenrun = %ld", avenrun[0]); if (tTd(3, 15)) - printf(", %ld, %ld", avenrun[1], avenrun[2]); -# endif - printf("\n"); + dprintf(", %ld, %ld", avenrun[1], avenrun[2]); +# endif /* LA_TYPE == LA_SHORT */ + dprintf("\n"); } if (tTd(3, 1)) - printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); + dprintf("getla: %d\n", + (int) (avenrun[0] + FSCALE/2) >> FSHIFT); return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); -# else /* LA_TYPE == LA_FLOAT */ +# else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) */ if (tTd(3, 5)) { - printf("getla: avenrun = %g", avenrun[0]); + dprintf("getla: avenrun = %g", avenrun[0]); if (tTd(3, 15)) - printf(", %g, %g", avenrun[1], avenrun[2]); - printf("\n"); + dprintf(", %g, %g", avenrun[1], avenrun[2]); + dprintf("\n"); } if (tTd(3, 1)) - printf("getla: %d\n", (int) (avenrun[0] +0.5)); + dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); return ((int) (avenrun[0] + 0.5)); -# endif +# endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) */ } -#endif /* LA_TYPE == LA_INT or LA_SHORT or LA_FLOAT */ +#endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) */ #if LA_TYPE == LA_READKSYM # include <sys/ksym.h> +static int getla() { static int kmem = -1; @@ -1544,11 +1690,11 @@ getla() if (kmem < 0) { if (tTd(3, 1)) - printf("getla: open(/dev/kmem): %s\n", + dprintf("getla: open(/dev/kmem): %s\n", errstring(errno)); - return (-1); + return -1; } - (void) fcntl(kmem, F_SETFD, 1); + (void) fcntl(kmem, F_SETFD, FD_CLOEXEC); } mirk.mirk_symname = LA_AVENRUN; mirk.mirk_buf = avenrun; @@ -1556,19 +1702,20 @@ getla() if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0) { if (tTd(3, 1)) - printf("getla: ioctl(MIOC_READKSYM) failed: %s\n", + dprintf("getla: ioctl(MIOC_READKSYM) failed: %s\n", errstring(errno)); return -1; } if (tTd(3, 5)) { - printf("getla: avenrun = %d", avenrun[0]); + dprintf("getla: avenrun = %d", avenrun[0]); if (tTd(3, 15)) - printf(", %d, %d", avenrun[1], avenrun[2]); - printf("\n"); + dprintf(", %d, %d", avenrun[1], avenrun[2]); + dprintf("\n"); } if (tTd(3, 1)) - printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); + dprintf("getla: %d\n", + (int) (avenrun[0] + FSCALE/2) >> FSHIFT); return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); } @@ -1578,7 +1725,7 @@ getla() # include <sys/dg_sys_info.h> -int +static int getla() { struct dg_sys_info_load_info load_info; @@ -1587,9 +1734,9 @@ getla() DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); if (tTd(3, 1)) - printf("getla: %d\n", (int) (load_info.one_minute + 0.5)); + dprintf("getla: %d\n", (int) (load_info.one_minute + 0.5)); - return((int) (load_info.one_minute + 0.5)); + return ((int) (load_info.one_minute + 0.5)); } #endif /* LA_TYPE == LA_DGUX */ @@ -1609,7 +1756,7 @@ struct pst_swapinfo; # include <sys/param.h> # include <sys/pstat.h> -int +static int getla() { struct pst_dynamic pstd; @@ -1619,7 +1766,7 @@ getla() return 0; if (tTd(3, 1)) - printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); + dprintf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); return (int) (pstd.psd_avg_1_min + 0.5); } @@ -1628,7 +1775,7 @@ getla() #if LA_TYPE == LA_SUBR -int +static int getla() { double avenrun[3]; @@ -1636,11 +1783,12 @@ getla() if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) { if (tTd(3, 1)) - perror("getla: getloadavg failed:"); - return (-1); + dprintf("getla: getloadavg failed: %s", + errstring(errno)); + return -1; } if (tTd(3, 1)) - printf("getla: %d\n", (int) (avenrun[0] +0.5)); + dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); return ((int) (avenrun[0] + 0.5)); } @@ -1652,13 +1800,13 @@ getla() ** This has been tested on NEXTSTEP release 2.1/3.X. */ -#if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 -# include <mach/mach.h> -#else -# include <mach.h> -#endif +# if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 +# include <mach/mach.h> +# else /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */ +# include <mach.h> +# endif /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */ -int +static int getla() { processor_set_t default_set; @@ -1671,7 +1819,8 @@ getla() if (error != KERN_SUCCESS) { if (tTd(3, 1)) - perror("getla: processor_set_default failed:"); + dprintf("getla: processor_set_default failed: %s", + errstring(errno)); return -1; } info_count = PROCESSOR_SET_BASIC_INFO_COUNT; @@ -1680,11 +1829,14 @@ getla() &info_count) != KERN_SUCCESS) { if (tTd(3, 1)) - perror("getla: processor_set_info failed:"); + dprintf("getla: processor_set_info failed: %s", + errstring(errno)); return -1; } if (tTd(3, 1)) - printf("getla: %d\n", (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE); + dprintf("getla: %d\n", + (int) ((info.load_average + (LOAD_SCALE / 2)) / + LOAD_SCALE)); return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE; } @@ -1702,9 +1854,9 @@ getla() # ifndef _PATH_LOADAVG # define _PATH_LOADAVG "/proc/loadavg" -# endif +# endif /* ! _PATH_LOADAVG */ -int +static int getla() { double avenrun; @@ -1715,22 +1867,22 @@ getla() if (fp == NULL) { if (tTd(3, 1)) - printf("getla: fopen(%s): %s\n", + dprintf("getla: fopen(%s): %s\n", _PATH_LOADAVG, errstring(errno)); return -1; } result = fscanf(fp, "%lf", &avenrun); - fclose(fp); + (void) fclose(fp); if (result != 1) { if (tTd(3, 1)) - printf("getla: fscanf() = %d: %s\n", + dprintf("getla: fscanf() = %d: %s\n", result, errstring(errno)); return -1; } if (tTd(3, 1)) - printf("getla(): %.2f\n", avenrun); + dprintf("getla(): %.2f\n", avenrun); return ((int) (avenrun + 0.5)); } @@ -1738,7 +1890,8 @@ getla() #endif /* LA_TYPE == LA_PROCSTR */ #if LA_TYPE == LA_IRIX6 -#include <sys/sysmp.h> + +# include <sys/sysmp.h> int getla(void) { @@ -1751,42 +1904,43 @@ int getla(void) if (kmem < 0) { if (tTd(3, 1)) - printf("getla: open(%s): %s\n", _PATH_KMEM, + dprintf("getla: open(%s): %s\n", _PATH_KMEM, errstring(errno)); return -1; } - (void) fcntl(kmem, F_SETFD, 1); + (void) fcntl(kmem, F_SETFD, FD_CLOEXEC); } - if (lseek(kmem, (sysmp(MP_KERNADDR, MPKA_AVENRUN) & 0x7fffffff), SEEK_SET) == -1 || - read(kmem, (char *)avenrun, sizeof(avenrun)) < sizeof(avenrun)) + if (lseek(kmem, (sysmp(MP_KERNADDR, MPKA_AVENRUN) & 0x7fffffff), SEEK_SET) == -1 || + read(kmem, (char *)avenrun, sizeof(avenrun)) < sizeof(avenrun)) { if (tTd(3, 1)) - printf("getla: lseek or read: %s\n", - errstring(errno)); + dprintf("getla: lseek or read: %s\n", + errstring(errno)); return -1; } if (tTd(3, 5)) { - printf("getla: avenrun = %ld", (long int) avenrun[0]); + dprintf("getla: avenrun = %ld", (long int) avenrun[0]); if (tTd(3, 15)) - printf(", %ld, %ld", - (long int) avenrun[1], (long int) avenrun[2]); - printf("\n"); + dprintf(", %ld, %ld", + (long int) avenrun[1], (long int) avenrun[2]); + dprintf("\n"); } if (tTd(3, 1)) - printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); + dprintf("getla: %d\n", + (int) (avenrun[0] + FSCALE/2) >> FSHIFT); return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); } -#endif +#endif /* LA_TYPE == LA_IRIX6 */ #if LA_TYPE == LA_KSTAT -#include <kstat.h> +# include <kstat.h> -int +static int getla() { static kstat_ctl_t *kc = NULL; @@ -1799,7 +1953,7 @@ getla() if (kc == NULL) { if (tTd(3, 1)) - printf("getla: kstat_open(): %s\n", + dprintf("getla: kstat_open(): %s\n", errstring(errno)); return -1; } @@ -1808,14 +1962,14 @@ getla() if (ksp == NULL) { if (tTd(3, 1)) - printf("getla: kstat_lookup(): %s\n", + dprintf("getla: kstat_lookup(): %s\n", errstring(errno)); return -1; } if (kstat_read(kc, ksp, NULL) < 0) { if (tTd(3, 1)) - printf("getla: kstat_read(): %s\n", + dprintf("getla: kstat_read(): %s\n", errstring(errno)); return -1; } @@ -1839,9 +1993,9 @@ getla() # ifndef _PATH_AVENRUN # define _PATH_AVENRUN "/dev/table/avenrun" -# endif +# endif /* ! _PATH_AVENRUN */ -int +static int getla() { static int afd = -1; @@ -1868,10 +2022,10 @@ getla() r = read(afd, &avenrun, sizeof avenrun); if (tTd(3, 5)) - printf("getla: avenrun = %d\n", avenrun); + dprintf("getla: avenrun = %d\n", avenrun); loadav = (int) (avenrun + FSCALE/2) >> FSHIFT; if (tTd(3, 1)) - printf("getla: %d\n", loadav); + dprintf("getla: %d\n", loadav); return loadav; } @@ -1890,34 +2044,35 @@ int getla() if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1) { if (tTd(3, 1)) - printf("getla: table %s\n", errstring(errno)); - return (-1); + dprintf("getla: table %s\n", errstring(errno)); + return -1; } if (tTd(3, 1)) - printf("getla: scale = %d\n", tab.tl_lscale); + dprintf("getla: scale = %d\n", tab.tl_lscale); if (tab.tl_lscale) - ave = (tab.tl_avenrun.l[0] + (tab.tl_lscale/2)) / tab.tl_lscale; + ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) / + tab.tl_lscale); else - ave = (int) (tab.tl_avenrun.d[0] + 0.5); + ave = (int) (tab.tl_avenrun.d[2] + 0.5); if (tTd(3, 1)) - printf("getla: %d\n", ave); + dprintf("getla: %d\n", ave); return ave; } -#endif +#endif /* LA_TYPE == LA_ALPHAOSF */ #if LA_TYPE == LA_ZERO -int +static int getla() { if (tTd(3, 1)) - printf("getla: ZERO\n"); - return (0); + dprintf("getla: ZERO\n"); + return 0; } #endif /* LA_TYPE == LA_ZERO */ @@ -1947,12 +2102,12 @@ getla() /* Non Apollo stuff removed by Don Lewis 11/15/93 */ #ifndef lint -static char rcsid[] = "@(#)$Id: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $"; -#endif /* !lint */ +static char rcsid[] = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $"; +#endif /* ! lint */ #ifdef apollo # undef volatile -# include <apollo/base.h> +# include <apollo/base.h> /* ARGSUSED */ int getloadavg( call_data ) @@ -1964,9 +2119,40 @@ int getloadavg( call_data ) long loadav[3]; proc1_$get_loadav(loadav, &st); *avenrun = loadav[0] / (double) (1 << 16); - return(0); + return 0; } -# endif /* apollo */ +#endif /* apollo */ +/* +** SM_GETLA -- get the current load average and set macro +** +** Parameters: +** e -- the envelope for the load average macro. +** +** Returns: +** The current load average as an integer. +** +** Side Effects: +** Sets the load average macro ({load_avg}) if +** envelope e is not NULL. +*/ + +int +sm_getla(e) + ENVELOPE *e; +{ + register int la; + + la = getla(); + if (e != NULL) + { + char labuf[8]; + + snprintf(labuf, sizeof labuf, "%d", CurrentLA); + define(macid("{load_avg}", NULL), newstr(labuf), e); + } + return la; +} + /* ** SHOULDQUEUE -- should this message be queued or sent? ** @@ -1974,7 +2160,7 @@ int getloadavg( call_data ) ** ** Parameters: ** pri -- the priority of the message in question. -** ctime -- the message creation time. +** ct -- the message creation time. ** ** Returns: ** TRUE -- if this message should be queued up for the @@ -1985,42 +2171,43 @@ int getloadavg( call_data ) ** none. */ -extern int get_num_procs_online __P((void)); - +/* ARGSUSED1 */ bool -shouldqueue(pri, ctime) +shouldqueue(pri, ct) long pri; - time_t ctime; + time_t ct; { bool rval; - int queuela = QueueLA * get_num_procs_online(); if (tTd(3, 30)) - printf("shouldqueue: CurrentLA=%d, pri=%ld: ", CurrentLA, pri); - if (CurrentLA < queuela) + dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ", + CurrentLA, pri); + if (CurrentLA < QueueLA) { if (tTd(3, 30)) - printf("FALSE (CurrentLA < QueueLA)\n"); - return (FALSE); + dprintf("FALSE (CurrentLA < QueueLA)\n"); + return FALSE; } #if 0 /* this code is reported to cause oscillation around RefuseLA */ if (CurrentLA >= RefuseLA && QueueLA < RefuseLA) { if (tTd(3, 30)) - printf("TRUE (CurrentLA >= RefuseLA)\n"); - return (TRUE); + dprintf("TRUE (CurrentLA >= RefuseLA)\n"); + return TRUE; } -#endif - rval = pri > (QueueFactor / (CurrentLA - queuela + 1)); +#endif /* 0 */ + rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1)); if (tTd(3, 30)) - printf("%s (by calculation)\n", rval ? "TRUE" : "FALSE"); + dprintf("%s (by calculation)\n", rval ? "TRUE" : "FALSE"); return rval; } /* ** REFUSECONNECTIONS -- decide if connections should be refused ** ** Parameters: -** port -- port number (for error messages only) +** name -- daemon name (for error messages only) +** e -- the current envelope. +** d -- number of daemon ** ** Returns: ** TRUE if incoming SMTP connections should be refused @@ -2032,58 +2219,48 @@ shouldqueue(pri, ctime) */ bool -refuseconnections(port) - int port; +refuseconnections(name, e, d) + char *name; + ENVELOPE *e; + int d; { - int refusela = RefuseLA * get_num_procs_online(); time_t now; - static time_t lastconn = (time_t) 0; - static int conncnt = 0; - extern bool enoughdiskspace __P((long)); + static time_t lastconn[MAXDAEMONS]; + static int conncnt[MAXDAEMONS]; + #ifdef XLA if (!xla_smtp_ok()) return TRUE; -#endif +#endif /* XLA */ now = curtime(); - if (now != lastconn) + if (now != lastconn[d]) { - lastconn = now; - conncnt = 0; + lastconn[d] = now; + conncnt[d] = 0; } - else if (conncnt++ > ConnRateThrottle && ConnRateThrottle > 0) + else if (conncnt[d]++ > ConnRateThrottle && ConnRateThrottle > 0) { /* sleep to flatten out connection load */ - sm_setproctitle(TRUE, "deferring connections on port %d: %d per second", - port, ConnRateThrottle); - if (LogLevel >= 14) + sm_setproctitle(TRUE, e, "deferring connections on daemon %s: %d per second", + name, ConnRateThrottle); + if (LogLevel >= 9) sm_syslog(LOG_INFO, NOQID, - "deferring connections on port %d: %d per second", - port, ConnRateThrottle); - sleep(1); + "deferring connections on daemon %s: %d per second", + name, ConnRateThrottle); + (void) sleep(1); } CurrentLA = getla(); - if (CurrentLA >= refusela) + if (RefuseLA > 0 && CurrentLA >= RefuseLA) { - sm_setproctitle(TRUE, "rejecting connections on port %d: load average: %d", - port, CurrentLA); - if (LogLevel >= 14) + sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: load average: %d", + name, CurrentLA); + if (LogLevel >= 9) sm_syslog(LOG_INFO, NOQID, - "rejecting connections on port %d: load average: %d", - port, CurrentLA); - return TRUE; - } - - if (!enoughdiskspace(MinBlocksFree + 1)) - { - sm_setproctitle(TRUE, "rejecting connections on port %d: min free: %d", - port, MinBlocksFree); - if (LogLevel >= 14) - sm_syslog(LOG_INFO, NOQID, - "rejecting connections on port %d: min free: %d", - port, MinBlocksFree); + "rejecting connections on daemon %s: load average: %d", + name, CurrentLA); return TRUE; } @@ -2092,12 +2269,12 @@ refuseconnections(port) proc_list_probe(); if (CurChildren >= MaxChildren) { - sm_setproctitle(TRUE, "rejecting connections on port %d: %d children, max %d", - port, CurChildren, MaxChildren); - if (LogLevel >= 14) + sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: %d children, max %d", + name, CurChildren, MaxChildren); + if (LogLevel >= 9) sm_syslog(LOG_INFO, NOQID, - "rejecting connections on port %d: %d children, max %d", - port, CurChildren, MaxChildren); + "rejecting connections on daemon %s: %d children, max %d", + name, CurChildren, MaxChildren); return TRUE; } } @@ -2130,37 +2307,38 @@ refuseconnections(port) #ifndef SPT_TYPE # define SPT_TYPE SPT_REUSEARGV -#endif +#endif /* ! SPT_TYPE */ + #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN # if SPT_TYPE == SPT_PSTAT # include <sys/pstat.h> -# endif +# endif /* SPT_TYPE == SPT_PSTAT */ # if SPT_TYPE == SPT_PSSTRINGS # include <machine/vmparam.h> # include <sys/exec.h> # ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ # undef SPT_TYPE # define SPT_TYPE SPT_REUSEARGV -# else +# else /* ! PS_STRINGS */ # ifndef NKPDE /* FreeBSD 2.0 */ # define NKPDE 63 typedef unsigned int *pt_entry_t; -# endif -# endif -# endif +# endif /* ! NKPDE */ +# endif /* ! PS_STRINGS */ +# endif /* SPT_TYPE == SPT_PSSTRINGS */ # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV # define SETPROC_STATIC static -# else +# else /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */ # define SETPROC_STATIC -# endif +# endif /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */ # if SPT_TYPE == SPT_SYSMIPS # include <sys/sysmips.h> # include <sys/sysnews.h> -# endif +# endif /* SPT_TYPE == SPT_SYSMIPS */ # if SPT_TYPE == SPT_SCO # include <sys/immu.h> @@ -2169,26 +2347,29 @@ typedef unsigned int *pt_entry_t; # include <sys/fs/s5param.h> # if PSARGSZ > MAXLINE # define SPT_BUFSIZE PSARGSZ -# endif -# endif +# endif /* PSARGSZ > MAXLINE */ +# endif /* SPT_TYPE == SPT_SCO */ # ifndef SPT_PADCHAR # define SPT_PADCHAR ' ' -# endif +# endif /* ! SPT_PADCHAR */ #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ -# ifndef SPT_BUFSIZE -# define SPT_BUFSIZE MAXLINE -# endif +#ifndef SPT_BUFSIZE +# define SPT_BUFSIZE MAXLINE +#endif /* ! SPT_BUFSIZE */ /* ** Pointers for setproctitle. ** This allows "ps" listings to give more useful information. */ -char **Argv = NULL; /* pointer to argument vector */ -char *LastArgv = NULL; /* end of argv */ +static char **Argv = NULL; /* pointer to argument vector */ +static char *LastArgv = NULL; /* end of argv */ +#if SPT_TYPE != SPT_BUILTIN +static void setproctitle __P((const char *, ...)); +#endif /* SPT_TYPE != SPT_BUILTIN */ void initsetproctitle(argc, argv, envp) @@ -2218,57 +2399,52 @@ initsetproctitle(argc, argv, envp) Argv = argv; /* - ** Determine how much space we can use for setproctitle. + ** Determine how much space we can use for setproctitle. ** Use all contiguous argv and envp pointers starting at argv[0] - */ + */ for (i = 0; i < argc; i++) { - if (i==0 || LastArgv + 1 == argv[i]) + if (i == 0 || LastArgv + 1 == argv[i]) LastArgv = argv[i] + strlen(argv[i]); - else - continue; } - for (i=0; envp[i] != NULL; i++) + for (i = 0; LastArgv != NULL && envp[i] != NULL; i++) { if (LastArgv + 1 == envp[i]) LastArgv = envp[i] + strlen(envp[i]); - else - continue; } } #if SPT_TYPE != SPT_BUILTIN - /*VARARGS1*/ -void +static void # ifdef __STDC__ setproctitle(const char *fmt, ...) -# else +# else /* __STDC__ */ setproctitle(fmt, va_alist) const char *fmt; va_dcl -# endif +# endif /* __STDC__ */ { # if SPT_TYPE != SPT_NONE - register char *p; register int i; + register char *p; SETPROC_STATIC char buf[SPT_BUFSIZE]; VA_LOCAL_DECL # if SPT_TYPE == SPT_PSTAT union pstun pst; -# endif +# endif /* SPT_TYPE == SPT_PSTAT */ # if SPT_TYPE == SPT_SCO off_t seek_off; static int kmem = -1; static int kmempid = -1; struct user u; -# endif +# endif /* SPT_TYPE == SPT_SCO */ p = buf; /* print sendmail: heading for grep */ - (void) strcpy(p, "sendmail: "); + (void) strlcpy(p, "sendmail: ", SPACELEFT(buf, p)); p += strlen(p); /* print the argument string */ @@ -2281,14 +2457,14 @@ setproctitle(fmt, va_alist) # if SPT_TYPE == SPT_PSTAT pst.pst_command = buf; pstat(PSTAT_SETCMD, pst, i, 0, 0); -# endif +# endif /* SPT_TYPE == SPT_PSTAT */ # if SPT_TYPE == SPT_PSSTRINGS PS_STRINGS->ps_nargvstr = 1; PS_STRINGS->ps_argvstr = buf; -# endif +# endif /* SPT_TYPE == SPT_PSSTRINGS */ # if SPT_TYPE == SPT_SYSMIPS sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf); -# endif +# endif /* SPT_TYPE == SPT_SYSMIPS */ # if SPT_TYPE == SPT_SCO if (kmem < 0 || kmempid != getpid()) { @@ -2297,30 +2473,33 @@ setproctitle(fmt, va_alist) kmem = open(_PATH_KMEM, O_RDWR, 0); if (kmem < 0) return; - (void) fcntl(kmem, F_SETFD, 1); + (void) fcntl(kmem, F_SETFD, FD_CLOEXEC); kmempid = getpid(); } buf[PSARGSZ - 1] = '\0'; seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u; if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off) (void) write(kmem, buf, PSARGSZ); -# endif +# endif /* SPT_TYPE == SPT_SCO */ # if SPT_TYPE == SPT_REUSEARGV + if (LastArgv == NULL) + return; + if (i > LastArgv - Argv[0] - 2) { i = LastArgv - Argv[0] - 2; buf[i] = '\0'; } - (void) strcpy(Argv[0], buf); + (void) strlcpy(Argv[0], buf, i + 1); p = &Argv[0][i]; while (p < LastArgv) *p++ = SPT_PADCHAR; Argv[1] = NULL; -# endif +# endif /* SPT_TYPE == SPT_REUSEARGV */ # if SPT_TYPE == SPT_CHANGEARGV Argv[0] = buf; Argv[1] = 0; -# endif +# endif /* SPT_TYPE == SPT_CHANGEARGV */ # endif /* SPT_TYPE != SPT_NONE */ } @@ -2333,6 +2512,7 @@ setproctitle(fmt, va_alist) ** ** Parameters: ** status -- whether or not to store as process status +** e -- the current envelope. ** fmt -- a printf style format string. ** a, b, c -- possible parameters to fmt. ** @@ -2342,26 +2522,36 @@ setproctitle(fmt, va_alist) /*VARARGS2*/ void -# ifdef __STDC__ -sm_setproctitle(bool status, const char *fmt, ...) -# else -sm_setproctitle(status, fmt, va_alist) +#ifdef __STDC__ +sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...) +#else /* __STDC__ */ +sm_setproctitle(status, e, fmt, va_alist) bool status; + ENVELOPE *e; const char *fmt; va_dcl -#endif +#endif /* __STDC__ */ { char buf[SPT_BUFSIZE]; - VA_LOCAL_DECL + /* print the argument string */ VA_START(fmt); - (void) vsnprintf(buf, SPT_BUFSIZE, fmt, ap); + (void) vsnprintf(buf, sizeof buf, fmt, ap); VA_END; if (status) proc_list_set(getpid(), buf); - setproctitle("%s", buf); + + if (ProcTitlePrefix != NULL) + { + char prefix[SPT_BUFSIZE]; + + expand(ProcTitlePrefix, prefix, sizeof prefix, e); + setproctitle("%s: %s", prefix, buf); + } + else + setproctitle("%s", buf); } /* ** WAITFOR -- wait for a particular process id. @@ -2381,37 +2571,37 @@ int waitfor(pid) pid_t pid; { -#ifdef WAITUNION +# ifdef WAITUNION union wait st; -#else +# else /* WAITUNION */ auto int st; -#endif +# endif /* WAITUNION */ pid_t i; -#if defined(ISC_UNIX) || defined(_SCO_unix_) +# if defined(ISC_UNIX) || defined(_SCO_unix_) int savesig; -#endif +# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ do { errno = 0; -#if defined(ISC_UNIX) || defined(_SCO_unix_) +# if defined(ISC_UNIX) || defined(_SCO_unix_) savesig = releasesignal(SIGCHLD); -#endif +# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ i = wait(&st); -#if defined(ISC_UNIX) || defined(_SCO_unix_) +# if defined(ISC_UNIX) || defined(_SCO_unix_) if (savesig > 0) blocksignal(SIGCHLD); -#endif +# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ if (i > 0) - proc_list_drop(i); + (void) proc_list_drop(i); } while ((i >= 0 || errno == EINTR) && i != pid); if (i < 0) return -1; -#ifdef WAITUNION +# ifdef WAITUNION return st.w_status; -#else +# else /* WAITUNION */ return st; -#endif +# endif /* WAITUNION */ } /* ** REAPCHILD -- pick up the body of my child, lest it become a zombie @@ -2424,21 +2614,25 @@ waitfor(pid) ** ** Side Effects: ** Picks up extant zombies. +** Control socket exits may restart/shutdown daemon. */ +/* ARGSUSED0 */ SIGFUNC_DECL reapchild(sig) int sig; { - int olderrno = errno; + int save_errno = errno; + int st; pid_t pid; -# ifdef HASWAITPID +#if HASWAITPID auto int status; int count; count = 0; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + st = status; if (count++ > 1000) { if (LogLevel > 0) @@ -2447,14 +2641,13 @@ reapchild(sig) pid, status); break; } - proc_list_drop(pid); - } -# else +#else /* HASWAITPID */ # ifdef WNOHANG union wait status; while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0) - proc_list_drop(pid); + { + st = status.w_status; # else /* WNOHANG */ auto int status; @@ -2466,13 +2659,33 @@ reapchild(sig) */ if ((pid = wait(&status)) > 0) - proc_list_drop(pid); + { + st = status; # endif /* WNOHANG */ -# endif -# ifdef SYS5SIGNALS +#endif /* HASWAITPID */ + /* Drop PID and check if it was a control socket child */ + if (proc_list_drop(pid) == PROC_CONTROL && + WIFEXITED(st)) + { + /* if so, see if we need to restart or shutdown */ + if (WEXITSTATUS(st) == EX_RESTART) + { + /* emulate a SIGHUP restart */ + sighup(0); + /* NOTREACHED */ + } + else if (WEXITSTATUS(st) == EX_SHUTDOWN) + { + /* emulate a SIGTERM shutdown */ + intsig(0); + /* NOTREACHED */ + } + } + } +#ifdef SYS5SIGNALS (void) setsignal(SIGCHLD, reapchild); -# endif - errno = olderrno; +#endif /* SYS5SIGNALS */ + errno = save_errno; return SIGFUNC_RETURN; } /* @@ -2489,7 +2702,7 @@ reapchild(sig) ** none. */ -#ifdef NEEDPUTENV +#if NEEDPUTENV # if NEEDPUTENV == 2 /* no setenv(3) call available */ @@ -2498,10 +2711,10 @@ putenv(str) char *str; { char **current; - int matchlen, envlen=0; + int matchlen, envlen = 0; char *tmp; char **newenv; - static int first=1; + static bool first = TRUE; extern char **environ; /* @@ -2518,13 +2731,15 @@ putenv(str) * Search for an existing string in the environment and find the * length of environ. If found, replace and exit. */ - for (current=environ; *current; current++) { + for (current = environ; *current; current++) + { ++envlen; - if (strncmp(str, *current, matchlen) == 0) { + if (strncmp(str, *current, matchlen) == 0) + { /* found it, now insert the new version */ *current = (char *)str; - return(0); + return 0; } } @@ -2532,28 +2747,31 @@ putenv(str) * There wasn't already a slot so add space for a new slot. * If this is our first time through, use malloc(), else realloc(). */ - if (first) { + if (first) + { newenv = (char **) malloc(sizeof(char *) * (envlen + 2)); if (newenv == NULL) - return(-1); + return -1; - first=0; + first = FALSE; (void) memcpy(newenv, environ, sizeof(char *) * envlen); - } else { + } + else + { newenv = (char **) realloc((char *)environ, sizeof(char *) * (envlen + 2)); if (newenv == NULL) - return(-1); + return -1; } /* actually add in the new entry */ environ = newenv; environ[envlen] = (char *)str; - environ[envlen+1] = NULL; + environ[envlen + 1] = NULL; - return(0); + return 0; } -#else /* implement putenv() in terms of setenv() */ +# else /* NEEDPUTENV == 2 */ int putenv(env) @@ -2569,13 +2787,13 @@ putenv(env) l = p - env; if (l > sizeof nbuf - 1) l = sizeof nbuf - 1; - bcopy(env, nbuf, l); + memmove(nbuf, env, l); nbuf[l] = '\0'; return setenv(nbuf, ++p, 1); } -# endif -#endif +# endif /* NEEDPUTENV == 2 */ +#endif /* NEEDPUTENV */ /* ** UNSETENV -- remove a variable from the environment ** @@ -2595,7 +2813,7 @@ putenv(env) ** Modifies environ. */ -#ifndef HASUNSETENV +#if !HASUNSETENV void unsetenv(name) @@ -2616,7 +2834,7 @@ unsetenv(name) *pp = pp[1]; } -#endif +#endif /* !HASUNSETENV */ /* ** GETDTABLESIZE -- return number of file descriptors ** @@ -2634,33 +2852,33 @@ unsetenv(name) #ifdef SOLARIS # include <sys/resource.h> -#endif +#endif /* SOLARIS */ int getdtsize() { -#ifdef RLIMIT_NOFILE +# ifdef RLIMIT_NOFILE struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) return rl.rlim_cur; -#endif +# endif /* RLIMIT_NOFILE */ -# ifdef HASGETDTABLESIZE +# if HASGETDTABLESIZE return getdtablesize(); -# else +# else /* HASGETDTABLESIZE */ # ifdef _SC_OPEN_MAX return sysconf(_SC_OPEN_MAX); -# else +# else /* _SC_OPEN_MAX */ return NOFILE; -# endif -# endif +# endif /* _SC_OPEN_MAX */ +# endif /* HASGETDTABLESIZE */ } /* ** UNAME -- get the UUCP name of this system. */ -#ifndef HASUNAME +#if !HASUNAME int uname(name) @@ -2680,7 +2898,7 @@ uname(name) if (n != NULL) *n = '\0'; if (name->nodename[0] != '\0') - return (0); + return 0; } /* try /usr/include/whoami.h -- has a #define somewhere */ @@ -2689,15 +2907,17 @@ uname(name) char buf[MAXLINE]; while (fgets(buf, MAXLINE, file) != NULL) + { if (sscanf(buf, "#define sysname \"%*[^\"]\"", NODE_LENGTH, name->nodename) > 0) break; + } (void) fclose(file); if (name->nodename[0] != '\0') - return (0); + return 0; } -#ifdef TRUST_POPEN +# if 0 /* ** Popen is known to have security holes. */ @@ -2711,20 +2931,20 @@ uname(name) if (n != NULL) *n = '\0'; if (name->nodename[0] != '\0') - return (0); + return 0; } -#endif +# endif /* 0 */ - return (-1); + return -1; } -#endif /* HASUNAME */ +#endif /* !HASUNAME */ /* ** INITGROUPS -- initialize groups ** ** Stub implementation for System V style systems */ -#ifndef HASINITGROUPS +#if !HASINITGROUPS initgroups(name, basegid) char *name; @@ -2733,7 +2953,7 @@ initgroups(name, basegid) return 0; } -#endif +#endif /* !HASINITGROUPS */ /* ** SETGROUPS -- set group list ** @@ -2750,17 +2970,17 @@ setgroups(ngroups, grouplist) return 0; } -#endif +#endif /* ! NGROUPS_MAX */ /* ** SETSID -- set session id (for non-POSIX systems) */ -#ifndef HASSETSID +#if !HASSETSID pid_t setsid __P ((void)) { -#ifdef TIOCNOTTY +# ifdef TIOCNOTTY int fd; fd = open("/dev/tty", O_RDWR, 0); @@ -2769,33 +2989,33 @@ setsid __P ((void)) (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0); (void) close(fd); } -#endif /* TIOCNOTTY */ -# ifdef SYS5SETPGRP +# endif /* TIOCNOTTY */ +# ifdef SYS5SETPGRP return setpgrp(); -# else +# else /* SYS5SETPGRP */ return setpgid(0, getpid()); -# endif +# endif /* SYS5SETPGRP */ } -#endif +#endif /* !HASSETSID */ /* ** FSYNC -- dummy fsync */ -#ifdef NEEDFSYNC +#if NEEDFSYNC fsync(fd) int fd; { # ifdef O_SYNC return fcntl(fd, F_SETFL, O_SYNC); -# else +# else /* O_SYNC */ /* nothing we can do */ return 0; -# endif +# endif /* O_SYNC */ } -#endif +#endif /* NEEDFSYNC */ /* ** DGUX_INET_ADDR -- inet_addr for DG/UX ** @@ -2806,7 +3026,7 @@ fsync(fd) #ifdef DGUX_5_4_2 -#undef inet_addr +# undef inet_addr long dgux_inet_addr(host) @@ -2818,12 +3038,12 @@ dgux_inet_addr(host) return haddr.s_addr; } -#endif +#endif /* DGUX_5_4_2 */ /* ** GETOPT -- for old systems or systems with bogus implementations */ -#ifdef NEEDGETOPT +#if NEEDGETOPT /* * Copyright (c) 1985 Regents of the University of California. @@ -2837,29 +3057,27 @@ dgux_inet_addr(host) ** to reset if invoked by the program to scan args for a 2nd time */ -#if defined(LIBC_SCCS) && !defined(lint) +# if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86"; -#endif /* LIBC_SCCS and not lint */ - -#include <stdio.h> +# endif /* defined(LIBC_SCCS) && !defined(lint) */ /* * get option letter from argument vector */ -#ifdef _CONVEX_SOURCE +# ifdef _CONVEX_SOURCE extern int optind, opterr, optopt; extern char *optarg; -#else +# else /* _CONVEX_SOURCE */ int opterr = 1; /* if error message should be printed */ int optind = 1; /* index into parent argv vector */ int optopt = 0; /* character checked for validity */ char *optarg = NULL; /* argument associated with option */ -#endif +# endif /* _CONVEX_SOURCE */ -#define BADCH (int)'?' -#define EMSG "" -#define tell(s) if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); \ - fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);} +# define BADCH (int)'?' +# define EMSG "" +# define tell(s) if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); \ + fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);} int getopt(nargc,nargv,ostr) @@ -2900,21 +3118,21 @@ getopt(nargc,nargv,ostr) place = EMSG; tell(": option requires an argument -- "); } - else optarg = nargv[optind]; /* white space */ + else optarg = nargv[optind]; /* white space */ place = EMSG; ++optind; } return(optopt); /* dump back option letter */ } -#endif +#endif /* NEEDGETOPT */ /* ** VFPRINTF, VSPRINTF -- for old 4.3 BSD systems missing a real version */ -#ifdef NEEDVPRINTF +#if NEEDVPRINTF -#define MAXARG 16 +# define MAXARG 16 vfprintf(fp, fmt, ap) FILE *fp; @@ -2948,7 +3166,7 @@ vsprintf(s, fmt, ap) bp[12], bp[13], bp[14], bp[15]); } -#endif +#endif /* NEEDVPRINTF */ /* ** USERSHELLOK -- tell if a user's shell is ok for unrestricted use ** @@ -2965,52 +3183,52 @@ vsprintf(s, fmt, ap) # ifndef _PATH_SHELLS # define _PATH_SHELLS "/etc/shells" -# endif +# endif /* ! _PATH_SHELLS */ # if defined(_AIX3) || defined(_AIX4) # include <userconf.h> # if _AIX4 >= 40200 # include <userpw.h> -# endif +# endif /* _AIX4 >= 40200 */ # include <usersec.h> -# endif +# endif /* defined(_AIX3) || defined(_AIX4) */ -char *DefaultUserShells[] = +static char *DefaultUserShells[] = { "/bin/sh", /* standard shell */ "/usr/bin/sh", "/bin/csh", /* C shell */ "/usr/bin/csh", -#ifdef __hpux -# ifdef V4FS +# ifdef __hpux +# ifdef V4FS "/usr/bin/rsh", /* restricted Bourne shell */ "/usr/bin/ksh", /* Korn shell */ "/usr/bin/rksh", /* restricted Korn shell */ "/usr/bin/pam", "/usr/bin/keysh", /* key shell (extended Korn shell) */ "/usr/bin/posix/sh", -# else +# else /* V4FS */ "/bin/rsh", /* restricted Bourne shell */ "/bin/ksh", /* Korn shell */ "/bin/rksh", /* restricted Korn shell */ "/bin/pam", "/usr/bin/keysh", /* key shell (extended Korn shell) */ "/bin/posix/sh", -# endif -#endif -#if defined(_AIX3) || defined(_AIX4) +# endif /* V4FS */ +# endif /* __hpux */ +# if defined(_AIX3) || defined(_AIX4) "/bin/ksh", /* Korn shell */ "/usr/bin/ksh", "/bin/tsh", /* trusted shell */ "/usr/bin/tsh", "/bin/bsh", /* Bourne shell */ "/usr/bin/bsh", -#endif -#if defined(__svr4__) || defined(__svr5__) +# endif /* defined(_AIX3) || defined(_AIX4) */ +# if defined(__svr4__) || defined(__svr5__) "/bin/ksh", /* Korn shell */ "/usr/bin/ksh", -#endif -#ifdef sgi +# endif /* defined(__svr4__) || defined(__svr5__) */ +# ifdef sgi "/sbin/sh", /* SGI's shells really live in /sbin */ "/sbin/csh", "/bin/ksh", /* Korn shell */ @@ -3018,11 +3236,11 @@ char *DefaultUserShells[] = "/usr/bin/ksh", "/bin/tcsh", /* Extended csh */ "/usr/bin/tcsh", -#endif +# endif /* sgi */ NULL }; -#endif +#endif /* !HASGETUSERSHELL */ #define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/" @@ -3031,7 +3249,7 @@ usershellok(user, shell) char *user; char *shell; { -#if HASGETUSERSHELL +# if HASGETUSERSHELL register char *p; extern char *getusershell(); @@ -3045,10 +3263,10 @@ usershellok(user, shell) break; endusershell(); return p != NULL; -#else -# if USEGETCONFATTR +# else /* HASGETUSERSHELL */ +# if USEGETCONFATTR auto char *v; -# endif +# endif /* USEGETCONFATTR */ register FILE *shellf; char buf[MAXLINE]; @@ -3056,7 +3274,7 @@ usershellok(user, shell) ConfigLevel <= 1) return TRUE; -# if USEGETCONFATTR +# if USEGETCONFATTR /* ** Naturally IBM has a "better" idea..... ** @@ -3080,14 +3298,14 @@ usershellok(user, shell) } return FALSE; } -# endif +# endif /* USEGETCONFATTR */ shellf = fopen(_PATH_SHELLS, "r"); if (shellf == NULL) { /* no /etc/shells; see if it is one of the std shells */ char **d; - + if (errno != ENOENT && LogLevel > 3) sm_syslog(LOG_ERR, NOQID, "usershellok: cannot open %s: %s", @@ -3116,13 +3334,13 @@ usershellok(user, shell) *p = '\0'; if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0) { - fclose(shellf); + (void) fclose(shellf); return TRUE; } } - fclose(shellf); + (void) fclose(shellf); return FALSE; -#endif +# endif /* HASGETUSERSHELL */ } /* ** FREEDISKSPACE -- see how much free space is on the queue filesystem @@ -3135,7 +3353,7 @@ usershellok(user, shell) ** block size is stored. ** ** Returns: -** The number of bytes free on the queue filesystem. +** The number of blocks free on the queue filesystem. ** -1 if the statfs call fails. ** ** Side effects: @@ -3153,83 +3371,83 @@ usershellok(user, shell) #ifndef SFS_TYPE # define SFS_TYPE SFS_NONE -#endif +#endif /* ! SFS_TYPE */ #if SFS_TYPE == SFS_USTAT # include <ustat.h> -#endif +#endif /* SFS_TYPE == SFS_USTAT */ #if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS # include <sys/statfs.h> -#endif +#endif /* SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS */ #if SFS_TYPE == SFS_VFS # include <sys/vfs.h> -#endif +#endif /* SFS_TYPE == SFS_VFS */ #if SFS_TYPE == SFS_MOUNT # include <sys/mount.h> -#endif +#endif /* SFS_TYPE == SFS_MOUNT */ #if SFS_TYPE == SFS_STATVFS # include <sys/statvfs.h> -#endif +#endif /* SFS_TYPE == SFS_STATVFS */ long freediskspace(dir, bsize) char *dir; long *bsize; { -#if SFS_TYPE != SFS_NONE -# if SFS_TYPE == SFS_USTAT +# if SFS_TYPE != SFS_NONE +# if SFS_TYPE == SFS_USTAT struct ustat fs; struct stat statbuf; -# define FSBLOCKSIZE DEV_BSIZE -# define SFS_BAVAIL f_tfree -# else -# if defined(ultrix) +# define FSBLOCKSIZE DEV_BSIZE +# define SFS_BAVAIL f_tfree +# else /* SFS_TYPE == SFS_USTAT */ +# if defined(ultrix) struct fs_data fs; -# define SFS_BAVAIL fd_bfreen -# define FSBLOCKSIZE 1024L -# else -# if SFS_TYPE == SFS_STATVFS +# define SFS_BAVAIL fd_bfreen +# define FSBLOCKSIZE 1024L +# else /* defined(ultrix) */ +# if SFS_TYPE == SFS_STATVFS struct statvfs fs; -# define FSBLOCKSIZE fs.f_frsize -# else +# define FSBLOCKSIZE fs.f_frsize +# else /* SFS_TYPE == SFS_STATVFS */ struct statfs fs; -# define FSBLOCKSIZE fs.f_bsize -# endif -# endif -# endif -# ifndef SFS_BAVAIL -# define SFS_BAVAIL f_bavail -# endif - -# if SFS_TYPE == SFS_USTAT +# define FSBLOCKSIZE fs.f_bsize +# endif /* SFS_TYPE == SFS_STATVFS */ +# endif /* defined(ultrix) */ +# endif /* SFS_TYPE == SFS_USTAT */ +# ifndef SFS_BAVAIL +# define SFS_BAVAIL f_bavail +# endif /* ! SFS_BAVAIL */ + +# if SFS_TYPE == SFS_USTAT if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) -# else -# if SFS_TYPE == SFS_4ARGS +# else /* SFS_TYPE == SFS_USTAT */ +# if SFS_TYPE == SFS_4ARGS if (statfs(dir, &fs, sizeof fs, 0) == 0) -# else -# if SFS_TYPE == SFS_STATVFS +# else /* SFS_TYPE == SFS_4ARGS */ +# if SFS_TYPE == SFS_STATVFS if (statvfs(dir, &fs) == 0) -# else -# if defined(ultrix) +# else /* SFS_TYPE == SFS_STATVFS */ +# if defined(ultrix) if (statfs(dir, &fs) > 0) -# else +# else /* defined(ultrix) */ if (statfs(dir, &fs) == 0) -# endif -# endif -# endif -# endif +# endif /* defined(ultrix) */ +# endif /* SFS_TYPE == SFS_STATVFS */ +# endif /* SFS_TYPE == SFS_4ARGS */ +# endif /* SFS_TYPE == SFS_USTAT */ { if (bsize != NULL) *bsize = FSBLOCKSIZE; if (fs.SFS_BAVAIL <= 0) return 0; else if (fs.SFS_BAVAIL > LONG_MAX) - return LONG_MAX; + return (long) LONG_MAX; else return (long) fs.SFS_BAVAIL; } -#endif - return (-1); +# endif /* SFS_TYPE != SFS_NONE */ + return -1; } /* ** ENOUGHDISKSPACE -- is there enough free space on the queue fs? @@ -3240,6 +3458,7 @@ freediskspace(dir, bsize) ** msize -- the size to check against. If zero, we don't yet ** know how big the message will be, so just check for ** a "reasonable" amount. +** log -- log message? ** ** Returns: ** TRUE if there is enough space. @@ -3247,22 +3466,25 @@ freediskspace(dir, bsize) */ bool -enoughdiskspace(msize) +enoughdiskspace(msize, log) long msize; + bool log; { - long bfree, bsize; + long bfree; + long bsize; if (MinBlocksFree <= 0 && msize <= 0) { if (tTd(4, 80)) - printf("enoughdiskspace: no threshold\n"); + dprintf("enoughdiskspace: no threshold\n"); return TRUE; } - if ((bfree = freediskspace(QueueDir, &bsize)) >= 0) + bfree = freediskspace(QueueDir, &bsize); + if (bfree >= 0) { if (tTd(4, 80)) - printf("enoughdiskspace: bavail=%ld, need=%ld\n", + dprintf("enoughdiskspace: bavail=%ld, need=%ld\n", bfree, msize); /* convert msize to block count */ @@ -3272,7 +3494,7 @@ enoughdiskspace(msize) if (bfree < msize) { - if (LogLevel > 0) + if (log && LogLevel > 0) sm_syslog(LOG_ALERT, CurEnv->e_id, "low on space (have %ld, %s needs %ld in %s)", bfree, @@ -3282,7 +3504,7 @@ enoughdiskspace(msize) } } else if (tTd(4, 80)) - printf("enoughdiskspace failure: min=%ld, need=%ld: %s\n", + dprintf("enoughdiskspace failure: min=%ld, need=%ld: %s\n", MinBlocksFree, msize, errstring(errno)); return TRUE; } @@ -3316,73 +3538,76 @@ transienterror(err) case ENOSPC: /* No space left on device */ #ifdef ETIMEDOUT case ETIMEDOUT: /* Connection timed out */ -#endif +#endif /* ETIMEDOUT */ #ifdef ESTALE case ESTALE: /* Stale NFS file handle */ -#endif +#endif /* ESTALE */ #ifdef ENETDOWN case ENETDOWN: /* Network is down */ -#endif +#endif /* ENETDOWN */ #ifdef ENETUNREACH case ENETUNREACH: /* Network is unreachable */ -#endif +#endif /* ENETUNREACH */ #ifdef ENETRESET case ENETRESET: /* Network dropped connection on reset */ -#endif +#endif /* ENETRESET */ #ifdef ECONNABORTED case ECONNABORTED: /* Software caused connection abort */ -#endif +#endif /* ECONNABORTED */ #ifdef ECONNRESET case ECONNRESET: /* Connection reset by peer */ -#endif +#endif /* ECONNRESET */ #ifdef ENOBUFS case ENOBUFS: /* No buffer space available */ -#endif +#endif /* ENOBUFS */ #ifdef ESHUTDOWN case ESHUTDOWN: /* Can't send after socket shutdown */ -#endif +#endif /* ESHUTDOWN */ #ifdef ECONNREFUSED case ECONNREFUSED: /* Connection refused */ -#endif +#endif /* ECONNREFUSED */ #ifdef EHOSTDOWN case EHOSTDOWN: /* Host is down */ -#endif +#endif /* EHOSTDOWN */ #ifdef EHOSTUNREACH case EHOSTUNREACH: /* No route to host */ -#endif +#endif /* EHOSTUNREACH */ #ifdef EDQUOT case EDQUOT: /* Disc quota exceeded */ -#endif +#endif /* EDQUOT */ #ifdef EPROCLIM case EPROCLIM: /* Too many processes */ -#endif +#endif /* EPROCLIM */ #ifdef EUSERS case EUSERS: /* Too many users */ -#endif +#endif /* EUSERS */ #ifdef EDEADLK case EDEADLK: /* Resource deadlock avoided */ -#endif +#endif /* EDEADLK */ #ifdef EISCONN case EISCONN: /* Socket already connected */ -#endif +#endif /* EISCONN */ #ifdef EINPROGRESS case EINPROGRESS: /* Operation now in progress */ -#endif +#endif /* EINPROGRESS */ #ifdef EALREADY case EALREADY: /* Operation already in progress */ -#endif +#endif /* EALREADY */ #ifdef EADDRINUSE case EADDRINUSE: /* Address already in use */ -#endif +#endif /* EADDRINUSE */ #ifdef EADDRNOTAVAIL case EADDRNOTAVAIL: /* Can't assign requested address */ -#endif +#endif /* EADDRNOTAVAIL */ #ifdef ETXTBSY case ETXTBSY: /* (Apollo) file locked */ -#endif +#endif /* ETXTBSY */ #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) case ENOSR: /* Out of streams resources */ -#endif +#endif /* defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) */ +#ifdef ENOLCK + case ENOLCK: /* No locks available */ +#endif /* ENOLCK */ case E_SM_OPENTIMEOUT: /* PSEUDO: open timed out */ return TRUE; } @@ -3422,7 +3647,7 @@ lockfile(fd, filename, ext, type) if (ext == NULL) ext = ""; - bzero(&lfd, sizeof lfd); + memset(&lfd, '\0', sizeof lfd); if (bitset(LOCK_UN, type)) lfd.l_type = F_UNLCK; else if (bitset(LOCK_EX, type)) @@ -3436,7 +3661,7 @@ lockfile(fd, filename, ext, type) action = F_SETLKW; if (tTd(55, 60)) - printf("lockfile(%s%s, action=%d, type=%d): ", + dprintf("lockfile(%s%s, action=%d, type=%d): ", filename, ext, action, lfd.l_type); while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR) @@ -3444,13 +3669,13 @@ lockfile(fd, filename, ext, type) if (i >= 0) { if (tTd(55, 60)) - printf("SUCCESS\n"); + dprintf("SUCCESS\n"); return TRUE; } save_errno = errno; if (tTd(55, 60)) - printf("(%s) ", errstring(save_errno)); + dprintf("(%s) ", errstring(save_errno)); /* ** On SunOS, if you are testing using -oQ/tmp/mqueue or @@ -3464,40 +3689,41 @@ lockfile(fd, filename, ext, type) if (save_errno == EINVAL) { if (tTd(55, 60)) - printf("SUCCESS\n"); + dprintf("SUCCESS\n"); return TRUE; } - if (!bitset(LOCK_NB, type) || (save_errno != EACCES && save_errno != EAGAIN)) + if (!bitset(LOCK_NB, type) || + (save_errno != EACCES && save_errno != EAGAIN)) { int omode = -1; # ifdef F_GETFL (void) fcntl(fd, F_GETFL, &omode); errno = save_errno; -# endif +# endif /* F_GETFL */ syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", filename, ext, fd, type, omode, geteuid()); dumpfd(fd, TRUE, TRUE); } -# else +# else /* !HASFLOCK */ if (ext == NULL) ext = ""; if (tTd(55, 60)) - printf("lockfile(%s%s, type=%o): ", filename, ext, type); + dprintf("lockfile(%s%s, type=%o): ", filename, ext, type); while ((i = flock(fd, type)) < 0 && errno == EINTR) continue; if (i >= 0) { if (tTd(55, 60)) - printf("SUCCESS\n"); + dprintf("SUCCESS\n"); return TRUE; } save_errno = errno; if (tTd(55, 60)) - printf("(%s) ", errstring(save_errno)); + dprintf("(%s) ", errstring(save_errno)); if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK) { @@ -3505,14 +3731,14 @@ lockfile(fd, filename, ext, type) # ifdef F_GETFL (void) fcntl(fd, F_GETFL, &omode); errno = save_errno; -# endif +# endif /* F_GETFL */ syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", filename, ext, fd, type, omode, geteuid()); dumpfd(fd, TRUE, TRUE); } -# endif +# endif /* !HASFLOCK */ if (tTd(55, 60)) - printf("FAIL\n"); + dprintf("FAIL\n"); errno = save_errno; return FALSE; } @@ -3571,19 +3797,19 @@ lockfile(fd, filename, ext, type) #ifndef IS_SAFE_CHOWN # define IS_SAFE_CHOWN > 0 -#endif +#endif /* ! IS_SAFE_CHOWN */ bool chownsafe(fd, safedir) int fd; bool safedir; { -#if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ +# if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H)) int rval; /* give the system administrator a chance to override */ - if (bitset(DBS_ASSUMESAFECHOWN, DontBlameSendmail)) + if (bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail)) return TRUE; /* @@ -3594,14 +3820,14 @@ chownsafe(fd, safedir) errno = 0; rval = fpathconf(fd, _PC_CHOWN_RESTRICTED); -# if SAFENFSPATHCONF +# if SAFENFSPATHCONF return errno == 0 && rval IS_SAFE_CHOWN; -# else +# else /* SAFENFSPATHCONF */ return safedir && errno == 0 && rval IS_SAFE_CHOWN; -# endif -#else - return bitset(DBS_ASSUMESAFECHOWN, DontBlameSendmail); -#endif +# endif /* SAFENFSPATHCONF */ +# else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ */ + return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail); +# endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ */ } /* ** RESETLIMITS -- reset system controlled resource limits @@ -3618,12 +3844,12 @@ chownsafe(fd, safedir) #if HASSETRLIMIT # ifdef RLIMIT_NEEDS_SYS_TIME_H # include <sys/time.h> -# endif +# endif /* RLIMIT_NEEDS_SYS_TIME_H */ # include <sys/resource.h> -#endif +#endif /* HASSETRLIMIT */ #ifndef FD_SETSIZE # define FD_SETSIZE 256 -#endif +#endif /* ! FD_SETSIZE */ void resetlimits() @@ -3637,13 +3863,13 @@ resetlimits() # ifdef RLIMIT_NOFILE lim.rlim_cur = lim.rlim_max = FD_SETSIZE; (void) setrlimit(RLIMIT_NOFILE, &lim); -# endif -#else +# endif /* RLIMIT_NOFILE */ +#else /* HASSETRLIMIT */ # if HASULIMIT (void) ulimit(2, 0x3fffff); (void) ulimit(4, FD_SETSIZE); -# endif -#endif +# endif /* HASULIMIT */ +#endif /* HASSETRLIMIT */ errno = 0; } /* @@ -3660,7 +3886,6 @@ getcfname() return ConfFile; #if NETINFO { - extern char *ni_propval __P((char *, char *, char *, char *, int)); char *cflocation; cflocation = ni_propval("/locations", NULL, "sendmail", @@ -3668,7 +3893,7 @@ getcfname() if (cflocation != NULL) return cflocation; } -#endif +#endif /* NETINFO */ return _PATH_SENDMAILCF; } @@ -3707,7 +3932,7 @@ setvendor(vendor) VendorCode = VENDOR_SUN; return TRUE; } -#endif +#endif /* SUN_EXTENSIONS */ #if defined(VENDOR_NAME) && defined(VENDOR_CODE) if (strcasecmp(vendor, VENDOR_NAME) == 0) @@ -3715,7 +3940,7 @@ setvendor(vendor) VendorCode = VENDOR_CODE; return TRUE; } -#endif +#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ return FALSE; } @@ -3735,20 +3960,20 @@ getvendor(vendorcode) { #if defined(VENDOR_NAME) && defined(VENDOR_CODE) /* - ** Can't have the same switch case twice so need to + ** Can't have the same switch case twice so need to ** handle VENDOR_CODE outside of switch. It might ** match one of the existing VENDOR_* codes. */ if (vendorcode == VENDOR_CODE) return VENDOR_NAME; -#endif +#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ switch (vendorcode) { case VENDOR_BERKELEY: return "Berkeley"; - + case VENDOR_SUN: return "Sun"; @@ -3780,7 +4005,7 @@ getvendor(vendorcode) #if SHARE_V1 int DefShareUid; /* default share uid to run as -- unused??? */ -#endif +#endif /* SHARE_V1 */ void vendor_pre_defaults(e) @@ -3789,15 +4014,19 @@ vendor_pre_defaults(e) #if SHARE_V1 /* OTHERUID is defined in shares.h, do not be alarmed */ DefShareUid = OTHERUID; -#endif +#endif /* SHARE_V1 */ #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) sun_pre_defaults(e); -#endif +#endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */ #ifdef apollo - /* stupid domain/os can't even open /etc/sendmail.cf without this */ + /* + ** stupid domain/os can't even open + ** /etc/mail/sendmail.cf without this + */ + setuserenv("ISP", NULL); setuserenv("SYSTYPE", NULL); -#endif +#endif /* apollo */ } @@ -3807,14 +4036,14 @@ vendor_post_defaults(e) { #ifdef __QNX__ char *p; - + /* Makes sure the SOCK environment variable remains */ if (p = getextenv("SOCK")) setuserenv("SOCK", p); -#endif +#endif /* __QNX__ */ #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) sun_post_defaults(e); -#endif +#endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */ } /* ** VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode @@ -3824,6 +4053,9 @@ void vendor_daemon_setup(e) ENVELOPE *e; { +#if HASSETLOGIN + (void) setlogin(RunAsUserName); +#endif /* HASSETLOGIN */ #if SECUREWARE if (getluid() != -1) { @@ -3848,18 +4080,18 @@ void vendor_set_uid(uid) UID_T uid; { - /* + /* ** We need to setup the share groups (lnodes) - ** and and auditing inforation (luid's) + ** and add auditing information (luid's) ** before we loose our ``root''ness. */ #if SHARE_V1 if (setupshares(uid, syserr) != 0) syserr("Unable to set up shares"); -#endif +#endif /* SHARE_V1 */ #if SECUREWARE (void) setup_secure(uid); -#endif +#endif /* SECUREWARE */ } /* ** VALIDATE_CONNECTION -- check connection for rationality @@ -3883,7 +4115,7 @@ vendor_set_uid(uid) /* tcpwrappers does no logging, but you still have to declare these -- ugh */ int allow_severity = LOG_INFO; int deny_severity = LOG_NOTICE; -#endif +#endif /* TCPWRAPPERS */ #if DAEMON char * @@ -3892,38 +4124,32 @@ validate_connection(sap, hostname, e) char *hostname; ENVELOPE *e; { -#if TCPWRAPPERS +# if TCPWRAPPERS char *host; -#endif +# endif /* TCPWRAPPERS */ if (tTd(48, 3)) - printf("validate_connection(%s, %s)\n", + dprintf("validate_connection(%s, %s)\n", hostname, anynet_ntoa(sap)); - if (rscheck("check_relay", hostname, anynet_ntoa(sap), e) != EX_OK) + if (rscheck("check_relay", hostname, anynet_ntoa(sap), + e, TRUE, TRUE, 4) != EX_OK) { static char reject[BUFSIZ*2]; extern char MsgBuf[]; if (tTd(48, 4)) - printf(" ... validate_connection: BAD (rscheck)\n"); + dprintf(" ... validate_connection: BAD (rscheck)\n"); - if (strlen(MsgBuf) > 5) - { - if (isascii(MsgBuf[0]) && isdigit(MsgBuf[0]) && - isascii(MsgBuf[1]) && isdigit(MsgBuf[1]) && - isascii(MsgBuf[2]) && isdigit(MsgBuf[2])) - strcpy(reject, &MsgBuf[4]); - else - strcpy(reject, MsgBuf); - } + if (strlen(MsgBuf) >= 3) + (void) strlcpy(reject, MsgBuf, sizeof reject); else - strcpy(reject, "Access denied"); + (void) strlcpy(reject, "Access denied", sizeof reject); return reject; } -#if TCPWRAPPERS +# if TCPWRAPPERS if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']') host = "unknown"; else @@ -3931,20 +4157,20 @@ validate_connection(sap, hostname, e) if (!hosts_ctl("sendmail", host, anynet_ntoa(sap), STRING_UNKNOWN)) { if (tTd(48, 4)) - printf(" ... validate_connection: BAD (tcpwrappers)\n"); + dprintf(" ... validate_connection: BAD (tcpwrappers)\n"); if (LogLevel >= 4) - sm_syslog(LOG_NOTICE, NOQID, + sm_syslog(LOG_NOTICE, e->e_id, "tcpwrappers (%s, %s) rejection", host, anynet_ntoa(sap)); return "Access denied"; } -#endif +# endif /* TCPWRAPPERS */ if (tTd(48, 4)) - printf(" ... validate_connection: OK\n"); + dprintf(" ... validate_connection: OK\n"); return NULL; } -#endif +#endif /* DAEMON */ /* ** STRTOL -- convert string to long integer ** @@ -3953,11 +4179,11 @@ validate_connection(sap, hostname, e) ** This is taken verbatim from the 4.4-Lite C library. */ -#ifdef NEEDSTRTOL +#if NEEDSTRTOL -#if defined(LIBC_SCCS) && !defined(lint) +# if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ +# endif /* defined(LIBC_SCCS) && !defined(lint) */ /* * Convert a string to a long integer. @@ -4044,10 +4270,10 @@ strtol(nptr, endptr, base) acc = -acc; if (endptr != 0) *endptr = (char *)(any ? s - 1 : nptr); - return (acc); + return acc; } -#endif +#endif /* NEEDSTRTOL */ /* ** STRSTR -- find first substring in string ** @@ -4061,7 +4287,7 @@ strtol(nptr, endptr, base) ** NULL if little is not contained in big. */ -#ifdef NEEDSTRSTR +#if NEEDSTRSTR char * strstr(big, little) @@ -4084,7 +4310,7 @@ strstr(big, little) return NULL; } -#endif +#endif /* NEEDSTRSTR */ /* ** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX ** @@ -4092,13 +4318,71 @@ strstr(big, little) ** routines. For example, Solaris versions at least through 2.3 ** don't properly deliver a canonical h_name field. This tries to ** work around these problems. +** +** Support IPv6 as well as IPv4. */ -struct hostent * -sm_gethostbyname(name) +#if NETINET6 && NEEDSGETIPNODE && __RES < 19990909 + +# ifndef AI_DEFAULT +# define AI_DEFAULT 0 /* dummy */ +# endif /* ! AI_DEFAULT */ +# ifndef AI_ADDRCONFIG +# define AI_ADDRCONFIG 0 /* dummy */ +# endif /* ! AI_ADDRCONFIG */ +# ifndef AI_V4MAPPED +# define AI_V4MAPPED 0 /* dummy */ +# endif /* ! AI_V4MAPPED */ +# ifndef AI_ALL +# define AI_ALL 0 /* dummy */ +# endif /* ! AI_ALL */ + +static struct hostent * +getipnodebyname(name, family, flags, err) char *name; + int family; + int flags; + int *err; +{ + bool resv6 = TRUE; + struct hostent *h; + + if (family == AF_INET6) + { + /* From RFC2133, section 6.1 */ + resv6 = bitset(RES_USE_INET6, _res.options); + _res.options |= RES_USE_INET6; + } + h_errno = 0; + h = gethostbyname(name); + *err = h_errno; + if (family == AF_INET6 && !resv6) + _res.options &= ~RES_USE_INET6; + return h; +} + +static struct hostent * +getipnodebyaddr(addr, len, family, err) + char *addr; + int len; + int family; + int *err; { struct hostent *h; + + h_errno = 0; + h = gethostbyaddr(addr, len, family); + *err = h_errno; + return h; +} +#endif /* NEEDSGETIPNODE && NETINET6 && __RES < 19990909 */ + +struct hostent * +sm_gethostbyname(name, family) + char *name; + int family; +{ + struct hostent *h = NULL; #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) # if SOLARIS == 20300 || SOLARIS == 203 static struct hostent hp; @@ -4106,28 +4390,44 @@ sm_gethostbyname(name) extern struct hostent *_switch_gethostbyname_r(); if (tTd(61, 10)) - printf("_switch_gethostbyname_r(%s)... ", name); + dprintf("_switch_gethostbyname_r(%s)... ", name); h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); -# else +# else /* SOLARIS == 20300 || SOLARIS == 203 */ extern struct hostent *__switch_gethostbyname(); if (tTd(61, 10)) - printf("__switch_gethostbyname(%s)... ", name); + dprintf("__switch_gethostbyname(%s)... ", name); h = __switch_gethostbyname(name); -# endif -#else +# endif /* SOLARIS == 20300 || SOLARIS == 203 */ +#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ int nmaps; +# if NETINET6 + int flags = AI_DEFAULT|AI_ALL; + int err; +# endif /* NETINET6 */ + int save_errno; char *maptype[MAXMAPSTACK]; short mapreturn[MAXMAPACTIONS]; char hbuf[MAXNAME]; if (tTd(61, 10)) - printf("gethostbyname(%s)... ", name); + dprintf("sm_gethostbyname(%s, %d)... ", name, family); + +# if NETINET6 +# if ADDRCONFIG_IS_BROKEN + flags &= ~AI_ADDRCONFIG; +# endif /* ADDRCONFIG_IS_BROKEN */ + h = getipnodebyname(name, family, flags, &err); + h_errno = err; +# else /* NETINET6 */ h = gethostbyname(name); +# endif /* NETINET6 */ + + save_errno = errno; if (h == NULL) { if (tTd(61, 10)) - printf("failure\n"); + dprintf("failure\n"); nmaps = switch_map_find("hosts", maptype, mapreturn); while (--nmaps >= 0) @@ -4138,27 +4438,77 @@ sm_gethostbyname(name) { /* try short name */ if (strlen(name) > (SIZE_T) sizeof hbuf - 1) + { + errno = save_errno; return NULL; - strcpy(hbuf, name); + } + (void) strlcpy(hbuf, name, sizeof hbuf); shorten_hostname(hbuf); /* if it hasn't been shortened, there's no point */ if (strcmp(hbuf, name) != 0) { if (tTd(61, 10)) - printf("gethostbyname(%s)... ", hbuf); + dprintf("sm_gethostbyname(%s, %d)... ", + hbuf, family); + +# if NETINET6 + h = getipnodebyname(hbuf, family, + AI_V4MAPPED|AI_ALL, + &err); + h_errno = err; + save_errno = errno; +# else /* NETINET6 */ h = gethostbyname(hbuf); + save_errno = errno; +# endif /* NETINET6 */ } } } -#endif +#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ if (tTd(61, 10)) { if (h == NULL) - printf("failure\n"); + dprintf("failure\n"); else - printf("%s\n", h->h_name); + { + dprintf("%s\n", h->h_name); + if (tTd(61, 11)) + { +#if NETINET6 + struct in6_addr ia6; + char buf6[INET6_ADDRSTRLEN]; +#else /* NETINET6 */ + struct in_addr ia; +#endif /* NETINET6 */ + int i; + + if (h->h_aliases != NULL) + for (i = 0; h->h_aliases[i] != NULL; + i++) + dprintf("\talias: %s\n", + h->h_aliases[i]); + for (i = 0; h->h_addr_list[i] != NULL; i++) + { + char *addr; + +#if NETINET6 + memmove(&ia6, h->h_addr_list[i], + IN6ADDRSZ); + addr = anynet_ntop(&ia6, + buf6, sizeof buf6); +#else /* NETINET6 */ + memmove(&ia, h->h_addr_list[i], + INADDRSZ); + addr = (char *) inet_ntoa(ia); +#endif /* NETINET6 */ + if (addr != NULL) + dprintf("\taddr: %s\n", addr); + } + } + } } + errno = save_errno; return h; } @@ -4168,50 +4518,62 @@ sm_gethostbyaddr(addr, len, type) int len; int type; { + struct hostent *hp; #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) # if SOLARIS == 20300 || SOLARIS == 203 - static struct hostent hp; + static struct hostent he; static char buf[1000]; extern struct hostent *_switch_gethostbyaddr_r(); - return _switch_gethostbyaddr_r(addr, len, type, &hp, buf, sizeof(buf), &h_errno); -# else + hp = _switch_gethostbyaddr_r(addr, len, type, &he, buf, sizeof(buf), &h_errno); +# else /* SOLARIS == 20300 || SOLARIS == 203 */ extern struct hostent *__switch_gethostbyaddr(); - return __switch_gethostbyaddr(addr, len, type); -# endif -#else - return gethostbyaddr(addr, len, type); -#endif + hp = __switch_gethostbyaddr(addr, len, type); +# endif /* SOLARIS == 20300 || SOLARIS == 203 */ +#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ +# if NETINET6 + int err; +# endif /* NETINET6 */ + +# if NETINET6 + hp = getipnodebyaddr(addr, len, type, &err); + h_errno = err; +# else /* NETINET6 */ + hp = gethostbyaddr(addr, len, type); +# endif /* NETINET6 */ + return hp; +#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ } /* ** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid */ + struct passwd * sm_getpwnam(user) char *user; { -#ifdef _AIX4 +# ifdef _AIX4 extern struct passwd *_getpwnam_shadow(const char *, const int); return _getpwnam_shadow(user, 0); -#else +# else /* _AIX4 */ return getpwnam(user); -#endif +# endif /* _AIX4 */ } struct passwd * sm_getpwuid(uid) UID_T uid; { -#if defined(_AIX4) && 0 +# if defined(_AIX4) && 0 extern struct passwd *_getpwuid_shadow(const int, const int); return _getpwuid_shadow(uid,0); -#else +# else /* defined(_AIX4) && 0 */ return getpwuid(uid); -#endif +# endif /* defined(_AIX4) && 0 */ } /* ** SECUREWARE_SETUP_SECURE -- Convex SecureWare setup @@ -4242,7 +4604,7 @@ secureware_setup_secure(uid) if (getluid() != -1) return; - + if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN) { switch (rc) @@ -4267,7 +4629,7 @@ secureware_setup_secure(uid) syserr("Could not set kernel privs, uid = %d", uid); default: - syserr("Unknown return code (%d) from set_secure_info(%d)", + syserr("Unknown return code (%d) from set_secure_info(%d)", rc, uid); break; } @@ -4276,7 +4638,7 @@ secureware_setup_secure(uid) } #endif /* SECUREWARE */ /* -** ADD_LOCAL_HOST_NAMES -- Add a hostname to class 'w' based on IP address +** ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address ** ** Add hostnames to class 'w' based on the IP address read from ** the network interface. @@ -4288,28 +4650,37 @@ secureware_setup_secure(uid) ** 0 if successful, -1 if host lookup fails. */ -int +static int add_hostnames(sa) SOCKADDR *sa; { struct hostent *hp; + char **ha; + char hnb[MAXHOSTNAMELEN]; /* lookup name with IP address */ switch (sa->sa.sa_family) { +#if NETINET case AF_INET: hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr, sizeof(sa->sin.sin_addr), sa->sa.sa_family); break; +#endif /* NETINET */ + +#if NETINET6 + case AF_INET6: + hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr, + sizeof(sa->sin6.sin6_addr), sa->sa.sa_family); + break; +#endif /* NETINET6 */ default: -#if _FFR_LOG_UNSUPPORTED_FAMILIES - /* XXX: Give warning about unsupported family */ + /* Give warning about unsupported family */ if (LogLevel > 3) sm_syslog(LOG_WARNING, NOQID, "Unsupported address family %d: %.100s", sa->sa.sa_family, anynet_ntoa(sa)); -#endif return -1; } @@ -4317,15 +4688,20 @@ add_hostnames(sa) { int save_errno = errno; - if (LogLevel > 3) + if (LogLevel > 3 && +#if NETINET6 + !(sa->sa.sa_family == AF_INET6 && + IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) && +#endif /* NETINET6 */ + TRUE) sm_syslog(LOG_WARNING, NOQID, "gethostbyaddr(%.100s) failed: %d\n", anynet_ntoa(sa), #if NAMED_BIND h_errno -#else +#else /* NAMED_BIND */ -1 -#endif +#endif /* NAMED_BIND */ ); errno = save_errno; return -1; @@ -4336,19 +4712,37 @@ add_hostnames(sa) { setclass('w', (char *) hp->h_name); if (tTd(0, 4)) - printf("\ta.k.a.: %s\n", hp->h_name); + dprintf("\ta.k.a.: %s\n", hp->h_name); + + if (snprintf(hnb, sizeof hnb, "[%s]", hp->h_name) < sizeof hnb + && !wordinclass((char *) hnb, 'w')) + setclass('w', hnb); + } + else + { + if (tTd(0, 43)) + dprintf("\ta.k.a.: %s (already in $=w)\n", hp->h_name); } /* save all it aliases name */ - while (*hp->h_aliases) + for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) { - if (!wordinclass(*hp->h_aliases, 'w')) + if (!wordinclass(*ha, 'w')) { - setclass('w', *hp->h_aliases); + setclass('w', *ha); if (tTd(0, 4)) - printf("\ta.k.a.: %s\n", *hp->h_aliases); + dprintf("\ta.k.a.: %s\n", *ha); + if (snprintf(hnb, sizeof hnb, + "[%s]", *ha) < sizeof hnb && + !wordinclass((char *) hnb, 'w')) + setclass('w', hnb); + } + else + { + if (tTd(0, 43)) + dprintf("\ta.k.a.: %s (already in $=w)\n", + *ha); } - hp->h_aliases++; } return 0; } @@ -4365,23 +4759,206 @@ add_hostnames(sa) ** Loads $=w with the names of all the interfaces. */ +#if !NETINET +# define SIOCGIFCONF_IS_BROKEN 1 /* XXX */ +#endif /* !NETINET */ + #if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN struct rtentry; struct mbuf; -# include <arpa/inet.h> # ifndef SUNOS403 # include <sys/time.h> -# endif -# if _AIX4 >= 40300 +# endif /* ! SUNOS403 */ +# if (_AIX4 >= 40300) && !defined(_NET_IF_H) # undef __P -# endif +# endif /* (_AIX4 >= 40300) && !defined(_NET_IF_H) */ # include <net/if.h> -#endif +#endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ void load_if_names() { -#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN +#if NETINET6 && defined(SIOCGLIFCONF) + int s; + int i; + struct lifconf lifc; + struct lifnum lifn; + int numifs; + + s = socket(InetMode, SOCK_DGRAM, 0); + if (s == -1) + return; + + /* get the list of known IP address from the kernel */ +# ifdef SIOCGLIFNUM + lifn.lifn_family = AF_UNSPEC; + lifn.lifn_flags = 0; + if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) + { + /* can't get number of interfaces -- fall back */ + if (tTd(0, 4)) + dprintf("SIOCGLIFNUM failed: %s\n", errstring(errno)); + numifs = -1; + } + else + { + numifs = lifn.lifn_count; + if (tTd(0, 42)) + dprintf("system has %d interfaces\n", numifs); + } + if (numifs < 0) +# endif /* SIOCGLIFNUM */ + numifs = MAXINTERFACES; + + if (numifs <= 0) + { + close(s); + return; + } + lifc.lifc_len = numifs * sizeof (struct lifreq); + lifc.lifc_buf = xalloc(lifc.lifc_len); + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_flags = 0; + if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) + { + if (tTd(0, 4)) + dprintf("SIOCGLIFCONF failed: %s\n", errstring(errno)); + close(s); + return; + } + + /* scan the list of IP address */ + if (tTd(0, 40)) + dprintf("scanning for interface specific names, lifc_len=%d\n", + lifc.lifc_len); + + for (i = 0; i < lifc.lifc_len; ) + { + struct lifreq *ifr = (struct lifreq *)&lifc.lifc_buf[i]; + SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr; + char *addr; + struct in6_addr ia6; + struct in_addr ia; +# ifdef SIOCGLIFFLAGS + struct lifreq ifrf; +# endif /* SIOCGLIFFLAGS */ + char ip_addr[256]; + char buf6[INET6_ADDRSTRLEN]; + int af = ifr->lifr_addr.ss_family; + + /* + ** We must close and recreate the socket each time + ** since we don't know what type of socket it is now + ** (each status function may change it). + */ + + (void) close(s); + + s = socket(af, SOCK_DGRAM, 0); + if (s == -1) + return; + + /* + ** If we don't have a complete ifr structure, + ** don't try to use it. + */ + + if ((lifc.lifc_len - i) < sizeof *ifr) + break; + +# ifdef BSD4_4_SOCKADDR + if (sa->sa.sa_len > sizeof ifr->lifr_addr) + i += sizeof ifr->lifr_name + sa->sa.sa_len; + else +# endif /* BSD4_4_SOCKADDR */ + i += sizeof *ifr; + + if (tTd(0, 20)) + dprintf("%s\n", anynet_ntoa(sa)); + + if (af != AF_INET && af != AF_INET6) + continue; + +# ifdef SIOCGLIFFLAGS + memset(&ifrf, '\0', sizeof(struct lifreq)); + (void) strlcpy(ifrf.lifr_name, ifr->lifr_name, + sizeof(ifrf.lifr_name)); + if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0) + { + if (tTd(0, 4)) + dprintf("SIOCGLIFFLAGS failed: %s\n", + errstring(errno)); + continue; + } + else if (tTd(0, 41)) + dprintf("\tflags: %lx\n", + (unsigned long)ifrf.lifr_flags); + + if (!bitset(IFF_UP, ifrf.lifr_flags)) + continue; +# endif /* SIOCGLIFFLAGS */ + + ip_addr[0] = '\0'; + + /* extract IP address from the list*/ + switch (af) + { + case AF_INET6: + ia6 = sa->sin6.sin6_addr; + if (ia6.s6_addr == in6addr_any.s6_addr) + { + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + message("WARNING: interface %s is UP with %s address", + ifr->lifr_name, + addr == NULL ? "(NULL)" : addr); + continue; + } + + /* save IP address in text from */ + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + if (addr != NULL) + (void) snprintf(ip_addr, sizeof ip_addr, + "[%.*s]", + sizeof ip_addr - 3, addr); + break; + + case AF_INET: + ia = sa->sin.sin_addr; + if (ia.s_addr == INADDR_ANY || + ia.s_addr == INADDR_NONE) + { + message("WARNING: interface %s is UP with %s address", + ifr->lifr_name, inet_ntoa(ia)); + continue; + } + + /* save IP address in text from */ + (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", + sizeof ip_addr - 3, inet_ntoa(ia)); + break; + } + + if (*ip_addr == '\0') + continue; + + if (!wordinclass(ip_addr, 'w')) + { + setclass('w', ip_addr); + if (tTd(0, 4)) + dprintf("\ta.k.a.: %s\n", ip_addr); + } + +# ifdef SIOCGLIFFLAGS + /* skip "loopback" interface "lo" */ + if (bitset(IFF_LOOPBACK, ifrf.lifr_flags)) + continue; +# endif /* SIOCGLIFFLAGS */ + (void) add_hostnames(sa); + } + free(lifc.lifc_buf); + close(s); +#else /* NETINET6 && defined(SIOCGLIFCONF) */ +# if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN int s; int i; struct ifconf ifc; @@ -4392,23 +4969,23 @@ load_if_names() return; /* get the list of known IP address from the kernel */ -# if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN +# if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) { /* can't get number of interfaces -- fall back */ if (tTd(0, 4)) - printf("SIOCGIFNUM failed: %s\n", errstring(errno)); + dprintf("SIOCGIFNUM failed: %s\n", errstring(errno)); numifs = -1; } else if (tTd(0, 42)) - printf("system has %d interfaces\n", numifs); + dprintf("system has %d interfaces\n", numifs); if (numifs < 0) -# endif - numifs = 512; +# endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */ + numifs = MAXINTERFACES; if (numifs <= 0) { - close(s); + (void) close(s); return; } ifc.ifc_len = numifs * sizeof (struct ifreq); @@ -4416,71 +4993,128 @@ load_if_names() if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { if (tTd(0, 4)) - printf("SIOGIFCONF failed: %s\n", errstring(errno)); - close(s); + dprintf("SIOCGIFCONF failed: %s\n", errstring(errno)); + (void) close(s); return; } /* scan the list of IP address */ if (tTd(0, 40)) - printf("scanning for interface specific names, ifc_len=%d\n", + dprintf("scanning for interface specific names, ifc_len=%d\n", ifc.ifc_len); for (i = 0; i < ifc.ifc_len; ) { + int af; struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i]; SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr; +# if NETINET6 + char *addr; + struct in6_addr ia6; +# endif /* NETINET6 */ struct in_addr ia; -#ifdef SIOCGIFFLAGS +# ifdef SIOCGIFFLAGS struct ifreq ifrf; -#endif +# endif /* SIOCGIFFLAGS */ char ip_addr[256]; - extern char *inet_ntoa(); +# if NETINET6 + char buf6[INET6_ADDRSTRLEN]; +# endif /* NETINET6 */ -#ifdef BSD4_4_SOCKADDR + /* + ** If we don't have a complete ifr structure, + ** don't try to use it. + */ + + if ((ifc.ifc_len - i) < sizeof *ifr) + break; + +# ifdef BSD4_4_SOCKADDR if (sa->sa.sa_len > sizeof ifr->ifr_addr) i += sizeof ifr->ifr_name + sa->sa.sa_len; else -#endif +# endif /* BSD4_4_SOCKADDR */ i += sizeof *ifr; if (tTd(0, 20)) - printf("%s\n", anynet_ntoa(sa)); - - if (ifr->ifr_addr.sa_family != AF_INET) + dprintf("%s\n", anynet_ntoa(sa)); + + af = ifr->ifr_addr.sa_family; + if (af != AF_INET +# if NETINET6 + && af != AF_INET6 +# endif /* NETINET6 */ + ) continue; -#ifdef SIOCGIFFLAGS - bzero(&ifrf, sizeof(struct ifreq)); - strncpy(ifrf.ifr_name, ifr->ifr_name, sizeof(ifrf.ifr_name)); - ioctl(s, SIOCGIFFLAGS, (char *) &ifrf); +# ifdef SIOCGIFFLAGS + memset(&ifrf, '\0', sizeof(struct ifreq)); + (void) strlcpy(ifrf.ifr_name, ifr->ifr_name, + sizeof(ifrf.ifr_name)); + (void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf); if (tTd(0, 41)) - printf("\tflags: %x\n", ifrf.ifr_flags); -# define IFRFREF ifrf -#else -# define IFRFREF (*ifr) -#endif + dprintf("\tflags: %lx\n", + (unsigned long) ifrf.ifr_flags); +# define IFRFREF ifrf +# else /* SIOCGIFFLAGS */ +# define IFRFREF (*ifr) +# endif /* SIOCGIFFLAGS */ + if (!bitset(IFF_UP, IFRFREF.ifr_flags)) continue; + ip_addr[0] = '\0'; + /* extract IP address from the list*/ - ia = sa->sin.sin_addr; - if (ia.s_addr == INADDR_ANY || ia.s_addr == INADDR_NONE) + switch (af) { - message("WARNING: interface %s is UP with %s address", - ifr->ifr_name, inet_ntoa(ia)); - continue; + case AF_INET: + ia = sa->sin.sin_addr; + if (ia.s_addr == INADDR_ANY || + ia.s_addr == INADDR_NONE) + { + message("WARNING: interface %s is UP with %s address", + ifr->ifr_name, inet_ntoa(ia)); + continue; + } + + /* save IP address in text from */ + (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", + (int) sizeof ip_addr - 3, + inet_ntoa(ia)); + break; + +# if NETINET6 + case AF_INET6: + ia6 = sa->sin6.sin6_addr; + if (ia6.s6_addr == in6addr_any.s6_addr) + { + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + message("WARNING: interface %s is UP with %s address", + ifr->ifr_name, + addr == NULL ? "(NULL)" : addr); + continue; + } + + /* save IP address in text from */ + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + if (addr != NULL) + (void) snprintf(ip_addr, sizeof ip_addr, + "[%.*s]", + (int) sizeof ip_addr - 3, addr); + break; + +# endif /* NETINET6 */ } - /* save IP address in text from */ - (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", - (int)sizeof ip_addr - 3, - inet_ntoa(ia)); + if (ip_addr[0] == '\0') + continue; + if (!wordinclass(ip_addr, 'w')) { setclass('w', ip_addr); if (tTd(0, 4)) - printf("\ta.k.a.: %s\n", ip_addr); + dprintf("\ta.k.a.: %s\n", ip_addr); } /* skip "loopback" interface "lo" */ @@ -4490,9 +5124,37 @@ load_if_names() (void) add_hostnames(sa); } free(ifc.ifc_buf); - close(s); -# undef IFRFREF -#endif + (void) close(s); +# undef IFRFREF +# endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ +#endif /* NETINET6 && defined(SIOCGLIFCONF) */ +} +/* +** ISLOOPBACK -- is socket address in the loopback net? +** +** Parameters: +** sa -- socket address. +** +** Returns: +** TRUE -- is socket address in the loopback net? +** FALSE -- otherwise +** +*/ + +bool +isloopback(sa) + SOCKADDR sa; +{ +#if NETINET6 + if (IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr)) + return TRUE; +#else /* NETINET6 */ + /* XXX how to correctly extract IN_LOOPBACKNET part? */ + if (((ntohl(sa.sin.sin_addr.s_addr) & IN_CLASSA_NET) + >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) + return TRUE; +#endif /* NETINET6 */ + return FALSE; } /* ** GET_NUM_PROCS_ONLINE -- return the number of processors currently online @@ -4504,21 +5166,70 @@ load_if_names() ** The number of processors online. */ -int +static int get_num_procs_online() { int nproc = 0; -#if _FFR_SCALE_LA_BY_NUM_PROCS -#ifdef _SC_NPROCESSORS_ONLN +#ifdef USESYSCTL +# if defined(CTL_HW) && defined(HW_NCPU) + size_t sz; + int mib[2]; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + sz = (size_t) sizeof nproc; + (void) sysctl(mib, 2, &nproc, &sz, NULL, 0); +# endif /* defined(CTL_HW) && defined(HW_NCPUS) */ +#else /* USESYSCTL */ +# ifdef _SC_NPROCESSORS_ONLN nproc = (int) sysconf(_SC_NPROCESSORS_ONLN); -#endif -#endif +# else /* _SC_NPROCESSORS_ONLN */ +# ifdef __hpux +# include <sys/pstat.h> + struct pst_dynamic psd; + + if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) + nproc = psd.psd_proc_cnt; +# endif /* __hpux */ +# endif /* _SC_NPROCESSORS_ONLN */ +#endif /* USESYSCTL */ + if (nproc <= 0) nproc = 1; return nproc; } /* +** SEED_RANDOM -- seed the random number generator +** +** Parameters: +** none +** +** Returns: +** none +*/ + +void +seed_random() +{ +#if HASSRANDOMDEV + srandomdev(); +#else /* HASSRANDOMDEV */ + long seed; + struct timeval t; + + seed = (long) getpid(); + if (gettimeofday(&t, NULL) >= 0) + seed += t.tv_sec + t.tv_usec; + +# if HASRANDOM + (void) srandom(seed); +# else /* HASRANDOM */ + (void) srand((unsigned int) seed); +# endif /* HASRANDOM */ +#endif /* HASSRANDOMDEV */ +} +/* ** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE ** ** Parameters: @@ -4533,61 +5244,61 @@ get_num_procs_online() /* VARARGS3 */ void -# ifdef __STDC__ +#ifdef __STDC__ sm_syslog(int level, const char *id, const char *fmt, ...) -# else +#else /* __STDC__ */ sm_syslog(level, id, fmt, va_alist) int level; const char *id; const char *fmt; va_dcl -#endif +#endif /* __STDC__ */ { static char *buf = NULL; - static size_t bufsize = MAXLINE; + static size_t bufsize; char *begin, *end; + int save_errno; int seq = 1; int idlen; + char buf0[MAXLINE]; extern int SnprfOverflow; extern int SyslogErrno; extern char *DoprEnd; VA_LOCAL_DECL - extern void sm_dopr __P((char *, const char *, va_list)); - - SyslogErrno = errno; + + save_errno = SyslogErrno = errno; if (id == NULL) - { id = "NOQUEUE"; - idlen = 9; - } else if (strcmp(id, NOQID) == 0) - { id = ""; - idlen = 0; - } - else - idlen = strlen(id + 2); -bufalloc: - if (buf == NULL) - buf = (char *) xalloc(sizeof(char) * bufsize); + idlen = strlen(id); - /* do a virtual vsnprintf into buf */ - VA_START(fmt); - buf[0] = 0; - DoprEnd = buf + bufsize - 1; - SnprfOverflow = 0; - sm_dopr(buf, fmt, ap); - *DoprEnd = '\0'; - VA_END; - /* end of virtual vsnprintf */ + if (buf == NULL) + { + buf = buf0; + bufsize = sizeof buf0; + } - if (SnprfOverflow) + for (;;) { + /* do a virtual vsnprintf into buf */ + VA_START(fmt); + buf[0] = 0; + DoprEnd = buf + bufsize - 1; + SnprfOverflow = 0; + sm_dopr(buf, fmt, ap); + *DoprEnd = '\0'; + VA_END; + /* end of virtual vsnprintf */ + + if (SnprfOverflow == 0) + break; + /* String too small, redo with correct size */ bufsize += SnprfOverflow + 1; - free(buf); - buf = NULL; - goto bufalloc; + if (buf != buf0) + free(buf); + buf = xalloc(bufsize * sizeof (char)); } if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE) { @@ -4596,22 +5307,25 @@ bufalloc: syslog(level, "%s", buf); else syslog(level, "%s: %s", id, buf); -#else +#else /* LOG */ /*XXX should do something more sensible */ if (*id == '\0') fprintf(stderr, "%s\n", buf); else fprintf(stderr, "%s: %s\n", id, buf); -#endif +#endif /* LOG */ + if (buf == buf0) + buf = NULL; + errno = save_errno; return; } begin = buf; while (*begin != '\0' && - (strlen(begin) + idlen + 5) > SYSLOG_BUFSIZE) + (strlen(begin) + idlen + 5) > SYSLOG_BUFSIZE) { char save; - + if (seq == 999) { /* Too many messages */ @@ -4635,24 +5349,29 @@ bufalloc: *end = 0; #if LOG syslog(level, "%s[%d]: %s ...", id, seq++, begin); -#else +#else /* LOG */ fprintf(stderr, "%s[%d]: %s ...\n", id, seq++, begin); -#endif +#endif /* LOG */ *end = save; begin = end; } if (seq == 999) #if LOG - syslog(level, "%s[%d]: log terminated, too many parts", id, seq); -#else - fprintf(stderr, "%s[%d]: log terminated, too many parts\n", id, seq); -#endif + syslog(level, "%s[%d]: log terminated, too many parts", + id, seq); +#else /* LOG */ + fprintf(stderr, "%s[%d]: log terminated, too many parts\n", + id, seq); +#endif /* LOG */ else if (*begin != '\0') #if LOG syslog(level, "%s[%d]: %s", id, seq, begin); -#else +#else /* LOG */ fprintf(stderr, "%s[%d]: %s\n", id, seq, begin); -#endif +#endif /* LOG */ + if (buf == buf0) + buf = NULL; + errno = save_errno; } /* ** HARD_SYSLOG -- call syslog repeatedly until it works @@ -4668,20 +5387,20 @@ bufalloc: # ifdef V4FS # define XCNST const # define CAST (const char *) -# else +# else /* V4FS */ # define XCNST # define CAST -# endif +# endif /* V4FS */ void # ifdef __STDC__ hard_syslog(int pri, XCNST char *msg, ...) -# else +# else /* __STDC__ */ hard_syslog(pri, msg, va_alist) int pri; XCNST char *msg; va_dcl -# endif +# endif /* __STDC__ */ { int i; char buf[SYSLOG_BUFSIZE]; @@ -4696,19 +5415,19 @@ hard_syslog(pri, msg, va_alist) } # undef CAST -#endif +#endif /* defined(__hpux) && !defined(HPUX11) */ +#if NEEDLOCAL_HOSTNAME_LENGTH /* ** LOCAL_HOSTNAME_LENGTH ** ** This is required to get sendmail to compile against BIND 4.9.x ** on Ultrix. +** +** Unfortunately, a Compaq Y2K patch kit provides it without +** bumping __RES in /usr/include/resolv.h so we can't automatically +** figure out whether it is needed. */ -#if defined(ultrix) && NAMED_BIND - -# include <resolv.h> -# if __RES >= 19931104 && __RES < 19950621 - int local_hostname_length(hostname) char *hostname; @@ -4720,15 +5439,15 @@ local_hostname_length(hostname) len_host = strlen(hostname); len_domain = strlen(_res.defdname); if (len_host > len_domain && - (strcasecmp(hostname + len_host - len_domain,_res.defdname) == 0) && + (strcasecmp(hostname + len_host - len_domain, + _res.defdname) == 0) && hostname[len_host - len_domain - 1] == '.') return len_host - len_domain - 1; else return 0; } +#endif /* NEEDLOCAL_HOSTNAME_LENGTH */ -# endif -#endif /* ** Compile-Time options */ @@ -4737,88 +5456,106 @@ char *CompileOptions[] = { #ifdef HESIOD "HESIOD", -#endif +#endif /* HESIOD */ #if HES_GETMAILHOST "HES_GETMAILHOST", -#endif +#endif /* HES_GETMAILHOST */ #ifdef LDAPMAP "LDAPMAP", -#endif +#endif /* LDAPMAP */ +#ifdef MAP_NSD + "MAP_NSD", +#endif /* MAP_NSD */ #ifdef MAP_REGEX "MAP_REGEX", -#endif +#endif /* MAP_REGEX */ #if LOG "LOG", -#endif +#endif /* LOG */ #if MATCHGECOS "MATCHGECOS", -#endif +#endif /* MATCHGECOS */ #if MIME7TO8 "MIME7TO8", -#endif +#endif /* MIME7TO8 */ #if MIME8TO7 "MIME8TO7", -#endif +#endif /* MIME8TO7 */ #if NAMED_BIND "NAMED_BIND", -#endif +#endif /* NAMED_BIND */ #ifdef NDBM "NDBM", -#endif +#endif /* NDBM */ #if NETINET "NETINET", -#endif +#endif /* NETINET */ +#if NETINET6 + "NETINET6", +#endif /* NETINET6 */ #if NETINFO "NETINFO", -#endif +#endif /* NETINFO */ #if NETISO "NETISO", -#endif +#endif /* NETISO */ #if NETNS "NETNS", -#endif +#endif /* NETNS */ #if NETUNIX "NETUNIX", -#endif +#endif /* NETUNIX */ #if NETX25 "NETX25", -#endif +#endif /* NETX25 */ #ifdef NEWDB "NEWDB", -#endif +#endif /* NEWDB */ #ifdef NIS "NIS", -#endif +#endif /* NIS */ #ifdef NISPLUS "NISPLUS", -#endif +#endif /* NISPLUS */ +#ifdef PH_MAP + "PH_MAP", +#endif /* PH_MAP */ #if QUEUE "QUEUE", -#endif +#endif /* QUEUE */ +#if SASL + "SASL", +#endif /* SASL */ #if SCANF "SCANF", -#endif +#endif /* SCANF */ +#if SFIO + "SFIO", +#endif /* SFIO */ #if SMTP "SMTP", -#endif +#endif /* SMTP */ #if SMTPDEBUG "SMTPDEBUG", -#endif +#endif /* SMTPDEBUG */ +#if STARTTLS + "STARTTLS", +#endif /* STARTTLS */ #ifdef SUID_ROOT_FILES_OK "SUID_ROOT_FILES_OK", -#endif +#endif /* SUID_ROOT_FILES_OK */ #if TCPWRAPPERS "TCPWRAPPERS", -#endif +#endif /* TCPWRAPPERS */ #if USERDB "USERDB", -#endif +#endif /* USERDB */ #if XDEBUG "XDEBUG", -#endif +#endif /* XDEBUG */ #ifdef XLA "XLA", -#endif +#endif /* XLA */ NULL }; @@ -4831,108 +5568,133 @@ char *OsCompileOptions[] = { #if BOGUS_O_EXCL "BOGUS_O_EXCL", -#endif +#endif /* BOGUS_O_EXCL */ +#if FAST_PID_RECYCLE + "FAST_PID_RECYCLE", +#endif /* FAST_PID_RECYCLE */ +#if HASFCHOWN + "HASFCHOWN", +#endif /* HASFCHOWN */ #if HASFCHMOD "HASFCHMOD", -#endif +#endif /* HASFCHMOD */ #if HASFLOCK "HASFLOCK", -#endif +#endif /* HASFLOCK */ #if HASGETDTABLESIZE "HASGETDTABLESIZE", -#endif +#endif /* HASGETDTABLESIZE */ #if HASGETUSERSHELL "HASGETUSERSHELL", -#endif +#endif /* HASGETUSERSHELL */ #if HASINITGROUPS "HASINITGROUPS", -#endif +#endif /* HASINITGROUPS */ #if HASLSTAT "HASLSTAT", -#endif +#endif /* HASLSTAT */ +#if HASRANDOM + "HASRANDOM", +#endif /* HASRANDOM */ +#if HASSETLOGIN + "HASSETLOGIN", +#endif /* HASSETLOGIN */ #if HASSETREUID "HASSETREUID", -#endif +#endif /* HASSETREUID */ #if HASSETRLIMIT "HASSETRLIMIT", -#endif +#endif /* HASSETRLIMIT */ #if HASSETSID "HASSETSID", -#endif +#endif /* HASSETSID */ #if HASSETUSERCONTEXT "HASSETUSERCONTEXT", -#endif +#endif /* HASSETUSERCONTEXT */ #if HASSETVBUF "HASSETVBUF", -#endif +#endif /* HASSETVBUF */ #if HASSNPRINTF "HASSNPRINTF", -#endif +#endif /* HASSNPRINTF */ #if HAS_ST_GEN "HAS_ST_GEN", -#endif +#endif /* HAS_ST_GEN */ +#if HASSRANDOMDEV + "HASSRANDOMDEV", +#endif /* HASSRANDOMDEV */ +#if HASURANDOMDEV + "HASURANDOMDEV", +#endif /* HASURANDOMDEV */ #if HASSTRERROR "HASSTRERROR", -#endif +#endif /* HASSTRERROR */ #if HASULIMIT "HASULIMIT", -#endif +#endif /* HASULIMIT */ #if HASUNAME "HASUNAME", -#endif +#endif /* HASUNAME */ #if HASUNSETENV "HASUNSETENV", -#endif +#endif /* HASUNSETENV */ #if HASWAITPID "HASWAITPID", -#endif +#endif /* HASWAITPID */ #if IDENTPROTO "IDENTPROTO", -#endif +#endif /* IDENTPROTO */ #if IP_SRCROUTE "IP_SRCROUTE", -#endif +#endif /* IP_SRCROUTE */ #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL "LOCK_ON_OPEN", -#endif +#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ #if NEEDFSYNC "NEEDFSYNC", -#endif +#endif /* NEEDFSYNC */ #if NOFTRUNCATE "NOFTRUNCATE", -#endif +#endif /* NOFTRUNCATE */ #if RLIMIT_NEEDS_SYS_TIME_H "RLIMIT_NEEDS_SYS_TIME_H", -#endif +#endif /* RLIMIT_NEEDS_SYS_TIME_H */ #if SAFENFSPATHCONF "SAFENFSPATHCONF", -#endif +#endif /* SAFENFSPATHCONF */ #if SECUREWARE "SECUREWARE", -#endif +#endif /* SECUREWARE */ #if SHARE_V1 "SHARE_V1", -#endif +#endif /* SHARE_V1 */ #if SIOCGIFCONF_IS_BROKEN "SIOCGIFCONF_IS_BROKEN", -#endif +#endif /* SIOCGIFCONF_IS_BROKEN */ #if SIOCGIFNUM_IS_BROKEN "SIOCGIFNUM_IS_BROKEN", -#endif +#endif /* SIOCGIFNUM_IS_BROKEN */ +#if SNPRINTF_IS_BROKEN + "SNPRINTF_IS_BROKEN", +#endif /* SNPRINTF_IS_BROKEN */ +#if SO_REUSEADDR_IS_BROKEN + "SO_REUSEADDR_IS_BROKEN", +#endif /* SO_REUSEADDR_IS_BROKEN */ #if SYS5SETPGRP "SYS5SETPGRP", -#endif +#endif /* SYS5SETPGRP */ #if SYSTEM5 "SYSTEM5", -#endif +#endif /* SYSTEM5 */ #if USE_SA_SIGACTION "USE_SA_SIGACTION", -#endif +#endif /* USE_SA_SIGACTION */ #if USE_SIGLONGJMP "USE_SIGLONGJMP", -#endif +#endif /* USE_SIGLONGJMP */ #if USESETEUID "USESETEUID", -#endif +#endif /* USESETEUID */ NULL }; + diff --git a/contrib/sendmail/src/conf.h b/contrib/sendmail/src/conf.h index b8df01d..c748bf3 100644 --- a/contrib/sendmail/src/conf.h +++ b/contrib/sendmail/src/conf.h @@ -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. @@ -9,7 +10,7 @@ * the sendmail distribution. * * - * @(#)conf.h 8.385 (Berkeley) 1/28/1999 + * $Id: conf.h,v 8.496.4.20 2000/07/15 17:35:19 gshapiro Exp $ */ /* $FreeBSD$ */ @@ -21,59 +22,108 @@ ** included in the next release. */ +#ifndef CONF_H +#define CONF_H 1 + #ifdef __GNUC__ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ -#endif +#endif /* __GNUC__ */ # include <sys/param.h> # include <sys/types.h> +# if SFIO && defined(SF_APPEND) +# undef SF_APPEND /* Both sfio/stdio.h and sys/stat.h define it */ +# endif /* SFIO && defined(SF_APPEND) */ # include <sys/stat.h> -#ifndef __QNX__ +# ifndef __QNX__ /* in QNX this grabs bogus LOCK_* manifests */ -# include <sys/file.h> -#endif +# include <sys/file.h> +# endif /* ! __QNX__ */ # include <sys/wait.h> # include <limits.h> # include <fcntl.h> # include <signal.h> # include <netdb.h> # include <pwd.h> +# include <grp.h> + +/* make sure TOBUFSIZ isn't larger than system limit for size of exec() args */ +#ifdef ARG_MAX +# if ARG_MAX > 4096 +# define SM_ARG_MAX 4096 +# else /* ARG_MAX > 4096 */ +# define SM_ARG_MAX ARG_MAX +# endif /* ARG_MAX > 4096 */ +#else /* ARG_MAX */ +# define SM_ARG_MAX 4096 +#endif /* ARG_MAX */ /********************************************************************** ** Table sizes, etc.... ** There shouldn't be much need to change these.... **********************************************************************/ -# define MAXLINE 2048 /* max line length */ -# define MAXNAME 256 /* max length of a name */ -# define MAXPV 40 /* max # of parms to mailers */ -# define MAXATOM 200 /* max atoms per address */ -# define MAXMAILERS 25 /* maximum mailers known to system */ -# define MAXRWSETS 200 /* max # of sets of rewriting rules */ -# define MAXPRIORITIES 25 /* max values for Precedence: field */ -# define MAXMXHOSTS 100 /* max # of MX records for one host */ -# define SMTPLINELIM 990 /* maximum SMTP line length */ -# define MAXKEY 128 /* maximum size of a database key */ -# define MEMCHUNKSIZE 1024 /* chunk size for memory allocation */ -# define MAXUSERENVIRON 100 /* max envars saved, must be >= 3 */ -# define MAXALIASDB 12 /* max # of alias databases */ -# define MAXMAPSTACK 12 /* max # of stacked or sequenced maps */ -# define MAXTOCLASS 8 /* max # of message timeout classes */ -# define MAXMIMEARGS 20 /* max args in Content-Type: */ -# define MAXMIMENESTING 20 /* max MIME multipart nesting */ -# define QUEUESEGSIZE 1000 /* increment for queue size */ -# define MAXQFNAME 20 /* max qf file name length */ -# define MACBUFSIZE 4096 /* max expanded macro buffer size */ -# define TOBUFSIZE 512 /* max buffer to hold address list */ -# define MAXSHORTSTR 203 /* max short string length */ -# if _FFR_MAX_MIME_HEADER_LENGTH -# define MAXMACNAMELEN 25 /* max macro name length */ -# else -# define MAXMACNAMELEN 20 /* max macro name length */ -# endif -# ifndef MAXHDRSLEN -# define MAXHDRSLEN (32 * 1024) /* max size of message headers */ -# endif +#define MAXLINE 2048 /* max line length */ +#define MAXNAME 256 /* max length of a name */ +#define MAXPV 256 /* max # of parms to mailers */ +#define MAXATOM 1000 /* max atoms per address */ +#define MAXRWSETS 200 /* max # of sets of rewriting rules */ +#define MAXPRIORITIES 25 /* max values for Precedence: field */ +#define MAXMXHOSTS 100 /* max # of MX records for one host */ +#define SMTPLINELIM 990 /* maximum SMTP line length */ +#define MAXKEY 128 /* maximum size of a database key */ +#define MEMCHUNKSIZE 1024 /* chunk size for memory allocation */ +#define MAXUSERENVIRON 100 /* max envars saved, must be >= 3 */ +#define MAXALIASDB 12 /* max # of alias databases */ +#define MAXMAPSTACK 12 /* max # of stacked or sequenced maps */ +#if _FFR_MILTER +# define MAXFILTERS 25 /* max # of milter filters */ +# define MAXFILTERMACROS 50 /* max # of macros per milter cmd */ +#endif /* _FFR_MILTER */ +#define MAXSMTPARGS 20 /* max # of ESMTP args for MAIL/RCPT */ +#define MAXTOCLASS 8 /* max # of message timeout classes */ +#define MAXRESTOTYPES 3 /* max # of resolver timeout types */ +#define MAXMIMEARGS 20 /* max args in Content-Type: */ +#define MAXMIMENESTING 20 /* max MIME multipart nesting */ +#define QUEUESEGSIZE 1000 /* increment for queue size */ +#define MAXQFNAME 20 /* max qf file name length */ +#define MACBUFSIZE 4096 /* max expanded macro buffer size */ +#define TOBUFSIZE SM_ARG_MAX /* max buffer to hold address list */ +#define MAXSHORTSTR 203 /* max short string length */ +#define MAXMACNAMELEN 25 /* max macro name length */ +#define MAXMACROID 0377 /* max macro id number */ +#ifndef MAXHDRSLEN +# define MAXHDRSLEN (32 * 1024) /* max size of message headers */ +#endif /* ! MAXHDRSLEN */ +#define MAXDAEMONS 10 /* max number of ports to listen to */ +#ifndef MAXINTERFACES +# define MAXINTERFACES 512 /* number of interfaces to probe */ +#endif /* MAXINTERFACES */ +#ifndef MAXSYMLINKS +# define MAXSYMLINKS 32 /* max number of symlinks in a path */ +#endif /* ! MAXSYMLINKS */ +#define MAXLINKPATHLEN (MAXPATHLEN * MAXSYMLINKS) /* max link-expanded file */ +#define DATA_PROGRESS_TIMEOUT 300 /* how ofter to check DATA progress */ +#define ENHSCLEN 10 /* max len of enhanced status code */ +#if _FFR_DYNAMIC_TOBUF +# define DEFAULT_MAX_RCPT 100 /* max number of RCPTs per envelope */ +#endif /* _FFR_DYNAMIC_TOBUF */ + +#if SASL +# ifndef AUTH_MECHANISMS +# if STARTTLS && _FFR_EXT_MECH +# define AUTH_MECHANISMS "EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5" +# else /* STARTTLS && _FFR_EXT_MECH */ +# define AUTH_MECHANISMS "GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5" +# endif /* STARTTLS && _FFR_EXT_MECH */ +# endif /* ! AUTH_MECHANISMS */ +#endif /* SASL */ + +#ifdef LDAPMAP +# define LDAPMAP_MAX_ATTR 64 +# define LDAPMAP_MAX_FILTER 1024 +# define LDAPMAP_MAX_PASSWD 256 +#endif /* LDAPMAP */ /********************************************************************** ** Compilation options. @@ -82,41 +132,45 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ ** All can be overridden from Makefile. **********************************************************************/ -# ifndef NETINET -# define NETINET 1 /* include internet support */ -# endif +#ifndef NETINET +# define NETINET 1 /* include internet support */ +#endif /* ! NETINET */ -# ifndef NETISO -# define NETISO 0 /* do not include ISO socket support */ -# endif +#ifndef NETINET6 +# define NETINET6 0 /* do not include IPv6 support */ +#endif /* ! NETINET6 */ -# ifndef NAMED_BIND -# define NAMED_BIND 1 /* use Berkeley Internet Domain Server */ -# endif +#ifndef NETISO +# define NETISO 0 /* do not include ISO socket support */ +#endif /* ! NETISO */ -# ifndef XDEBUG -# define XDEBUG 1 /* enable extended debugging */ -# endif +#ifndef NAMED_BIND +# define NAMED_BIND 1 /* use Berkeley Internet Domain Server */ +#endif /* ! NAMED_BIND */ -# ifndef MATCHGECOS -# define MATCHGECOS 1 /* match user names from gecos field */ -# endif +#ifndef XDEBUG +# define XDEBUG 1 /* enable extended debugging */ +#endif /* ! XDEBUG */ -# ifndef DSN -# define DSN 1 /* include delivery status notification code */ -# endif +#ifndef MATCHGECOS +# define MATCHGECOS 1 /* match user names from gecos field */ +#endif /* ! MATCHGECOS */ -# if !defined(USERDB) && (defined(NEWDB) || defined(HESIOD)) -# define USERDB 1 /* look in user database */ -# endif +#ifndef DSN +# define DSN 1 /* include delivery status notification code */ +#endif /* ! DSN */ -# ifndef MIME8TO7 -# define MIME8TO7 1 /* 8->7 bit MIME conversions */ -# endif +#if !defined(USERDB) && (defined(NEWDB) || defined(HESIOD)) +# define USERDB 1 /* look in user database */ +#endif /* !defined(USERDB) && (defined(NEWDB) || defined(HESIOD)) */ -# ifndef MIME7TO8 -# define MIME7TO8 1 /* 7->8 bit MIME conversions */ -# endif +#ifndef MIME8TO7 +# define MIME8TO7 1 /* 8->7 bit MIME conversions */ +#endif /* ! MIME8TO7 */ + +#ifndef MIME7TO8 +# define MIME7TO8 1 /* 7->8 bit MIME conversions */ +#endif /* ! MIME7TO8 */ /********************************************************************** ** "Hard" compilation options. @@ -125,7 +179,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ ** be turned off unless absolutely necessary. **********************************************************************/ -# define LOG 1 /* enable logging -- don't turn off */ +#define LOG 1 /* enable logging -- don't turn off */ /********************************************************************** ** End of site-specific configuration. @@ -143,13 +197,15 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ #ifdef __STDC__ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ -#endif +#endif /* __STDC__ */ /* ** Assume you have standard calls; can be #undefed below if necessary. */ +#ifndef HASLSTAT # define HASLSTAT 1 /* has lstat(2) call */ +#endif /* ! HASLSTAT */ /********************************************************************** ** Operating system configuration. ** @@ -170,7 +226,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ # define SYSTEM5 1 /* include all the System V defines */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ -# define USESETEUID 1 /* has useable seteuid(2) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ # define BOGUS_O_EXCL 1 /* exclusive open follows symlinks */ # define seteuid(e) setresuid(-1, e, -1) # define IP_SRCROUTE 1 /* can check IP source routing */ @@ -180,10 +236,18 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ # define GIDSET_T gid_t # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ -# endif -# ifndef HPUX11 -# define syslog hard_syslog -# endif +# endif /* ! HASGETUSERSHELL */ +# ifdef HPUX11 +# define HASFCHOWN 1 /* has fchown(2) */ +# define HASSNPRINTF 1 /* has snprintf(3) */ +# ifndef BROKEN_RES_SEARCH +# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ +# endif /* ! BROKEN_RES_SEARCH */ +# else /* HPUX11 */ +# ifndef NOT_SENDMAIL +# define syslog hard_syslog +# endif /* ! NOT_SENDMAIL */ +# endif /* HPUX11 */ # define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # ifdef V4FS @@ -191,32 +255,32 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ # define _PATH_UNIX "/stand/vmunix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ # ifndef IDENTPROTO # define IDENTPROTO 1 /* TCP/IP implementation fixed in 10.0 */ -# endif - -# else +# endif /* ! IDENTPROTO */ +# include <sys/mpctl.h> /* for mpctl() in get_num_procs_online() */ +# else /* V4FS */ /* HP-UX 9.x */ # define _PATH_UNIX "/hp-ux" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # ifdef __STDC__ extern void hard_syslog(int, char *, ...); -# else +# else /* __STDC__ */ extern void hard_syslog(); -# endif +# endif /* __STDC__ */ # define FDSET_CAST (int *) /* cast for fd_set parameters to select */ -# endif +# endif /* V4FS */ -#endif +#endif /* __hpux */ /* @@ -225,13 +289,17 @@ extern void hard_syslog(); #ifdef _AIX4 # define _AIX3 1 /* pull in AIX3 stuff */ +# define BSD4_4_SOCKADDR /* has sa_len */ # define USESETEUID 1 /* seteuid(2) works */ # define TZ_TYPE TZ_NAME /* use tzname[] vector */ # define SOCKOPT_LEN_T size_t /* arg#5 to getsockopt */ # if _AIX4 >= 40200 # define HASSETREUID 1 /* setreuid(2) works as of AIX 4.2 */ # define SOCKADDR_LEN_T size_t /* e.g., arg#3 to accept, getsockname */ -# endif +# endif /* _AIX4 >= 40200 */ +# if _AIX4 >= 40300 +# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */ +# endif /* _AIX4 >= 40300 */ # if defined(_ILS_MACROS) /* IBM versions aren't side-effect clean */ # undef isascii # define isascii(c) !(c & ~0177) @@ -239,8 +307,8 @@ extern void hard_syslog(); # define isdigit(__a) (_IS(__a,_ISDIGIT)) # undef isspace # define isspace(__a) (_IS(__a,_ISSPACE)) -# endif -#endif +# endif /* defined(_ILS_MACROS) */ +#endif /* _AIX4 */ /* @@ -251,6 +319,7 @@ extern void hard_syslog(); # include <paths.h> # include <sys/machine.h> /* to get byte order */ # include <sys/select.h> +# define HASFCHOWN 1 /* has fchown(2) */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ @@ -262,7 +331,7 @@ extern void hard_syslog(); # define LA_TYPE LA_INT # define FSHIFT 16 # define LA_AVENRUN "avenrun" -#endif +#endif /* _AIX3 */ /* @@ -303,11 +372,11 @@ typedef int pid_t; /* make this sendmail in a completely different place */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/local/newmail/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/local/newmail/sendmail.pid" -# endif -#endif +# endif /* ! _PATH_SENDMAILPID */ +#endif /* AIX */ /* @@ -317,9 +386,9 @@ typedef int pid_t; ** ** Use IRIX64 instead of IRIX for 64-bit IRIX (6.0). ** Use IRIX5 instead of IRIX for IRIX 5.x. -** +** ** This version tries to be adaptive using _MIPS_SIM: -** _MIPS_SIM == _ABIO32 (= 1) Abi: -32 on IRIX 6.2 +** _MIPS_SIM == _ABIO32 (= 1) Abi: -32 on IRIX 6.2 ** _MIPS_SIM == _ABIN32 (= 2) Abi: -n32 on IRIX 6.2 ** _MIPS_SIM == _ABI64 (= 3) Abi: -64 on IRIX 6.2 ** @@ -333,15 +402,14 @@ typedef int pid_t; #if defined(__sgi) # ifndef IRIX # define IRIX -# endif +# endif /* ! IRIX */ # if _MIPS_SIM > 0 && !defined(IRIX5) # define IRIX5 /* IRIX5 or IRIX6 */ -# endif +# endif /* _MIPS_SIM > 0 && !defined(IRIX5) */ # if _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64) # define IRIX6 /* IRIX6 */ -# endif - -#endif +# endif /* _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64) */ +#endif /* defined(__sgi) */ #ifdef IRIX # define SYSTEM5 1 /* this is a System-V derived system */ @@ -356,34 +424,35 @@ typedef int pid_t; # define SFS_BAVAIL f_bfree /* alternate field name */ # define SYSLOG_BUFSIZE 512 # ifdef IRIX6 -# define STAT64 1 +# define STAT64 1 # define QUAD_T unsigned long long # define LA_TYPE LA_IRIX6 /* figure out at run time */ # define SAFENFSPATHCONF 0 /* pathconf(2) lies on NFS filesystems */ -# else +# else /* IRIX6 */ # define LA_TYPE LA_INT # ifdef IRIX64 -# define STAT64 1 +# define STAT64 1 # define QUAD_T unsigned long long # define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */ -# else -# define STAT64 0 +# else /* IRIX64 */ +# define STAT64 0 # define NAMELISTMASK 0x7fffffff /* mask for nlist() values */ -# endif -# endif +# endif /* IRIX64 */ +# endif /* IRIX6 */ # if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) # include <sys/cdefs.h> # include <paths.h> # define ARGV_T char *const * +# define HASFCHOWN 1 /* has fchown(2) */ # define HASSETRLIMIT 1 /* has setrlimit(2) syscall */ -# define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */ +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ -# else +# else /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ # define ARGV_T const char ** # define WAITUNION 1 /* use "union wait" as wait argument type */ -# endif -#endif +# endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ +#endif /* IRIX */ /* @@ -401,78 +470,95 @@ typedef int pid_t; # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define IP_SRCROUTE 1 /* can check IP source routing */ # define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ +# ifndef HASFCHOWN +# define HASFCHOWN 1 /* fchown(2) */ +# endif /* ! HASFCHOWN */ # ifdef SOLARIS_2_3 # define SOLARIS 20300 /* for back compat only -- use -DSOLARIS=20300 */ -# endif +# endif /* SOLARIS_2_3 */ # if defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4)) # define SOLARIS 1 /* unknown Solaris version */ -# endif +# endif /* defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4)) */ # ifdef SOLARIS /* Solaris 2.x (a.k.a. SunOS 5.x) */ # ifndef __svr4__ -# define __svr4__ /* use all System V Releae 4 defines below */ -# endif +# define __svr4__ /* use all System V Release 4 defines below */ +# endif /* ! __svr4__ */ # define GIDSET_T gid_t # define USE_SA_SIGACTION 1 /* use sa_sigaction field */ # ifndef _PATH_UNIX # define _PATH_UNIX "/dev/ksyms" -# endif +# endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ # ifndef _PATH_HOSTS # define _PATH_HOSTS "/etc/inet/hosts" -# endif +# endif /* ! _PATH_HOSTS */ # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ -# endif +# endif /* ! SYSLOG_BUFSIZE */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME -# endif +# endif /* ! TZ_TYPE */ # if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) # define USESETEUID 1 /* seteuid works as of 2.3 */ -# endif +# endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ # if SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) # define HASSETREUID 1 /* setreuid works as of 2.5 */ # if SOLARIS < 207 || (SOLARIS > 10000 && SOLARIS < 20700) # ifndef LA_TYPE # define LA_TYPE LA_KSTAT /* use kstat(3k) -- may work in < 2.5 */ -# endif -# endif -# endif +# endif /* ! LA_TYPE */ +# ifndef RANDOMSHIFT /* random() doesn't work well (sometimes) */ +# define RANDOMSHIFT 8 +# endif /* RANDOMSHIFT */ +# endif /* SOLARIS < 207 || (SOLARIS > 10000 && SOLARIS < 20700) */ +# else /* SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) */ +# ifndef HASRANDOM +# define HASRANDOM 0 /* doesn't have random(3) */ +# endif /* ! HASRANDOM */ +# endif /* SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) */ # if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) # define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ -# endif +# endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ # if SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) # ifndef LA_TYPE +# include <sys/loadavg.h> # define LA_TYPE LA_SUBR /* getloadavg(3c) appears in 2.7 */ -# endif +# endif /* ! LA_TYPE */ # define HASGETUSERSHELL 1 /* getusershell(3c) bug fixed in 2.7 */ -# endif +# endif /* SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) */ +# if SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) +# undef NETINET6 +# define NETINET6 1 /* IPv6 added in 2.8 */ +# define HASSTRL 1 /* str*(3) added in 2.8 */ +# endif /* SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */ -# endif +# endif /* ! HASGETUSERSHELL */ -# else +# else /* SOLARIS */ /* SunOS 4.0.3 or 4.1.x */ # define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */ # define HASSETREUID 1 /* has setreuid(2) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ -# endif +# endif /* ! HASFLOCK */ # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ # include <memory.h> # include <vfork.h> # ifdef __GNUC__ # define strtoul strtol /* gcc library bogosity */ -# endif +# endif /* __GNUC__ */ +# define memmove(d, s, l) (bcopy((s), (d), (l))) # ifdef SUNOS403 /* special tweaking for SunOS 4.0.3 */ @@ -488,19 +574,19 @@ typedef int pid_t; typedef int pid_t; extern char *getenv(); -# else +# else /* SUNOS403 */ /* 4.1.x specifics */ # define HASSETSID 1 /* has Posix setsid(2) call */ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ -# endif -# endif +# endif /* SUNOS403 */ +# endif /* SOLARIS */ # ifndef LA_TYPE # define LA_TYPE LA_INT -# endif +# endif /* ! LA_TYPE */ -#endif /* sun && !BSD */ +#endif /* defined(sun) && !defined(BSD) */ /* ** DG/UX @@ -512,9 +598,9 @@ extern char *getenv(); #ifdef DGUX_5_4_2 # define DGUX 1 -#endif +#endif /* DGUX_5_4_2 */ -#ifdef DGUX +#ifdef DGUX # define SYSTEM5 1 # define LA_TYPE LA_DGUX # define HASSETREUID 1 /* has setreuid(2) call */ @@ -526,7 +612,7 @@ extern char *getenv(); # define HASSNPRINTF 1 /* has snprintf(3) */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # define SPT_TYPE SPT_NONE /* don't use setproctitle */ # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ @@ -540,8 +626,8 @@ extern char *getenv(); # ifdef DGUX_5_4_2 # define inet_addr dgux_inet_addr extern long dgux_inet_addr(); -# endif -#endif +# endif /* DGUX_5_4_2 */ +#endif /* DGUX */ /* @@ -558,39 +644,43 @@ extern long dgux_inet_addr(); # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASFCHOWN 1 /* has fchown(2) syscall */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ -# endif +# endif /* ! HASFLOCK */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # ifndef BROKEN_RES_SEARCH # define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ -# endif +# endif /* ! BROKEN_RES_SEARCH */ +# if !defined(NEEDLOCAL_HOSTNAME_LENGTH) && NAMED_BIND && __RES >= 19931104 && __RES < 19950621 +# define NEEDLOCAL_HOSTNAME_LENGTH 1 /* see sendmail/README */ +# endif /* !defined(NEEDLOCAL_HOSTNAME_LENGTH) && NAMED_BIND && __RES >= 19931104 && __RES < 19950621 */ # ifdef vax # define LA_TYPE LA_FLOAT -# else +# else /* vax */ # define LA_TYPE LA_INT # define LA_AVENRUN "avenrun" -# endif +# endif /* vax */ # define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* pre-4.4 TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # define SYSLOG_BUFSIZE 256 -#endif +#endif /* ultrix */ /* ** OSF/1 for KSR. ** -** Contributed by Todd C. Miller <Todd.Miller@cs.colorado.edu> +** Contributed by Todd C. Miller <Todd.Miller@cs.colorado.edu> */ #ifdef __ksr__ -# define __osf__ 1 /* get OSF/1 defines below */ +# define __osf__ 1 /* get OSF/1 defines below */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ -# endif -#endif +# endif /* ! TZ_TYPE */ +#endif /* __ksr__ */ /* @@ -604,40 +694,44 @@ extern long dgux_inet_addr(); # define __osf__ 1 /* get OSF/1 defines below */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ -# endif +# endif /* ! TZ_TYPE */ # define GIDSET_T gid_t # define MAXNAMLEN NAME_MAX -#endif +#endif /* __PARAGON__ */ /* -** OSF/1 (tested on Alpha) -- now known as Digital UNIX. +** Tru64 UNIX, formerly known as Digital UNIX, formerly known as DEC OSF/1 ** ** Tested for 3.2 and 4.0. */ #ifdef __osf__ +# define HASUNAME 1 /* has uname(2) call */ # define HASUNSETENV 1 /* has unsetenv(3) call */ -# define USESETEUID 1 /* has useable seteuid(2) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASFCHOWN 1 /* has fchown(2) syscall */ +# define HASSETLOGIN 1 /* has setlogin(2) */ # define IP_SRCROUTE 1 /* can check IP source routing */ # define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# define GIDSET_T gid_t +# if _FFR_MILTER +# define SM_INT32 int /* 32bit integer */ +# endif /* _FFR_MILTER */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ -# endif +# endif /* ! HASFLOCK */ # define LA_TYPE LA_ALPHAOSF # define SFS_TYPE SFS_STATVFS /* use <sys/statvfs.h> statfs() impl */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/var/run/sendmail.pid" -# endif -# define bcopy(s, d, l) (memmove((d), (s), (l))) -# define bzero(d, l) (memset((d), '\0', (l))) -# define bcmp(s, d, l) (memcmp((s), (d), (l))) -#endif +# endif /* ! _PATH_SENDMAILPID */ +#endif /* __osf__ */ /* @@ -649,7 +743,7 @@ extern long dgux_inet_addr(); # define NEEDPUTENV 2 /* need putenv(3) call; no setenv(3) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ -# endif +# endif /* ! HASFLOCK */ # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ # define WAITUNION 1 /* use "union wait" as wait argument type */ # define UID_T int /* compiler gripes on uid_t */ @@ -658,38 +752,42 @@ extern long dgux_inet_addr(); # define setpgid setpgrp # ifndef NOT_SENDMAIL # define sleep sleepX -# endif +# endif /* ! NOT_SENDMAIL */ # ifndef LA_TYPE # define LA_TYPE LA_MACH -# endif +# endif /* ! LA_TYPE */ # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # ifndef _POSIX_SOURCE typedef int pid_t; # undef WEXITSTATUS # undef WIFEXITED -# endif +# undef WIFSTOPPED +# undef WTERMSIG +# endif /* ! _POSIX_SOURCE */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/sendmail/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ # ifdef TCPWRAPPERS # ifndef HASUNSETENV # define HASUNSETENV 1 -# endif +# endif /* ! HASUNSETENV */ # undef NEEDPUTENV -# endif +# endif /* TCPWRAPPERS */ -#endif +#endif /* NeXT */ /* ** Apple Rhapsody ** Contributed by Wilfredo Sanchez <wsanchez@apple.com> +** +** Also used for Apple Darwin support. */ -#ifdef __APPLE__ +#if defined(DARWIN) # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASFLOCK 1 /* has flock(2) syscall */ # define HASUNAME 1 /* has uname(2) syscall */ @@ -698,13 +796,13 @@ typedef int pid_t; # define HASINITGROUPS 1 # define HASSETVBUF 1 # define HASSETREUID 1 -# define USESETEUID 1 /* has useable seteuid(2) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ # define HASLSTAT 1 # define HASSETRLIMIT 1 # define HASWAITPID 1 # define HASSTRERROR 1 /* has strerror(3) */ # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ -# define USESTRERROR 1 /* has strerror(3) */ +# define HASSTRERROR 1 /* has strerror(3) */ # define HASGETDTABLESIZE 1 # define HASGETUSERSHELL 1 # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ @@ -717,7 +815,7 @@ typedef int pid_t; # define SPT_TYPE SPT_PSSTRINGS # define SPT_PADCHAR '\0' /* pad process title with nulls */ # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ -#endif +#endif /* DARWIN */ /* @@ -729,7 +827,7 @@ typedef int pid_t; #if defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) # include <paths.h> # define HASUNSETENV 1 /* has unsetenv(3) call */ -# define USESETEUID 1 /* has useable seteuid(2) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # define HASSTRERROR 1 /* has strerror(3) */ @@ -741,10 +839,10 @@ typedef int pid_t; # define NETLINK 1 /* supports AF_LINK */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR -# endif +# endif /* ! LA_TYPE */ # define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */ # define SPT_TYPE SPT_PSSTRINGS /* use PS_STRINGS pointer */ -#endif +#endif /* defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) */ /* @@ -756,8 +854,9 @@ typedef int pid_t; # include <paths.h> # define HASUNSETENV 1 /* has the unsetenv(3) call */ # define HASSETSID 1 /* has the setsid(2) POSIX syscall */ -# define USESETEUID 1 /* has useable seteuid(2) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASSETLOGIN 1 /* has setlogin(2) */ # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # define HASUNAME 1 /* has uname(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ @@ -769,21 +868,21 @@ typedef int pid_t; # define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR -# endif +# endif /* ! LA_TYPE */ # define GIDSET_T gid_t # define QUAD_T quad_t # if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 /* version 1.1 or later */ # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ -# else +# else /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 */ /* version 1.0 or earlier */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ -# endif +# endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 */ # if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701 /* on 3.x */ # define HASSETUSERCONTEXT 1 /* has setusercontext */ -# endif -#endif +# endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701 */ +#endif /* __bsdi__ */ /* @@ -797,29 +896,26 @@ typedef int pid_t; # include <unix.h> # include <sys/select.h> # undef NGROUPS_MAX -# define HASSETSID 1 /* has the setsid(2) POSIX syscall */ -# define USESETEUID 1 /* has useable seteuid(2) call */ -# define HASFCHMOD 1 /* has fchmod(2) syscall */ -# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ -# define HASSETREUID 1 /* has setreuid(2) call */ +# define HASSETSID 1 /* has the setsid(2) POSIX syscall */ +# define USESETEUID 1 /* has usable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ +# define HASSETREUID 1 /* has setreuid(2) call */ # define HASSTRERROR 1 /* has strerror(3) */ # define HASFLOCK 0 -# undef HASINITGROUPS /* has initgroups(3) call */ -# define NEEDGETOPT 1 /* use sendmail's getopt */ -# define IP_SRCROUTE 1 /* can check IP source routing */ -# define TZ_TYPE TZ_TMNAME /* use tmname variable */ -# define GIDSET_T gid_t -# define LA_TYPE LA_ZERO -# define SFS_TYPE SFS_NONE -# define SPT_TYPE SPT_REUSEARGV -# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# undef HASINITGROUPS /* has initgroups(3) call */ +# define NEEDGETOPT 1 /* use sendmail's getopt */ +# define IP_SRCROUTE 1 /* can check IP source routing */ +# define TZ_TYPE TZ_TMNAME /* use tmname variable */ +# define GIDSET_T gid_t +# define LA_TYPE LA_ZERO +# define SFS_TYPE SFS_NONE +# define SPT_TYPE SPT_REUSEARGV +# define SPT_PADCHAR '\0' /* pad process title with nulls */ # define HASGETUSERSHELL 0 # define E_PSEUDOBASE 512 -# define bcopy(s, d, l) (memmove((d), (s), (l))) -# define bzero(d, l) (memset((d), '\0', (l))) -# define bcmp(s, d, l) (memcmp((s), (d), (l))) # define _FILE_H_INCLUDED -#endif +#endif /* defined(__QNX__) */ /* @@ -833,14 +929,11 @@ typedef int pid_t; #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # include <paths.h> -# if defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) -# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" -# define USE_VENDOR_CF_PATH -# endif # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASSETSID 1 /* has the setsid(2) POSIX syscall */ -# define USESETEUID 1 /* has useable seteuid(2) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASFCHOWN 1 /* fchown(2) */ # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # define HASUNAME 1 /* has uname(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ @@ -853,37 +946,59 @@ typedef int pid_t; # define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # define GIDSET_T gid_t # define QUAD_T unsigned long long +# define SFIO_STDIO_COMPAT 1 /* can use RES_DEBUG */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR -# endif +# endif /* ! LA_TYPE */ # define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */ # if defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ -# endif +# endif /* defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) */ +# if defined(__NetBSD__) && ((__NetBSD_Version__ > 102070000) || (NetBSD1_2 > 8) || defined(NetBSD1_4) || defined(NetBSD1_3)) +# define HASURANDOMDEV 1 /* has /dev/urandom(4) */ +# endif /* defined(__NetBSD__) && ((__NetBSD_Version__ > 102070000) || (NetBSD1_2 > 8) || defined(NetBSD1_4) || defined(NetBSD1_3)) */ # if defined(__FreeBSD__) +# define HASSETLOGIN 1 /* has setlogin(2) */ +# if __FreeBSD_version >= 227001 +# define HASSRANDOMDEV 1 /* has srandomdev(3) */ +# define HASURANDOMDEV 1 /* has /dev/urandom(4) */ +# endif /* __FreeBSD_version >= 227001 */ # undef SPT_TYPE # if __FreeBSD__ >= 2 # include <osreldate.h> # if __FreeBSD_version >= 199512 /* 2.2-current when it appeared */ # include <libutil.h> # define SPT_TYPE SPT_BUILTIN -# endif +# endif /* __FreeBSD_version >= 199512 */ # if __FreeBSD_version >= 222000 /* 2.2.2-release and later */ -# define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ -# endif -# endif +# define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ +# endif /* __FreeBSD_version >= 222000 */ +# if __FreeBSD_version >= 330000 /* 3.3.0-release and later */ +# ifndef HASSTRL +# define HASSTRL 1 /* has strlc{py,at}(3) functions */ +# endif /* HASSTRL */ +# endif /* __FreeBSD_version >= 330000 */ +# define USESYSCTL 1 /* use sysctl(3) for getting ncpus */ +# include <sys/sysctl.h> +# endif /* __FreeBSD__ >= 2 */ # ifndef SPT_TYPE # define SPT_TYPE SPT_REUSEARGV # define SPT_PADCHAR '\0' /* pad process title with nulls */ -# endif -# endif +# endif /* ! SPT_TYPE */ +# endif /* defined(__FreeBSD__) */ # if defined(__OpenBSD__) # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ -# endif -#endif - +# define HASSETLOGIN 1 /* has setlogin(2) */ +# define HASURANDOMDEV 1 /* has /dev/urandom(4) */ +# if OpenBSD < 199912 +# define HASSTRL 0 /* strlcat(3) is broken in 2.5 and earlier */ +# else /* OpenBSD < 199912 */ +# define HASSTRL 1 /* has strlc{py,at}(3) functions */ +# endif /* OpenBSD < 199912 */ +# endif /* defined(__OpenBSD__) */ +#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) */ /* @@ -898,24 +1013,24 @@ typedef int pid_t; # define HASINITGROUPS 1 /* has initgroups(3) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ -# endif +# endif /* ! HASFLOCK */ # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ # define NEEDSTRTOL 1 /* need the strtol() function */ # define setpgid setpgrp # ifndef LA_TYPE # define LA_TYPE LA_FLOAT -# endif +# endif /* ! LA_TYPE */ # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # undef HASSETVBUF /* don't actually have setvbuf(3) */ # undef WEXITSTATUS # undef WIFEXITED # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" -# endif -#endif +# endif /* ! _PATH_SENDMAILPID */ +#endif /* defined(MACH) && defined(i386) && !defined(__GNU__) */ @@ -923,44 +1038,37 @@ typedef int pid_t; ** GNU OS (hurd) ** Largely BSD & posix compatible. ** Port contributed by Miles Bader <miles@gnu.ai.mit.edu>. +** Updated by Mark Kettenis <kettenis@wins.uva.nl>. */ -#ifdef __GNU_HURD__ -# define SIOCGIFCONF_IS_BROKEN 1 -# define IP_SRCROUTE 0 -# define HASFCHMOD 1 -# define HASFLOCK 1 -# define HASUNAME 1 -# define HASUNSETENV 1 -# define HASSETSID 1 -# define HASINITGROUPS 1 -# define HASSETVBUF 1 -# define HASSETREUID 1 -# define USESETEUID 1 -# define HASLSTAT 1 -# define HASSETRLIMIT 1 -# define HASWAITPID 1 -# define HASGETDTABLESIZE 1 -# define HASSTRERROR 1 -/* # define NEEDGETOPT 1 */ -# define HASGETUSERSHELL 1 -# define ERRLIST_PREDEFINED 1 -# define BSD4_4_SOCKADDR 1 +#if defined(__GNU__) && !defined(NeXT) +# include <paths.h> +# define HASFCHMOD 1 /* has fchmod(2) call */ +# define HASFCHOWN 1 /* has fchown(2) call */ +# define HASUNAME 1 /* has uname(2) call */ +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define HASSTRERROR 1 /* has strerror(3) */ # define GIDSET_T gid_t -# define LA_TYPE LA_MACH - -/* GNU uses mach[34], which renames some rpcs from mach2.x. */ -# define host_self mach_host_self +# define SOCKADDR_LEN_T socklen_t +# define SOCKOPT_LEN_T socklen_t +# if (__GLIBC__ == 2 && __GLIBC_MINOR__ > 1) || __GLIBC__ > 2 +# define LA_TYPE LA_SUBR +# else +# define LA_TYPE LA_MACH + /* GNU uses mach[34], which renames some rpcs from mach2.x. */ +# define host_self mach_host_self +# endif # define SFS_TYPE SFS_STATFS # define SPT_TYPE SPT_CHANGEARGV - -/* GNU has no MAXPATHLEN; ideally the code should be changed to not use it. */ +# define ERRLIST_PREDEFINED 1 /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR 1 /* has sa_len */ +# define SIOCGIFCONF_IS_BROKEN 1 /* SIOCGFCONF doesn't work */ +# define HAS_IN_H 1 /* GNU has netinet/in.h. */ +/* GNU has no MAXPATHLEN; ideally the code should be changed to not use it. */ # define MAXPATHLEN 2048 - -/* Define device num frobbing macros. */ -# define major(x) ((x)>>8) -# define minor(x) ((x)&0xFF) -#endif /* GNU */ +#endif /* defined(__GNU__) && !defined(NeXT) */ /* ** 4.3 BSD -- this is for very old systems @@ -978,18 +1086,17 @@ typedef int pid_t; # define setpgid setpgrp # ifndef LA_TYPE # define LA_TYPE LA_FLOAT -# endif +# endif /* ! LA_TYPE */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # undef WEXITSTATUS # undef WIFEXITED typedef short pid_t; -extern int errno; -#endif +#endif /* defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) */ /* @@ -1016,6 +1123,7 @@ extern int errno; # define SIOCGIFNUM_IS_BROKEN 1 /* SIOCGIFNUM returns bogus value */ # define HASSNPRINTF 1 /* has snprintf(3) call */ # define HASFCHMOD 1 /* has fchmod(2) call */ +# define HASFCHOWN 1 /* has fchown(2) call */ # define HASSETRLIMIT 1 /* has setrlimit(2) call */ # define USESETEUID 1 /* has seteuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ @@ -1023,21 +1131,21 @@ extern int errno; # define RLIMIT_NEEDS_SYS_TIME_H 1 # ifndef LA_TYPE # define LA_TYPE LA_DEVSHORT -# endif +# endif /* ! LA_TYPE */ # define _PATH_AVENRUN "/dev/table/avenrun" # ifndef _SCO_unix_4_2 # define _SCO_unix_4_2 -# else +# else /* ! _SCO_unix_4_2 */ # define SOCKADDR_LEN_T size_t /* e.g., arg#3 to accept, getsockname */ # define SOCKOPT_LEN_T size_t /* arg#5 to getsockopt */ -# endif -#endif +# endif /* ! _SCO_unix_4_2 */ +#endif /* _SCO_DS >= 1 */ /* SCO UNIX 3.2v4.2/Open Desktop 3.0 */ #ifdef _SCO_unix_4_2 # define _SCO_unix_ # define HASSETREUID 1 /* has setreuid(2) call */ -#endif +#endif /* _SCO_unix_4_2 */ /* SCO UNIX 3.2v4.0 Open Desktop 2.0 and earlier */ #ifdef _SCO_unix_ @@ -1057,24 +1165,24 @@ extern int errno; # define _PATH_UNIX "/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ /* stuff fixed in later releases */ # ifndef _SCO_unix_4_2 # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ -# endif +# endif /* ! _SCO_unix_4_2 */ # ifndef _SCO_DS # define ftruncate chsize /* use chsize(2) to emulate ftruncate */ # define NEEDFSYNC 1 /* needs the fsync(2) call stub */ # define NETUNIX 0 /* no unix domain socket support */ # define LA_TYPE LA_SHORT -# endif +# endif /* ! _SCO_DS */ -#endif +#endif /* _SCO_unix_ */ /* @@ -1100,12 +1208,11 @@ extern int errno; # define _PATH_UNIX "/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" -# endif - -#endif +# endif /* ! _PATH_SENDMAILPID */ +#endif /* ISC_UNIX */ /* @@ -1139,7 +1246,6 @@ typedef short pid_t; typedef unsigned long mode_t; /* some stuff that should have been in the include files */ -# include <grp.h> extern char *malloc(); extern struct passwd *getpwent(); extern struct passwd *getpwnam(); @@ -1148,7 +1254,7 @@ extern char *getenv(); extern struct group *getgrgid(); extern struct group *getgrnam(); -#endif +#endif /* ALTOS_SYSTEM_V */ /* @@ -1181,7 +1287,7 @@ extern struct group *getgrnam(); # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef S_IREAD # define S_IREAD _S_IREAD # define S_IWRITE _S_IWRITE @@ -1189,26 +1295,26 @@ extern struct group *getgrnam(); # define S_IFMT _S_IFMT # define S_IFCHR _S_IFCHR # define S_IFBLK _S_IFBLK -# endif +# endif /* ! S_IREAD */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TIMEZONE -# endif +# endif /* ! TZ_TYPE */ # ifndef IDENTPROTO # define IDENTPROTO 1 -# endif +# endif /* ! IDENTPROTO */ # ifndef SHARE_V1 # define SHARE_V1 1 /* version 1 of the fair share scheduler */ -# endif +# endif /* ! SHARE_V1 */ # if !defined(__GNUC__ ) # define UID_T int /* GNUC gets it right, ConvexC botches */ # define GID_T int /* GNUC gets it right, ConvexC botches */ -# endif +# endif /* !defined(__GNUC__ ) */ # if SECUREWARE # define FORK fork /* SecureWare wants the real fork! */ -# else +# else /* SECUREWARE */ # define FORK vfork /* the rest of the OS versions don't care */ -# endif -#endif +# endif /* SECUREWARE */ +#endif /* _CONVEX_SOURCE */ /* @@ -1222,7 +1328,7 @@ extern struct group *getgrnam(); # define HASUNSETENV 1 /* has unsetenv(3) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ -# endif +# endif /* ! HASFLOCK */ # define WAITUNION 1 /* use "union wait" as wait argument type */ # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ # define NEEDPUTENV 1 /* need putenv(3) call */ @@ -1235,7 +1341,6 @@ extern struct group *getgrnam(); # define setpgid setpgrp -extern int errno; typedef int pid_t; # define SIGFUNC_DEFINED # define SIGFUNC_RETURN (0) @@ -1248,14 +1353,14 @@ extern void *malloc(); # ifdef RISCOS_4_0 # ifndef ARBPTR_T # define ARBPTR_T char * -# endif +# endif /* ! ARBPTR_T */ # undef HASFLOCK # define HASFLOCK 0 # endif /* RISCOS_4_0 */ # include <sys/time.h> -#endif +#endif /* RISCOS */ /* @@ -1273,12 +1378,16 @@ extern void *malloc(); ** gcc-2.8.1 glibc-2.0.94 linux-2.1.109 ** ** NOTE: Override HASFLOCK as you will but, as of 1.99.6, mixed-style -** file locking is no longer allowed. In particular, make sure +** file locking is no longer allowed. In particular, make sure ** your DBM library and sendmail are both using either flock(2) ** *or* fcntl(2) file locking, but not both. */ #ifdef __linux__ +# include <linux/version.h> +# if !defined(KERNEL_VERSION) /* not defined in 2.0.x kernel series */ +# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +# endif /* KERNEL_VERSION */ # define BSD 1 /* include BSD defines */ # define USESETEUID 0 /* Have it due to POSIX, but doesn't work */ # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ @@ -1286,34 +1395,73 @@ extern void *malloc(); # define HASUNSETENV 1 /* has unsetenv(3) call */ # ifndef HASSNPRINTF # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ -# endif +# endif /* ! HASSNPRINTF */ # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define GIDSET_T gid_t /* from <linux/types.h> */ # define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */ -# define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */ +# ifndef IP_SRCROUTE +# define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */ +# endif /* ! IP_SRCROUTE */ +# ifndef HAS_IN_H +# define HAS_IN_H 1 /* use netinet/in.h */ +# endif /* ! HAS_IN_H */ # define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ # ifndef HASFLOCK -# include <linux/version.h> # if LINUX_VERSION_CODE < 66399 # define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */ -# else +# else /* LINUX_VERSION_CODE < 66399 */ # define HASFLOCK 1 /* flock(2) fixed after 1.3.95 */ -# endif -# endif +# endif /* LINUX_VERSION_CODE < 66399 */ +# endif /* ! HASFLOCK */ # ifndef LA_TYPE # define LA_TYPE LA_PROCSTR -# endif +# endif /* ! LA_TYPE */ # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() impl */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0)) +# ifndef HASURANDOMDEV +# define HASURANDOMDEV 1 /* 2.0 (at least) has linux/drivers/char/random.c */ +# endif /* ! HASURANDOMDEV */ +# endif /* LINUX_VERSION_CODE */ # ifndef TZ_TYPE # define TZ_TYPE TZ_NONE /* no standard for Linux */ -# endif +# endif /* ! TZ_TYPE */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/var/run/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ # include <sys/sysmacros.h> # undef atol /* wounded in <stdlib.h> */ -#endif +# if NETINET6 + /* + ** Linux doesn't have a good way to tell userland what interfaces are + ** IPv6-capable. Therefore, the BIND resolver can not determine if there + ** are IPv6 interfaces to honor AI_ADDRCONFIG. Unfortunately, it assumes + ** that none are present. (Excuse the macro name ADDRCONFIG_IS_BROKEN.) + */ +# define ADDRCONFIG_IS_BROKEN 1 + + /* + ** Indirectly included from glibc's <feature.h>. IPv6 support is native + ** in 2.1 and later, but the APIs appear before the functions. + */ +# if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define GLIBC_VERSION ((__GLIBC__ << 8) + __GLIBC_MINOR__) +# if (GLIBC_VERSION >= 0x201) +# undef IPPROTO_ICMPV6 /* linux #defines, glibc enums */ +# else /* (GLIBC_VERSION >= 0x201) */ +# include <linux/in6.h> /* IPv6 support */ +# endif /* (GLIBC_VERSION >= 0x201) */ +# if (GLIBC_VERSION == 0x201 && !defined(NEEDSGETIPNODE)) + /* Have APIs in <netdb.h>, but no support in glibc */ +# define NEEDSGETIPNODE 1 +# endif /* (GLIBC_VERSION == 0x201 && ! NEEDSGETIPNODE) */ +# undef GLIBC_VERSION +# endif /* defined(__GLIBC__) && defined(__GLIBC_MINOR__) */ +# endif /* NETINET6 */ +# ifndef HASFCHOWN +# define HASFCHOWN 1 /* fchown(2) */ +# endif /* ! HASFCHOWN */ +#endif /* __linux__ */ /* @@ -1331,7 +1479,7 @@ extern void *malloc(); #ifdef DELL_SVR4 /* no changes necessary */ /* see general __svr4__ defines below */ -#endif +#endif /* DELL_SVR4 */ /* @@ -1355,23 +1503,23 @@ extern void *malloc(); # define ERRLIST_PREDEFINED 1 # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # ifndef LA_TYPE # define LA_TYPE LA_INT # define FSHIFT 16 -# endif +# endif /* ! LA_TYPE */ # define LA_AVENRUN "avenrun" # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # define TZ_TYPE TZ_TZNAME # ifndef _PATH_UNIX # define _PATH_UNIX "/unix" /* should be in <paths.h> */ -# endif +# endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # undef WIFEXITED # undef WEXITSTATUS -#endif +#endif /* _AUX_SOURCE */ /* @@ -1393,7 +1541,7 @@ extern struct passwd *getpwent(), *getpwnam(), *getpwuid(); extern struct group *getgrent(), *getgrnam(), *getgrgid(); # undef WIFEXITED # undef WEXITSTATUS -#endif +#endif /* UMAXV */ /* @@ -1411,7 +1559,7 @@ extern struct group *getgrent(), *getgrnam(), *getgrgid(); typedef int pid_t; # undef WIFEXITED # undef WEXITSTATUS -#endif +#endif /* titan */ /* @@ -1427,9 +1575,9 @@ typedef int pid_t; # define BSD4_3 1 /* to get signal() in conf.c */ # define WAITUNION 1 # define LA_TYPE LA_FLOAT -# ifdef _POSIX_VERSION +# ifdef _POSIX_VERSION # undef _POSIX_VERSION /* set in <unistd.h> */ -# endif +# endif /* _POSIX_VERSION */ # undef HASSETVBUF /* don't actually have setvbuf(3) */ # define setpgid setpgrp @@ -1443,15 +1591,15 @@ typedef int pid_t; # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # ifndef _PATH_UNIX # define _PATH_UNIX "/dynix" -# endif +# endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif -#endif +# endif /* ! _PATH_VENDOR_CF */ +#endif /* sequent */ /* @@ -1477,14 +1625,14 @@ typedef int pid_t; # define SPT_TYPE SPT_NONE /* don't use setproctitle */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" -# endif -#endif +# endif /* ! _PATH_SENDMAILPID */ +#endif /* _SEQUENT_ */ /* @@ -1500,7 +1648,7 @@ typedef int pid_t; # define LA_TYPE LA_ZERO # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ # define SFS_BAVAIL f_bfree /* alternate field name */ -#endif +#endif /* UNICOS */ /* @@ -1523,24 +1671,24 @@ typedef int pid_t; # define TZ_TYPE TZ_TZNAME # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" -# endif -# undef S_IFSOCK /* S_IFSOCK and S_IFIFO are the same */ -# undef S_IFIFO +# endif /* ! _PATH_SENDMAILPID */ +# undef S_IFSOCK /* S_IFSOCK and S_IFIFO are the same */ +# undef S_IFIFO # define S_IFIFO 0010000 # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # define RLIMIT_NEEDS_SYS_TIME_H 1 # if defined(NGROUPS_MAX) && !NGROUPS_MAX # undef NGROUPS_MAX -# endif -#endif +# endif /* defined(NGROUPS_MAX) && !NGROUPS_MAX */ +#endif /* apollo */ /* -** System V Rel 5.x (a.k.a Unixware7 w/o BSD-Compatiblity Libs ie. native) +** System V Rel 5.x (a.k.a Unixware7 w/o BSD-Compatibility Libs ie. native) ** ** Contributed by Paul Gampe <paulg@apnic.net> */ @@ -1558,18 +1706,20 @@ typedef int pid_t; # define SOCKOPT_LEN_T size_t # ifndef _PATH_UNIX # define _PATH_UNIX "/stand/unix" -# endif +# endif /* ! _PATH_UNIX */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ -# define SYSLOG_BUFSIZE 1024 /* unsure */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 /* unsure */ +# endif /* SYSLOG_BUFSIZE */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" -# endif -#endif +# endif /* ! _PATH_SENDMAILPID */ +#endif /* __svr5__ */ -/* ###################################################################### */ +/* ###################################################################### */ /* ** UnixWare 2.x @@ -1579,7 +1729,7 @@ typedef int pid_t; # define UNIXWARE 1 # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # undef offsetof /* avoid stddefs.h, sys/sysmacros.h conflict */ -#endif +#endif /* UNIXWARE2 */ /* @@ -1604,15 +1754,15 @@ typedef int pid_t; # undef WEXITSTATUS # ifndef _PATH_UNIX # define _PATH_UNIX "/unix" -# endif +# endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ # define SYSLOG_BUFSIZE 128 -#endif +#endif /* UNIXWARE */ /* @@ -1625,13 +1775,13 @@ typedef int pid_t; # define SYSTEM5 1 /* looks like System V */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ -# endif +# endif /* ! HASGETUSERSHELL */ # define DEV_BSIZE 512 /* device block size not defined */ # define GIDSET_T gid_t # undef LOG /* syslog not available */ # define NEEDFSYNC 1 /* no fsync in system library */ # define GETSHORT _getshort -#endif +#endif /* CLIX */ /* @@ -1646,7 +1796,7 @@ typedef int pid_t; # define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ # define SYSLOG_BUFSIZE 1024 # define SPT_TYPE SPT_NONE -#endif +#endif /* NCR_MP_RAS2 */ /* @@ -1657,10 +1807,19 @@ typedef int pid_t; #ifdef NCR_MP_RAS3 # define __svr4__ +# define HASFCHOWN 1 /* has fchown(2) call */ # define SIOCGIFNUM_IS_BROKEN 1 /* SIOCGIFNUM has non-std interface */ +# define SO_REUSEADDR_IS_BROKEN 1 /* doesn't work if accept() fails */ # define SYSLOG_BUFSIZE 1024 -# define SPT_TYPE SPT_NONE -#endif +# define SPT_TYPE SPT_NONE +# ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE +# define _XOPEN_SOURCE_EXTENDED 1 +# include <sys/resource.h> +# undef _XOPEN_SOURCE +# undef _XOPEN_SOURCE_EXTENDED +# endif /* ! _XOPEN_SOURCE */ +#endif /* NCR_MP_RAS3 */ /* @@ -1671,38 +1830,46 @@ typedef int pid_t; #ifdef NonStop_UX_BXX # define __svr4__ -#endif +#endif /* NonStop_UX_BXX */ /* -** Hitachi 3050R & 3050RX Workstations running HI-UX/WE2. +** Hitachi 3050R/3050RX and 3500 Workstations running HI-UX/WE2. ** -** Tested for 1.04 and 1.03 +** Tested for 1.04, 1.03 ** From Akihiro Hashimoto ("Hash") <hash@dominic.ipc.chiba-u.ac.jp>. +** +** Tested for 4.02, 6.10 and 7.10 +** From Motonori NAKAMURA <motonori@media.kyoto-u.ac.jp>. */ -#ifdef __H3050R +#if !defined(__hpux) && (defined(_H3050R) || defined(_HIUX_SOURCE)) # define SYSTEM5 1 /* include all the System V defines */ # define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ # define setreuid(r, e) setresuid(r, e, -1) # define LA_TYPE LA_FLOAT +# define SPT_TYPE SPT_PSTAT # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ -# define HASSETVBUF /* HI-UX has no setlinebuf */ +# ifndef HASSETVBUF +# define HASSETVBUF /* HI-UX has no setlinebuf */ +# endif /* ! HASSETVBUF */ # ifndef GIDSET_T # define GIDSET_T gid_t -# endif +# endif /* ! GIDSET_T */ # ifndef _PATH_UNIX # define _PATH_UNIX "/HI-UX" -# endif +# endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ -# endif +# endif /* ! HASGETUSERSHELL */ +# define FDSET_CAST (int *) /* cast for fd_set parameters to select */ /* ** avoid m_flags conflict between Berkeley DB 1.85 db.h & sys/sysmacros.h @@ -1712,11 +1879,11 @@ typedef int pid_t; # ifdef __STDC__ extern int syslog(int, char *, ...); -#else +# else /* __STDC__ */ extern int syslog(); -# endif +# endif /* __STDC__ */ -#endif +#endif /* !defined(__hpux) && (defined(_H3050R) || defined(_HIUX_SOURCE)) */ /* @@ -1736,7 +1903,7 @@ extern int syslog(); # define HASSETVBUF 1 /* has setvbuf(3) function */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* does not have getusershell(3) function */ -# endif +# endif /* ! HASGETUSERSHELL */ # define GIDSET_T gid_t /* type of 2nd arg to getgroups(2) isn't int */ # define LA_TYPE LA_ZERO /* doesn't have load average */ # define SFS_TYPE SFS_4ARGS /* use 4-arg statfs() */ @@ -1744,8 +1911,8 @@ extern int syslog(); # define _PATH_UNIX "/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif -#endif +# endif /* ! _PATH_VENDOR_CF */ +#endif /* _UTS */ /* ** Cray Computer Corporation's CSOS @@ -1763,7 +1930,7 @@ extern int syslog(); # define SFS_BAVAIL f_bfree /* alternate field name */ # define _POSIX_CHOWN_RESTRICTED -1 extern struct group *getgrent(), *getgrnam(), *getgrgid(); -#endif +#endif /* _CRAYCOM */ /* @@ -1777,7 +1944,7 @@ extern struct group *getgrent(), *getgrnam(), *getgrgid(); /* NEWS-OS 4.2.1R */ # ifndef BSD # define BSD /* has BSD routines */ -# endif +# endif /* ! BSD */ # define HASUNSETENV 1 /* has unsetenv(2) call */ # undef HASSETVBUF /* don't actually have setvbuf(3) */ # define WAITUNION 1 /* use "union wait" as wait argument type */ @@ -1785,7 +1952,7 @@ extern struct group *getgrent(), *getgrnam(), *getgrgid(); # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ -# endif +# endif /* ! HASFLOCK */ # define setpgid setpgrp # undef WIFEXITED # undef WEXITSTATUS @@ -1796,33 +1963,33 @@ typedef int (*sigfunc_t)(); # define SIGFUNC_RETURN (0) # define SIGFUNC_DECL int -# else +# else /* ! __svr4 */ /* NEWS-OS 6.0.3 with /bin/cc */ # ifndef __svr4__ -# define __svr4__ /* use all System V Releae 4 defines below */ -# endif +# define __svr4__ /* use all System V Release 4 defines below */ +# endif /* ! __svr4__ */ # define HASSETSID 1 /* has Posix setsid(2) call */ # define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */ # define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */ # ifndef SPT_TYPE # define SPT_TYPE SPT_SYSMIPS /* use sysmips() (OS 6.0.2 or later) */ -# endif +# endif /* ! SPT_TYPE */ # define GIDSET_T gid_t # undef WIFEXITED # undef WEXITSTATUS # ifndef SYSLOG_BUFSIZE -# define SYSLOG_BUFSIZE 1024 -# endif +# define SYSLOG_BUFSIZE 256 +# endif /* ! SYSLOG_BUFSIZE */ # define _PATH_UNIX "/stand/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ -# endif -#endif +# endif /* ! __svr4 */ +#endif /* sony_news */ /* @@ -1834,7 +2001,7 @@ typedef int (*sigfunc_t)(); #ifdef luna # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif +# endif /* ! IDENTPROTO */ # define HASUNSETENV 1 /* has unsetenv(2) call */ # define NEEDPUTENV 1 /* need putenv(3) call */ # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ @@ -1845,15 +2012,15 @@ typedef int (*sigfunc_t)(); # define NEEDVPRINTF 1 /* need a replacement for vprintf(3) */ # define LA_TYPE LA_INT # define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ -# endif +# endif /* uniosb */ # ifdef luna2 # define LA_TYPE LA_SUBR # define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ -# endif +# endif /* luna2 */ # ifdef luna88k # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # define LA_TYPE LA_INT -# endif +# endif /* luna88k */ # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # define setpgid setpgrp # undef WIFEXITED @@ -1864,13 +2031,12 @@ typedef int (*sigfunc_t)(); # define SIGFUNC_RETURN (0) # define SIGFUNC_DECL int extern char *getenv(); -extern int errno; # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" -# endif -#endif +# endif /* ! _PATH_VENDOR_CF */ +#endif /* luna */ + - /* ** NEC EWS-UX/V 4.2 (with /usr/ucb/cc) ** @@ -1879,8 +2045,8 @@ extern int errno; #if defined(nec_ews_svr4) || defined(_nec_ews_svr4) # ifndef __svr4__ -# define __svr4__ /* use all System V Releae 4 defines below */ -# endif +# define __svr4__ /* use all System V Release 4 defines below */ +# endif /* ! __svr4__ */ # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # define HASSETSID 1 /* has Posix setsid(2) call */ # define LA_TYPE LA_READKSYM /* use MIOC_READSYM ioctl */ @@ -1889,10 +2055,16 @@ extern int errno; # undef WIFEXITED # undef WEXITSTATUS # define NAMELISTMASK 0x7fffffff /* mask for nlist() values */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ -# endif -#endif +# endif /* ! SYSLOG_BUFSIZE */ +#endif /* defined(nec_ews_svr4) || defined(_nec_ews_svr4) */ /* @@ -1900,7 +2072,7 @@ extern int errno; ** ** From Diego R. Lopez <drlopez@cica.es>. ** Additional changes from Fumio Moriya and Toshiaki Nomura of the -** Fujitsu Fresoftware gruop <dsfrsoft@oai6.yk.fujitsu.co.jp>. +** Fujitsu Fresoftware group <dsfrsoft@oai6.yk.fujitsu.co.jp>. */ #ifdef __uxp__ @@ -1912,17 +2084,17 @@ extern int errno; # define HASFLOCK 0 # if UXPDS == 10 # define HASSNPRINTF 0 /* no snprintf(3) or vsnprintf(3) */ -# else +# else /* UXPDS == 10 */ # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ -# endif +# endif /* UXPDS == 10 */ # define _PATH_UNIX "/stand/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" -# endif -#endif +# endif /* ! _PATH_SENDMAILPID */ +#endif /* __uxp__ */ /* ** Pyramid DC/OSx @@ -1934,8 +2106,8 @@ extern int errno; # define GIDSET_T gid_t # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif -#endif +# endif /* ! IDENTPROTO */ +#endif /* DCOSx */ /* ** Concurrent Computer Corporation Maxion @@ -1959,7 +2131,7 @@ extern int errno; # define SFS_BAVAIL f_bavail # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 256 /* Use 256 bytes */ -# endif +# endif /* ! SYSLOG_BUFSIZE */ # undef WUNTRACED # undef WIFEXITED @@ -1969,7 +2141,7 @@ extern int errno; # undef WTERMSIG # undef WSTOPSIG -#endif +#endif /* __MAXION__ */ /* ** Harris Nighthawk PowerUX (nh6000 box) @@ -1980,29 +2152,30 @@ extern int errno; #ifdef _PowerUX # ifndef __svr4__ # define __svr4__ -# endif +# endif /* ! __svr4__ */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ # define SYSLOG_BUFSIZE 1024 # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # define LA_TYPE LA_ZERO typedef struct msgb mblk_t; # undef offsetof /* avoid stddefs.h and sys/sysmacros.h conflict */ -#endif +#endif /* _PowerUX */ /* -** Siemens Nixdorf Informationssysteme AG SINIX +** Siemens Nixdorf Informationssysteme AG SINIX ** ** Contributed by Gerald Rinske <Gerald.Rinske@mch.sni.de> ** of Siemens Business Services VAS. */ #ifdef sinix +# define HASRANDOM 0 /* has random(3) */ # define SYSLOG_BUFSIZE 1024 -#endif +#endif /* sinix */ /* ** CRAY T3E @@ -2012,7 +2185,31 @@ typedef struct msgb mblk_t; */ #ifdef _CRAY # define GET_IPOPT_DST(dst) *(struct in_addr *)&(dst) -#endif +#endif /* _CRAY */ + +/* +** Motorola 922, MC88110, UNIX SYSTEM V/88 Release 4.0 Version 4.3 +** +** Contributed by Sergey Rusanov <rsm@utfoms.udmnet.ru> +*/ + +#ifdef MOTO +# define HASFCHMOD 1 +# define HASSETRLIMIT 0 +# define HASSETSID 1 +# define HASSETREUID 1 +# define HASULIMIT 1 +# define HASWAITPID 1 +# define HASGETDTABLESIZE 1 +# define HASGETUSERSHELL 1 +# define IP_SRCROUTE 0 +# define IDENTPROTO 0 +# define RES_DNSRCH_VARIABLE _res_dnsrch +# define _PATH_UNIX "/unix" +# define _PATH_VENDOR_CF "/etc/sendmail.cf" +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +#endif /* MOTO */ + /********************************************************************** ** End of Per-Operating System defines @@ -2028,52 +2225,52 @@ typedef struct msgb mblk_t; # define HASINITGROUPS 1 /* has initgroups(3) call */ # ifndef IP_SRCROUTE # define IP_SRCROUTE 1 /* can check IP source routing */ -# endif +# endif /* ! IP_SRCROUTE */ # ifndef HASSETRLIMIT # define HASSETRLIMIT 1 /* has setrlimit(2) call */ -# endif +# endif /* ! HASSETRLIMIT */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ -# endif +# endif /* ! HASFLOCK */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone variable */ -# endif -#endif +# endif /* ! TZ_TYPE */ +#endif /* BSD */ /* general System V Release 4 defines */ #ifdef __svr4__ # define SYSTEM5 1 -# define USESETEUID 1 /* has useable seteuid(2) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define BSD_COMP 1 /* get BSD ioctl calls */ # ifndef HASSETRLIMIT # define HASSETRLIMIT 1 /* has setrlimit(2) call */ -# endif +# endif /* ! HASSETRLIMIT */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ -# endif +# endif /* ! HASGETUSERSHELL */ # ifndef HASFCHMOD # define HASFCHMOD 1 /* most (all?) SVr4s seem to have fchmod(2) */ -# endif +# endif /* ! HASFCHMOD */ # ifndef _PATH_UNIX # define _PATH_UNIX "/unix" -# endif +# endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" -# endif +# endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" -# endif +# endif /* ! _PATH_SENDMAILPID */ # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 128 -# endif +# endif /* ! SYSLOG_BUFSIZE */ # ifndef SFS_TYPE # define SFS_TYPE SFS_STATVFS -# endif +# endif /* ! SFS_TYPE */ # define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ -#endif +#endif /* __svr4__ */ /* general System V defines */ #ifdef SYSTEM5 @@ -2083,38 +2280,30 @@ typedef struct msgb mblk_t; # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ # ifndef HASULIMIT # define HASULIMIT 1 /* has the ulimit(2) syscall */ -# endif +# endif /* ! HASULIMIT */ # ifndef LA_TYPE # ifdef MIOC_READKSYM # define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */ -# else +# else /* MIOC_READKSYM */ # define LA_TYPE LA_INT /* assume integer load average */ -# endif -# endif +# endif /* MIOC_READKSYM */ +# endif /* ! LA_TYPE */ # ifndef SFS_TYPE # define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */ -# endif +# endif /* ! SFS_TYPE */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ -# endif -# define bcopy(s, d, l) (memmove((d), (s), (l))) -# define bzero(d, l) (memset((d), '\0', (l))) -# define bcmp(s, d, l) (memcmp((s), (d), (l))) -#endif +# endif /* ! TZ_TYPE */ +#endif /* SYSTEM5 */ /* general POSIX defines */ #ifdef _POSIX_VERSION # define HASSETSID 1 /* has Posix setsid(2) call */ # define HASWAITPID 1 /* has Posix waitpid(2) call */ # if _POSIX_VERSION >= 199500 && !defined(USESETEUID) -# define USESETEUID 1 /* has useable seteuid(2) call */ -# endif -# ifndef bcopy -# define bcopy(s, d, l) (memmove((d), (s), (l))) -# define bzero(d, l) (memset((d), '\0', (l))) -# define bcmp(s, d, l) (memcmp((s), (d), (l))) -# endif -#endif +# define USESETEUID 1 /* has usable seteuid(2) call */ +# endif /* _POSIX_VERSION >= 199500 && !defined(USESETEUID) */ +#endif /* _POSIX_VERSION */ /* ** Tweaking for systems that (for example) claim to be BSD or POSIX ** but don't have all the standard BSD or POSIX routines (boo hiss). @@ -2122,26 +2311,15 @@ typedef struct msgb mblk_t; #ifdef titan # undef HASINITGROUPS /* doesn't have initgroups(3) call */ -#endif +#endif /* titan */ #ifdef _CRAYCOM # undef HASSETSID /* despite POSIX claim, doesn't have setsid */ -#endif - -#ifdef ISC_UNIX -# undef bcopy /* despite SystemV claim, uses BSD bcopy */ -#endif - -#ifdef ALTOS_SYSTEM_V -# undef bcopy /* despite SystemV claim, uses BSD bcopy */ -# undef bzero /* despite SystemV claim, uses BSD bzero */ -# undef bcmp /* despite SystemV claim, uses BSD bcmp */ -#endif - -#if defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4) -# undef bcopy /* SunOS 4 doesn't have memmove() */ -#endif +#endif /* _CRAYCOM */ +#ifdef MOTO +# undef USESETEUID +#endif /* MOTO */ /* ** Due to a "feature" in some operating systems such as Ultrix 4.3 and @@ -2156,55 +2334,77 @@ typedef struct msgb mblk_t; #ifndef IDENTPROTO # define IDENTPROTO 1 /* use IDENT proto (RFC 1413) */ -#endif +#endif /* ! IDENTPROTO */ #ifndef IP_SRCROUTE # define IP_SRCROUTE 1 /* Detect IP source routing */ -#endif +#endif /* ! IP_SRCROUTE */ #ifndef HASGETUSERSHELL # define HASGETUSERSHELL 1 /* libc has getusershell(3) call */ -#endif +#endif /* ! HASGETUSERSHELL */ #ifndef NETUNIX # define NETUNIX 1 /* include unix domain support */ -#endif +#endif /* ! NETUNIX */ + +#ifndef HASRANDOM +# define HASRANDOM 1 /* has random(3) support */ +#endif /* ! HASRANDOM */ #ifndef HASFLOCK # define HASFLOCK 0 /* assume no flock(2) support */ -#endif +#endif /* ! HASFLOCK */ #ifndef HASSETREUID # define HASSETREUID 0 /* assume no setreuid(2) call */ -#endif +#endif /* ! HASSETREUID */ #ifndef HASFCHMOD # define HASFCHMOD 0 /* assume no fchmod(2) syscall */ -#endif +#endif /* ! HASFCHMOD */ #ifndef USESETEUID # define USESETEUID 0 /* assume no seteuid(2) call or no saved ids */ -#endif +#endif /* ! USESETEUID */ #ifndef HASSETRLIMIT # define HASSETRLIMIT 0 /* assume no setrlimit(2) support */ -#endif +#endif /* ! HASSETRLIMIT */ #ifndef HASULIMIT # define HASULIMIT 0 /* assume no ulimit(2) support */ -#endif +#endif /* ! HASULIMIT */ #ifndef SECUREWARE # define SECUREWARE 0 /* assume no SecureWare C2 auditing hooks */ -#endif +#endif /* ! SECUREWARE */ #ifndef USE_SIGLONGJMP # define USE_SIGLONGJMP 0 /* assume setjmp handles signals properly */ -#endif +#endif /* ! USE_SIGLONGJMP */ #ifndef FDSET_CAST # define FDSET_CAST /* (empty) cast for fd_set arg to select */ -#endif +#endif /* ! FDSET_CAST */ + +/* +** Pick a mailer setuid method for changing the current uid +*/ + +#define USE_SETEUID 0 +#define USE_SETREUID 1 +#define USE_SETUID 2 + +#if USESETEUID +# define MAILER_SETUID_METHOD USE_SETEUID +#else /* USESETEUID */ +# if HASSETREUID +# define MAILER_SETUID_METHOD USE_SETREUID +# else /* HASSETREUID */ +# define MAILER_SETUID_METHOD USE_SETUID +# endif /* HASSETREUID */ +#endif /* USESETEUID */ /* ** If no type for argument two of getgroups call is defined, assume @@ -2214,39 +2414,39 @@ typedef struct msgb mblk_t; #ifndef GIDSET_T # define GIDSET_T int -#endif +#endif /* ! GIDSET_T */ #ifndef UID_T # define UID_T uid_t -#endif +#endif /* ! UID_T */ #ifndef GID_T # define GID_T gid_t -#endif +#endif /* ! GID_T */ #ifndef SIZE_T # define SIZE_T size_t -#endif +#endif /* ! SIZE_T */ #ifndef MODE_T # define MODE_T mode_t -#endif +#endif /* ! MODE_T */ #ifndef ARGV_T # define ARGV_T char ** -#endif +#endif /* ! ARGV_T */ #ifndef SOCKADDR_LEN_T # define SOCKADDR_LEN_T int -#endif +#endif /* ! SOCKADDR_LEN_T */ #ifndef SOCKOPT_LEN_T # define SOCKOPT_LEN_T int -#endif +#endif /* ! SOCKOPT_LEN_T */ #ifndef QUAD_T # define QUAD_T unsigned long -#endif +#endif /* ! QUAD_T */ /********************************************************************** ** Remaining definitions should never have to be changed. They are ** primarily to provide back compatibility for older systems -- for @@ -2256,46 +2456,60 @@ typedef struct msgb mblk_t; /* System 5 compatibility */ #ifndef S_ISREG # define S_ISREG(foo) ((foo & S_IFMT) == S_IFREG) -#endif +#endif /* ! S_ISREG */ #ifndef S_ISDIR # define S_ISDIR(foo) ((foo & S_IFMT) == S_IFDIR) -#endif +#endif /* ! S_ISDIR */ #if !defined(S_ISLNK) && defined(S_IFLNK) # define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK) -#endif +#endif /* !defined(S_ISLNK) && defined(S_IFLNK) */ +#if !defined(S_ISFIFO) +# if defined(S_IFIFO) +# define S_ISFIFO(foo) ((foo & S_IFMT) == S_IFIFO) +# else /* defined(S_IFIFO) */ +# define S_ISFIFO(foo) FALSE +# endif /* defined(S_IFIFO) */ +#endif /* !defined(S_ISFIFO) */ #ifndef S_IRUSR # define S_IRUSR 0400 -#endif +#endif /* ! S_IRUSR */ #ifndef S_IWUSR # define S_IWUSR 0200 -#endif +#endif /* ! S_IWUSR */ #ifndef S_IRGRP # define S_IRGRP 0040 -#endif +#endif /* ! S_IRGRP */ #ifndef S_IWGRP # define S_IWGRP 0020 -#endif +#endif /* ! S_IWGRP */ #ifndef S_IROTH # define S_IROTH 0004 -#endif +#endif /* ! S_IROTH */ #ifndef S_IWOTH # define S_IWOTH 0002 -#endif +#endif /* ! S_IWOTH */ + +/* close-on-exec flag */ +#ifndef FD_CLOEXEC +# define FD_CLOEXEC 1 +#endif /* ! FD_CLOEXEC */ /* ** Older systems don't have this error code -- it should be in ** /usr/include/sysexits.h. */ -# ifndef EX_CONFIG +#ifndef EX_CONFIG # define EX_CONFIG 78 /* configuration error */ -# endif +#endif /* ! EX_CONFIG */ -/* pseudo-code used in server SMTP */ -# define EX_QUIT 22 /* drop out of server immediately */ +/* pseudo-codes */ +#define EX_QUIT 22 /* drop out of server immediately */ +#define EX_RESTART 23 /* restart sendmail daemon */ +#define EX_SHUTDOWN 24 /* shutdown sendmail daemon */ /* pseudo-code used for mci_setstat */ -# define EX_NOTSTICKY -5 /* don't save persistent status */ +#define EX_NOTSTICKY -5 /* don't save persistent status */ /* @@ -2305,67 +2519,76 @@ typedef struct msgb mblk_t; #define ST_MODE_NOFILE 0171147 /* unlikely to occur */ -/* -** These are used in a few cases where we need some special -** error codes, but where the system doesn't provide something -** reasonable. They are printed in errstring. -*/ - -#ifndef E_PSEUDOBASE -# define E_PSEUDOBASE 256 -#endif - -#define E_SM_OPENTIMEOUT (E_PSEUDOBASE + 0) /* Timeout on file open */ -#define E_SM_NOSLINK (E_PSEUDOBASE + 1) /* Symbolic links not allowed */ -#define E_SM_NOHLINK (E_PSEUDOBASE + 2) /* Hard links not allowed */ -#define E_SM_REGONLY (E_PSEUDOBASE + 3) /* Regular files only */ -#define E_SM_ISEXEC (E_PSEUDOBASE + 4) /* Executable files not allowed */ -#define E_SM_WWDIR (E_PSEUDOBASE + 5) /* World writable directory */ -#define E_SM_GWDIR (E_PSEUDOBASE + 6) /* Group writable directory */ -#define E_SM_FILECHANGE (E_PSEUDOBASE + 7) /* File changed after open */ -#define E_SM_WWFILE (E_PSEUDOBASE + 8) /* World writable file */ -#define E_SM_GWFILE (E_PSEUDOBASE + 9) /* Group writable file */ -#define E_DNSBASE (E_PSEUDOBASE + 20) /* base for DNS h_errno */ - /* type of arbitrary pointer */ #ifndef ARBPTR_T # define ARBPTR_T void * -#endif +#endif /* ! ARBPTR_T */ #ifndef __P -# include "cdefs.h" -#endif +# include "sendmail/cdefs.h" +#endif /* ! __P */ #if HESIOD && !defined(NAMED_BIND) # define NAMED_BIND 1 /* not one without the other */ -#endif +#endif /* HESIOD && !defined(NAMED_BIND) */ -#if NAMED_BIND && !defined(__ksr__) && !defined(h_errno) +# if NAMED_BIND && !defined( __ksr__ ) && !defined( h_errno ) extern int h_errno; -#endif +# endif /* NAMED_BIND && !defined( __ksr__ ) && !defined( h_errno ) */ + +#ifdef LDAPMAP +# include <sys/time.h> +# include <lber.h> +# include <ldap.h> + +/* Some LDAP constants */ +# define LDAPMAP_FALSE 0 +# define LDAPMAP_TRUE 1 + +/* +** ldap_init(3) is broken in Umich 3.x and OpenLDAP 1.0/1.1. +** Use the lack of LDAP_OPT_SIZELIMIT to detect old API implementations +** and assume (falsely) that all old API implementations are broken. +** (OpenLDAP 1.2 and later have a working ldap_init(), add -DUSE_LDAP_INIT) +*/ + +# if defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_INIT) +# define USE_LDAP_INIT 1 +# endif /* defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_INIT) */ + +/* +** LDAP_OPT_SIZELIMIT is not defined under Umich 3.x nor OpenLDAP 1.x, +** hence ldap_set_option() must not exist. +*/ + +# if defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_SET_OPTION) +# define USE_LDAP_SET_OPTION 1 +# endif /* defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_SET_OPTION) */ + +#endif /* LDAPMAP */ /* ** Do some required dependencies */ -#if NETINET || NETISO +#if NETINET || NETINET6 || NETISO # ifndef SMTP # define SMTP 1 /* enable user and server SMTP */ -# endif +# endif /* ! SMTP */ # ifndef QUEUE # define QUEUE 1 /* enable queueing */ -# endif +# endif /* ! QUEUE */ # ifndef DAEMON # define DAEMON 1 /* include the daemon (requires IPC & SMTP) */ -# endif -#endif +# endif /* ! DAEMON */ +#endif /* NETINET || NETINET6 || NETISO */ /* ** Arrange to use either varargs or stdargs */ -# ifdef __STDC__ +#ifdef __STDC__ # include <stdarg.h> @@ -2373,7 +2596,7 @@ extern int h_errno; # define VA_START(f) va_start(ap, f) # define VA_END va_end(ap) -# else +#else /* __STDC__ */ # include <varargs.h> @@ -2381,91 +2604,100 @@ extern int h_errno; # define VA_START(f) va_start(ap) # define VA_END va_end(ap) -# endif +#endif /* __STDC__ */ -#ifdef HASUNAME +#if HASUNAME # include <sys/utsname.h> # ifdef newstr # undef newstr -# endif -#else /* ! HASUNAME */ +# endif /* newstr */ +#else /* HASUNAME */ # define NODE_LENGTH 32 struct utsname { - char nodename[NODE_LENGTH+1]; + char nodename[NODE_LENGTH + 1]; }; #endif /* HASUNAME */ #if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V) # define MAXHOSTNAMELEN 256 -#endif +#endif /* !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V) */ #if !defined(SIGCHLD) && defined(SIGCLD) # define SIGCHLD SIGCLD -#endif +#endif /* !defined(SIGCHLD) && defined(SIGCLD) */ #ifndef STDIN_FILENO # define STDIN_FILENO 0 -#endif +#endif /* ! STDIN_FILENO */ #ifndef STDOUT_FILENO # define STDOUT_FILENO 1 -#endif +#endif /* ! STDOUT_FILENO */ #ifndef STDERR_FILENO # define STDERR_FILENO 2 -#endif +#endif /* ! STDERR_FILENO */ #ifndef LOCK_SH # define LOCK_SH 0x01 /* shared lock */ # define LOCK_EX 0x02 /* exclusive lock */ # define LOCK_NB 0x04 /* non-blocking lock */ # define LOCK_UN 0x08 /* unlock */ -#endif +#endif /* ! LOCK_SH */ #ifndef S_IXOTH # define S_IXOTH (S_IEXEC >> 6) -#endif +#endif /* ! S_IXOTH */ #ifndef S_IXGRP # define S_IXGRP (S_IEXEC >> 3) -#endif +#endif /* ! S_IXGRP */ #ifndef S_IXUSR # define S_IXUSR (S_IEXEC) -#endif +#endif /* ! S_IXUSR */ #ifndef SEEK_SET # define SEEK_SET 0 # define SEEK_CUR 1 # define SEEK_END 2 -#endif +#endif /* ! SEEK_SET */ #ifndef SIG_ERR # define SIG_ERR ((void (*)()) -1) -#endif +#endif /* ! SIG_ERR */ #ifndef WEXITSTATUS # define WEXITSTATUS(st) (((st) >> 8) & 0377) -#endif +#endif /* ! WEXITSTATUS */ #ifndef WIFEXITED # define WIFEXITED(st) (((st) & 0377) == 0) -#endif +#endif /* ! WIFEXITED */ +#ifndef WIFSTOPPED +# define WIFSTOPPED(st) (((st) & 0100) == 0) +#endif /* ! WIFSTOPPED */ +#ifndef WCOREDUMP +# define WCOREDUMP(st) (((st) & 0200) != 0) +#endif /* ! WCOREDUMP */ +#ifndef WTERMSIG +# define WTERMSIG(st) (((st) & 0177)) +#endif /* ! WTERMSIG */ #ifndef SIGFUNC_DEFINED typedef void (*sigfunc_t) __P((int)); -#endif +#endif /* ! SIGFUNC_DEFINED */ #ifndef SIGFUNC_RETURN # define SIGFUNC_RETURN -#endif +#endif /* ! SIGFUNC_RETURN */ #ifndef SIGFUNC_DECL # define SIGFUNC_DECL void -#endif +#endif /* ! SIGFUNC_DECL */ /* size of syslog buffer */ #ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 -#endif +#endif /* ! SYSLOG_BUFSIZE */ /* ** Size of prescan buffer. @@ -2473,12 +2705,23 @@ typedef void (*sigfunc_t) __P((int)); ** not be changed; there are some hard-to-define dependencies. */ -# define PSBUFSIZE (MAXNAME + MAXATOM) /* size of prescan buffer */ +#define PSBUFSIZE (MAXNAME + MAXATOM) /* size of prescan buffer */ /* fork routine -- set above using #ifdef _osname_ or in Makefile */ -# ifndef FORK +#ifndef FORK # define FORK fork /* function to call to fork mailer */ -# endif +#endif /* ! FORK */ + + +/* random routine -- set above using #ifdef _osname_ or in Makefile */ +#if HASRANDOM +# define get_random() random() +#else /* HASRANDOM */ +# define get_random() ((long) rand()) +# ifndef RANDOMSHIFT +# define RANDOMSHIFT 8 +# endif /* RANDOMSHIFT */ +#endif /* HASRANDOM */ /* ** Default to using scanf in readcf. @@ -2486,7 +2729,14 @@ typedef void (*sigfunc_t) __P((int)); #ifndef SCANF # define SCANF 1 -#endif +#endif /* ! SCANF */ + +#if _FFR_MILTER +/* 32 bit type */ +# ifndef SM_INT32 +# define SM_INT32 int32_t +# endif /* SM_INT32 */ +#endif /* _FFR_MILTER */ /* ** SVr4 and similar systems use different routines for setjmp/longjmp @@ -2496,21 +2746,35 @@ typedef void (*sigfunc_t) __P((int)); #if USE_SIGLONGJMP # ifdef jmp_buf # undef jmp_buf -# endif +# endif /* jmp_buf */ # define jmp_buf sigjmp_buf # ifdef setjmp # undef setjmp -# endif +# endif /* setjmp */ # define setjmp(env) sigsetjmp(env, 1) # ifdef longjmp # undef longjmp -# endif +# endif /* longjmp */ # define longjmp(env, val) siglongjmp(env, val) -#endif +#endif /* USE_SIGLONGJMP */ #if !defined(NGROUPS_MAX) && defined(NGROUPS) # define NGROUPS_MAX NGROUPS /* POSIX naming convention */ -#endif +#endif /* !defined(NGROUPS_MAX) && defined(NGROUPS) */ + +/* +** Some snprintf() implementations are rumored not to NUL terminate. +*/ +#if SNPRINTF_IS_BROKEN +# ifdef snprintf +# undef snprintf +# endif /* snprintf */ +# define snprintf sm_snprintf +# ifdef vsnprintf +# undef vsnprintf +# endif /* vsnprintf */ +# define vsnprintf sm_vsnprintf +#endif /* SNPRINTF_IS_BROKEN */ /* ** If we don't have a system syslog, simulate it. @@ -2525,4 +2789,14 @@ typedef void (*sigfunc_t) __P((int)); # define LOG_NOTICE 5 /* normal but significant condition */ # define LOG_INFO 6 /* informational */ # define LOG_DEBUG 7 /* debug-level messages */ -#endif +#endif /* !LOG */ + +#if SFIO && defined(ERRLIST_PREDEFINED) +# undef ERRLIST_PREDEFINED +#endif /* SFIO && defined(ERRLIST_PREDEFINED) */ + +#ifndef SFIO_STDIO_COMPAT +# define SFIO_STDIO_COMPAT 0 +#endif /* ! SFIO_STDIO_COMPAT */ + +#endif /* CONF_H */ diff --git a/contrib/sendmail/src/err.c b/contrib/sendmail/src/err.c index 38a3576..8b65cf8 100644 --- a/contrib/sendmail/src/err.c +++ b/contrib/sendmail/src/err.c @@ -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,117 @@ 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; + /* 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); +} +/* +** 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); - fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap); + 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]) { @@ -205,7 +320,7 @@ usrerr(fmt, va_alist) if (CurEnv->e_message != NULL) break; - /* fall through.... */ + /* FALLTHROUGH */ case '5': case '6': @@ -216,12 +331,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 +344,7 @@ 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); @@ -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 */ } diff --git a/contrib/sendmail/src/headers.c b/contrib/sendmail/src/headers.c index f5b7bee..ac830a1 100644 --- a/contrib/sendmail/src/headers.c +++ b/contrib/sendmail/src/headers.c @@ -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,16 @@ */ #ifndef lint -static char sccsid[] = "@(#)headers.c 8.136 (Berkeley) 1/26/1999"; -#endif /* not lint */ +static char id[] = "@(#)$Id: headers.c,v 8.203.4.6 2000/07/19 02:53:32 ca Exp $"; +#endif /* ! lint */ -# include <errno.h> -# include "sendmail.h" +/* $FreeBSD$ */ + +#include <sendmail.h> + +static bool fix_mime_header __P((char *)); +static int priencode __P((char *)); +static void put_vanilla_header __P((HDR *, char *, MCI *)); /* ** SETUPHEADERS -- initialize headers in symbol table @@ -43,11 +49,13 @@ setupheaders() /* ** CHOMPHEADER -- process and save a header line. ** -** Called by collect and by readcf to deal with header lines. +** Called by collect, readcf, and readqf to deal with header lines. ** ** Parameters: ** line -- header as a text line. -** def -- if set, this is a default value. +** pflag -- flags: +** CHHDR_DEF: this is a default value. +** CHHDR_CHECK: call rulesets. ** hdrp -- a pointer to the place to save the header. ** e -- the envelope including this header. ** @@ -59,32 +67,34 @@ setupheaders() ** Contents of 'line' are destroyed. */ -struct hdrinfo NormalHeader = { NULL, 0, NULL }; +static struct hdrinfo NormalHeader = { NULL, 0, NULL }; -int -chompheader(line, def, hdrp, e) +u_long +chompheader(line, pflag, hdrp, e) char *line; - bool def; + int pflag; HDR **hdrp; register ENVELOPE *e; { + u_char mid = '\0'; register char *p; register HDR *h; HDR **hp; char *fname; char *fvalue; bool cond = FALSE; + bool dropfrom; bool headeronly; STAB *s; struct hdrinfo *hi; bool nullheader = FALSE; - BITMAP mopts; + BITMAP256 mopts; if (tTd(31, 6)) { - printf("chompheader: "); + dprintf("chompheader: "); xputs(line); - printf("\n"); + dprintf("\n"); } headeronly = hdrp != NULL; @@ -94,21 +104,76 @@ chompheader(line, def, hdrp, e) /* strip off options */ clrbitmap(mopts); p = line; - if (*p == '?') + if (!bitset(pflag, CHHDR_USER) && *p == '?') { - /* have some */ - register char *q = strchr(p + 1, *p); - - if (q != NULL) + int c; + register char *q; + + q = strchr(++p, '?'); + if (q == NULL) + goto hse; + + *q = '\0'; + c = *p & 0377; + + /* possibly macro conditional */ + if (c == MACROEXPAND) { - *q++ = '\0'; - while (*++p != '\0') - setbitn(*p, mopts); - p = q; + /* catch ?$? */ + if (*++p == '\0') + { + *q = '?'; + goto hse; + } + + mid = (u_char) *p++; + + /* catch ?$abc? */ + if (*p != '\0') + { + *q = '?'; + goto hse; + } + } + else if (*p == '$') + { + /* catch ?$? */ + if (*++p == '\0') + { + *q = '?'; + goto hse; + } + + mid = (u_char)macid(p, NULL); + if (bitset(0200, mid)) + p += strlen(macname(mid)) + 2; + else + p++; + + /* catch ?$abc? */ + if (*p != '\0') + { + *q = '?'; + goto hse; + } + } else - syserr("553 header syntax error, line \"%s\"", line); - cond = TRUE; + { + while (*p != '\0') + { + if (!isascii(*p)) + { + *q = '?'; + goto hse; + } + + setbitn(*p, mopts); + cond = TRUE; + p++; + } + } + p = q + 1; } /* find canonical name */ @@ -120,7 +185,8 @@ chompheader(line, def, hdrp, e) p++; if (*p++ != ':' || fname == fvalue) { - syserr("553 header syntax error, line \"%s\"", line); +hse: + syserr("553 5.3.0 header syntax error, line \"%s\"", line); return 0; } *fvalue = '\0'; @@ -141,7 +207,7 @@ chompheader(line, def, hdrp, e) return H_EOH; /* check to see if it represents a ruleset call */ - if (def) + if (bitset(pflag, CHHDR_DEF)) { char hbuf[50]; @@ -151,12 +217,18 @@ chompheader(line, def, hdrp, e) if ((*p++ & 0377) == CALLSUBR) { auto char *endp; + bool strc; + strc = *p == '+'; /* strip comments? */ + if (strc) + ++p; if (strtorwset(p, &endp, ST_ENTER) > 0) { *endp = '\0'; s = stab(fname, ST_HEADER, ST_ENTER); s->s_header.hi_ruleset = newstr(p); + if (!strc) + s->s_header.hi_flags |= H_STRIPCOMM; } return 0; } @@ -172,19 +244,20 @@ chompheader(line, def, hdrp, e) if (tTd(31, 9)) { if (s == NULL) - printf("no header flags match\n"); + dprintf("no header flags match\n"); else - printf("header match, flags=%x, ruleset=%s\n", + dprintf("header match, flags=%lx, ruleset=%s\n", hi->hi_flags, hi->hi_ruleset == NULL ? "<NULL>" : hi->hi_ruleset); } /* see if this is a resent message */ - if (!def && !headeronly && bitset(H_RESENT, hi->hi_flags)) + if (!bitset(pflag, CHHDR_DEF) && !headeronly && + bitset(H_RESENT, hi->hi_flags)) e->e_flags |= EF_RESENT; /* if this is an Errors-To: header keep track of it now */ - if (UseErrorsTo && !def && !headeronly && + if (UseErrorsTo && !bitset(pflag, CHHDR_DEF) && !headeronly && bitset(H_ERRORSTO, hi->hi_flags)) (void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e); @@ -210,8 +283,74 @@ chompheader(line, def, hdrp, e) ** If there is a check ruleset, verify it against the header. */ - if (!def && hi->hi_ruleset != NULL) - (void) rscheck(hi->hi_ruleset, fvalue, NULL, e); + if (bitset(pflag, CHHDR_CHECK)) + { + bool stripcom = FALSE; + char *rs; + + /* no ruleset? look for default */ + rs = hi->hi_ruleset; + if (rs == NULL) + { + s = stab("*", ST_HEADER, ST_FIND); + if (s != NULL) + { + rs = (&s->s_header)->hi_ruleset; + stripcom = bitset((&s->s_header)->hi_flags, + H_STRIPCOMM); + } + } + else + stripcom = bitset(hi->hi_flags, H_STRIPCOMM); + if (rs != NULL) + { + int l; + char qval[MAXNAME]; + char hlen[16]; + char *sp, *dp; + + dp = qval; + l = 0; + dp[l++] = '"'; + for (sp = fvalue; *sp != '\0' && l < MAXNAME - 2; sp++) + { + switch(*sp) + { + case '\011': /* ht */ + case '\012': /* nl */ + case '\013': /* vt */ + case '\014': /* np */ + case '\015': /* cr */ + dp[l++] = ' '; + break; + case '"': + dp[l++] = '\\'; + /* FALLTHROUGH */ + default: + dp[l++] = *sp; + break; + } + } + dp[l++] = '"'; + dp[l++] = '\0'; + l = strlen(fvalue); + snprintf(hlen, sizeof hlen, "%d", l); + define(macid("{hdrlen}", NULL), newstr(hlen), e); + if (l >= MAXNAME) + { + if (LogLevel > 9) + sm_syslog(LOG_WARNING, e->e_id, + "Warning: truncated header '%s' before check with '%s' len=%d max=%d", + fname, rs, l, MAXNAME); + } + if ((sp = macvalue(macid("{currHeader}", NULL), e)) != + NULL) + free(sp); + define(macid("{currHeader}", NULL), newstr(qval), e); + define(macid("{hdr_name}", NULL), newstr(fname), e); + (void) rscheck(rs, fvalue, NULL, e, stripcom, TRUE, 4); + } + } /* ** Drop explicit From: if same as what we would generate. @@ -219,28 +358,31 @@ chompheader(line, def, hdrp, e) ** insert the full name information in all circumstances. */ + dropfrom = FALSE; p = "resent-from"; if (!bitset(EF_RESENT, e->e_flags)) p += 7; - if (!def && !headeronly && !bitset(EF_QUEUERUN, e->e_flags) && - strcasecmp(fname, p) == 0) + if (!bitset(pflag, CHHDR_DEF) && !headeronly && + !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0) { if (tTd(31, 2)) { - printf("comparing header from (%s) against default (%s or %s)\n", + dprintf("comparing header from (%s) against default (%s or %s)\n", fvalue, e->e_from.q_paddr, e->e_from.q_user); } if (e->e_from.q_paddr != NULL && + e->e_from.q_mailer != NULL && + bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) && (strcmp(fvalue, e->e_from.q_paddr) == 0 || strcmp(fvalue, e->e_from.q_user) == 0)) - return hi->hi_flags; + dropfrom = TRUE; } /* delete default value for this header */ for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link) { if (strcasecmp(fname, h->h_field) == 0 && - bitset(H_DEFAULT, h->h_flags) && + !bitset(H_USER, h->h_flags) && !bitset(H_FORCE, h->h_flags)) { if (nullheader) @@ -248,13 +390,20 @@ chompheader(line, def, hdrp, e) /* user-supplied value was null */ return 0; } + if (dropfrom) + { + /* make this look like the user entered it */ + h->h_flags |= H_USER; + return hi->hi_flags; + } h->h_value = NULL; if (!cond) { /* copy conditions from default case */ - bcopy((char *)h->h_mflags, (char *)mopts, - sizeof mopts); + memmove((char *)mopts, (char *)h->h_mflags, + sizeof mopts); } + h->h_macro = mid; } } @@ -263,20 +412,24 @@ chompheader(line, def, hdrp, e) h->h_field = newstr(fname); h->h_value = newstr(fvalue); h->h_link = NULL; - bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts); + memmove((char *) h->h_mflags, (char *) mopts, sizeof mopts); + h->h_macro = mid; *hp = h; h->h_flags = hi->hi_flags; + if (bitset(pflag, CHHDR_USER)) + h->h_flags |= H_USER; /* strip EOH flag if parsing MIME headers */ if (headeronly) h->h_flags &= ~H_EOH; - if (def) + if (bitset(pflag, CHHDR_DEF)) h->h_flags |= H_DEFAULT; - if (cond) + if (cond || mid != '\0') h->h_flags |= H_CHECK; /* hack to see if this is a new format message */ - if (!def && !headeronly && bitset(H_RCPT|H_FROM, h->h_flags) && + if (!bitset(pflag, CHHDR_DEF) && !headeronly && + bitset(H_RCPT|H_FROM, h->h_flags) && (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL || strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL)) { @@ -293,7 +446,8 @@ chompheader(line, def, hdrp, e) ** Parameters: ** field -- the name of the header field. ** value -- the value of the field. -** hp -- an indirect pointer to the header structure list. +** flags -- flags to add to h_flags. +** hdrlist -- an indirect pointer to the header structure list. ** ** Returns: ** none. @@ -303,9 +457,10 @@ chompheader(line, def, hdrp, e) */ void -addheader(field, value, hdrlist) +addheader(field, value, flags, hdrlist) char *field; char *value; + int flags; HDR **hdrlist; { register HDR *h; @@ -327,10 +482,11 @@ addheader(field, value, hdrlist) h->h_field = field; h->h_value = newstr(value); h->h_link = *hp; - h->h_flags = H_DEFAULT; + h->h_flags = flags; if (s != NULL) h->h_flags |= s->s_header.hi_flags; clrbitmap(h->h_mflags); + h->h_macro = '\0'; *hp = h; } /* @@ -362,9 +518,9 @@ hvalue(field, header) { if (!bitset(H_DEFAULT, h->h_flags) && strcasecmp(h->h_field, field) == 0) - return (h->h_value); + return h->h_value; } - return (NULL); + return NULL; } /* ** ISHEADER -- predicate telling if argument is a header. @@ -439,7 +595,6 @@ eatheader(e, full) int hopcnt = 0; char *msgid; char buf[MAXLINE]; - extern int priencode __P((char *)); /* ** Set up macros for possible expansion in headers. @@ -456,12 +611,8 @@ eatheader(e, full) p = hvalue("full-name", e->e_header); if (p != NULL) { - extern bool rfc822_string __P((char *)); - if (!rfc822_string(p)) { - extern char *addquotes __P((char *)); - /* ** Quote a full name with special characters ** as a comment so crackaddr() doesn't destroy @@ -473,37 +624,34 @@ eatheader(e, full) } if (tTd(32, 1)) - printf("----- collected header -----\n"); + dprintf("----- collected header -----\n"); msgid = NULL; for (h = e->e_header; h != NULL; h = h->h_link) { if (tTd(32, 1)) - printf("%s: ", h->h_field); + dprintf("%s: ", h->h_field); if (h->h_value == NULL) { if (tTd(32, 1)) - printf("<NULL>\n"); + dprintf("<NULL>\n"); continue; } /* do early binding */ - if (bitset(H_DEFAULT, h->h_flags)) + if (bitset(H_DEFAULT, h->h_flags) && + !bitset(H_BINDLATE, h->h_flags)) { if (tTd(32, 1)) { - printf("("); + dprintf("("); xputs(h->h_value); - printf(") "); + dprintf(") "); } expand(h->h_value, buf, sizeof buf, e); if (buf[0] != '\0') { if (bitset(H_FROM, h->h_flags)) - { - extern char *crackaddr __P((char *)); - expand(crackaddr(buf), buf, sizeof buf, e); - } h->h_value = newstr(buf); h->h_flags &= ~H_DEFAULT; } @@ -512,7 +660,7 @@ eatheader(e, full) if (tTd(32, 1)) { xputs(h->h_value); - printf("\n"); + dprintf("\n"); } /* count the number of times it has been processed */ @@ -526,7 +674,7 @@ eatheader(e, full) { #if 0 int saveflags = e->e_flags; -#endif +#endif /* 0 */ (void) sendtolist(h->h_value, NULLADDR, &e->e_sendqueue, 0, e); @@ -536,11 +684,11 @@ eatheader(e, full) ** Change functionality so a fatal error on an ** address doesn't affect the entire envelope. */ - + /* delete fatal errors generated by this address */ if (!bitset(EF_FATALERRS, saveflags)) e->e_flags &= ~EF_FATALERRS; -#endif +#endif /* 0 */ } /* save the message-id for logging */ @@ -555,7 +703,7 @@ eatheader(e, full) } } if (tTd(32, 1)) - printf("----------------------------\n"); + dprintf("----------------------------\n"); /* if we are just verifying (that is, sendmail -t -bv), drop out now */ if (OpMode == MD_VERIFY) @@ -640,7 +788,7 @@ eatheader(e, full) if (hi->hi_field != NULL) { if (tTd(32, 2)) - printf("eatheader: setsender(*%s == %s)\n", + dprintf("eatheader: setsender(*%s == %s)\n", hi->hi_field, p); setsender(p, e, NULL, '\0', TRUE); } @@ -684,7 +832,7 @@ logsender(e, msgid) l = strlen(msgid); if (l > sizeof mbuf - 1) l = sizeof mbuf - 1; - bcopy(msgid, mbuf, l); + memmove(mbuf, msgid, l); mbuf[l] = '\0'; p = mbuf; while ((p = strchr(p, '\n')) != NULL) @@ -694,6 +842,7 @@ logsender(e, msgid) if (bitset(EF_RESPONSE, e->e_flags)) name = "[RESPONSE]"; else if ((name = macvalue('_', e)) != NULL) + /* EMPTY */ ; else if (RealHostName == NULL) name = "localhost"; @@ -712,12 +861,12 @@ logsender(e, msgid) } /* some versions of syslog only take 5 printf args */ -# if (SYSLOG_BUFSIZE) >= 256 +#if (SYSLOG_BUFSIZE) >= 256 sbp = sbuf; snprintf(sbp, SPACELEFT(sbuf, sbp), - "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d", + "from=%.200s, size=%ld, class=%d, nrcpts=%d", e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr, - e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts); + e->e_msgsize, e->e_class, e->e_nrcpts); sbp += strlen(sbp); if (msgid != NULL) { @@ -732,24 +881,47 @@ logsender(e, msgid) } p = macvalue('r', e); if (p != NULL) + { (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", proto=%.20s", p); + sbp += strlen(sbp); + } + p = macvalue(macid("{daemon_name}", NULL), e); + if (p != NULL) + { + (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", daemon=%.20s", p); + sbp += strlen(sbp); + } +# if SASL + p = macvalue(macid("{auth_type}", NULL), e); + if (p != NULL) + { + (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", mech=%.12s", p); + sbp += strlen(sbp); + } + p = macvalue(macid("{auth_author}", NULL), e); + if (p != NULL) + { + (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", auth=%.30s", p); + sbp += strlen(sbp); + } +# endif /* SASL */ sm_syslog(LOG_INFO, e->e_id, - "%.850s, relay=%.100s", - sbuf, name); + "%.850s, relay=%.100s", + sbuf, name); -# else /* short syslog buffer */ +#else /* (SYSLOG_BUFSIZE) >= 256 */ sm_syslog(LOG_INFO, e->e_id, - "from=%s", - e->e_from.q_paddr == NULL ? "<NONE>" - : shortenstring(e->e_from.q_paddr, 83)); + "from=%s", + e->e_from.q_paddr == NULL ? "<NONE>" + : shortenstring(e->e_from.q_paddr, 83)); sm_syslog(LOG_INFO, e->e_id, - "size=%ld, class=%ld, pri=%ld, nrcpts=%d", - e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts); + "size=%ld, class=%ld, nrcpts=%d", + e->e_msgsize, e->e_class, e->e_nrcpts); if (msgid != NULL) sm_syslog(LOG_INFO, e->e_id, - "msgid=%s", - shortenstring(mbuf, 83)); + "msgid=%s", + shortenstring(mbuf, 83)); sbp = sbuf; *sbp = '\0'; if (e->e_bodytype != NULL) @@ -764,8 +936,8 @@ logsender(e, msgid) sbp += strlen(sbp); } sm_syslog(LOG_INFO, e->e_id, - "%.400srelay=%.100s", sbuf, name); -# endif + "%.400srelay=%.100s", sbuf, name); +#endif /* (SYSLOG_BUFSIZE) >= 256 */ } /* ** PRIENCODE -- encode external priority names into internal values. @@ -780,7 +952,7 @@ logsender(e, msgid) ** none. */ -int +static int priencode(p) char *p; { @@ -788,12 +960,12 @@ priencode(p) for (i = 0; i < NumPriorities; i++) { - if (!strcasecmp(p, Priorities[i].pri_name)) - return (Priorities[i].pri_val); + if (strcasecmp(p, Priorities[i].pri_name) == 0) + return Priorities[i].pri_val; } /* unknown priority */ - return (0); + return 0; } /* ** CRACKADDR -- parse an address and turn it into a macro @@ -848,7 +1020,7 @@ crackaddr(addr) static char buf[MAXNAME + 1]; if (tTd(33, 1)) - printf("crackaddr(%s)\n", addr); + dprintf("crackaddr(%s)\n", addr); /* strip leading spaces */ while (*addr != '\0' && isascii(*addr) && isspace(*addr)) @@ -1147,19 +1319,19 @@ crackaddr(addr) if (tTd(33, 1)) { - printf("crackaddr=>`"); + dprintf("crackaddr=>`"); xputs(buf); - printf("'\n"); + dprintf("'\n"); } - return (buf); + return buf; } /* ** PUTHEADER -- put the header part of a message from the in-core copy ** ** Parameters: ** mci -- the connection information. -** h -- the header to put. +** hdr -- the header to put. ** e -- envelope to use. ** flags -- MIME conversion flags. ** @@ -1175,7 +1347,7 @@ crackaddr(addr) */ #ifndef MAX # define MAX(a,b) (((a)>(b))?(a):(b)) -#endif +#endif /* ! MAX */ void putheader(mci, hdr, e, flags) @@ -1189,7 +1361,7 @@ putheader(mci, hdr, e, flags) char obuf[MAXLINE]; if (tTd(34, 1)) - printf("--- putheader, mailer = %s ---\n", + dprintf("--- putheader, mailer = %s ---\n", mci->mci_mailer->m_name); /* @@ -1204,30 +1376,30 @@ putheader(mci, hdr, e, flags) for (h = hdr; h != NULL; h = h->h_link) { register char *p = h->h_value; - extern bool bitintersect __P((BITMAP, BITMAP)); if (tTd(34, 11)) { - printf(" %s: ", h->h_field); + dprintf(" %s: ", h->h_field); xputs(p); } -#if _FFR_MAX_MIME_HEADER_LENGTH + /* Skip empty headers */ + if (h->h_value == NULL) + continue; + /* heuristic shortening of MIME fields to avoid MUA overflows */ if (MaxMimeFieldLength > 0 && wordinclass(h->h_field, macid("{checkMIMEFieldHeaders}", NULL))) { - extern bool fix_mime_header __P((char *)); - if (fix_mime_header(h->h_value)) { sm_syslog(LOG_ALERT, e->e_id, - "Truncated MIME %s header due to field size (possible attack)", - h->h_field); + "Truncated MIME %s header due to field size (possible attack)", + h->h_field); if (tTd(34, 11)) - printf(" truncated MIME %s header due to field size (possible attack)\n", - h->h_field); + dprintf(" truncated MIME %s header due to field size (possible attack)\n", + h->h_field); } } @@ -1235,15 +1407,15 @@ putheader(mci, hdr, e, flags) wordinclass(h->h_field, macid("{checkMIMETextHeaders}", NULL))) { - if (strlen(h->h_value) > MaxMimeHeaderLength) + if (strlen(h->h_value) > (size_t)MaxMimeHeaderLength) { h->h_value[MaxMimeHeaderLength - 1] = '\0'; sm_syslog(LOG_ALERT, e->e_id, - "Truncated long MIME %s header (possible attack)", - h->h_field); + "Truncated long MIME %s header (possible attack)", + h->h_field); if (tTd(34, 11)) - printf(" truncated long MIME %s header (possible attack)\n", - h->h_field); + dprintf(" truncated long MIME %s header (possible attack)\n", + h->h_field); } } @@ -1251,19 +1423,16 @@ putheader(mci, hdr, e, flags) wordinclass(h->h_field, macid("{checkMIMEHeaders}", NULL))) { - extern bool shorten_rfc822_string __P((char *, int)); - if (shorten_rfc822_string(h->h_value, MaxMimeHeaderLength)) { sm_syslog(LOG_ALERT, e->e_id, - "Truncated long MIME %s header (possible attack)", - h->h_field); + "Truncated long MIME %s header (possible attack)", + h->h_field); if (tTd(34, 11)) - printf(" truncated long MIME %s header (possible attack)\n", - h->h_field); + dprintf(" truncated long MIME %s header (possible attack)\n", + h->h_field); } } -#endif /* ** Suppress Content-Transfer-Encoding: if we are MIMEing @@ -1277,23 +1446,25 @@ putheader(mci, hdr, e, flags) !bitset(M87F_NO8TO7, flags)) { if (tTd(34, 11)) - printf(" (skipped (content-transfer-encoding))\n"); + dprintf(" (skipped (content-transfer-encoding))\n"); continue; } if (bitset(MCIF_INMIME, mci->mci_flags)) { if (tTd(34, 11)) - printf("\n"); + dprintf("\n"); put_vanilla_header(h, p, mci); continue; } if (bitset(H_CHECK|H_ACHECK, h->h_flags) && - !bitintersect(h->h_mflags, mci->mci_mailer->m_flags)) + !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) && + (h->h_macro == '\0' || + macvalue(h->h_macro & 0377, e) == NULL)) { if (tTd(34, 11)) - printf(" (skipped)\n"); + dprintf(" (skipped)\n"); continue; } @@ -1301,32 +1472,29 @@ putheader(mci, hdr, e, flags) if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags)) { if (tTd(34, 11)) - printf(" (skipped (resent))\n"); + dprintf(" (skipped (resent))\n"); continue; } /* suppress return receipts if requested */ if (bitset(H_RECEIPTTO, h->h_flags) && -#if _FFR_DSN_RRT_OPTION (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags))) -#else - bitset(EF_NORECEIPT, e->e_flags)) -#endif { if (tTd(34, 11)) - printf(" (skipped (receipt))\n"); + dprintf(" (skipped (receipt))\n"); continue; } /* macro expand value if generated internally */ - if (bitset(H_DEFAULT, h->h_flags)) + if (bitset(H_DEFAULT, h->h_flags) || + bitset(H_BINDLATE, h->h_flags)) { expand(p, buf, sizeof buf, e); p = buf; if (*p == '\0') { if (tTd(34, 11)) - printf(" (skipped -- null value)\n"); + dprintf(" (skipped -- null value)\n"); continue; } } @@ -1337,7 +1505,7 @@ putheader(mci, hdr, e, flags) if (bitset(EF_DELETE_BCC, e->e_flags)) { if (tTd(34, 11)) - printf(" (skipped -- bcc)\n"); + dprintf(" (skipped -- bcc)\n"); } else { @@ -1350,7 +1518,7 @@ putheader(mci, hdr, e, flags) } if (tTd(34, 11)) - printf("\n"); + dprintf("\n"); if (bitset(H_FROM|H_RCPT, h->h_flags)) { @@ -1369,7 +1537,7 @@ putheader(mci, hdr, e, flags) /* ** If we are converting this to a MIME message, add the - ** MIME headers. + ** MIME headers (but not in MIME mode!). */ #if MIME8TO7 @@ -1377,10 +1545,10 @@ putheader(mci, hdr, e, flags) bitset(EF_HAS8BIT, e->e_flags) && !bitset(EF_DONT_MIME, e->e_flags) && !bitnset(M_8BITS, mci->mci_mailer->m_flags) && - !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8, mci->mci_flags)) + !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) && + hvalue("MIME-Version", e->e_header) == NULL) { - if (hvalue("MIME-Version", e->e_header) == NULL) - putline("MIME-Version: 1.0", mci); + putline("MIME-Version: 1.0", mci); if (hvalue("Content-Type", e->e_header) == NULL) { snprintf(obuf, sizeof obuf, @@ -1391,7 +1559,7 @@ putheader(mci, hdr, e, flags) if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL) putline("Content-Transfer-Encoding: 8bit", mci); } -#endif +#endif /* MIME8TO7 */ } /* ** PUT_VANILLA_HEADER -- output a fairly ordinary header @@ -1405,7 +1573,7 @@ putheader(mci, hdr, e, flags) ** none. */ -void +static void put_vanilla_header(h, v, mci) HDR *h; char *v; @@ -1417,10 +1585,8 @@ put_vanilla_header(h, v, mci) char obuf[MAXLINE]; putflags = PXLF_HEADER; -#if _FFR_7BITHDRS if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) putflags |= PXLF_STRIP8BIT; -#endif (void) snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field); obp = obuf + strlen(obuf); while ((nlp = strchr(v, '\n')) != NULL) @@ -1428,7 +1594,7 @@ put_vanilla_header(h, v, mci) int l; l = nlp - v; - if (SPACELEFT(obuf, obp) - 1 < l) + if (SPACELEFT(obuf, obp) - 1 < (size_t)l) l = SPACELEFT(obuf, obp) - 1; snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v); @@ -1439,7 +1605,7 @@ put_vanilla_header(h, v, mci) *obp++ = ' '; } snprintf(obp, SPACELEFT(obuf, obp), "%.*s", - (int)(sizeof obuf - (obp - obuf) - 1), v); + (int) sizeof obuf - (obp - obuf) - 1, v); putxline(obuf, strlen(obuf), mci, putflags); } /* @@ -1480,12 +1646,10 @@ commaize(h, p, oldstyle, mci, e) */ if (tTd(14, 2)) - printf("commaize(%s: %s)\n", h->h_field, p); + dprintf("commaize(%s: %s)\n", h->h_field, p); -#if _FFR_7BITHDRS if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) putflags |= PXLF_STRIP8BIT; -#endif obp = obuf; (void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", h->h_field); @@ -1507,7 +1671,7 @@ commaize(h, p, oldstyle, mci, e) register int c; char savechar; int flags; - auto int stat; + auto int status; /* ** Find the end of the name. New style names @@ -1562,16 +1726,15 @@ commaize(h, p, oldstyle, mci, e) else if (e->e_from.q_mailer != NULL && bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags)) { - extern char *udbsender __P((char *)); char *q; q = udbsender(name); if (q != NULL) name = q; } -#endif - stat = EX_OK; - name = remotename(name, mci->mci_mailer, flags, &stat, e); +#endif /* USERDB */ + status = EX_OK; + name = remotename(name, mci->mci_mailer, flags, &status, e); if (*name == '\0') { *p = savechar; @@ -1579,6 +1742,13 @@ commaize(h, p, oldstyle, mci, e) } name = denlstring(name, FALSE, TRUE); + /* + ** record data progress so DNS timeouts + ** don't cause DATA timeouts + */ + + DataProgress = TRUE; + /* output the name with nice formatting */ opos += strlen(name); if (!firstone) @@ -1588,7 +1758,7 @@ commaize(h, p, oldstyle, mci, e) snprintf(obp, SPACELEFT(obuf, obp), ",\n"); putxline(obuf, strlen(obuf), mci, putflags); obp = obuf; - (void) strcpy(obp, " "); + (void) strlcpy(obp, " ", sizeof obp); opos = strlen(obp); obp += opos; opos += strlen(name); @@ -1632,14 +1802,14 @@ copyheader(header) while (header != NULL) { - newhdr = (HDR *) xalloc(sizeof(HDR)); + newhdr = (HDR *) xalloc(sizeof *newhdr); STRUCTCOPY(*header, *newhdr); *tail = newhdr; tail = &newhdr->h_link; header = header->h_link; } *tail = NULL; - + return ret; } /* @@ -1659,40 +1829,38 @@ copyheader(header) ** string modified in place */ -bool +static bool fix_mime_header(string) char *string; { bool modified = FALSE; char *begin = string; char *end; - extern char *find_character __P((char *, char)); - extern bool shorten_rfc822_string __P((char *, int)); - + if (string == NULL || *string == '\0') return FALSE; - + /* Split on each ';' */ while ((end = find_character(begin, ';')) != NULL) { char save = *end; char *bp; - + *end = '\0'; - + /* Shorten individual parameter */ if (shorten_rfc822_string(begin, MaxMimeFieldLength)) modified = TRUE; - + /* Collapse the possibly shortened string with rest */ bp = begin + strlen(begin); if (bp != end) { char *ep = end; - + *end = save; end = bp; - + /* copy character by character due to overlap */ while (*ep != '\0') *bp++ = *ep++; @@ -1702,7 +1870,7 @@ fix_mime_header(string) *end = save; if (*end == '\0') break; - + /* Move past ';' */ begin = end + 1; } diff --git a/contrib/sendmail/src/mailq.1 b/contrib/sendmail/src/mailq.1 index bead1a2..d7160f9 100644 --- a/contrib/sendmail/src/mailq.1 +++ b/contrib/sendmail/src/mailq.1 @@ -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. diff --git a/contrib/sendmail/src/mci.c b/contrib/sendmail/src/mci.c index 8ebb7a0..171c71b 100644 --- a/contrib/sendmail/src/mci.c +++ b/contrib/sendmail/src/mci.c @@ -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; - - strncpy(newptr, e->d_name, - sizeof newpath - (newptr - newpath) - 1); - newpath[sizeof newpath - 1] = '\0'; - - ret = mci_traverse_persistent(action, newpath); + leftone = removedone = FALSE; + while ((e = readdir(d)) != NULL) + { + if (e->d_name[0] == '.') + continue; + + (void) strlcpy(newptr, e->d_name, + sizeof newpath - + (newptr - 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; } diff --git a/contrib/sendmail/src/savemail.c b/contrib/sendmail/src/savemail.c index 3ef6b43..9a196b0 100644 --- a/contrib/sendmail/src/savemail.c +++ b/contrib/sendmail/src/savemail.c @@ -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,10 +12,16 @@ */ #ifndef lint -static char sccsid[] = "@(#)savemail.c 8.140 (Berkeley) 1/18/1999"; -#endif /* not lint */ +static char id[] = "@(#)$Id: savemail.c,v 8.212.4.3 2000/06/13 07:16:26 gshapiro Exp $"; +#endif /* ! lint */ -# include "sendmail.h" +/* $FreeBSD$ */ + +#include <sendmail.h> + + +static void errbody __P((MCI *, ENVELOPE *, char *)); +static bool pruneroute __P((char *)); /* ** SAVEMAIL -- Save mail on error @@ -39,14 +46,14 @@ static char sccsid[] = "@(#)savemail.c 8.140 (Berkeley) 1/18/1999"; */ /* defines for state machine */ -# define ESM_REPORT 0 /* report to sender's terminal */ -# define ESM_MAIL 1 /* mail back to sender */ -# define ESM_QUIET 2 /* messages have already been returned */ -# define ESM_DEADLETTER 3 /* save in ~/dead.letter */ -# define ESM_POSTMASTER 4 /* return to postmaster */ -# define ESM_USRTMP 5 /* save in /usr/tmp/dead.letter */ -# define ESM_PANIC 6 /* leave the locked queue/transcript files */ -# define ESM_DONE 7 /* the message is successfully delivered */ +#define ESM_REPORT 0 /* report to sender's terminal */ +#define ESM_MAIL 1 /* mail back to sender */ +#define ESM_QUIET 2 /* mail has already been returned */ +#define ESM_DEADLETTER 3 /* save in ~/dead.letter */ +#define ESM_POSTMASTER 4 /* return to postmaster */ +#define ESM_DEADLETTERDROP 5 /* save in DeadLetterDrop */ +#define ESM_PANIC 6 /* call loseqfile() */ +#define ESM_DONE 7 /* message is successfully delivered */ void @@ -61,13 +68,12 @@ savemail(e, sendbody) register char *p; MCI mcibuf; int flags; - char buf[MAXLINE+1]; - extern char *ttypath __P((void)); - extern bool writable __P((char *, ADDRESS *, int)); + long sff; + char buf[MAXLINE + 1]; if (tTd(6, 1)) { - printf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n e_from=", + dprintf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n e_from=", e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id, ExitStat); printaddr(&e->e_from, FALSE); @@ -90,7 +96,7 @@ savemail(e, sendbody) if (parseaddr(e->e_sender, &e->e_from, RF_COPYPARSE|RF_SENDERADDR, '\0', NULL, e) == NULL) { - syserr("553 Cannot parse Postmaster!"); + syserr("553 5.3.5 Cannot parse Postmaster!"); finis(TRUE, EX_SOFTWARE); } } @@ -107,6 +113,8 @@ savemail(e, sendbody) ** ESM_MAIL Mail response to the sender. ** ESM_DEADLETTER Save response in ~/dead.letter. ** ESM_POSTMASTER Mail response to the postmaster. + ** ESM_DEADLETTERDROP + ** If DeadLetterDrop set, save it there. ** ESM_PANIC Save response anywhere possible. */ @@ -132,7 +140,8 @@ savemail(e, sendbody) return; default: - syserr("554 savemail: bogus errormode x%x\n", e->e_errormode); + syserr("554 5.3.0 savemail: bogus errormode x%x\n", + e->e_errormode); state = ESM_MAIL; break; } @@ -152,7 +161,7 @@ savemail(e, sendbody) while (state != ESM_DONE) { if (tTd(6, 5)) - printf(" state %d\n", state); + dprintf(" state %d\n", state); switch (state) { @@ -182,24 +191,17 @@ savemail(e, sendbody) printf("Errors occurred while sending mail.\r\n"); if (e->e_xfp != NULL) { - (void) fflush(e->e_xfp); - fp = fopen(queuename(e, 'x'), "r"); + (void) bfrewind(e->e_xfp); + printf("Transcript follows:\r\n"); + while (fgets(buf, sizeof buf, e->e_xfp) != NULL && + !ferror(stdout)) + (void) fputs(buf, stdout); } else - fp = NULL; - if (fp == NULL) { syserr("Cannot open %s", queuename(e, 'x')); printf("Transcript of session is unavailable.\r\n"); } - else - { - printf("Transcript follows:\r\n"); - while (fgets(buf, sizeof buf, fp) != NULL && - !ferror(stdout)) - fputs(buf, stdout); - (void) xfclose(fp, "savemail transcript", e->e_id); - } printf("Original message will be saved in dead.letter.\r\n"); state = ESM_DEADLETTER; break; @@ -231,14 +233,14 @@ savemail(e, sendbody) if (!emptyaddr(&e->e_from)) { char from[TOBUFSIZE]; - extern bool pruneroute __P((char *)); - if (strlen(e->e_from.q_paddr) + 1 > sizeof from) + if (strlen(e->e_from.q_paddr) >= sizeof from) { state = ESM_POSTMASTER; break; } - strcpy(from, e->e_from.q_paddr); + (void) strlcpy(from, e->e_from.q_paddr, + sizeof from); if (!DontPruneRoutes && pruneroute(from)) { @@ -248,7 +250,7 @@ savemail(e, sendbody) a = a->q_next) { if (sameaddr(a, &e->e_from)) - a->q_flags |= QDONTSEND; + a->q_state = QS_DUPLICATE; } } (void) sendtolist(from, NULLADDR, @@ -267,8 +269,10 @@ savemail(e, sendbody) /* check to see if there are any good addresses */ for (q = e->e_errorqueue; q != NULL; q = q->q_next) - if (!bitset(QBADADDR|QDONTSEND, q->q_flags)) + { + if (QS_IS_SENDABLE(q->q_state)) break; + } if (q == NULL) { /* this is an error-error */ @@ -294,12 +298,12 @@ savemail(e, sendbody) */ q = NULL; - if (sendtolist(DoubleBounceAddr, - NULLADDR, &q, 0, e) <= 0) + expand(DoubleBounceAddr, buf, sizeof buf, e); + if (sendtolist(buf, NULLADDR, &q, 0, e) <= 0) { - syserr("553 cannot parse %s!", DoubleBounceAddr); + syserr("553 5.3.0 cannot parse %s!", buf); ExitStat = EX_SOFTWARE; - state = ESM_USRTMP; + state = ESM_DEADLETTERDROP; break; } flags = RTSF_PM_BOUNCE; @@ -312,7 +316,7 @@ savemail(e, sendbody) } /* didn't work -- last resort */ - state = ESM_USRTMP; + state = ESM_DEADLETTERDROP; break; case ESM_DEADLETTER: @@ -342,27 +346,37 @@ savemail(e, sendbody) /* we have a home directory; write dead.letter */ define('z', p, e); + + /* get the sender for the UnixFromLine */ + p = macvalue('g', e); + define('g', e->e_sender, e); + expand("\201z/dead.letter", buf, sizeof buf, e); - flags = SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID; + sff = SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID; if (RealUid == 0) - flags |= SFF_ROOTOK; + sff |= SFF_ROOTOK; e->e_to = buf; - if (mailfile(buf, FileMailer, NULL, flags, e) == EX_OK) + if (writable(buf, NULL, sff) && + mailfile(buf, FileMailer, NULL, sff, e) == EX_OK) { int oldverb = Verbose; - Verbose = 1; - message("Saved message in %s", buf); + if (OpMode != MD_DAEMON && OpMode != MD_SMTP) + Verbose = 1; + if (Verbose > 0) + message("Saved message in %s", buf); Verbose = oldverb; + define('g', p, e); state = ESM_DONE; break; } + define('g', p, e); state = ESM_MAIL; break; - case ESM_USRTMP: + case ESM_DEADLETTERDROP: /* - ** Log the mail in /usr/tmp/dead.letter. + ** Log the mail in DeadLetterDrop file. */ if (e->e_class < 0) @@ -372,55 +386,63 @@ savemail(e, sendbody) } if ((SafeFileEnv != NULL && SafeFileEnv[0] != '\0') || - DeadLetterDrop == NULL || DeadLetterDrop[0] == '\0') + DeadLetterDrop == NULL || + DeadLetterDrop[0] == '\0') { state = ESM_PANIC; break; } - flags = SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT|SFF_MUSTOWN; - if (!writable(DeadLetterDrop, NULL, flags) || + sff = SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT|SFF_MUSTOWN; + if (!writable(DeadLetterDrop, NULL, sff) || (fp = safefopen(DeadLetterDrop, O_WRONLY|O_APPEND, - FileMode, flags)) == NULL) + FileMode, sff)) == NULL) { state = ESM_PANIC; break; } - bzero(&mcibuf, sizeof mcibuf); + memset(&mcibuf, '\0', sizeof mcibuf); mcibuf.mci_out = fp; mcibuf.mci_mailer = FileMailer; if (bitnset(M_7BITS, FileMailer->m_flags)) mcibuf.mci_flags |= MCIF_7BIT; - mcibuf.mci_contentlen = 0; + + /* get the sender for the UnixFromLine */ + p = macvalue('g', e); + define('g', e->e_sender, e); putfromline(&mcibuf, e); (*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER); (*e->e_putbody)(&mcibuf, e, NULL); putline("\n", &mcibuf); (void) fflush(fp); - if (ferror(fp)) + if (ferror(fp) || + fclose(fp) < 0) state = ESM_PANIC; else { int oldverb = Verbose; - Verbose = 1; - message("Saved message in %s", DeadLetterDrop); + if (OpMode != MD_DAEMON && OpMode != MD_SMTP) + Verbose = 1; + if (Verbose > 0) + message("Saved message in %s", + DeadLetterDrop); Verbose = oldverb; if (LogLevel > 3) sm_syslog(LOG_NOTICE, e->e_id, - "Saved message in %s", - DeadLetterDrop); + "Saved message in %s", + DeadLetterDrop); state = ESM_DONE; } - (void) xfclose(fp, "savemail", DeadLetterDrop); + define('g', p, e); break; default: - syserr("554 savemail: unknown state %d", state); + syserr("554 5.3.5 savemail: unknown state %d", state); - /* fall through ... */ + /* FALLTHROUGH */ case ESM_PANIC: /* leave the locked queue & transcript files around */ @@ -467,22 +489,21 @@ returntosender(msg, returnq, flags, e) register ADDRESS *q; char *p; char buf[MAXNAME + 1]; - extern void errbody __P((MCI *, ENVELOPE *, char *)); if (returnq == NULL) - return (-1); + return -1; if (msg == NULL) msg = "Unable to deliver mail"; if (tTd(6, 1)) { - printf("\n*** Return To Sender: msg=\"%s\", depth=%d, e=%lx, returnq=", - msg, returndepth, (u_long) e); + dprintf("\n*** Return To Sender: msg=\"%s\", depth=%d, e=%lx, returnq=", + msg, returndepth, (u_long) e); printaddr(returnq, TRUE); if (tTd(6, 20)) { - printf("Sendq="); + dprintf("Sendq="); printaddr(e->e_sendqueue, TRUE); } } @@ -490,76 +511,119 @@ returntosender(msg, returnq, flags, e) if (++returndepth >= MAXRETURNS) { if (returndepth != MAXRETURNS) - syserr("554 returntosender: infinite recursion on %s", returnq->q_paddr); + syserr("554 5.3.0 returntosender: infinite recursion on %s", + returnq->q_paddr); /* don't "unrecurse" and fake a clean exit */ /* returndepth--; */ - return (0); + return 0; } - define('g', e->e_from.q_paddr, e); + define('g', e->e_sender, e); define('u', NULL, e); /* initialize error envelope */ ee = newenvelope(&errenvelope, e); define('a', "\201b", ee); - define('r', "internal", ee); + define('r', "", ee); define('s', "localhost", ee); define('_', "localhost", ee); +#if SASL + define(macid("{auth_type}", NULL), "", ee); + define(macid("{auth_authen}", NULL), "", ee); + define(macid("{auth_author}", NULL), "", ee); + define(macid("{auth_ssf}", NULL), "", ee); +#endif /* SASL */ +#if STARTTLS + define(macid("{cert_issuer}", NULL), "", ee); + define(macid("{cert_subject}", NULL), "", ee); + define(macid("{cipher_bits}", NULL), "", ee); + define(macid("{cipher}", NULL), "", ee); + define(macid("{tls_version}", NULL), "", ee); + define(macid("{verify}", NULL), "", ee); +# if _FFR_TLS_1 + define(macid("{alg_bits}", NULL), "", ee); + define(macid("{cn_issuer}", NULL), "", ee); + define(macid("{cn_subject}", NULL), "", ee); +# endif /* _FFR_TLS_1 */ +#endif /* STARTTLS */ + ee->e_puthdr = putheader; ee->e_putbody = errbody; ee->e_flags |= EF_RESPONSE|EF_METOO; if (!bitset(EF_OLDSTYLE, e->e_flags)) ee->e_flags &= ~EF_OLDSTYLE; + if (bitset(EF_DONT_MIME, e->e_flags)) + { + ee->e_flags |= EF_DONT_MIME; + + /* + ** If we can't convert to MIME and we don't pass + ** 8-bit, we can't send the body. + */ + + if (bitset(EF_HAS8BIT, e->e_flags) && + !bitset(MM_PASS8BIT, MimeMode)) + flags &= ~RTSF_SEND_BODY; + } + ee->e_sendqueue = returnq; ee->e_msgsize = ERRORFUDGE; - if (bitset(RTSF_SEND_BODY, flags)) + if (bitset(RTSF_SEND_BODY, flags) && + !bitset(PRIV_NOBODYRETN, PrivacyFlags)) ee->e_msgsize += e->e_msgsize; else ee->e_flags |= EF_NO_BODY_RETN; initsys(ee); + +#if NAMED_BIND + _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; + _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; +#endif /* NAMED_BIND */ for (q = returnq; q != NULL; q = q->q_next) { - if (bitset(QBADADDR, q->q_flags)) + if (QS_IS_BADADDR(q->q_state)) continue; q->q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS); q->q_flags |= QPINGONFAILURE; - if (!bitset(QDONTSEND, q->q_flags)) + if (!QS_IS_DEAD(q->q_state)) ee->e_nrcpts++; if (q->q_alias == NULL) - addheader("To", q->q_paddr, &ee->e_header); + addheader("To", q->q_paddr, 0, &ee->e_header); } if (LogLevel > 5) { - if (bitset(EF_RESPONSE|EF_WARNING, e->e_flags)) + if (bitset(EF_RESPONSE, e->e_flags)) p = "return to sender"; + else if (bitset(EF_WARNING, e->e_flags)) + p = "sender notify"; else if (bitset(RTSF_PM_BOUNCE, flags)) p = "postmaster notify"; else p = "DSN"; sm_syslog(LOG_INFO, e->e_id, - "%s: %s: %s", - ee->e_id, p, shortenstring(msg, MAXSHORTSTR)); + "%s: %s: %s", + ee->e_id, p, shortenstring(msg, MAXSHORTSTR)); } if (SendMIMEErrors) { - addheader("MIME-Version", "1.0", &ee->e_header); + addheader("MIME-Version", "1.0", 0, &ee->e_header); (void) snprintf(buf, sizeof buf, "%s.%ld/%.100s", - ee->e_id, (long)curtime(), MyHostName); + ee->e_id, (long) curtime(), MyHostName); ee->e_msgboundary = newstr(buf); (void) snprintf(buf, sizeof buf, #if DSN - "multipart/report; report-type=delivery-status;\n\tboundary=\"%s\"", -#else - "multipart/mixed; boundary=\"%s\"", -#endif - ee->e_msgboundary); - addheader("Content-Type", buf, &ee->e_header); + "multipart/report; report-type=delivery-status;\n\tboundary=\"%s\"", +#else /* DSN */ + "multipart/mixed; boundary=\"%s\"", +#endif /* DSN */ + ee->e_msgboundary); + addheader("Content-Type", buf, 0, &ee->e_header); p = hvalue("Content-Transfer-Encoding", e->e_header); if (p != NULL && strcasecmp(p, "binary") != 0) @@ -567,48 +631,50 @@ returntosender(msg, returnq, flags, e) if (p == NULL && bitset(EF_HAS8BIT, e->e_flags)) p = "8bit"; if (p != NULL) - addheader("Content-Transfer-Encoding", p, &ee->e_header); + addheader("Content-Transfer-Encoding", + p, 0, &ee->e_header); } if (strncmp(msg, "Warning:", 8) == 0) { - addheader("Subject", msg, &ee->e_header); + addheader("Subject", msg, 0, &ee->e_header); p = "warning-timeout"; } else if (strncmp(msg, "Postmaster warning:", 19) == 0) { - addheader("Subject", msg, &ee->e_header); + addheader("Subject", msg, 0, &ee->e_header); p = "postmaster-warning"; } else if (strcmp(msg, "Return receipt") == 0) { - addheader("Subject", msg, &ee->e_header); + addheader("Subject", msg, 0, &ee->e_header); p = "return-receipt"; } else if (bitset(RTSF_PM_BOUNCE, flags)) { - snprintf(buf, sizeof buf, "Postmaster notify: %.*s", - (int)sizeof buf - 20, msg); - addheader("Subject", buf, &ee->e_header); + snprintf(buf, sizeof buf, + "Postmaster notify: see transcript for details"); + addheader("Subject", buf, 0, &ee->e_header); p = "postmaster-notification"; } else { - snprintf(buf, sizeof buf, "Returned mail: %.*s", - (int)sizeof buf - 20, msg); - addheader("Subject", buf, &ee->e_header); + snprintf(buf, sizeof buf, + "Returned mail: see transcript for details"); + addheader("Subject", buf, 0, &ee->e_header); p = "failure"; } (void) snprintf(buf, sizeof buf, "auto-generated (%s)", p); - addheader("Auto-Submitted", buf, &ee->e_header); + addheader("Auto-Submitted", buf, 0, &ee->e_header); /* fake up an address header for the from person */ expand("\201n", buf, sizeof buf, e); - if (parseaddr(buf, &ee->e_from, RF_COPYALL|RF_SENDERADDR, '\0', NULL, e) == NULL) + if (parseaddr(buf, &ee->e_from, + RF_COPYALL|RF_SENDERADDR, '\0', NULL, e) == NULL) { - syserr("553 Can't parse myself!"); + syserr("553 5.3.5 Can't parse myself!"); ExitStat = EX_SOFTWARE; returndepth--; - return (-1); + return -1; } ee->e_from.q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS); ee->e_from.q_flags |= QPINGONFAILURE; @@ -632,11 +698,12 @@ returntosender(msg, returnq, flags, e) returndepth--; /* check for delivery errors */ - if (ee->e_parent == NULL || !bitset(EF_RESPONSE, ee->e_parent->e_flags)) + if (ee->e_parent == NULL || + !bitset(EF_RESPONSE, ee->e_parent->e_flags)) return 0; for (q = ee->e_sendqueue; q != NULL; q = q->q_next) { - if (bitset(QQUEUEUP|QSENT, q->q_flags)) + if (QS_IS_ATTEMPTED(q->q_state)) return 0; } return -1; @@ -659,18 +726,20 @@ returntosender(msg, returnq, flags, e) ** Outputs the body of an error message. */ -void +/* ARGSUSED2 */ +static void errbody(mci, e, separator) register MCI *mci; register ENVELOPE *e; char *separator; { - register FILE *xfile; - char *p; - register ADDRESS *q = NULL; bool printheader; bool sendbody; bool pm_notify; + int save_errno; + register FILE *xfile; + char *p; + register ADDRESS *q = NULL; char buf[MAXLINE]; if (bitset(MCIF_INHEADER, mci->mci_flags)) @@ -709,8 +778,10 @@ errbody(mci, e, separator) else { for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) - if (bitset(QBADADDR, q->q_flags)) + { + if (QS_IS_BADADDR(q->q_state)) break; + } } if (!pm_notify && q == NULL && !bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags)) @@ -726,33 +797,40 @@ errbody(mci, e, separator) putline("", mci); } snprintf(buf, sizeof buf, "The original message was received at %s", - arpadate(ctime(&e->e_parent->e_ctime))); + arpadate(ctime(&e->e_parent->e_ctime))); putline(buf, mci); expand("from \201_", buf, sizeof buf, e->e_parent); putline(buf, mci); + + /* include id in postmaster copies */ + if (pm_notify && e->e_parent->e_id != NULL) + { + snprintf(buf, sizeof buf, "with id %s", e->e_parent->e_id); + putline(buf, mci); + } putline("", mci); /* ** Output error message header (if specified and available). */ - if (ErrMsgFile != NULL && !bitset(EF_SENDRECEIPT, e->e_parent->e_flags)) + if (ErrMsgFile != NULL && + !bitset(EF_SENDRECEIPT, e->e_parent->e_flags)) { if (*ErrMsgFile == '/') { - int sff = SFF_ROOTOK|SFF_REGONLY; + long sff = SFF_ROOTOK|SFF_REGONLY; if (DontLockReadFiles) sff |= SFF_NOLOCK; - if (!bitset(DBS_ERRORHEADERINUNSAFEDIRPATH, DontBlameSendmail)) + if (!bitnset(DBS_ERRORHEADERINUNSAFEDIRPATH, + DontBlameSendmail)) sff |= SFF_SAFEDIRPATH; xfile = safefopen(ErrMsgFile, O_RDONLY, 0444, sff); if (xfile != NULL) { while (fgets(buf, sizeof buf, xfile) != NULL) { - extern void translate_dollars __P((char *)); - translate_dollars(buf); expand(buf, buf, sizeof buf, e); putline(buf, mci); @@ -776,7 +854,7 @@ errbody(mci, e, separator) printheader = TRUE; for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) { - if (!bitset(QBADADDR, q->q_flags) || + if (!QS_IS_BADADDR(q->q_state) || !bitset(QPINGONFAILURE, q->q_flags)) continue; @@ -790,10 +868,18 @@ errbody(mci, e, separator) snprintf(buf, sizeof buf, "%s", shortenstring(q->q_paddr, MAXSHORTSTR)); putline(buf, mci); + if (q->q_rstatus != NULL) + { + snprintf(buf, sizeof buf, " (reason: %s)", + shortenstring(exitstat(q->q_rstatus), + MAXSHORTSTR)); + putline(buf, mci); + } if (q->q_alias != NULL) { snprintf(buf, sizeof buf, " (expanded from: %s)", - shortenstring(q->q_alias->q_paddr, MAXSHORTSTR)); + shortenstring(q->q_alias->q_paddr, + MAXSHORTSTR)); putline(buf, mci); } } @@ -803,7 +889,7 @@ errbody(mci, e, separator) printheader = TRUE; for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) { - if (bitset(QBADADDR, q->q_flags) || + if (QS_IS_BADADDR(q->q_state) || !bitset(QPRIMARY, q->q_flags) || !bitset(QDELAYED, q->q_flags)) continue; @@ -821,7 +907,8 @@ errbody(mci, e, separator) if (q->q_alias != NULL) { snprintf(buf, sizeof buf, " (expanded from: %s)", - shortenstring(q->q_alias->q_paddr, MAXSHORTSTR)); + shortenstring(q->q_alias->q_paddr, + MAXSHORTSTR)); putline(buf, mci); } } @@ -831,7 +918,7 @@ errbody(mci, e, separator) printheader = TRUE; for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) { - if (bitset(QBADADDR, q->q_flags) || + if (QS_IS_BADADDR(q->q_state) || !bitset(QPRIMARY, q->q_flags) || bitset(QDELAYED, q->q_flags)) continue; @@ -859,12 +946,13 @@ errbody(mci, e, separator) } snprintf(buf, sizeof buf, "%s (%s)", - shortenstring(q->q_paddr, MAXSHORTSTR), p); + shortenstring(q->q_paddr, MAXSHORTSTR), p); putline(buf, mci); if (q->q_alias != NULL) { snprintf(buf, sizeof buf, " (expanded from: %s)", - shortenstring(q->q_alias->q_paddr, MAXSHORTSTR)); + shortenstring(q->q_alias->q_paddr, + MAXSHORTSTR)); putline(buf, mci); } } @@ -876,25 +964,25 @@ errbody(mci, e, separator) */ (void) fflush(stdout); - p = queuename(e->e_parent, 'x'); - if ((xfile = fopen(p, "r")) == NULL) + if (e->e_parent->e_xfp == NULL) { - syserr("Cannot open %s", p); - putline(" ----- Transcript of session is unavailable -----\n", mci); + putline(" ----- Transcript of session is unavailable -----\n", + mci); } else { printheader = TRUE; + (void) bfrewind(e->e_parent->e_xfp); if (e->e_xfp != NULL) (void) fflush(e->e_xfp); - while (fgets(buf, sizeof buf, xfile) != NULL) + while (fgets(buf, sizeof buf, e->e_parent->e_xfp) != NULL) { if (printheader) - putline(" ----- Transcript of session follows -----\n", mci); + putline(" ----- Transcript of session follows -----\n", + mci); printheader = FALSE; putline(buf, mci); } - (void) xfclose(xfile, "errbody xscript", p); } errno = 0; @@ -918,8 +1006,9 @@ errbody(mci, e, separator) /* original envelope id from MAIL FROM: line */ if (e->e_parent->e_envid != NULL) { - (void) snprintf(buf, sizeof buf, "Original-Envelope-Id: %.800s", - xuntextify(e->e_parent->e_envid)); + (void) snprintf(buf, sizeof buf, + "Original-Envelope-Id: %.800s", + xuntextify(e->e_parent->e_envid)); putline(buf, mci); } @@ -936,14 +1025,15 @@ errbody(mci, e, separator) if (e->e_parent->e_from.q_mailer == NULL || (p = e->e_parent->e_from.q_mailer->m_mtatype) == NULL) p = "dns"; - (void) snprintf(buf, sizeof buf, "Received-From-MTA: %s; %.800s", - p, RealHostName); + (void) snprintf(buf, sizeof buf, + "Received-From-MTA: %s; %.800s", + p, RealHostName); putline(buf, mci); } /* Arrival-Date: -- when it arrived here */ (void) snprintf(buf, sizeof buf, "Arrival-Date: %s", - arpadate(ctime(&e->e_parent->e_ctime))); + arpadate(ctime(&e->e_parent->e_ctime))); putline(buf, mci); /* @@ -955,7 +1045,7 @@ errbody(mci, e, separator) register ADDRESS *r; char *action; - if (bitset(QBADADDR, q->q_flags)) + if (QS_IS_BADADDR(q->q_state)) action = "failed"; else if (!bitset(QPRIMARY, q->q_flags)) continue; @@ -980,8 +1070,9 @@ errbody(mci, e, separator) /* Original-Recipient: -- passed from on high */ if (q->q_orcpt != NULL) { - (void) snprintf(buf, sizeof buf, "Original-Recipient: %.800s", - q->q_orcpt); + (void) snprintf(buf, sizeof buf, + "Original-Recipient: %.800s", + q->q_orcpt); putline(buf, mci); } @@ -991,40 +1082,71 @@ errbody(mci, e, separator) p = "rfc822"; for (r = q; r->q_alias != NULL; r = r->q_alias) continue; - if (strchr(r->q_user, '@') != NULL) + if (strcasecmp(p, "rfc822") != 0) + { + (void) snprintf(buf, sizeof buf, + "Final-Recipient: %s; %.800s", + r->q_mailer->m_addrtype, + r->q_user); + } + else if (strchr(r->q_user, '@') != NULL) { (void) snprintf(buf, sizeof buf, - "Final-Recipient: %s; %.800s", - p, r->q_user); + "Final-Recipient: %s; %.800s", + p, r->q_user); } else if (strchr(r->q_paddr, '@') != NULL) { + char *qp; + bool b; + + qp = r->q_paddr; + /* strip brackets from address */ + b = FALSE; + if (*qp == '<') + { + b = qp[strlen(qp) - 1] == '>'; + if (b) + qp[strlen(qp) - 1] = '\0'; + qp++; + } (void) snprintf(buf, sizeof buf, - "Final-Recipient: %s; %.800s", - p, r->q_paddr); + "Final-Recipient: %s; %.800s", + p, qp); + /* undo damage */ + if (b) + qp[strlen(qp)] = '>'; } else { (void) snprintf(buf, sizeof buf, - "Final-Recipient: %s; %.700s@%.100s", - p, r->q_user, MyHostName); + "Final-Recipient: %s; %.700s@%.100s", + p, r->q_user, MyHostName); } putline(buf, mci); /* X-Actual-Recipient: -- the real problem address */ if (r != q && q->q_user[0] != '\0') { - if (strchr(q->q_user, '@') == NULL) + if (q->q_mailer != NULL && + q->q_mailer->m_addrtype != NULL) + p = q->q_mailer->m_addrtype; + else + p = "rfc822"; + + if (strcasecmp(p, "rfc822") == 0 && + strchr(q->q_user, '@') == NULL) { (void) snprintf(buf, sizeof buf, - "X-Actual-Recipient: %s; %.700s@%.100s", - p, q->q_user, MyHostName); + "X-Actual-Recipient: %s; %.700s@%.100s", + p, q->q_user, + MyHostName); } else { (void) snprintf(buf, sizeof buf, - "X-Actual-Recipient: %s; %.800s", - p, q->q_user); + "X-Actual-Recipient: %s; %.800s", + p, q->q_user); } putline(buf, mci); } @@ -1036,9 +1158,9 @@ errbody(mci, e, separator) /* Status: -- what _really_ happened? */ if (q->q_status != NULL) p = q->q_status; - else if (bitset(QBADADDR, q->q_flags)) + else if (QS_IS_BADADDR(q->q_state)) p = "5.0.0"; - else if (bitset(QQUEUEUP, q->q_flags)) + else if (QS_IS_QUEUEUP(q->q_state)) p = "4.0.0"; else p = "2.0.0"; @@ -1052,8 +1174,8 @@ errbody(mci, e, separator) (p = q->q_mailer->m_mtatype) == NULL) p = "dns"; (void) snprintf(buf, sizeof buf, - "Remote-MTA: %s; %.800s", - p, q->q_statmta); + "Remote-MTA: %s; %.800s", + p, q->q_statmta); p = &buf[strlen(buf) - 1]; if (*p == '.') *p = '\0'; @@ -1067,8 +1189,8 @@ errbody(mci, e, separator) if (p == NULL) p = "smtp"; (void) snprintf(buf, sizeof buf, - "Diagnostic-Code: %s; %.800s", - p, q->q_rstatus); + "Diagnostic-Code: %s; %.800s", + p, q->q_rstatus); putline(buf, mci); } @@ -1076,26 +1198,25 @@ errbody(mci, e, separator) if (q->q_statdate == (time_t) 0L) q->q_statdate = curtime(); (void) snprintf(buf, sizeof buf, - "Last-Attempt-Date: %s", - arpadate(ctime(&q->q_statdate))); + "Last-Attempt-Date: %s", + arpadate(ctime(&q->q_statdate))); putline(buf, mci); /* Will-Retry-Until: -- for delayed messages only */ - if (bitset(QQUEUEUP, q->q_flags) && - !bitset(QBADADDR, q->q_flags)) + if (QS_IS_QUEUEUP(q->q_state)) { time_t xdate; xdate = e->e_parent->e_ctime + TimeOuts.to_q_return[e->e_parent->e_timeoutclass]; snprintf(buf, sizeof buf, - "Will-Retry-Until: %s", - arpadate(ctime(&xdate))); + "Will-Retry-Until: %s", + arpadate(ctime(&xdate))); putline(buf, mci); } } } -#endif +#endif /* DSN */ /* ** Output text of original message @@ -1113,33 +1234,37 @@ errbody(mci, e, separator) putline(" ----- Original message follows -----\n", mci); else putline(" ----- Message header follows -----\n", mci); - (void) fflush(mci->mci_out); } else { (void) snprintf(buf, sizeof buf, "--%s", - e->e_msgboundary); + e->e_msgboundary); putline(buf, mci); (void) snprintf(buf, sizeof buf, "Content-Type: %s", - sendbody ? "message/rfc822" - : "text/rfc822-headers"); + sendbody ? "message/rfc822" + : "text/rfc822-headers"); putline(buf, mci); - p = hvalue("Content-Transfer-Encoding", e->e_parent->e_header); + p = hvalue("Content-Transfer-Encoding", + e->e_parent->e_header); if (p != NULL && strcasecmp(p, "binary") != 0) p = NULL; - if (p == NULL && bitset(EF_HAS8BIT, e->e_parent->e_flags)) + if (p == NULL && + bitset(EF_HAS8BIT, e->e_parent->e_flags)) p = "8bit"; if (p != NULL) { - (void) snprintf(buf, sizeof buf, "Content-Transfer-Encoding: %s", - p); + (void) snprintf(buf, sizeof buf, + "Content-Transfer-Encoding: %s", + p); putline(buf, mci); } } putline("", mci); + save_errno = errno; putheader(mci, e->e_parent->e_header, e->e_parent, M87F_OUTER); + errno = save_errno; if (sendbody) putbody(mci, e->e_parent, e->e_msgboundary); else if (e->e_msgboundary == NULL) @@ -1160,6 +1285,7 @@ errbody(mci, e, separator) putline(buf, mci); } putline("", mci); + (void) fflush(mci->mci_out); /* ** Cleanup and exit @@ -1293,8 +1419,8 @@ xtextify(t, taboo) strchr(taboo, c) != NULL) { *p++ = '+'; - *p++ = "0123456789abcdef"[c >> 4]; - *p++ = "0123456789abcdef"[c & 0xf]; + *p++ = "0123456789ABCDEF"[c >> 4]; + *p++ = "0123456789ABCDEF"[c & 0xf]; } else *p++ = c; @@ -1421,22 +1547,22 @@ xtextok(s) } /* ** PRUNEROUTE -- prune an RFC-822 source route -** +** ** Trims down a source route to the last internet-registered hop. ** This is encouraged by RFC 1123 section 5.3.3. -** +** ** Parameters: ** addr -- the address -** +** ** Returns: ** TRUE -- address was modified ** FALSE -- address could not be pruned -** +** ** Side Effects: ** modifies addr in-place */ -bool +static bool pruneroute(addr) char *addr; { @@ -1460,14 +1586,14 @@ pruneroute(addr) i = strlen(at + 1); if (i >= (SIZE_T) sizeof hostbuf) return FALSE; - strcpy(hostbuf, at + 1); + (void) strlcpy(hostbuf, at + 1, sizeof hostbuf); hostbuf[i - 1] = '\0'; while (start) { - if (getmxrr(hostbuf, mxhosts, FALSE, &rcode) > 0) + if (getmxrr(hostbuf, mxhosts, NULL, FALSE, &rcode) > 0) { - strcpy(addr + 1, start + 1); + (void) strlcpy(addr + 1, start + 1, strlen(addr) - 1); return TRUE; } c = *start; @@ -1475,12 +1601,12 @@ pruneroute(addr) comma = strrchr(addr, ','); if (comma != NULL && comma[1] == '@' && strlen(comma + 2) < (SIZE_T) sizeof hostbuf) - strcpy(hostbuf, comma + 2); + (void) strlcpy(hostbuf, comma + 2, sizeof hostbuf); else comma = NULL; *start = c; start = comma; } -#endif +#endif /* NAMED_BIND */ return FALSE; } diff --git a/contrib/sendmail/src/sendmail.8 b/contrib/sendmail/src/sendmail.8 index be31d2e..a256033 100644 --- a/contrib/sendmail/src/sendmail.8 +++ b/contrib/sendmail/src/sendmail.8 @@ -1,580 +1,687 @@ -.\" 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) 1988, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. +.\" The Regents of the University of California. All rights reserved. .\" .\" By using this file, you agree to the terms and conditions set .\" forth in the LICENSE file which can be found at the top level of .\" the sendmail distribution. .\" .\" -.\" @(#)sendmail.8 8.20 (Berkeley) 8/2/1998 +.\" $Id: sendmail.8,v 8.36 2000/02/01 05:49:57 gshapiro Exp $ .\" -.Dd August 2, 1998 -.Dt SENDMAIL 8 -.Os BSD 4 -.Sh NAME -.Nm sendmail -.Nd an electronic mail transport agent -.Sh SYNOPSIS -.Nm sendmail -.Op Ar flags -.Op Ar address ... -.Nm newaliases -.Nm mailq -.Op Fl v -.Sh DESCRIPTION -.Nm Sendmail +.\" $FreeBSD$ +.\" +.TH SENDMAIL 8 "$Date: 2000/02/01 05:49:57 $" +.SH NAME +.B sendmail +\- an electronic mail transport agent +.SH SYNOPSIS +.B sendmail +.RI [ flags "] [" "address ..." ] +.br +.B newaliases +.br +.B mailq +.RB [ \-v ] +.br +.B hoststat +.br +.B purgestat +.br +.B smtpd +.SH DESCRIPTION +.B Sendmail sends a message to one or more -.Em recipients , -routing the message over whatever networks +.I recipients, +routing the message over whatever networks are necessary. -.Nm Sendmail -does internetwork forwarding as necessary +.B Sendmail +does internetwork forwarding as necessary to deliver the message to the correct place. -.Pp -.Nm Sendmail -is not intended as a user interface routine; -other programs provide user-friendly +.PP +.B Sendmail +is not intended as a user interface routine; +other programs provide user-friendly front ends; -.Nm sendmail +.B sendmail is used only to deliver pre-formatted messages. -.Pp +.PP With no flags, -.Nm sendmail -reads its standard input -up to an end-of-file -or a line consisting only of a single dot +.B sendmail +reads its standard input +up to an end-of-file +or a line consisting only of a single dot and sends a copy of the message found there -to all of the addresses listed. -It determines the network(s) to use +to all of the addresses listed. +It determines the network(s) to use based on the syntax and contents of the addresses. -.Pp -Local addresses are looked up in a file +.PP +Local addresses are looked up in a file and aliased appropriately. -Aliasing can be prevented by preceding the address +Aliasing can be prevented by preceding the address with a backslash. -Normally the sender is not included in any alias -expansions, e.g., -if `john' sends to `group', -and `group' includes `john' in the expansion, -then the letter will not be delivered to `john'. -.Ss Parameters -.Bl -tag -width Fl -.It Fl B Ns Ar type +Beginning with 8.10, the sender is included in any alias +expansions, e.g., +if `john' sends to `group', +and `group' includes `john' in the expansion, +then the letter will also be delivered to `john'. +.SS Parameters +.TP +.BI \-B type Set the body type to -.Ar type . -Current legal values -.Li 7BIT -or -.Li 8BITMIME . -.It Fl ba -Go into -.Tn ARPANET -mode. -All input lines must end with a CR-LF, -and all messages will be generated with a CR-LF at the end. -Also, -the ``From:'' and ``Sender:'' +.IR type . +Current legal values are +7BIT +or +8BITMIME. +.TP +.B \-ba +Go into +ARPANET +mode. All input lines must end with a CR-LF, +and all messages will be generated with a CR-LF at the end. +Also, +the ``From:'' and ``Sender:'' fields are examined for the name of the sender. -.It Fl bd -Run as a daemon. This requires Berkeley -.Tn IPC . -.Nm Sendmail -will fork and run in background +.TP +.B \-bd +Run as a daemon. This requires Berkeley +IPC. +.B Sendmail +will fork and run in background listening on socket 25 for incoming -.Tn SMTP -connections. -This is normally run from -.Pa /etc/rc . -.It Fl bD +SMTP +connections. +This is normally run from +/etc/rc. +.TP +.B \-bD Same as -.Fl bd +.B \-bd except runs in foreground. -.It Fl bh +.TP +.B \-bh Print the persistent host status database. -.It Fl bH -Purge the persistent host status database. -.It Fl bi +.TP +.B \-bH +Purge expired entries from the persistent host status database. +.TP +.B \-bi Initialize the alias database. -.It Fl bm +.TP +.B \-bm Deliver mail in the usual way (default). -.It Fl bp +.TP +.B \-bp Print a listing of the queue. -.It Fl bs -Use the -.Tn SMTP -protocol as described in -.Tn RFC821 -on standard input and output. +.TP +.B \-bs +Use the +SMTP +protocol as described in +RFC821 +on standard input and output. This flag implies all the operations of the -.Fl ba -flag that are compatible with -.Tn SMTP . -.It Fl bt -Run in address test mode. -This mode reads addresses and shows the steps in parsing; +.B \-ba +flag that are compatible with +SMTP. +.TP +.B \-bt +Run in address test mode. +This mode reads addresses and shows the steps in parsing; it is used for debugging configuration tables. -.It Fl bv +.TP +.B \-bv Verify names only \- do not try to collect or deliver a message. -Verify mode is normally used for validating +Verify mode is normally used for validating users or mailing lists. -.It Fl C Ns Ar file +.TP +.BI \-C file Use alternate configuration file. -.Nm Sendmail +.B Sendmail refuses to run as root if an alternate configuration file is specified. -.It Fl d Ns Ar X +.TP +.BI \-d X Set debugging value to -.Ar X . +.IR X . .ne 1i -.It Fl F Ns Ar fullname +.TP +.BI \-F fullname Set the full name of the sender. -.It Fl f Ns Ar name -Sets the name of the ``from'' person -(i.e., the sender of the mail). -.Fl f -can only be used -by ``trusted'' users +.TP +.BI \-f name +Sets the name of the ``from'' person +(i.e., the envelope sender of the mail). +This address may also be used in the From: header +if that header is missing during initial submission. +The envelope sender address is used as the recipient +for delivery status notifications +and may also appear in a Return-Path: header. +.B \-f +should only be used +by ``trusted'' users (normally -.Em root , -.Em daemon , +.IR root ", " daemon , and -.Em network ) -or if the person you are trying to become +.IR network ) +or if the person you are trying to become is the same as the person you are. -.It Fl h Ns Ar N +Otherwise, +an X-Authentication-Warning header +will be added to the message. +.TP +.BI \-h N Set the hop count to -.Ar N . -The hop count is incremented every time the mail is +.IR N . +The hop count is incremented every time the mail is processed. -When it reaches a limit, +When it reaches a limit, the mail is returned with an error message, -the victim of an aliasing loop. -If not specified, +the victim of an aliasing loop. +If not specified, ``Received:'' lines in the message are counted. -.It Fl i +.TP +.B \-i Ignore dots alone on lines by themselves in incoming messages. This should be set if you are reading data from a file. -.It Fl N Ar dsn +.TP +.BI "\-L " tag +Set the identifier used in syslog messages to the supplied +.IR tag . +.TP +.BI "\-N " dsn Set delivery status notification conditions to -.Ar dsn, -which can be -.Ql never -for no notifications -or a comma separated list of the values -.Ql failure -to be notified if delivery failed, -.Ql delay -to be notified if delivery is delayed, and -.Ql success +.IR dsn , +which can be +`never' +for no notifications +or a comma separated list of the values +`failure' +to be notified if delivery failed, +`delay' +to be notified if delivery is delayed, and +`success' to be notified when the message is successfully delivered. -.It Fl n +.TP +.B \-n Don't do aliasing. -.It Fl O Ar option Ns = Ns Em value +.TP +\fB\-O\fP \fIoption\fR=\fIvalue\fR Set option -.Ar option +.I option to the specified -.Em value . -This form uses long names. -See below for more details. -.It Fl o Ns Ar x Em value +.IR value . +This form uses long names. See below for more details. +.TP +.BI \-o "x value" Set option -.Ar x +.I x to the specified -.Em value . -This form uses single character names only. -The short names are not described in this manual page; +.IR value . +This form uses single character names only. +The short names are not described in this manual page; see the -.%T "Sendmail Installation and Operation Guide" +.I "Sendmail Installation and Operation Guide" for details. -.It Fl p Ns Ar protocol -Set the name of the protocol used to receive the message. -This can be a simple protocol name such as ``UUCP'' +.TP +.BI \-p protocol +Set the name of the protocol used to receive the message. +This can be a simple protocol name such as ``UUCP'' or a protocol and hostname, such as ``UUCP:ucbvax''. -.It Fl q Ns Bq Ar time -Processed saved messages in the queue at given intervals. +.TP +\fB\-q\fR[\fItime\fR] +Processed saved messages in the queue at given intervals. If -.Ar time -is omitted, -process the queue once. -.Xr Time -is given as a tagged number, -with -.Ql s -being seconds, -.Ql m -being minutes, -.Ql h -being hours, -.Ql d -being days, -and -.Ql w +.I time +is omitted, process the queue once. +.I Time +is given as a tagged number, +with +`s' +being seconds, +`m' +being minutes, +`h' +being hours, +`d' +being days, +and +`w' being weeks. -For example, -.Ql \-q1h30m -or -.Ql \-q90m +For example, +`\-q1h30m' +or +`\-q90m' would both set the timeout to one hour thirty minutes. If -.Ar time +.I time is specified, -.Nm sendmail -will run in background. +.B sendmail +will run in the background. This option can be used safely with -.Fl bd . -.It Fl qI Ns Ar substr +.BR \-bd . +.TP +.BI \-qI substr Limit processed jobs to those containing -.Ar substr +.I substr as a substring of the queue id. -.It Fl qR Ns Ar substr +.TP +.BI \-qR substr Limit processed jobs to those containing -.Ar substr +.I substr as a substring of one of the recipients. -.It Fl qS Ns Ar substr +.TP +.BI \-qS substr Limit processed jobs to those containing -.Ar substr +.I substr as a substring of the sender. -.It Fl R Ar return -Set the amount of the message to be returned +.TP +.BI "\-R " return +Set the amount of the message to be returned if the message bounces. The -.Ar return -parameter can be -.Ql full -to return the entire message or -.Ql hdrs -to return only the headers. -.It Fl r Ns Ar name +.I return +parameter can be +`full' +to return the entire message or +`hdrs' +to return only the headers. +In the latter case also local bounces return only the headers. +.TP +.BI \-r name An alternate and obsolete form of the -.Fl f +.B \-f flag. -.It Fl t -Read message for recipients. -To:, Cc:, and Bcc: lines will be scanned for recipient addresses. +.TP +.B \-t +Read message for recipients. +To:, Cc:, and Bcc: lines will be scanned for recipient addresses. The Bcc: line will be deleted before transmission. -.It Fl U -Initial (user) submission. -This should -.Em always +.TP +.B \-U +Initial (user) submission. This should +.I always be set when called from a user agent such as -.Nm Mail +.B Mail or -.Nm exmh +.B exmh and -.Em never +.I never be set when called by a network delivery agent such as -.Nm rmail . -.It Fl V Ar envid -Set the original envelope id. -This is propagated across SMTP to servers that support DSNs +.BR rmail . +.TP +.BI "\-V " envid +Set the original envelope id. +This is propagated across SMTP to servers that support DSNs and is returned in DSN-compliant error messages. -.It Fl v -Go into verbose mode. +.TP +.B \-v +Go into verbose mode. Alias expansions will be announced, etc. -.It Fl X Ar logfile +.TP +.BI "\-X " logfile Log all traffic in and out of mailers in the indicated log file. -This should only be used as a last resort -for debugging mailer bugs. +This should only be used as a last resort +for debugging mailer bugs. It will log a lot of data very quickly. -.It Fl - -Stop processing command flags and use the rest of the arguments -as addresses. -.El -.Ss Options +.TP +.B \-\- +Stop processing command flags and use the rest of the arguments as +addresses. +.SS Options There are also a number of processing options that may be set. -Normally these will only be used by a system administrator. -Options may be set either on the command line +Normally these will only be used by a system administrator. +Options may be set either on the command line using the -.Fl o -flag (for short names), -the -.Fl O -flag (for long names), -or in the configuration file. +.B \-o +flag (for short names), the +.B \-O +flag (for long names), +or in the configuration file. This is a partial list limited to those options that are likely to be useful -on the command line -and only shows the long names; +on the command line +and only shows the long names; for a complete list (and details), consult the -.%T "Sendmail Installation and Operation Guide" . +.IR "Sendmail Installation and Operation Guide" . The options are: -.Bl -tag -width Fl -.It Li AliasFile= Ns Ar file +.TP +.RI AliasFile= file Use alternate alias file. -.It Li HoldExpensive -On mailers that are considered ``expensive'' to connect to, -don't initiate immediate connection. +.TP +HoldExpensive +On mailers that are considered ``expensive'' to connect to, +don't initiate immediate connection. This requires queueing. -.It Li CheckpointInterval= Ns Ar N +.TP +.RI CheckpointInterval= N Checkpoint the queue file after every -.Ar N -successful deliveries (default 10). -This avoids excessive duplicate deliveries -when sending to long mailing lists +.I N +successful deliveries (default 10). +This avoids excessive duplicate deliveries +when sending to long mailing lists interrupted by system crashes. .ne 1i -.It Li DeliveryMode= Ns Ar x +.TP +.RI DeliveryMode= x Set the delivery mode to -.Ar x . -Delivery modes are -.Ql i -for interactive (synchronous) delivery, -.Ql b -for background (asynchronous) delivery, -.Ql q +.IR x . +Delivery modes are +`i' +for interactive (synchronous) delivery, +`b' +for background (asynchronous) delivery, +`q' for queue only \- i.e., -actual delivery is done the next time the queue is run, and -.Ql d -for deferred \- the same as -.Ql q -except that database lookups (notably DNS and NIS lookups) are avoided. -.It Li ErrorMode= Ns Ar x +actual delivery is done the next time the queue is run, and +`d' +for deferred \- the same as +`q' +except that database lookups for maps which have set the \-D option +(default for the host map) are avoided. +.TP +.RI ErrorMode= x Set error processing to mode -.Ar x . -Valid modes are -.Ql m -to mail back the error message, -.Ql w -to ``write'' back the error message -(or mail it back if the sender is not logged in), -.Ql p -to print the errors on the terminal -(default), -.Ql q -to throw away error messages -(only exit status is returned), -and -.Ql e -to do special processing for the BerkNet. -If the text of the message is not mailed back -by +.IR x . +Valid modes are +`m' +to mail back the error message, +`w' +to ``write'' +back the error message +(or mail it back if the sender is not logged in), +`p' +to print the errors on the terminal +(default), +`q' +to throw away error messages +(only exit status is returned), +and +`e' +to do special processing for the BerkNet. +If the text of the message is not mailed back +by modes -.Ql m +`m' or -.Ql w -and if the sender is local to this machine, +`w' +and if the sender is local to this machine, a copy of the message is appended to the file -.Pa dead.letter +.I dead.letter in the sender's home directory. -.It Li SaveFromLine +.TP +SaveFromLine Save -.Tn UNIX Ns \-style +UNIX-style From lines at the front of messages. -.It Li MaxHopCount= Ar N -The maximum number of times a message is allowed to ``hop'' +.TP +.RI MaxHopCount= N +The maximum number of times a message is allowed to ``hop'' before we decide it is in a loop. -.It Li IgnoreDots -Do not take dots on a line by themselves +.TP +IgnoreDots +Do not take dots on a line by themselves as a message terminator. -.It Li SendMimeErrors -Send error messages in MIME format. -If not set, the DSN (Delivery Status Notification) SMTP extension +.TP +SendMimeErrors +Send error messages in MIME format. +If not set, the DSN (Delivery Status Notification) SMTP extension is disabled. -.It Li ConnectionCacheTimeout= Ns Ar timeout +.TP +.RI ConnectionCacheTimeout= timeout Set connection cache timeout. -.It Li ConnectionCacheSize= Ns Ar N +.TP +.RI ConnectionCacheSize= N Set connection cache size. -.It Li LogLevel= Ns Ar n +.TP +.RI LogLevel= n The log level. -.It Li MeToo -Send to ``me'' (the sender) also if I am in an alias expansion. -.It Li CheckAliases +.TP +.RI MeToo= False +Don't send to ``me'' (the sender) if I am in an alias expansion. +.TP +CheckAliases Validate the right hand side of aliases during a -.Xr newaliases 1 +newaliases(1) command. -.It Li OldStyleHeaders -If set, this message may have -old style headers. -If not set, -this message is guaranteed to have new style headers -(i.e., commas instead of spaces between addresses). -If set, an adaptive algorithm is used that will correctly +.TP +OldStyleHeaders +If set, this message may have +old style headers. +If not set, +this message is guaranteed to have new style headers +(i.e., commas instead of spaces between addresses). +If set, an adaptive algorithm is used that will correctly determine the header format in most cases. -.It Li QueueDirectory= Ns Ar queuedir +.TP +.RI QueueDirectory= queuedir Select the directory in which to queue messages. -.It Li StatusFile= Ns Ar file +.TP +.RI StatusFile= file Save statistics in the named file. -.It Li Timeout.queuereturn= Ns Ar time -Set the timeout on undelivered messages in the queue to the specified time. -After delivery has failed -(e.g., because of a host being down) -for this amount of time, -failed messages will be returned to the sender. +.TP +.RI Timeout.queuereturn= time +Set the timeout on undelivered messages in the queue to the specified time. +After delivery has failed +(e.g., because of a host being down) +for this amount of time, +failed messages will be returned to the sender. The default is five days. -.It Li UserDatabaseSpec= Ns Ar userdatabase +.TP +.RI UserDatabaseSpec= userdatabase If set, a user database is consulted to get forwarding information. -You can consider this an adjunct to the aliasing mechanism, -except that the database is intended to be distributed; -aliases are local to a particular host. +You can consider this an adjunct to the aliasing mechanism, +except that the database is intended to be distributed; +aliases are local to a particular host. This may not be available if your sendmail does not have the -.Dv USERDB +USERDB option compiled in. -.It Li ForkEachJob -Fork each job during queue runs. +.TP +ForkEachJob +Fork each job during queue runs. May be convenient on memory-poor machines. -.It Li SevenBitInput +.TP +SevenBitInput Strip incoming messages to seven bits. -.It Li EightBitMode= Ns Ar mode +.TP +.RI EightBitMode= mode Set the handling of eight bit input to seven bit destinations to -.Ar mode : -.Li m +.IR mode : +m (mimefy) will convert to seven-bit MIME format, -.Li p -(pass) will pass it as eight bits (but violates protocols), +p +(pass) will pass it as eight bits (but violates protocols), and -.Li s +s (strict) will bounce the message. -.It Li MinQueueAge= Ns Ar timeout +.TP +.RI MinQueueAge= timeout Sets how long a job must ferment in the queue between attempts to send it. -.It Li DefaultCharSet= Ns Ar charset -Sets the default character set used to label 8-bit data +.TP +.RI DefaultCharSet= charset +Sets the default character set used to label 8-bit data that is not otherwise labelled. -.It Li DialDelay= Ns Ar sleeptime -If opening a connection fails, +.TP +.RI DialDelay= sleeptime +If opening a connection fails, sleep for -.Ar sleeptime -seconds and try again. +.I sleeptime +seconds and try again. Useful on dial-on-demand sites. -.It Li NoRecipientAction= Ns Ar action -Set the behaviour when there are no recipient headers (To:, Cc: or Bcc:) -in the message to -.Ar action : -.Li none +.TP +.RI NoRecipientAction= action +Set the behaviour when there are no recipient headers (To:, Cc: or +Bcc:) in the message to +.IR action : +none leaves the message unchanged, -.Li add-to +add-to adds a To: header with the envelope recipients, -.Li add-apparently-to +add-apparently-to adds an Apparently-To: header with the envelope recipients, -.Li add-bcc +add-bcc adds an empty Bcc: header, and -.Li add-to-undisclosed +add-to-undisclosed adds a header reading -.Ql "To: undisclosed-recipients:;" . -.It Li MaxDaemonChildren= Ns Ar N +`To: undisclosed-recipients:;'. +.TP +.RI MaxDaemonChildren= N Sets the maximum number of children that an incoming SMTP daemon will allow to spawn at any time to -.Ar N . -.It Li ConnectionRateThrottle= Ns Ar N +.IR N . +.TP +.RI ConnectionRateThrottle= N Sets the maximum number of connections per second to the SMTP port to -.Ar N . -.El -.Pp -In aliases, -the first character of a name may be -a vertical bar to cause interpretation of -the rest of the name as a command -to pipe the mail to. -It may be necessary to quote the name +.IR N . +.PP +In aliases, +the first character of a name may be +a vertical bar to cause interpretation of +the rest of the name as a command +to pipe the mail to. +It may be necessary to quote the name to keep -.Nm sendmail -from suppressing the blanks from between arguments. +.B sendmail +from suppressing the blanks from between arguments. For example, a common alias is: -.Pp -.Bd -literal -offset indent -compact +.IP msgs: "|/usr/bin/msgs -s" -.Ed -.Pp +.PP Aliases may also have the syntax -.Dq :include: Ns Ar filename +.RI ``:include: filename '' to ask -.Xr sendmail -to read the named file for a list of recipients. +.B sendmail +to read the named file for a list of recipients. For example, an alias such as: -.Pp -.Bd -literal -offset indent -compact +.IP poets: ":include:/usr/local/lib/poets.list" -.Ed -.Pp +.PP would read -.Pa /usr/local/lib/poets.list +.I /usr/local/lib/poets.list for the list of addresses making up the group. -.Pp -.Nm Sendmail -returns an exit status -describing what it did. +.PP +.B Sendmail +returns an exit status +describing what it did. The codes are defined in -.Aq Pa sysexits.h : -.Bl -tag -width EX_UNAVAILABLE -compact -offset indent -.It Dv EX_OK +.RI < sysexits.h >: +.TP +EX_OK Successful completion on all addresses. -.It Dv EX_NOUSER +.TP +EX_NOUSER User name not recognized. -.It Dv EX_UNAVAILABLE -Catchall meaning necessary resources +.TP +EX_UNAVAILABLE +Catchall meaning necessary resources were not available. -.It Dv EX_SYNTAX +.TP +EX_SYNTAX Syntax error in address. -.It Dv EX_SOFTWARE -Internal software error, +.TP +EX_SOFTWARE +Internal software error, including bad arguments. -.It Dv EX_OSERR -Temporary operating system error, +.TP +EX_OSERR +Temporary operating system error, such as -.Dq cannot fork . -.It Dv EX_NOHOST +``cannot fork''. +.TP +EX_NOHOST Host name not recognized. -.It Dv EX_TEMPFAIL -Message could not be sent immediately, +.TP +EX_TEMPFAIL +Message could not be sent immediately, but was queued. -.El -.Pp +.PP If invoked as -.Nm newaliases , -.Nm sendmail -will rebuild the alias database. -If invoked as -.Nm mailq , -.Nm sendmail +.BR newaliases , +.B sendmail +will rebuild the alias database. If invoked as +.BR mailq , +.B sendmail will print the contents of the mail queue. -.Sh FILES +If invoked as +.BR hoststat , +.B sendmail +will print the persistent host status database. +If invoked as +.BR purgestat , +.B sendmail +will purge expired entries from the persistent host status database. +If invoked as +.BR smtpd , +.B sendmail +will act as a daemon, as if the +.B \-bd +option were specified. +.SH NOTES +.B sendmail +often gets blamed for many problems +that are actually the result of other problems, +such as overly permissive modes on directories. +For this reason, +.B sendmail +checks the modes on system directories and files +to determine if they can be trusted. +Although these checks can be turned off +and your system security reduced by setting the +.BR DontBlameSendmail +option, +the permission problems should be fixed. +For more information, see: + +.I http://www.sendmail.org/tips/DontBlameSendmail.html +.SH FILES Except for the file -.Pa /etc/sendmail.cf -itself and the daemon process ID file, -the following pathnames are all specified in -.Pa /etc/sendmail.cf. -Thus, +.I /etc/mail/sendmail.cf +itself the following pathnames are all specified in +.IR /etc/mail/sendmail.cf . +Thus, these values are only approximations. -.Pp -.Bl -tag -width /usr/lib/sendmail.fc -compact -.It Pa /etc/aliases +.PP +.TP + /etc/mail/aliases raw data for alias names -.It Pa /etc/aliases.db +.TP + /etc/mail/aliases.db data base of alias names -.It Pa /etc/sendmail.cf +.TP + /etc/mail/sendmail.cf configuration file -.It Pa /usr/share/misc/sendmail.hf +.TP + /etc/mail/helpfile help file -.It Pa /var/log/sendmail.st +.TP + /etc/mail/statistics collected statistics -.It Pa /var/spool/mqueue/* +.TP + /var/spool/mqueue/* temp files -.El -.Sh SEE ALSO -.Xr mail 1 , -.Xr syslog 3 , -.Xr aliases 5 , -.Xr mailaddr 7 , -.Xr mail.local 8 , -.Xr rc 8 , -.Xr rmail 8 ; -.Pp -DARPA +.SH SEE ALSO +mail(1), +syslog(3), +aliases(5), +mailaddr(7), +mail.local(8), +rc(8), +rmail(8) +.PP +DARPA Internet Request For Comments -.%T RFC819 , -.%T RFC821 , -.%T RFC822 . -.Rs -.%T "Sendmail \- An Internetwork Mail Router" -.%V SMM -.%N \&No. 9 -.Re -.Rs -.%T "Sendmail Installation and Operation Guide" -.%V SMM -.%N \&No. 8 -.Re -.Sh HISTORY +.IR RFC819 , +.IR RFC821 , +.IR RFC822 . +.IR "Sendmail \- An Internetwork Mail Router" , +No. 9, SMM. +.IR "Sendmail Installation and Operation Guide" , +No. 8, SMM. +.PP +http://www.sendmail.org/ +.SH HISTORY The -.Nm +.B sendmail command appeared in -.Bx 4.2 . +4.2BSD. |