diff --git a/gnu/dist/sendmail/cf/cf/README b/gnu/dist/sendmail/cf/cf/README new file mode 100644 index 000000000000..c724cdf4ee72 --- /dev/null +++ b/gnu/dist/sendmail/cf/cf/README @@ -0,0 +1,34 @@ + + SENDMAIL CONFIGURATION FILES INSTALLATION + +This document describes how to install the sendmail configuration files. +Please see ../README about the sendmail configuration files themselves. + +By default you need two .mc files: sendmail.mc and submit.mc. The +latter is an OS independent configuration file for the mail submission +program (MSP). See ../README for details about both files. + +Installation of these two files can be done via: + + make install-cf + +If you use a different name than "sendmail" for your main .mc file" +then you should use + + make install-cf CF=config + +where "config" is the name of your main .mc file. + +The default installation directory is /etc/mail and can be changed +by specifying + + MAILDIR=/other/dir + +The name of the source file for "submit.cf" can be overridden by + + SUBMIT=msp + +For more details see Makefile. + + +Revision: 1.2, Last updated Date: 2002/02/22 00:33:54 diff --git a/gnu/dist/sendmail/cf/cf/generic-mpeix.cf b/gnu/dist/sendmail/cf/cf/generic-mpeix.cf new file mode 100644 index 000000000000..93d1efc67395 --- /dev/null +++ b/gnu/dist/sendmail/cf/cf/generic-mpeix.cf @@ -0,0 +1,1375 @@ +# +# Copyright (c) 1998-2002 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. +# +# 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 CONFIGURATION FILE +##### +##### built by ca@wiz.smi.sendmail.com on Tue Feb 11 11:23:21 PST 2003 +##### in /extra/home/ca/sm-8.12.8/OpenSource/sendmail-8.12.8/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +##### +##### DO NOT EDIT THIS FILE! Only edit the source .mc file. +##### +###################################################################### +###################################################################### + +##### Id: cfhead.m4,v 8.108.2.1 2002/08/27 20:19:08 gshapiro Exp ##### +##### Id: cf.m4,v 8.32 1999/02/07 07:26:14 gshapiro Exp ##### +##### Id: generic-mpeix.mc,v 8.1 2001/12/13 23:56:37 gshapiro Exp ##### + +##### Id: mpeix.m4,v 1.1 2001/12/13 23:56:40 gshapiro Exp ##### + + +##### Id: generic.m4,v 8.15 1999/04/04 00:51:09 ca Exp ##### + +##### Id: redirect.m4,v 8.15 1999/08/06 01:47:36 gshapiro Exp ##### + +##### Id: use_cw_file.m4,v 8.11 2001/08/26 20:58:57 gshapiro Exp ##### + + + +##### Id: proto.m4,v 8.649.2.14 2002/12/30 15:46:02 ca Exp ##### + +# level 10 config file format +V10/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +O DontBlameSendmail=ForwardFileInGroupWritableDirPath + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +# my LDAP cluster +# need to set this before any LDAP lookups are done (including classes) +#D{sendmailMTACluster}$m + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T +C{ResOk}OKR + + +# Hosts for which relaying is permitted ($=R) +FR-o /etc/mail/relay-domains + +# arithmetic map +Karith arith + + + + + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +C{E}root + + + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.12.8 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +#O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# queue file mode (qf files) +#O QueueFileMode=0600 + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=25 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Family=inet, Address=0.0.0.0 + +# Modifiers to define {daemon_flags} for direct submissions +#O DirectSubmissionModifiers + +# Use as mail submission program? See sendmail/SECURITY +#O UseMSP + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# limit on number of concurrent queue runners +#O MaxQueueChildren + +# maximum number of queue-runners per queue-grouping with multiple queues +#O MaxRunnersPerQueue=1 + +# priority of queue runners (nice(3)) +#O NiceQueueRun + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# perform initial split of envelope without checking MX records +#O FastSplit=1 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# key for shared memory; 0 to turn off +#O SharedMemoryKey=0 + + + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.aconnect=0s +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 +#O Timeout.lhlo=2m +#O Timeout.auth=10m +#O Timeout.starttls=1h + +# time for DeliverBy; extension disabled if less than 0 +#O DeliverByMin=0 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/etc/mail/statistics + +# time zone handling: +# if undefined, use system default +# if defined but null, use TZ envariable passed in +# if defined and non-null, use that info +O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +O DefaultUser=SERVER.SENDMAIL + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# load average at which we delay connections; 0 means no limit +#O DelayLA=0 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=0 + +# maximum number of new connections per second +#O ConnectionRateThrottle=0 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (name hardwired on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +# True (the default) means they are not trustworthy. +#O UnsafeGroupWrites=True + + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# limit the rate recipients per SMTP envelope are accepted +# once the threshold number of recipients have been rejected +#O BadRcptThrottle=20 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +O TrustedUser=SERVER.SENDMAIL + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# lookup type to find information about local mailboxes +#O MailboxDatabase=pw + +# list of authentication mechanisms +#O AuthMechanisms=EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# SMTP AUTH flags +#O AuthOptions + +# SMTP AUTH maximum encryption strength +#O AuthMaxBits + +# SMTP STARTTLS server options +#O TLSSrvOptions + +# Input mail filters +#O InputMailFilters + + +# CA directory +#O CACertPath +# CA file +#O CACertFile +# Server Cert +#O ServerCertFile +# Server private key +#O ServerKeyFile +# Client Cert +#O ClientCertFile +# Client private key +#O ClientKeyFile +# DHParameters (only required if DSA/DH is used) +#O DHParameters +# Random data source (required for systems without /dev/urandom under OpenSSL) +#O RandFile + +############################ +# QUEUE GROUP DEFINITIONS # +############################ + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated$?{auth_ssf} bits=${auth_ssf}$.) + $.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version} + (version=${tls_version} cipher=${cipher} bits=${cipher_bits} verify=${verify})$.$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# handle null input (translate to <@> special case) +R$@ $@ <@> + +# strip group: syntax (not inside angle brackets!) and trailing semicolon +R$* $: $1 <@> mark addresses +R$* < $* > $* <@> $: $1 < $2 > $3 unmark +R@ $* <@> $: @ $1 unmark @host:... +R$* [ IPv6 : $+ ] <@> $: $1 [ IPv6 : $2 ] unmark IPv6 addr +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $+ :; > $* $@ $2 :; <@> catch +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# strip angle brackets -- note RFC733 heuristic to get innermost item +R$* $: < $1 > housekeeping <> +R$+ < $* > < $2 > strip excess on left +R< $* > $+ < $1 > strip excess on right +R<> $@ < @ > MAIL FROM:<> case +R< $+ > $: $1 remove housekeeping <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ [ $* ] : $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $1 : $2 ; < @ $3 > list syntax +R $+ : $* ; $@ $1 : $2; list syntax + +# find focus for @ syntax addresses +R$+ @ $+ $: $1 < @ $2 > focus on domain +R$+ < $+ @ $+ > $1 $2 < @ $3 > move gaze right +R$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv4/IPv6 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [addr] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$+ :; <@> $@ $1 : handle +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$+ <@> $#error $@ 5.1.3 $: "553 Hostname required" +R$* $: <> $1 +R<> $* < @ [ $* ] : $+ > $* $1 < @ [ $2 ] : $3 > $4 +R<> $* < @ [ $* ] , $+ > $* $1 < @ [ $2 ] , $3 > $4 +R<> $* < @ [ $* ] $+ > $* $#error $@ 5.1.2 $: "553 Invalid address" +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* @ > $* $#error $@ 5.1.2 $: "553 Invalid route address" +R$* @ $* < @ $* > $* $#error $@ 5.1.3 $: "553 Invalid route address" +R$* , $~O $* $#error $@ 5.1.3 $: "553 Invalid route address" + + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works + + +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# handle locally delivered names +R$=L $#local $: @ $1 special local names +R$+ $#local $: $1 regular local names + +########################################################################### +### Ruleset 5 -- special rewriting after aliases have been expanded ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#ok $@ $1 no change +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + + + + +# deal with plussed users so aliases work nicely +R$+ + * $#local $@ $&h $: $1 +R$+ + $* $#local $@ + $2 $: $1 + * + +# prepend an empty "forward host" on the front +R$+ $: <> $1 + + + +R< > $+ $: < > < $1 <> $&h > nope, restore +detail + +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in + +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension + +R< $~[ : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > + +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $~[ : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $~[ : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +R$* < @ *LOCAL* > $@ $1 < @ $j . > + +################################################################### +### Ruleset 94 -- convert envelope names to masqueraded form ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + + + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$+> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +# authenticated? +R$* $: $1 $| $>"tls_client" $&{verify} $| MAIL +R$* $| $#$+ $#$2 +R$* $| $* $: $1 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required for sender address" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $j > $: $1 < @ $j > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_addr} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required for sender address " $&f + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R<$={ResOk}> $* $@ domain ok: stop +R $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve" +R $* $#error $@ 5.1.8 $: "553 Domain of sender address " $&f " does not exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# empty address? +R<> $#error $@ nouser $: "553 User address required" +R$@ $#error $@ nouser $: "553 User address required" +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +###################################################################### +R$* $: $1 $| @ $>"Rcpt_ok" $1 +R$* $| @ $#TEMP $+ $: $1 $| T $2 +R$* $| @ $#$* $#$2 +R$* $| @ RELAY $@ RELAY +R$* $| @ $* $: O $| $>"Relay_ok" $1 +R$* $| T $+ $: T $2 $| $>"Relay_ok" $1 +R$* $| $#TEMP $+ $#error $2 +R$* $| $#$* $#$2 +R$* $| RELAY $@ RELAY +R T $+ $| $* $#error $1 +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +###################################################################### +### Rcpt_ok: is the recipient ok? +###################################################################### +SRcpt_ok +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + +# authenticated via TLS? +R$* $: $1 $| $>RelayTLS client authenticated? +R$* $| $# $+ $# $2 error/ok? +R$* $| $* $: $1 no + +R$* $: $1 $| $>"Local_Relay_Auth" $&{auth_type} +R$* $| $# $* $# $2 +R$* $| NO $: $1 +R$* $| $* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAY +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAY +R$+ < @ $* $=R > $@ RELAY + + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAY +R<$+> $* $: $2 + +###################################################################### +### Relay_ok: is the relay/sender ok? +###################################################################### +SRelay_ok +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAY originated locally +R0 $@ RELAY originated locally +R127.0.0.1 $@ RELAY originated locally +RIPv6:::1 $@ RELAY originated locally +R$=R $* $@ RELAY relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAY ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#TEMP $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: <@> $&{client_name} +# pass to name server to make hostname canonical +R<@> $* $=P $: $1 $2 +R<@> $+ $: $[ $1 $] +R$* . $1 strip trailing dots +R $=w $@ RELAY +R $* $=R $@ RELAY + + + + +###################################################################### +### trust_auth: is user trusted to authenticate as someone else? +### +### Parameters: +### $1: AUTH= parameter from MAIL command +###################################################################### + +SLocal_trust_auth +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +###################################################################### +### Relay_Auth: allow relaying based on authentication? +### +### Parameters: +### $1: ${auth_type} +###################################################################### +SLocal_Relay_Auth + + + +###################################################################### +### tls_client: is connection with client "good" enough? +### (done in server) +### +### Parameters: +### ${verify} $| (MAIL|STARTTLS) +###################################################################### +Stls_client +R$* $| $* $@ $>"TLS_connection" $1 + +###################################################################### +### tls_server: is connection with server "good" enough? +### (done in client) +### +### Parameter: +### ${verify} +###################################################################### +Stls_server +R$* $@ $>"TLS_connection" $1 + +###################################################################### +### TLS_connection: is TLS connection "good" enough? +### +### Parameters: +### ${verify} +### Requirement: RHS from access map, may be ? for none. +###################################################################### +STLS_connection +RSOFTWARE $#error $@ 4.7.0 $: "403 TLS handshake." + + +###################################################################### +### RelayTLS: allow relaying based on TLS authentication +### +### Parameters: +### none +###################################################################### +SRelayTLS +# authenticated? + +###################################################################### +### authinfo: lookup authinfo in the access map +### +### Parameters: +### $1: {server_name} +### $2: {server_addr} +###################################################################### +Sauthinfo + +# +###################################################################### +###################################################################### +##### +##### MAIL FILTER DEFINITIONS +##### +###################################################################### +###################################################################### + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### Id: local.m4,v 8.58 2000/10/26 01:58:29 ca Exp ##### + +# +# Envelope sender rewriting +# +SEnvFromL +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL +R$+ < @ $* > $: $1 strip host part +R$+ + $* $: < $&{addr_type} > $1 + $2 mark with addr type +R $+ + $* $: $1 remove +detail for sender +R< $* > $+ $: $2 else remove mark + +# +# Header sender rewriting +# +SHdrFromL +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain + +Mlocal, P=/bin/tsmail, F=lsDFMAw5:/|@qmu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=tsmail $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### Id: smtp.m4,v 8.64 2001/04/03 01:52:54 gshapiro Exp ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# do UUCP heuristics; note that these are shared with UUCP mailers +R$+ < @ $+ .UUCP. > $: < $2 ! > $1 convert to UUCP form +R$+ < @ $* > $* $@ $1 < @ $2 > $3 not UUCP form + +# leave these in .UUCP form to avoid further tampering +R< $&h ! > $- ! $+ $@ $2 < @ $1 .UUCP. > +R< $&h ! > $-.$+ ! $+ $@ $3 < @ $1.$2 > +R< $&h ! > $+ $@ $1 < @ $&h .UUCP. > +R< $+ ! > $+ $: $1 ! $2 < @ $Y > use UUCP_RELAY +R$+ < @ $~[ $* : $+ > $@ $1 < @ $4 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R:; <@> $@ list:; special case + +# do special header rewriting +R$* <@> $* $@ $1 <@> $2 pass null host through +R< @ $* > $* $@ < @ $1 > $2 pass route-addr through +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=TCP $h + diff --git a/gnu/dist/sendmail/cf/cf/generic-mpeix.mc b/gnu/dist/sendmail/cf/cf/generic-mpeix.mc new file mode 100644 index 000000000000..947248700fdf --- /dev/null +++ b/gnu/dist/sendmail/cf/cf/generic-mpeix.mc @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 2001 Sendmail, Inc. and its suppliers. +# 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. +# +# + +# +# This is a generic configuration file for HP MPE/iX. +# It has support for local and SMTP mail only. If you want to +# customize it, copy it to a name appropriate for your environment +# and do the modifications there. +# + +divert(0)dnl +VERSIONID(`Id: generic-mpeix.mc,v 8.1 2001/12/13 23:56:37 gshapiro Exp') +OSTYPE(mpeix)dnl +DOMAIN(generic)dnl +define(`confFORWARD_PATH', `$z/.forward')dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/dist/sendmail/cf/cf/generic-solaris.cf b/gnu/dist/sendmail/cf/cf/generic-solaris.cf new file mode 100644 index 000000000000..c71aea8fb8b4 --- /dev/null +++ b/gnu/dist/sendmail/cf/cf/generic-solaris.cf @@ -0,0 +1,1374 @@ +# +# Copyright (c) 1998-2002 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. +# +# 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 CONFIGURATION FILE +##### +##### built by ca@wiz.smi.sendmail.com on Tue Feb 11 11:23:22 PST 2003 +##### in /extra/home/ca/sm-8.12.8/OpenSource/sendmail-8.12.8/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +##### +##### DO NOT EDIT THIS FILE! Only edit the source .mc file. +##### +###################################################################### +###################################################################### + +##### Id: cfhead.m4,v 8.108.2.1 2002/08/27 20:19:08 gshapiro Exp ##### +##### Id: cf.m4,v 8.32 1999/02/07 07:26:14 gshapiro Exp ##### +##### Id: generic-solaris.mc,v 8.13 2001/06/27 21:46:30 gshapiro Exp ##### + +##### Id: solaris2.m4,v 8.22 1999/09/24 21:43:53 ca Exp ##### + +##### Id: generic.m4,v 8.15 1999/04/04 00:51:09 ca Exp ##### + +##### Id: redirect.m4,v 8.15 1999/08/06 01:47:36 gshapiro Exp ##### + +##### Id: use_cw_file.m4,v 8.11 2001/08/26 20:58:57 gshapiro Exp ##### + + + +##### Id: proto.m4,v 8.649.2.14 2002/12/30 15:46:02 ca Exp ##### + +# level 10 config file format +V10/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +# my LDAP cluster +# need to set this before any LDAP lookups are done (including classes) +#D{sendmailMTACluster}$m + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T +C{ResOk}OKR + + +# Hosts for which relaying is permitted ($=R) +FR-o /etc/mail/relay-domains + +# arithmetic map +Karith arith + + + + + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +C{E}root + + + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.12.8 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +#O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# queue file mode (qf files) +#O QueueFileMode=0600 + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=25 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Family=inet, Address=0.0.0.0 + +# Modifiers to define {daemon_flags} for direct submissions +#O DirectSubmissionModifiers + +# Use as mail submission program? See sendmail/SECURITY +#O UseMSP + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# limit on number of concurrent queue runners +#O MaxQueueChildren + +# maximum number of queue-runners per queue-grouping with multiple queues +#O MaxRunnersPerQueue=1 + +# priority of queue runners (nice(3)) +#O NiceQueueRun + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# perform initial split of envelope without checking MX records +#O FastSplit=1 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# key for shared memory; 0 to turn off +#O SharedMemoryKey=0 + + + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.aconnect=0s +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 +#O Timeout.lhlo=2m +#O Timeout.auth=10m +#O Timeout.starttls=1h + +# time for DeliverBy; extension disabled if less than 0 +#O DeliverByMin=0 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/etc/mail/statistics + +# time zone handling: +# if undefined, use system default +# if defined but null, use TZ envariable passed in +# if defined and non-null, use that info +#O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# load average at which we delay connections; 0 means no limit +#O DelayLA=0 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=0 + +# maximum number of new connections per second +#O ConnectionRateThrottle=0 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (name hardwired on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +# True (the default) means they are not trustworthy. +#O UnsafeGroupWrites=True + + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# limit the rate recipients per SMTP envelope are accepted +# once the threshold number of recipients have been rejected +#O BadRcptThrottle=20 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# lookup type to find information about local mailboxes +#O MailboxDatabase=pw + +# list of authentication mechanisms +#O AuthMechanisms=EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# SMTP AUTH flags +#O AuthOptions + +# SMTP AUTH maximum encryption strength +#O AuthMaxBits + +# SMTP STARTTLS server options +#O TLSSrvOptions + +# Input mail filters +#O InputMailFilters + + +# CA directory +#O CACertPath +# CA file +#O CACertFile +# Server Cert +#O ServerCertFile +# Server private key +#O ServerKeyFile +# Client Cert +#O ClientCertFile +# Client private key +#O ClientKeyFile +# DHParameters (only required if DSA/DH is used) +#O DHParameters +# Random data source (required for systems without /dev/urandom under OpenSSL) +#O RandFile + +############################ +# QUEUE GROUP DEFINITIONS # +############################ + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated$?{auth_ssf} bits=${auth_ssf}$.) + $.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version} + (version=${tls_version} cipher=${cipher} bits=${cipher_bits} verify=${verify})$.$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# handle null input (translate to <@> special case) +R$@ $@ <@> + +# strip group: syntax (not inside angle brackets!) and trailing semicolon +R$* $: $1 <@> mark addresses +R$* < $* > $* <@> $: $1 < $2 > $3 unmark +R@ $* <@> $: @ $1 unmark @host:... +R$* [ IPv6 : $+ ] <@> $: $1 [ IPv6 : $2 ] unmark IPv6 addr +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $+ :; > $* $@ $2 :; <@> catch +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# strip angle brackets -- note RFC733 heuristic to get innermost item +R$* $: < $1 > housekeeping <> +R$+ < $* > < $2 > strip excess on left +R< $* > $+ < $1 > strip excess on right +R<> $@ < @ > MAIL FROM:<> case +R< $+ > $: $1 remove housekeeping <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ [ $* ] : $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $1 : $2 ; < @ $3 > list syntax +R $+ : $* ; $@ $1 : $2; list syntax + +# find focus for @ syntax addresses +R$+ @ $+ $: $1 < @ $2 > focus on domain +R$+ < $+ @ $+ > $1 $2 < @ $3 > move gaze right +R$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv4/IPv6 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [addr] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$+ :; <@> $@ $1 : handle +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$+ <@> $#error $@ 5.1.3 $: "553 Hostname required" +R$* $: <> $1 +R<> $* < @ [ $* ] : $+ > $* $1 < @ [ $2 ] : $3 > $4 +R<> $* < @ [ $* ] , $+ > $* $1 < @ [ $2 ] , $3 > $4 +R<> $* < @ [ $* ] $+ > $* $#error $@ 5.1.2 $: "553 Invalid address" +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* @ > $* $#error $@ 5.1.2 $: "553 Invalid route address" +R$* @ $* < @ $* > $* $#error $@ 5.1.3 $: "553 Invalid route address" +R$* , $~O $* $#error $@ 5.1.3 $: "553 Invalid route address" + + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works + + +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# handle locally delivered names +R$=L $#local $: @ $1 special local names +R$+ $#local $: $1 regular local names + +########################################################################### +### Ruleset 5 -- special rewriting after aliases have been expanded ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#ok $@ $1 no change +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + + + + +# deal with plussed users so aliases work nicely +R$+ + * $#local $@ $&h $: $1 +R$+ + $* $#local $@ + $2 $: $1 + * + +# prepend an empty "forward host" on the front +R$+ $: <> $1 + + + +R< > $+ $: < > < $1 <> $&h > nope, restore +detail + +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in + +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension + +R< $~[ : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > + +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $~[ : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $~[ : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +R$* < @ *LOCAL* > $@ $1 < @ $j . > + +################################################################### +### Ruleset 94 -- convert envelope names to masqueraded form ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + + + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$+> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +# authenticated? +R$* $: $1 $| $>"tls_client" $&{verify} $| MAIL +R$* $| $#$+ $#$2 +R$* $| $* $: $1 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required for sender address" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $j > $: $1 < @ $j > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_addr} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required for sender address " $&f + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R<$={ResOk}> $* $@ domain ok: stop +R $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve" +R $* $#error $@ 5.1.8 $: "553 Domain of sender address " $&f " does not exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# empty address? +R<> $#error $@ nouser $: "553 User address required" +R$@ $#error $@ nouser $: "553 User address required" +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +###################################################################### +R$* $: $1 $| @ $>"Rcpt_ok" $1 +R$* $| @ $#TEMP $+ $: $1 $| T $2 +R$* $| @ $#$* $#$2 +R$* $| @ RELAY $@ RELAY +R$* $| @ $* $: O $| $>"Relay_ok" $1 +R$* $| T $+ $: T $2 $| $>"Relay_ok" $1 +R$* $| $#TEMP $+ $#error $2 +R$* $| $#$* $#$2 +R$* $| RELAY $@ RELAY +R T $+ $| $* $#error $1 +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +###################################################################### +### Rcpt_ok: is the recipient ok? +###################################################################### +SRcpt_ok +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + +# authenticated via TLS? +R$* $: $1 $| $>RelayTLS client authenticated? +R$* $| $# $+ $# $2 error/ok? +R$* $| $* $: $1 no + +R$* $: $1 $| $>"Local_Relay_Auth" $&{auth_type} +R$* $| $# $* $# $2 +R$* $| NO $: $1 +R$* $| $* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAY +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAY +R$+ < @ $* $=R > $@ RELAY + + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAY +R<$+> $* $: $2 + +###################################################################### +### Relay_ok: is the relay/sender ok? +###################################################################### +SRelay_ok +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAY originated locally +R0 $@ RELAY originated locally +R127.0.0.1 $@ RELAY originated locally +RIPv6:::1 $@ RELAY originated locally +R$=R $* $@ RELAY relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAY ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#TEMP $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: <@> $&{client_name} +# pass to name server to make hostname canonical +R<@> $* $=P $: $1 $2 +R<@> $+ $: $[ $1 $] +R$* . $1 strip trailing dots +R $=w $@ RELAY +R $* $=R $@ RELAY + + + + +###################################################################### +### trust_auth: is user trusted to authenticate as someone else? +### +### Parameters: +### $1: AUTH= parameter from MAIL command +###################################################################### + +SLocal_trust_auth +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +###################################################################### +### Relay_Auth: allow relaying based on authentication? +### +### Parameters: +### $1: ${auth_type} +###################################################################### +SLocal_Relay_Auth + + + +###################################################################### +### tls_client: is connection with client "good" enough? +### (done in server) +### +### Parameters: +### ${verify} $| (MAIL|STARTTLS) +###################################################################### +Stls_client +R$* $| $* $@ $>"TLS_connection" $1 + +###################################################################### +### tls_server: is connection with server "good" enough? +### (done in client) +### +### Parameter: +### ${verify} +###################################################################### +Stls_server +R$* $@ $>"TLS_connection" $1 + +###################################################################### +### TLS_connection: is TLS connection "good" enough? +### +### Parameters: +### ${verify} +### Requirement: RHS from access map, may be ? for none. +###################################################################### +STLS_connection +RSOFTWARE $#error $@ 4.7.0 $: "403 TLS handshake." + + +###################################################################### +### RelayTLS: allow relaying based on TLS authentication +### +### Parameters: +### none +###################################################################### +SRelayTLS +# authenticated? + +###################################################################### +### authinfo: lookup authinfo in the access map +### +### Parameters: +### $1: {server_name} +### $2: {server_addr} +###################################################################### +Sauthinfo + +# +###################################################################### +###################################################################### +##### +##### MAIL FILTER DEFINITIONS +##### +###################################################################### +###################################################################### + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### Id: local.m4,v 8.58 2000/10/26 01:58:29 ca Exp ##### + +# +# Envelope sender rewriting +# +SEnvFromL +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL +R$+ < @ $* > $: $1 strip host part +R$+ + $* $: < $&{addr_type} > $1 + $2 mark with addr type +R $+ + $* $: $1 remove +detail for sender +R< $* > $+ $: $2 else remove mark + +# +# Header sender rewriting +# +SHdrFromL +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain + +Mlocal, P=/usr/lib/mail.local, F=lsDFMAw5:/|@qfSmn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=mail.local -d $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### Id: smtp.m4,v 8.64 2001/04/03 01:52:54 gshapiro Exp ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# do UUCP heuristics; note that these are shared with UUCP mailers +R$+ < @ $+ .UUCP. > $: < $2 ! > $1 convert to UUCP form +R$+ < @ $* > $* $@ $1 < @ $2 > $3 not UUCP form + +# leave these in .UUCP form to avoid further tampering +R< $&h ! > $- ! $+ $@ $2 < @ $1 .UUCP. > +R< $&h ! > $-.$+ ! $+ $@ $3 < @ $1.$2 > +R< $&h ! > $+ $@ $1 < @ $&h .UUCP. > +R< $+ ! > $+ $: $1 ! $2 < @ $Y > use UUCP_RELAY +R$+ < @ $~[ $* : $+ > $@ $1 < @ $4 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R:; <@> $@ list:; special case + +# do special header rewriting +R$* <@> $* $@ $1 <@> $2 pass null host through +R< @ $* > $* $@ < @ $1 > $2 pass route-addr through +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=TCP $h + diff --git a/gnu/dist/sendmail/cf/cf/generic-solaris.mc b/gnu/dist/sendmail/cf/cf/generic-solaris.mc new file mode 100644 index 000000000000..6846a18b072d --- /dev/null +++ b/gnu/dist/sendmail/cf/cf/generic-solaris.mc @@ -0,0 +1,29 @@ +divert(-1) +# +# Copyright (c) 1998, 1999, 2001 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. +# +# 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. +# +# + +# +# This is a generic configuration file for SunOS 5.x (a.k.a. Solaris 2.x +# and Solaris 7 through the present version). +# +# It has support for local and SMTP mail only. If you want to +# customize it, copy it to a name appropriate for your environment +# and do the modifications there. +# + +divert(0)dnl +VERSIONID(`Id: generic-solaris.mc,v 8.13 2001/06/27 21:46:30 gshapiro Exp') +OSTYPE(solaris2)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/dist/sendmail/cf/cf/submit.cf b/gnu/dist/sendmail/cf/cf/submit.cf new file mode 100644 index 000000000000..990323077c7a --- /dev/null +++ b/gnu/dist/sendmail/cf/cf/submit.cf @@ -0,0 +1,1372 @@ +# +# Copyright (c) 1998-2002 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. +# +# 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 CONFIGURATION FILE +##### +##### +###################################################################### +##### +##### DO NOT EDIT THIS FILE! Only edit the source .mc file. +##### +###################################################################### +###################################################################### + +##### Id: cfhead.m4,v 8.108.2.1 2002/08/27 20:19:08 gshapiro Exp ##### +##### Id: cf.m4,v 8.32 1999/02/07 07:26:14 gshapiro Exp ##### +##### Id: submit.mc,v 8.6.2.4 2002/12/29 03:54:34 ca Exp ##### +##### Id: msp.m4,v 1.32 2002/03/26 22:02:03 ca Exp ##### + +##### Id: no_default_msa.m4,v 8.2 2001/02/14 05:03:22 gshapiro Exp ##### + + +##### Id: proto.m4,v 8.649.2.14 2002/12/30 15:46:02 ca Exp ##### + +# level 10 config file format +V10/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +# my LDAP cluster +# need to set this before any LDAP lookups are done (including classes) +#D{sendmailMTACluster}$m + +Cwlocalhost + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T +C{ResOk}OKR + + +# Hosts for which relaying is permitted ($=R) +FR-o /etc/mail/relay-domains + +# arithmetic map +Karith arith + + + + + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root + + + +# my name for error messages +DnMAILER-DAEMON + + +D{MTAHost}[127.0.0.1] + + +# Configuration version number +DZ8.12.8/Submit + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +#O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +#O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=i + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# queue file mode (qf files) +O QueueFileMode=0660 + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=25 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options + +O DaemonPortOptions=Name=NoMTA, Addr=127.0.0.1, M=E + +# SMTP client options +#O ClientPortOptions=Family=inet, Address=0.0.0.0 + +# Modifiers to define {daemon_flags} for direct submissions +#O DirectSubmissionModifiers + +# Use as mail submission program? See sendmail/SECURITY +O UseMSP=True + +# privacy flags +O PrivacyOptions=goaway,noetrn,restrictqrun + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# limit on number of concurrent queue runners +#O MaxQueueChildren + +# maximum number of queue-runners per queue-grouping with multiple queues +#O MaxRunnersPerQueue=1 + +# priority of queue runners (nice(3)) +#O NiceQueueRun + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# perform initial split of envelope without checking MX records +#O FastSplit=1 + +# queue directory +O QueueDirectory=/var/spool/clientmqueue + +# key for shared memory; 0 to turn off +#O SharedMemoryKey=0 + + + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.aconnect=0s +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 +#O Timeout.lhlo=2m +#O Timeout.auth=10m +#O Timeout.starttls=1h + +# time for DeliverBy; extension disabled if less than 0 +#O DeliverByMin=0 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/var/spool/clientmqueue/sm-client.st + +# time zone handling: +# if undefined, use system default +# if defined but null, use TZ envariable passed in +# if defined and non-null, use that info +O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# load average at which we delay connections; 0 means no limit +#O DelayLA=0 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=0 + +# maximum number of new connections per second +#O ConnectionRateThrottle=0 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (name hardwired on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +O DontInitGroups=True + +# are group-writable :include: and .forward files (un)trustworthy? +# True (the default) means they are not trustworthy. +#O UnsafeGroupWrites=True + + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +O RunAsUser=smmsp + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# limit the rate recipients per SMTP envelope are accepted +# once the threshold number of recipients have been rejected +#O BadRcptThrottle=20 + +# shall we get local names from our installed interfaces? +O DontProbeInterfaces=True + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +O TrustedUser=smmsp + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +#O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +O PidFile=/var/spool/clientmqueue/sm-client.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# lookup type to find information about local mailboxes +#O MailboxDatabase=pw + +# list of authentication mechanisms +#O AuthMechanisms=EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# SMTP AUTH flags +#O AuthOptions + +# SMTP AUTH maximum encryption strength +#O AuthMaxBits + +# SMTP STARTTLS server options +#O TLSSrvOptions + +# Input mail filters +#O InputMailFilters + + +# CA directory +#O CACertPath +# CA file +#O CACertFile +# Server Cert +#O ServerCertFile +# Server private key +#O ServerKeyFile +# Client Cert +#O ClientCertFile +# Client private key +#O ClientKeyFile +# DHParameters (only required if DSA/DH is used) +#O DHParameters +# Random data source (required for systems without /dev/urandom under OpenSSL) +#O RandFile + +############################ +# QUEUE GROUP DEFINITIONS # +############################ + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated$?{auth_ssf} bits=${auth_ssf}$.) + $.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version} + (version=${tls_version} cipher=${cipher} bits=${cipher_bits} verify=${verify})$.$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# handle null input (translate to <@> special case) +R$@ $@ <@> + +# strip group: syntax (not inside angle brackets!) and trailing semicolon +R$* $: $1 <@> mark addresses +R$* < $* > $* <@> $: $1 < $2 > $3 unmark +R@ $* <@> $: @ $1 unmark @host:... +R$* [ IPv6 : $+ ] <@> $: $1 [ IPv6 : $2 ] unmark IPv6 addr +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $+ :; > $* $@ $2 :; <@> catch +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# strip angle brackets -- note RFC733 heuristic to get innermost item +R$* $: < $1 > housekeeping <> +R$+ < $* > < $2 > strip excess on left +R< $* > $+ < $1 > strip excess on right +R<> $@ < @ > MAIL FROM:<> case +R< $+ > $: $1 remove housekeeping <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ [ $* ] : $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $1 : $2 ; < @ $3 > list syntax +R $+ : $* ; $@ $1 : $2; list syntax + +# find focus for @ syntax addresses +R$+ @ $+ $: $1 < @ $2 > focus on domain +R$+ < $+ @ $+ > $1 $2 < @ $3 > move gaze right +R$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# convert node::user addresses into a domain-based address +R$- :: $+ $@ $>Canonify2 $2 < @ $1 .DECNET > resolve DECnet names +R$- . $- :: $+ $@ $>Canonify2 $3 < @ $1.$2 .DECNET > numeric DECnet addr + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv4/IPv6 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [addr] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$+ :; <@> $@ $1 : handle +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# put DECnet back in :: form +R$+ @ $+ . DECNET $2 :: $1 u@h.DECNET => h::u +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$+ <@> $#error $@ 5.1.3 $: "553 Hostname required" +R$* $: <> $1 +R<> $* < @ [ $* ] : $+ > $* $1 < @ [ $2 ] : $3 > $4 +R<> $* < @ [ $* ] , $+ > $* $1 < @ [ $2 ] , $3 > $4 +R<> $* < @ [ $* ] $+ > $* $#error $@ 5.1.2 $: "553 Invalid address" +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* @ > $* $#error $@ 5.1.2 $: "553 Invalid route address" +R$* @ $* < @ $* > $* $#error $@ 5.1.3 $: "553 Invalid route address" +R$* , $~O $* $#error $@ 5.1.3 $: "553 Invalid route address" + + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works + + +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# handle locally delivered names +R$=L $#local $: @ $1 special local names +R$+ $#local $: $1 regular local names + +########################################################################### +### Ruleset 5 -- special rewriting after aliases have been expanded ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#ok $@ $1 no change +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + + + + +# deal with plussed users so aliases work nicely +R$+ + * $#local $@ $&h $: $1 +R$+ + $* $#local $@ + $2 $: $1 + * + +# prepend an empty "forward host" on the front +R$+ $: <> $1 + + + +R< > $+ $: < > < $1 <> $&h > nope, restore +detail + +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in + +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension + +R< $~[ : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > + +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $~[ : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $~[ : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +R$* < @ *LOCAL* > $@ $1 < @ $j . > + +################################################################### +### Ruleset 94 -- convert envelope names to masqueraded form ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + + + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$+> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +# authenticated? +R$* $: $1 $| $>"tls_client" $&{verify} $| MAIL +R$* $| $#$+ $#$2 +R$* $| $* $: $1 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required for sender address" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $j > $: $1 < @ $j > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_addr} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required for sender address " $&f + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R<$={ResOk}> $* $@ domain ok: stop +R $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve" +R $* $#error $@ 5.1.8 $: "553 Domain of sender address " $&f " does not exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# empty address? +R<> $#error $@ nouser $: "553 User address required" +R$@ $#error $@ nouser $: "553 User address required" +# check for deferred delivery mode +R$* $: < $&{deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +###################################################################### +R$* $: $1 $| @ $>"Rcpt_ok" $1 +R$* $| @ $#TEMP $+ $: $1 $| T $2 +R$* $| @ $#$* $#$2 +R$* $| @ RELAY $@ RELAY +R$* $| @ $* $: O $| $>"Relay_ok" $1 +R$* $| T $+ $: T $2 $| $>"Relay_ok" $1 +R$* $| $#TEMP $+ $#error $2 +R$* $| $#$* $#$2 +R$* $| RELAY $@ RELAY +R T $+ $| $* $#error $1 +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +###################################################################### +### Rcpt_ok: is the recipient ok? +###################################################################### +SRcpt_ok +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + +# authenticated via TLS? +R$* $: $1 $| $>RelayTLS client authenticated? +R$* $| $# $+ $# $2 error/ok? +R$* $| $* $: $1 no + +R$* $: $1 $| $>"Local_Relay_Auth" $&{auth_type} +R$* $| $# $* $# $2 +R$* $| NO $: $1 +R$* $| $* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAY +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAY +R$+ < @ $* $=R > $@ RELAY + + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAY +R<$+> $* $: $2 + +###################################################################### +### Relay_ok: is the relay/sender ok? +###################################################################### +SRelay_ok +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAY originated locally +R0 $@ RELAY originated locally +R127.0.0.1 $@ RELAY originated locally +RIPv6:::1 $@ RELAY originated locally +R$=R $* $@ RELAY relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAY ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#TEMP $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: <@> $&{client_name} +# pass to name server to make hostname canonical +R<@> $* $=P $: $1 $2 +R<@> $+ $: $[ $1 $] +R$* . $1 strip trailing dots +R $=w $@ RELAY +R $* $=R $@ RELAY + + + + +###################################################################### +### trust_auth: is user trusted to authenticate as someone else? +### +### Parameters: +### $1: AUTH= parameter from MAIL command +###################################################################### + +SLocal_trust_auth +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +###################################################################### +### Relay_Auth: allow relaying based on authentication? +### +### Parameters: +### $1: ${auth_type} +###################################################################### +SLocal_Relay_Auth + + + +###################################################################### +### tls_client: is connection with client "good" enough? +### (done in server) +### +### Parameters: +### ${verify} $| (MAIL|STARTTLS) +###################################################################### +Stls_client +R$* $| $* $@ $>"TLS_connection" $1 + +###################################################################### +### tls_server: is connection with server "good" enough? +### (done in client) +### +### Parameter: +### ${verify} +###################################################################### +Stls_server +R$* $@ $>"TLS_connection" $1 + +###################################################################### +### TLS_connection: is TLS connection "good" enough? +### +### Parameters: +### ${verify} +### Requirement: RHS from access map, may be ? for none. +###################################################################### +STLS_connection +RSOFTWARE $#error $@ 4.7.0 $: "403 TLS handshake." + + +###################################################################### +### RelayTLS: allow relaying based on TLS authentication +### +### Parameters: +### none +###################################################################### +SRelayTLS +# authenticated? + +###################################################################### +### authinfo: lookup authinfo in the access map +### +### Parameters: +### $1: {server_name} +### $2: {server_addr} +###################################################################### +Sauthinfo + + + + +SLocal_localaddr +R$+ $: $>ParseRecipient $1 +R$* < @ $+ > $* $#relay $@ ${MTAHost} $: $1 < @ $2 > $3 +# DECnet +R$+ :: $+ $#relay $@ ${MTAHost} $: $1 :: $2 +R$* $#relay $@ ${MTAHost} $: $1 < @ $j > +# +###################################################################### +###################################################################### +##### +##### MAIL FILTER DEFINITIONS +##### +###################################################################### +###################################################################### + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### Id: local.m4,v 8.58 2000/10/26 01:58:29 ca Exp ##### + +# +# Envelope sender rewriting +# +SEnvFromL +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL +R$+ < @ $* > $: $1 strip host part +R$+ + $* $: < $&{addr_type} > $1 + $2 mark with addr type +R $+ + $* $: $1 remove +detail for sender +R< $* > $+ $: $2 else remove mark + +# +# Header sender rewriting +# +SHdrFromL +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain + +Mlocal, P=[IPC], F=lmDFMuXkw5, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/SMTP, + A=TCP $h +Mprog, P=[IPC], F=lmDFMuXk5, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=TCP $h + +##################################### +### SMTP Mailer specification ### +##################################### + +##### Id: smtp.m4,v 8.64 2001/04/03 01:52:54 gshapiro Exp ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# do UUCP heuristics; note that these are shared with UUCP mailers +R$+ < @ $+ .UUCP. > $: < $2 ! > $1 convert to UUCP form +R$+ < @ $* > $* $@ $1 < @ $2 > $3 not UUCP form + +# leave these in .UUCP form to avoid further tampering +R< $&h ! > $- ! $+ $@ $2 < @ $1 .UUCP. > +R< $&h ! > $-.$+ ! $+ $@ $3 < @ $1.$2 > +R< $&h ! > $+ $@ $1 < @ $&h .UUCP. > +R< $+ ! > $+ $: $1 ! $2 < @ $Y > use UUCP_RELAY +R$+ < @ $~[ $* : $+ > $@ $1 < @ $4 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP +R$+ $: $>PseudoToReal $1 sender/recipient common +R:; <@> $@ list:; special case + +# do special header rewriting +R$* <@> $* $@ $1 <@> $2 pass null host through +R< @ $* > $* $@ < @ $1 > $2 pass route-addr through +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuXk5, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mesmtp, P=[IPC], F=mDFMuXak5, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Msmtp8, P=[IPC], F=mDFMuX8k5, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mdsmtp, P=[IPC], F=mDFMuXa%k5, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=TCP $h +Mrelay, P=[IPC], F=mDFMuXa8k, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=TCP $h + diff --git a/gnu/dist/sendmail/cf/cf/submit.mc b/gnu/dist/sendmail/cf/cf/submit.mc new file mode 100644 index 000000000000..5d4aca6f7e67 --- /dev/null +++ b/gnu/dist/sendmail/cf/cf/submit.mc @@ -0,0 +1,26 @@ +divert(-1) +# +# Copyright (c) 2001, 2002 Sendmail, Inc. and its suppliers. +# 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. +# +# + +# +# This is the prototype file for a set-group-ID sm-msp sendmail that +# acts as a initial mail submission program. +# + +divert(0)dnl +VERSIONID(`Id: submit.mc,v 8.6.2.4 2002/12/29 03:54:34 ca Exp') +define(`confCF_VERSION', `Submit')dnl +define(`__OSTYPE__',`')dnl dirty hack to keep proto.m4 from complaining +define(`_USE_DECNET_SYNTAX_', `1')dnl support DECnet +define(`confTIME_ZONE', `USE_TZ')dnl +define(`confDONT_INIT_GROUPS', `True')dnl +dnl +dnl If you use IPv6 only, change [127.0.0.1] to [IPv6:::1] +FEATURE(`msp', `[127.0.0.1]')dnl diff --git a/gnu/dist/sendmail/cf/feature/authinfo.m4 b/gnu/dist/sendmail/cf/feature/authinfo.m4 new file mode 100644 index 000000000000..8223f1d0ab67 --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/authinfo.m4 @@ -0,0 +1,22 @@ +divert(-1) +# +# Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0) +VERSIONID(`Id: authinfo.m4,v 1.7 2001/03/16 00:51:25 gshapiro Exp') +divert(-1) + +define(`_AUTHINFO_TABLE_', `') + +LOCAL_CONFIG +# authinfo list database: contains info for authentication as client +Kauthinfo ifelse(defn(`_ARG_'), `', DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`authinfo', + defn(`_ARG_'), `LDAP', `ldap -1 -v sendmailMTAMapValue -k (&(objectClass=sendmailMTAMapObject)(|(sendmailMTACluster=${sendmailMTACluster})(sendmailMTAHost=$j))(sendmailMTAMapName=authinfo)(sendmailMTAKey=%0))', + `_ARG_') diff --git a/gnu/dist/sendmail/cf/feature/compat_check.m4 b/gnu/dist/sendmail/cf/feature/compat_check.m4 new file mode 100644 index 000000000000..007adcd92bed --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/compat_check.m4 @@ -0,0 +1,33 @@ +divert(-1) +# +# Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +# 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. +# +# +divert(0) +VERSIONID(`Id: compat_check.m4,v 1.4 2002/02/26 22:15:31 gshapiro Exp') +divert(-1) +ifdef(`_ACCESS_TABLE_', `', +`errprint(`FEATURE(`compat_check') requires FEATURE(`access_db') +')') + +LOCAL_RULESETS +Scheck_compat +# look up the pair of addresses +# (we use <@> as the separator. Note this in the map too!) +R< $+ > $| $+ $: $1 $| $2 +R$+ $| < $+ > $: $1 $| $2 +R$+ $| $+ $: <$(access Compat:$1<@>$2 $:OK $)> +R$* $| $* $@ ok +# act on the result, +# it must be one of the following... anything else will be allowed.. +dnl for consistency with the other two even though discard does not take a +dnl reply code +R< DISCARD:$* > $#discard $: $1 " - discarded by check_compat" +R< DISCARD $* > $#discard $: $1 " - discarded by check_compat" +R< TEMP:$* > $#error $@ TEMPFAIL $: $1 " error from check_compat. Try again later" +R< ERROR:$* > $#error $@ UNAVAILABLE $: $1 " error from check_compat" diff --git a/gnu/dist/sendmail/cf/feature/enhdnsbl.m4 b/gnu/dist/sendmail/cf/feature/enhdnsbl.m4 new file mode 100644 index 000000000000..49dbc2d81f68 --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/enhdnsbl.m4 @@ -0,0 +1,44 @@ +divert(-1) +# +# Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0) +ifdef(`_EDNSBL_R_',`dnl',`dnl +VERSIONID(`Id: enhdnsbl.m4,v 1.9 2002/05/19 21:27:29 gshapiro Exp') +LOCAL_CONFIG +define(`_EDNSBL_R_',`')dnl +# map for enhanced DNS based blacklist lookups +Kednsbl dns -R A -a. -T -r`'ifdef(`EDNSBL_TO',`EDNSBL_TO',`5') +') +divert(-1) +define(`_EDNSBL_SRV_', `ifelse(len(X`'_ARG_),`1',`blackholes.mail-abuse.org',_ARG_)')dnl +define(`_EDNSBL_MSG_', `ifelse(len(X`'_ARG2_),`1',`"550 Rejected: " $`'&{client_addr} " listed at '_EDNSBL_SRV_`"',`_ARG2_')')dnl +define(`_EDNSBL_MSG_TMP_', `ifelse(_ARG3_,`t',`"451 Temporary lookup failure of " $`'&{client_addr} " at '_EDNSBL_SRV_`"',`_ARG3_')')dnl +define(`_EDNSBL_MATCH_', `ifelse(len(X`'_ARG4_),`1',`$`'+',_ARG4_)')dnl +divert(8) +# DNS based IP address spam list _EDNSBL_SRV_ +R$* $: $&{client_addr} +R$-.$-.$-.$- $: $(ednsbl $4.$3.$2.$1._EDNSBL_SRV_. $: OK $) +ROK $: OKSOFAR +ifelse(len(X`'_ARG3_),`1', +`R$+ $: TMPOK', +`R$+ $#error $@ 4.7.1 $: _EDNSBL_MSG_TMP_') +R_EDNSBL_MATCH_ $#error $@ 5.7.1 $: _EDNSBL_MSG_ +ifelse(len(X`'_ARG5_),`1',`dnl', +`R_ARG5_ $#error $@ 5.7.1 $: _EDNSBL_MSG_') +ifelse(len(X`'_ARG6_),`1',`dnl', +`R_ARG6_ $#error $@ 5.7.1 $: _EDNSBL_MSG_') +ifelse(len(X`'_ARG7_),`1',`dnl', +`R_ARG7_ $#error $@ 5.7.1 $: _EDNSBL_MSG_') +ifelse(len(X`'_ARG8_),`1',`dnl', +`R_ARG8_ $#error $@ 5.7.1 $: _EDNSBL_MSG_') +ifelse(len(X`'_ARG9_),`1',`dnl', +`R_ARG9_ $#error $@ 5.7.1 $: _EDNSBL_MSG_') +divert(-1) diff --git a/gnu/dist/sendmail/cf/feature/local_no_masquerade.m4 b/gnu/dist/sendmail/cf/feature/local_no_masquerade.m4 new file mode 100644 index 000000000000..c234d272b0b9 --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/local_no_masquerade.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 2000 Sendmail, Inc. and its suppliers. +# 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. +# + +divert(0) +VERSIONID(`Id: local_no_masquerade.m4,v 1.2 2000/08/03 15:54:59 ca Exp') +divert(-1) + +ifdef(`_MAILER_local_', + `errprint(`*** MAILER(`local') must appear after FEATURE(`local_no_masquerade')') +')dnl +define(`_LOCAL_NO_MASQUERADE_', `1') diff --git a/gnu/dist/sendmail/cf/feature/lookupdotdomain.m4 b/gnu/dist/sendmail/cf/feature/lookupdotdomain.m4 new file mode 100644 index 000000000000..eed6b235f436 --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/lookupdotdomain.m4 @@ -0,0 +1,22 @@ +divert(-1) +# +# Copyright (c) 2000 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0) +VERSIONID(`Id: lookupdotdomain.m4,v 1.1 2000/04/13 22:32:49 ca Exp') +divert(-1) + +ifdef(`_ACCESS_TABLE_', + `define(`_LOOKUPDOTDOMAIN_')', + `errprint(`*** ERROR: FEATURE(`lookupdotdomain') requires FEATURE(`access_db') +')') +ifdef(`_RELAY_HOSTS_ONLY_', + `errprint(`*** WARNING: FEATURE(`lookupdotdomain') does not work well with FEATURE(`relay_hosts_only') +')') diff --git a/gnu/dist/sendmail/cf/feature/msp.m4 b/gnu/dist/sendmail/cf/feature/msp.m4 new file mode 100644 index 000000000000..84fe14d53fa0 --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/msp.m4 @@ -0,0 +1,76 @@ +divert(-1) +# +# Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0)dnl +VERSIONID(`Id: msp.m4,v 1.32 2002/03/26 22:02:03 ca Exp') +divert(-1) +undefine(`ALIAS_FILE') +define(`confDELIVERY_MODE', `i') +define(`confUSE_MSP', `True') +define(`confFORWARD_PATH', `') +define(`confPRIVACY_FLAGS', `goaway,noetrn,restrictqrun') +define(`confDONT_PROBE_INTERFACES', `True') +dnl --------------------------------------------- +dnl run as this user (even if called by root) +ifdef(`confRUN_AS_USER',,`define(`confRUN_AS_USER', `smmsp')') +ifdef(`confTRUSTED_USER',,`define(`confTRUSTED_USER', confRUN_AS_USER)') +dnl --------------------------------------------- +dnl This queue directory must have the same group +dnl as sendmail and it must be group-writable. +dnl notice: do not test for QUEUE_DIR, it is set in some ostype/*.m4 files +ifdef(`MSP_QUEUE_DIR', +`define(`QUEUE_DIR', `MSP_QUEUE_DIR')', +`define(`QUEUE_DIR', `/var/spool/clientmqueue')') +define(`_MTA_HOST_', ifelse(defn(`_ARG_'), `', `[localhost]', `_ARG_')) +define(`_MSP_FQHN_',`dnl used to qualify addresses +ifdef(`MASQUERADE_NAME', ifdef(`_MASQUERADE_ENVELOPE_', `$M', `$j'), `$j')') +ifelse(_ARG2_, `MSA', `define(`RELAY_MAILER_ARGS', `TCP $h 587')') +dnl --------------------------------------------- +ifdef(`confPID_FILE', `dnl', +`define(`confPID_FILE', QUEUE_DIR`/sm-client.pid')') +define(`confQUEUE_FILE_MODE', `0660')dnl +ifdef(`STATUS_FILE', +`define(`_F_', +`define(`_b_', index(STATUS_FILE, `sendmail.st'))ifelse(_b_, `-1', `STATUS_FILE', `substr(STATUS_FILE, 0, _b_)sm-client.st')') +define(`STATUS_FILE', _F_) +undefine(`_b_') undefine(`_F_')', +`define(`STATUS_FILE', QUEUE_DIR`/sm-client.st')') +FEATURE(`no_default_msa')dnl +ifelse(defn(`_DPO_'), `', +`DAEMON_OPTIONS(`Name=NoMTA, Addr=127.0.0.1, M=E')dnl') +define(`_DEF_LOCAL_MAILER_FLAGS', `')dnl +define(`_DEF_LOCAL_SHELL_FLAGS', `')dnl +define(`LOCAL_MAILER_PATH', `[IPC]')dnl +define(`LOCAL_MAILER_FLAGS', `lmDFMuXkw5')dnl +define(`LOCAL_MAILER_ARGS', `TCP $h')dnl +define(`LOCAL_MAILER_DSN_DIAGNOSTIC_CODE', `SMTP')dnl +define(`LOCAL_SHELL_PATH', `[IPC]')dnl +define(`LOCAL_SHELL_FLAGS', `lmDFMuXk5')dnl +define(`LOCAL_SHELL_ARGS', `TCP $h')dnl +MODIFY_MAILER_FLAGS(`SMTP', `+k5')dnl +MODIFY_MAILER_FLAGS(`ESMTP', `+k5')dnl +MODIFY_MAILER_FLAGS(`DSMTP', `+k5')dnl +MODIFY_MAILER_FLAGS(`SMTP8', `+k5')dnl +MODIFY_MAILER_FLAGS(`RELAY', `+k')dnl +MAILER(`local')dnl +MAILER(`smtp')dnl + +LOCAL_CONFIG +D{MTAHost}_MTA_HOST_ + +LOCAL_RULESETS +SLocal_localaddr +R$+ $: $>ParseRecipient $1 +R$* < @ $+ > $* $#relay $@ ${MTAHost} $: $1 < @ $2 > $3 +ifdef(`_USE_DECNET_SYNTAX_', +`# DECnet +R$+ :: $+ $#relay $@ ${MTAHost} $: $1 :: $2', `dnl') +R$* $#relay $@ ${MTAHost} $: $1 < @ _MSP_FQHN_ > diff --git a/gnu/dist/sendmail/cf/feature/preserve_local_plus_detail.m4 b/gnu/dist/sendmail/cf/feature/preserve_local_plus_detail.m4 new file mode 100644 index 000000000000..905f3f14a929 --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/preserve_local_plus_detail.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 2000 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0) +VERSIONID(`Id: preserve_local_plus_detail.m4,v 8.1 2000/04/10 05:48:05 gshapiro Exp') +divert(-1) + +define(`_PRESERVE_LOCAL_PLUS_DETAIL_', `1') diff --git a/gnu/dist/sendmail/cf/feature/preserve_luser_host.m4 b/gnu/dist/sendmail/cf/feature/preserve_luser_host.m4 new file mode 100644 index 000000000000..8bbf518e094b --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/preserve_luser_host.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 2000, 2002 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0) +VERSIONID(`Id: preserve_luser_host.m4,v 1.3 2002/04/14 13:22:58 ca Exp') +divert(-1) + +ifdef(`LUSER_RELAY', `', +`errprint(`*** LUSER_RELAY should be defined before FEATURE(`preserve_luser_host') + ')') +define(`_PRESERVE_LUSER_HOST_', `1') +define(`_NEED_MACRO_MAP_', `1') diff --git a/gnu/dist/sendmail/cf/feature/queuegroup.m4 b/gnu/dist/sendmail/cf/feature/queuegroup.m4 new file mode 100644 index 000000000000..1cdc1e0d3661 --- /dev/null +++ b/gnu/dist/sendmail/cf/feature/queuegroup.m4 @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 2001 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0) +VERSIONID(`Id: queuegroup.m4,v 1.4 2001/03/28 00:39:39 ca Exp') +divert(-1) + +ifdef(`_ACCESS_TABLE_', `', + `errprint(`*** ERROR: FEATURE(`queuegroup') requires FEATURE(`access_db') +')') + +LOCAL_RULESETS +Squeuegroup +R< $+ > $1 +R $+ @ $+ $: $>SearchList $| <> +ifelse(len(X`'_ARG_),`1', +`R $@', +`R $# _ARG_') +R<$+> $# $1 diff --git a/gnu/dist/sendmail/cf/mailer/cyrusv2.m4 b/gnu/dist/sendmail/cf/mailer/cyrusv2.m4 new file mode 100644 index 000000000000..389c20d5c2dc --- /dev/null +++ b/gnu/dist/sendmail/cf/mailer/cyrusv2.m4 @@ -0,0 +1,29 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 2002 Sendmail, Inc. and its suppliers. +# 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. +# +# Contributed by Kenneth Murchison. +# + +_DEFIFNOT(`_DEF_CYRUSV2_MAILER_FLAGS', `lsDFMnqXz') +_DEFIFNOT(`CYRUSV2_MAILER_FLAGS', `A@/:|m') +ifdef(`CYRUSV2_MAILER_ARGS',, `define(`CYRUSV2_MAILER_ARGS', `FILE /var/imap/socket/lmtp')') +define(`_CYRUSV2_QGRP', `ifelse(defn(`CYRUSV2_MAILER_QGRP'),`',`', ` Q=CYRUSV2_MAILER_QGRP,')')dnl + +POPDIVERT + +######################################### +### Cyrus V2 Mailer specification ### +######################################### + +VERSIONID(`Id: cyrusv2.m4,v 1.1 2002/06/01 21:14:57 ca Exp') + +Mcyrusv2, P=[IPC], F=_MODMF_(CONCAT(_DEF_CYRUSV2_MAILER_FLAGS, CYRUSV2_MAILER_FLAGS), `CYRUSV2'), + S=EnvFromSMTP/HdrFromL, R=EnvToL/HdrToL, E=\r\n, + _OPTINS(`CYRUSV2_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`CYRUSV2_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`CYRUSV2_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,_CYRUSV2_QGRP + A=CYRUSV2_MAILER_ARGS diff --git a/gnu/dist/sendmail/cf/ostype/a-ux.m4 b/gnu/dist/sendmail/cf/ostype/a-ux.m4 new file mode 100644 index 000000000000..3cf6e5fa4202 --- /dev/null +++ b/gnu/dist/sendmail/cf/ostype/a-ux.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999, 2001 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. +# +# 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. +# +# + +divert(0) +VERSIONID(`Id: a-ux.m4,v 8.2 2001/07/23 16:19:36 gshapiro Exp') +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl +ifdef(`UUCP_MAILER_PATH',, `define(`UUCP_MAILER_PATH', /usr/bin/uux)')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `mn9')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail -d -r $f $u')')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/dist/sendmail/cf/ostype/aix5.m4 b/gnu/dist/sendmail/cf/ostype/aix5.m4 index b239b399fb3f..ccb7ba6a5cc5 100644 --- a/gnu/dist/sendmail/cf/ostype/aix5.m4 +++ b/gnu/dist/sendmail/cf/ostype/aix5.m4 @@ -10,7 +10,7 @@ divert(-1) # divert(0) -VERSIONID(`Id: aix5.m4,v 1.1.2.1 2000/12/09 03:32:08 ca Exp') +VERSIONID(`Id: aix5.m4,v 1.1 2000/12/08 21:53:36 ca Exp') ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/bellmail)')dnl ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', mail -F $g $u)')dnl _DEFIFNOT(`LOCAL_MAILER_FLAGS', `mn9')dnl diff --git a/gnu/dist/sendmail/cf/ostype/darwin.m4 b/gnu/dist/sendmail/cf/ostype/darwin.m4 index ccddbbc37e7c..a009b285601d 100644 --- a/gnu/dist/sendmail/cf/ostype/darwin.m4 +++ b/gnu/dist/sendmail/cf/ostype/darwin.m4 @@ -1,6 +1,6 @@ divert(-1) # -# Copyright (c) 2000 Sendmail, Inc. and its suppliers. +# Copyright (c) 2000, 2002 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set @@ -8,10 +8,11 @@ divert(-1) # the sendmail distribution. # # -# divert(0) -VERSIONID(`Id: darwin.m4,v 8.1.2.1 2000/06/15 06:37:04 gshapiro Exp') +VERSIONID(`Id: darwin.m4,v 8.3 2002/03/05 01:55:40 ca Exp') ifdef(`STATUS_FILE',, `define(`STATUS_FILE', `/var/log/sendmail.st')')dnl +dnl turn on S flag for local mailer +MODIFY_MAILER_FLAGS(`LOCAL', `+S')dnl ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /usr/libexec/mail.local)')dnl ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -z -a$g $h!rmail ($u)')')dnl diff --git a/gnu/dist/sendmail/cf/ostype/freebsd5.m4 b/gnu/dist/sendmail/cf/ostype/freebsd5.m4 new file mode 100644 index 000000000000..aa6cb10f04a7 --- /dev/null +++ b/gnu/dist/sendmail/cf/ostype/freebsd5.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 2001 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0) +VERSIONID(`Id: freebsd5.m4,v 1.1 2001/10/08 22:25:34 gshapiro Exp') +ifdef(`STATUS_FILE',, `define(`STATUS_FILE', `/var/log/sendmail.st')')dnl +dnl turn on S flag for local mailer +MODIFY_MAILER_FLAGS(`LOCAL', `+S')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_PATH',, `define(`UUCP_MAILER_PATH', `/usr/local/bin/uux')')dnl +ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -z -a$g $h!rmail ($u)')')dnl diff --git a/gnu/dist/sendmail/cf/ostype/mpeix.m4 b/gnu/dist/sendmail/cf/ostype/mpeix.m4 new file mode 100644 index 000000000000..37d543ebf1b0 --- /dev/null +++ b/gnu/dist/sendmail/cf/ostype/mpeix.m4 @@ -0,0 +1,22 @@ +divert(-1) +# +# Copyright (c) 2001 Sendmail, Inc. and its suppliers. +# 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. +# +# + +divert(0) +VERSIONID(`Id: mpeix.m4,v 1.1 2001/12/13 23:56:40 gshapiro Exp') + +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', `/bin/tsmail')')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `mu9')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `tsmail $u')')dnl +ifdef(`LOCAL_SHELL_PATH',, `define(`LOCAL_SHELL_PATH', `/bin/sh')')dnl +ifdef(`confDEF_USER_ID',, `define(`confDEF_USER_ID', `SERVER.SENDMAIL')')dnl +ifdef(`confTRUSTED_USER',, `define(`confTRUSTED_USER', `SERVER.SENDMAIL')')dnl +define(`confTIME_ZONE', `USE_TZ')dnl +define(`confDONT_BLAME_SENDMAIL', `ForwardFileInGroupWritableDirPath')dnl diff --git a/gnu/dist/sendmail/cf/ostype/solaris8.m4 b/gnu/dist/sendmail/cf/ostype/solaris8.m4 index 42e37cda312c..b99c8530f21e 100644 --- a/gnu/dist/sendmail/cf/ostype/solaris8.m4 +++ b/gnu/dist/sendmail/cf/ostype/solaris8.m4 @@ -15,7 +15,7 @@ divert(-1) # divert(0) -VERSIONID(`Id: solaris8.m4,v 8.1.2.2 2000/08/23 16:10:01 gshapiro Exp') +VERSIONID(`Id: solaris8.m4,v 8.2 2000/08/23 16:10:49 gshapiro Exp') divert(-1) ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g $h!rmail ($u)')') diff --git a/gnu/dist/sendmail/cf/sendmail.schema b/gnu/dist/sendmail/cf/sendmail.schema new file mode 100644 index 000000000000..7cd833e95364 --- /dev/null +++ b/gnu/dist/sendmail/cf/sendmail.schema @@ -0,0 +1,220 @@ +# Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +# 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. +# +# Id: sendmail.schema,v 8.19.2.1 2002/11/20 23:13:27 gshapiro Exp + +# Note that this schema is experimental at this point as it has had little +# public review. Therefore, it may change in future versions. Feedback +# via sendmail@sendmail.org is encouraged. + + +# OID arcs for Sendmail +# enterprise: 1.3.6.1.4.1 +# sendmail: enterprise.6152 +# sendmail-at: sendmail.3.1 +# sendmail-oc: sendmail.3.2 + +########################################################################### +# +# The Sendmail MTA attributes and objectclass +# +########################################################################### + +# attribute sendmailMTACluster cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.10 + NAME 'sendmailMTACluster' + DESC 'cluster name associated with a set of MTAs' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) + +# attribute sendmailMTAHost cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.11 + NAME 'sendmailMTAHost' + DESC 'host name associated with a MTA cluster' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) + +#objectClass sendmailMTA +# requires +# objectClass +# allows +# sendmailMTACluster, +# sendmailMTAHost, +# Description + +objectclass ( 1.3.6.1.4.1.6152.10.3.2.10 + NAME 'sendmailMTA' + SUP top STRUCTURAL + DESC 'Sendmail MTA definition' + MAY ( sendmailMTACluster $ sendmailMTAHost $ Description ) ) + +########################################################################### +# +# The Sendmail MTA shared attributes +# +########################################################################### + +# attribute sendmailMTAKey cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.13 + NAME 'sendmailMTAKey' + DESC 'key (left hand side) of an aliases or map entry' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) + +########################################################################### +# +# The Sendmail MTA Map attributes and objectclasses +# +########################################################################### + +# attribute sendmailMTAMapName cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.14 + NAME 'sendmailMTAMapName' + DESC 'identifier for the particular map' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} SINGLE-VALUE ) + +# attribute sendmailMTAMapValue cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.16 + NAME 'sendmailMTAMapValue' + DESC 'value (right hand side) of a map entry' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) + + +#objectClass sendmailMTAMap +# requires +# objectClass, +# sendmailMTAMapName, +# allows +# sendmailMTACluster, +# sendmailMTAHost, +# Description + +objectclass ( 1.3.6.1.4.1.6152.10.3.2.11 + NAME 'sendmailMTAMap' + SUP sendmailMTA STRUCTURAL + DESC 'Sendmail MTA map definition' + MUST sendmailMTAMapName + MAY ( sendmailMTACluster $ sendmailMTAHost $ Description ) ) + +#objectClass sendmailMTAObject +# requires +# objectClass, +# sendmailMTAMapName, +# sendmailMTAKey, +# sendmailMTAMapValue, +# allows +# sendmailMTACluster, +# sendmailMTAHost, +# Description + +objectclass ( 1.3.6.1.4.1.6152.10.3.2.12 + NAME 'sendmailMTAMapObject' + SUP sendmailMTAMap STRUCTURAL + DESC 'Sendmail MTA map object' + MUST ( sendmailMTAMapName $ sendmailMTAKey $ sendmailMTAMapValue ) + MAY ( sendmailMTACluster $ sendmailMTAHost $ Description ) ) + + +########################################################################### +# +# The Sendmail MTA Alias attributes and objectclasses +# +########################################################################### + +# attribute sendmailMTAAliasGrouping cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.18 + NAME 'sendmailMTAAliasGrouping' + DESC 'name that identifies a particular aliases grouping' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) + +# attribute sendmailMTAAliasValue cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.20 + NAME 'sendmailMTAAliasValue' + DESC 'value (right hand side) of an alias' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + +#objectClass sendmailMTAAlias +# requires +# objectClass, +# allows +# sendmailMTAAliasGrouping, +# sendmailMTACluster, +# sendmailMTAHost, +# Description + +objectclass ( 1.3.6.1.4.1.6152.10.3.2.13 + NAME 'sendmailMTAAlias' + SUP sendmailMTA STRUCTURAL + DESC 'Sendmail MTA alias definition' + MAY ( sendmailMTAAliasGrouping $ + sendmailMTACluster $ sendmailMTAHost $ Description ) ) + +#objectClass sendmailMTAAliasObject +# requires +# objectClass, +# sendmailMTAKey, +# sendmailMTAAliasValue, +# allows +# sendmailMTAAliasGrouping, +# sendmailMTACluster, +# sendmailMTAHost, +# Description + +objectclass ( 1.3.6.1.4.1.6152.10.3.2.14 + NAME 'sendmailMTAAliasObject' + SUP sendmailMTAAlias STRUCTURAL + DESC 'Sendmail MTA alias object' + MUST ( sendmailMTAKey $ sendmailMTAAliasValue ) + MAY ( sendmailMTAAliasGrouping $ + sendmailMTACluster $ sendmailMTAHost $ Description ) ) + +########################################################################### +# +# The Sendmail MTA Class attributes and objectclass +# +########################################################################### + +# attribute sendmailMTAClassName cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.22 + NAME 'sendmailMTAClassName' + DESC 'identifier for the class' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} SINGLE-VALUE ) + +# attribute sendmailMTAClassValue cis +attributetype ( 1.3.6.1.4.1.6152.10.3.1.23 + NAME 'sendmailMTAClassValue' + DESC 'member of a class' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + +#objectClass sendmailMTAClass +# requires +# objectClass, +# sendmailMTAClassName, +# sendmailMTAClassValue, +# allows +# sendmailMTACluster, +# sendmailMTAHost, +# Description + +objectclass ( 1.3.6.1.4.1.6152.10.3.2.15 + NAME 'sendmailMTAClass' + SUP sendmailMTA STRUCTURAL + DESC 'Sendmail MTA class definition' + MUST ( sendmailMTAClassName $ sendmailMTAClassValue ) + MAY ( sendmailMTACluster $ sendmailMTAHost $ Description ) ) diff --git a/gnu/dist/sendmail/contrib/cidrexpand b/gnu/dist/sendmail/contrib/cidrexpand index b61fc2e38c6e..67b62c565849 100644 --- a/gnu/dist/sendmail/contrib/cidrexpand +++ b/gnu/dist/sendmail/contrib/cidrexpand @@ -1,6 +1,6 @@ #!/usr/local/bin/perl -w -# v 0.2-very-very-beta +# v 0.2-very-beta # # 17 July 2000 Derek J. Balling (dredd@megacity.org) # @@ -13,10 +13,24 @@ # notation. Caveat: the address portion MUST be the start address or your # results will NOT be what what you want. # +# If you have two overlapping CIDR blocks with conflicting actions +# e.g. 10.2.3.128/25 REJECT and 10.2.3.143 ACCEPT +# make sure that the exceptions to the more general block are specified +# later in the access_db. +# +# the -r flag to makemap will make it "do the right thing" +# +# Modifications +# ------------- +# 5 Nov 2002 Richard Rognlie (richard@sendmail.com) +# Added code to deal with the prefix tags that may now be included in +# the access_db +# +# Added clarification in the notes for what to do if you have +# exceptions to a larger CIDR block. # # usage: -# cidrexpand < /etc/mail/access | makemap hash /etc/mail/access -# +# cidrexpand < /etc/mail/access | makemap -r hash /etc/mail/access # # Report bugs to: dredd@megacity.org # @@ -37,20 +51,20 @@ my $SENDMAIL = 1; while (<>) { - my ($left,$right,$space); + my ($prefix,$left,$right,$space); - if (! /^(\d+\.){3}\d+\/\d\d?$spaceregex.*/ ) + if (! /^(|\S\S*:)(\d+\.){3}\d+\/\d\d?$spaceregex.*/ ) { print; } else { - ($left,$space,$right) = /^((?:\d+\.){3}\d+\/\d\d?)($spaceregex)(.*)$/; + ($prefix,$left,$space,$right) = /^(|\S\S*:)((?:\d+\.){3}\d+\/\d\d?)($spaceregex)(.*)$/; my @new_lefts = expand_network($left); foreach my $nl (@new_lefts) { - print "$nl$space$right\n"; + print "$prefix$nl$space$right\n"; } } @@ -133,5 +147,13 @@ sub calc_changes $second = 255; $first = 2**($power-24) - 1; } + elsif ($mask == 0) + { + $fourth = 255; + $third = 255; + $second = 255; + $first = 255; + } + return ($first,$second,$third,$fourth); } diff --git a/gnu/dist/sendmail/contrib/dnsblaccess.m4 b/gnu/dist/sendmail/contrib/dnsblaccess.m4 new file mode 100644 index 000000000000..4d8f0c1ae9ef --- /dev/null +++ b/gnu/dist/sendmail/contrib/dnsblaccess.m4 @@ -0,0 +1,94 @@ +divert(-1) +# +# Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. +# 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. +# +# + +dnl ## This is a modified enhdnsbl, loosely based on the +dnl ## original. +dnl ## +dnl ## Use it as follows +dnl ## +dnl ## HACK(dnsblaccess, domain, optional-message, tempfail-message, keytag) +dnl ## +dnl ## The first argument (domain) is required. The other arguments +dnl ## are optional and have reasonable defaults. The +dnl ## optional-message is the error message given in case of a +dnl ## match. The default behavior for a tempfail is to accept the +dnl ## email. A tempfail-message value of `t' temporarily rejects +dnl ## with a default message. Otherwise the value should be your +dnl ## own message. The keytag is used to lookup the access map to +dnl ## further refine the result. I recommend a qualified keytag +dnl ## (containing a ".") as less likely to accidently conflict with +dnl ## other access tags. +dnl ## +dnl ## This is best illustrated with an example. Please do not use +dnl ## the example, as it refers to a bogus lookup list. +dnl ## +dnl ## Suppose that you use +dnl ## +dnl ## HACK(dnsblaccess, `rbl.bogus.org',`',`t',bogus.tag) +dnl ## +dnl ## and suppose that your access map contains the entries +dnl ## +dnl ## bogus.tag:127.0.0.2 REJECT +dnl ## bogus.tag:127.0.0.3 error:dialup mail from %1: listed at %2 +dnl ## bogus.tag:127.0.0.4 OK +dnl ## bogus.tag:127 REJECT +dnl ## bogus.tag: OK +dnl ## +dnl ## If an SMTP connection is received from 123.45.6.7, sendmail +dnl ## will lookup the A record for 7.6.45.123.bogus.org. If there +dnl ## is a temp failure for the lookup, sendmail will generate a +dnl ## temporary failure with a default message. If there is no +dnl ## A-record for this lookup, then the mail is treated as if the +dnl ## HACK line were not present. If the lookup returns 127.0.0.2, +dnl ## then a default message rejects the mail. If it returns +dnl ## 127.0.0.3, then the message +dnl ## "dialup mail from 123.45.6.7: listed at rbl.bogus.org" +dnl ## is used to reject the mail. If it returns 127.0.0.4, the +dnl ## mail is processed as if there were no HACK line. If the +dnl ## address returned is something else beginning with 127.*, the +dnl ## mail is rejected with a default error message. If the +dnl ## address returned does not begin 127, then the mail is +dnl ## processed as if the HACK line were not present. + +divert(0) +VERSIONID(`Id: dnsblaccess.m4,v 1.5 2002/05/19 21:30:06 gshapiro Exp') +ifdef(`_ACCESS_TABLE_', `dnl', + `errprint(`*** ERROR: dnsblaccess requires FEATURE(`access_db') +')') +ifdef(`_EDNSBL_R_',`dnl',`dnl +define(`_EDNSBL_R_', `1')dnl ## prevent multiple redefines of the map. +LOCAL_CONFIG +# map for enhanced DNS based blacklist lookups +Kednsbl dns -R A -a. -T -r`'ifdef(`EDNSBL_TO',`EDNSBL_TO',`5') +') +divert(-1) +define(`_EDNSBL_SRV_', `ifelse(len(X`'_ARG_),`1',`blackholes.mail-abuse.org',_ARG_)')dnl +define(`_EDNSBL_MSG_', `ifelse(len(X`'_ARG2_),`1',`"550 Rejected: " $`'&{client_addr} " listed at '_EDNSBL_SRV_`"',`_ARG2_')')dnl +define(`_EDNSBL_MSG_TMP_', `ifelse(_ARG3_,`t',`"451 Temporary lookup failure of " $`'&{client_addr} " at '_EDNSBL_SRV_`"',`_ARG3_')')dnl +define(`_EDNSBL_KEY_', `ifelse(len(X`'_ARG4_),`1',`dnsblaccess',_ARG4_)')dnl +divert(8) +# DNS based IP address spam list _EDNSBL_SRV_ +R$* $: $&{client_addr} +dnl IPv6? +R$-.$-.$-.$- $: $(ednsbl $4.$3.$2.$1._EDNSBL_SRV_. $: OK $) <>$1.$2.$3.$4 +ROK<>$* $: OKSOFAR +R$+<>$* $: > +R$* $- .<>$* <$(access _EDNSBL_KEY_`:'$1$2 $@$3 $@`'_EDNSBL_SRV_ $: ? $)> $1 <>$3 +R$* <>$* $:<$(access _EDNSBL_KEY_`:' $@$2 $@`'_EDNSBL_SRV_ $: ? $)> <>$2 +ifelse(len(X`'_ARG3_),`1', +`R<$*>$* $: TMPOK', +`R<$*>$* $#error $@ 4.7.1 $: _EDNSBL_MSG_TMP_') +R<$={Accept}>$* $: OKSOFAR +R $* $#error $@ $1.$2.$3 $: $4 +R $* $#error $: $1 +R $* $#discard $: discard +R<$*> $* $#error $@ 5.7.1 $: _EDNSBL_MSG_ +divert(-1) diff --git a/gnu/dist/sendmail/contrib/domainmap.m4 b/gnu/dist/sendmail/contrib/domainmap.m4 index fbaf62c82d99..540beff43efa 100644 --- a/gnu/dist/sendmail/contrib/domainmap.m4 +++ b/gnu/dist/sendmail/contrib/domainmap.m4 @@ -46,7 +46,7 @@ divert(-1)changequote(<<, >>)<< in the sendmail source tree. For more information, please see the following URL: - http://www-wsg.cso.uiuc.edu/sendmail/patches/domainmap.html + http://www-dev.cso.uiuc.edu/sendmail/domainmap/ Feedback is welcome. @@ -69,14 +69,16 @@ LOCAL_RULESETS SDomainMapLookup R $=L <@ $=w .> $@ $1 <@ $2 .> weed out local users, in case # Cw contains a mapped domain +R $+ <@ $+> $: $1 <@ $2 > <$&{addr_type}> check if sender +R $+ <@ $+> $#smtp $@ $2 $: $1 @ $2 do not process sender ifdef(`DOMAINMAP_NO_REGEX',`dnl -R $+ <@ $+> $: $1 <@ $2> <$2> find domain +R $+ <@ $+> <$*> $: $1 <@ $2> <$2> find domain R $+ <$+> <$+ . $+> $1 <$2> < $(dequote $3 "_" $4 $) > # change "." to "_" R $+ <$+> <$+ .> $: $1 <$2> < $(dequote "domain_" $3 $) > # prepend "domain_" dnl',`dnl -R $+ <@ $+> $: $1 <@ $2> <$2 :NOTDONE:> find domain +R $+ <@ $+> <$*> $: $1 <@ $2> <$2 :NOTDONE:> find domain R $+ <$+> <$+ . :NOTDONE:> $1 <$2> < $(domainmap_regex $3 $: $3 $) > # change "." and "-" to "_" R $+ <$+> <$+> $: $1 <$2> < $(dequote "domain_" $3 $) > diff --git a/gnu/dist/sendmail/contrib/doublebounce.pl b/gnu/dist/sendmail/contrib/doublebounce.pl index a853ec14f37f..12601d334792 100644 --- a/gnu/dist/sendmail/contrib/doublebounce.pl +++ b/gnu/dist/sendmail/contrib/doublebounce.pl @@ -1,232 +1,225 @@ #!/usr/bin/perl # doublebounce.pl -# attempt to return a doubly-bounced email to a postmaster -# jr@terra.net, 12/4/97 # -# invoke by creating an mail alias such as: -# doublebounce: "|/usr/local/sbin/doublebounce" -# then adding this line to your sendmail.cf: -# O DoubleBounceAddress=doublebounce +# Return a doubly-bounced e-mail to postmaster. Specific to sendmail, +# updated to work on sendmail 8.12.6. # -# optionally, add a "-d" flag in the aliases file, to send a -# debug trace to your own postmaster showing what is going on +# Based on the original doublebounce.pl code by jr@terra.net, 12/4/97. +# Updated by bicknell@ufp.org, 12/4/2002 to understand new sendmail DSN +# bounces. Code cleanup also performed, mainly making things more +# robust. # -# this allows the "postmaster" address to still go to a human being, -# while bounce messages can go to this script, which will bounce them -# back to the postmaster at the sending site. -# -# the algorithm is to scan the double-bounce error report generated -# by sendmail on stdin, for the original message (it starts after the -# second "Orignal message follows" marker), look for From, Sender, and -# Received headers from the point closest to the sender back to the point -# closest to us, and try to deliver a double-bounce report back to a -# postmaster at one of these sites in the hope that they can -# return the message to the original sender, or do something about -# the fact that that sender's return address is not valid. - +# Original intro included below, lines with ## +## attempt to return a doubly-bounced email to a postmaster +## jr@terra.net, 12/4/97 +## +## invoke by creating an mail alias such as: +## doublebounce: "|/usr/local/sbin/doublebounce" +## then adding this line to your sendmail.cf: +## O DoubleBounceAddress=doublebounce +## +## optionally, add a "-d" flag in the aliases file, to send a +## debug trace to your own postmaster showing what is going on +## +## this allows the "postmaster" address to still go to a human being, +## while bounce messages can go to this script, which will bounce them +## back to the postmaster at the sending site. +## +## the algorithm is to scan the double-bounce error report generated +## by sendmail on stdin, for the original message (it starts after the +## second "Orignal message follows" marker), look for From, Sender, and +## Received headers from the point closest to the sender back to the point +## closest to us, and try to deliver a double-bounce report back to a +## postmaster at one of these sites in the hope that they can +## return the message to the original sender, or do something about +## the fact that that sender's return address is not valid. use Socket; - -# look for debug flag -# -$dflag = 0; -$dflag = 1 if ($ARGV[0] eq "-d"); - -# get local host name -# you may need to edit these two lines for however your system does this -# -$host = `hostname`; chop($host); -$domain = `dnsdomainname`; chop($domain); - -# get temp file name -$tmp = "/tmp/doubb$$"; - -# save message from STDIN to a file -# I thought about reading it into a buffer here, but some messages -# are 10+Mb so a buffer may not be a good idea -# -if (! open(MSG, "+> $tmp")) { - # can't open temp file -- send message to local postmaster - # open(MAIL, "| /usr/sbin/sendmail -oeq postmaster"); - print MAIL ; - close(MAIL); - exit(1); -} -print MSG ; - -# scan message for list of possible sender sites -# note that original message appears after the second -# "Original message follows" marker -# look for From, Sender, and Reply-To and try them, too -# -$inhdr = 0; -$hdrs = 0; -$skip = 0; -seek(MSG, 0, 0); -while () { - chop; - if (/^ ----- Original message follows -----$/ - || /^ ----Unsent message follows----$/) { - $i = 0; - $inhdr = 1; - $hdrs++; - $skip = 1; - next; - } - if ($skip) { - $skip--; - next; - } - if (/^$/) { - last if ($hdrs >= 2); - $inhdr = 0; - next; - } - if (! $inhdr) { - next; - } - if (! /^[ \t]/) { $hdr[$i++] = $_ } - else { - $i--; - $hdr[$i++] .= $_; - } -} -$rcvd = 0; -for ($j = 0; $j < $i; $j++) { - print STDERR "DEBUG hdr[$j] = $hdr[$j]\n"; - if ($hdr[$j] =~ /^received:/i) { - ($addr[$rcvd++]) = $hdr[$j] =~ m/.*\sby\s([^\s]+)\s.*/; - } - if ($hdr[$j] =~ /^reply-to:/i) { - ($addr1{"reply-to"} = $hdr[$j]) =~ s/^reply-to: *//i; - } - if ($hdr[$j] =~ /^sender:/i) { - ($addr1{"sender"} = $hdr[$j]) =~ s/^sender: *//i; - } - if ($hdr[$j] =~ /^from:/i) { - ($addr1{"from"} = $hdr[$j]) =~ s/^from: *//i; - } -} - -# %addr and %addr1 arrays now contain lists of possible sites (or From headers). -# Go through them parsing for the site name, and attempting to send -# to the named person or postmaster@ each site in turn until successful -# -if ($dflag) { - open(DEBUG, "|/usr/sbin/sendmail postmaster"); - print DEBUG "Subject: double bounce dialog\n"; -} -$sent = 0; -# foreach $x ("from", "sender", "reply-to") { -foreach $x ("from", "sender") { - $y = &parseaddr($addr1{$x}); - if ($y) { - print DEBUG "Trying $y\n" if ($dflag); - if (&sendbounce("$y")) { - $sent++; - last; - } - $y =~ s/.*@//; - print DEBUG "Trying postmaster\@$y\n" if ($dflag); - if (&sendbounce("postmaster\@$y")) { - $sent++; - last; - } - } -} -if (! $sent) { - $rcvd--; - for ($i = $rcvd; $i >= 0; $i--) { - $y = &parseaddr($addr[$i]); - $y =~ s/.*@//; - if ($y) { - print DEBUG "Trying postmaster\@$y\n" if ($dflag); - if (&sendbounce("postmaster\@$y")) { - $sent++; - last; - } - } - } -} -if (! $sent) { - # queer things are happening to me - # $addr[0] should be own domain, so we should have just - # tried postmaster@our.domain. theoretically, we should - # not get here... - if ($dflag) { - print DEBUG "queer things are happening to me\n"; - print DEBUG "Trying postmaster\n"; - } - &sendbounce("postmaster"); -} - -# clean up and get out -# -if ($dflag) { - seek(MSG, 0, 0); - print DEBUG "\n---\n"; print DEBUG ; - close(DEBUG); -} -close(MSG); -unlink("$tmp"); -exit(0); - - - - +use Getopt::Std; +use POSIX; +use Sys::Syslog qw(:DEFAULT setlogsock); +use strict; +use vars qw( $opt_d $tmpfile); # parseaddr() # parse hostname from From: header # sub parseaddr { - local($hdr) = @_; - local($addr); + my($hdr) = @_; + my($addr); - if ($hdr =~ /<.*>/) { - ($addr) = $hdr =~ m/<(.*)>/; - return $addr; - } - if ($addr =~ /\s*\(/) { - ($addr) = $hdr =~ m/\s*(.*)\s*\(/; - return $addr; - } - ($addr) = $hdr =~ m/\s*(.*)\s*/; - return $addr; + if ($hdr =~ /<.*>/) { + ($addr) = $hdr =~ m/<(.*)>/; + $addr =~ s/.*\@//; + return $addr; + } + if ($addr =~ /\s*\(/) { + ($addr) = $hdr =~ m/\s*(.*)\s*\(/; + $addr =~ s/.*\@//; + return $addr; + } + ($addr) = $hdr =~ m/\s*(.*)\s*/; + $addr =~ s/.*\@//; + return $addr; } - # sendbounce() # send bounce to postmaster # # this re-invokes sendmail in immediate and quiet mode to try # to deliver to a postmaster. sendmail's exit status tells us -# wether the delivery attempt really was successful. +# whether the delivery attempt really was successful. # -sub sendbounce { - local($dest) = @_; - local($st); +sub send_bounce { + my($addr, $from) = @_; + my($st); + my($result); - open(MAIL, "| /usr/sbin/sendmail -ocn -odi -oeq $dest"); - print MAIL < + my($dest) = "postmaster\@" . parseaddr($addr); + + if ($opt_d) { + syslog ('info', "Attempting to send to user $dest"); + } + open(MAIL, "| /usr/sbin/sendmail -oeq $dest"); + print MAIL < Subject: Postmaster notify: double bounce -Reply-To: nobody\@$domain -Errors-To: nobody\@$domain +Reply-To: nobody +Errors-To: nobody Precedence: junk Auto-Submitted: auto-generated (postmaster notification) -The following message was received at $host.$domain for an invalid -recipient. The sender's address was also invalid. Since the message -originated at or transited through your mailer, this notification is being -sent to you in the hope that you will determine the real originator and -have them correct their From or Sender address. +The following message was received for an invalid recipient. The +sender's address was also invalid. Since the message originated +at or transited through your mailer, this notification is being +sent to you in the hope that you will determine the real originator +and have them correct their From or Sender address. -The invalid sender address was: $addr1{"from"}. +The from header on the original e-mail was: $from. - ----- The following is a double bounce at $host.$domain ----- + ----- The following is a double bounce ----- EOT - seek(MSG, 0, 0); - print MAIL ; - return close(MAIL); + + open(MSG, "<$tmpfile"); + print MAIL ; + close(MSG); + $result = close(MAIL); + if ($result) { + syslog('info', 'doublebounce successfully sent to %s', $dest); + } + return $result; } + +sub main { + # Get our command line options + getopts('d'); + + # Set up syslog + setlogsock('unix'); + openlog('doublebounce', 'pid', 'mail'); + + if ($opt_d) { + syslog('info', 'Processing a doublebounce.'); + } + + # The bounced e-mail may be large, so we'd better not try to buffer + # it in memory, get a temporary file. + $tmpfile = POSIX::tmpnam(); + + if (!open(MSG, ">$tmpfile")) { + syslog('err', "Unable to open temporary file $tmpfile"); + exit(75); # 75 is a temporary failure, sendmail should retry + } + print(MSG ); + close(MSG); + if (!open(MSG, "<$tmpfile")) { + syslog('err', "Unable to reopen temporary file $tmpfile"); + exit(74); # 74 is an IO error + } + + # Ok, now we can get down to business, find the original message + my($skip_lines, $in_header, $headers_found, @addresses); + $skip_lines = 0; + $in_header = 0; + $headers_found = 0; + while () { + if ($skip_lines > 0) { + $skip_lines--; + next; + } + chomp; + # Starting message depends on your version of sendmail + if (/^ ----- Original message follows -----$/ || + /^ ----Unsent message follows----$/ || + /^Content-Type: message\/rfc822$/) { + # Found the original message + $skip_lines++; + $in_header = 1; + $headers_found++; + next; + } + if (/^$/) { + if ($headers_found >= 2) { + # We only process two deep, even if there are more + last; + } + if ($in_header) { + # We've found the end of a header, scan for the next one + $in_header = 0; + } + next; + } + if ($in_header) { + if (! /^[ \t]/) { + # New Header + if (/^(received): (.*)/i || + /^(reply-to): (.*)/i || + /^(sender): (.*)/i || + /^(from): (.*)/i ) { + $addresses[$headers_found]{$1} = $2; + } + next; + } else { + # continuation header + # we should really process these, but we don't yet + next; + } + } else { + # Nothing to do if we're not in a header + next; + } + } + close(MSG); + + # Start with the original (inner) sender + my($addr, $sent); + foreach $addr (keys %{$addresses[2]}) { + if ($opt_d) { + syslog('info', "Trying to send to $addresses[2]{$addr} - $addresses[2]{\"From\"}"); + } + $sent = send_bounce($addresses[2]{$addr}, $addresses[2]{"From"}); + last if $sent; + } + if (!$sent && $opt_d) { + if ($opt_d) { + syslog('info', 'Unable to find original sender, falling back.'); + } + foreach $addr (keys %{$addresses[1]}) { + if ($opt_d) { + syslog('info', "Trying to send to $addresses[2]{$addr} - $addresses[2]{\"From\"}"); + } + $sent = send_bounce($addresses[1]{$addr}, $addresses[2]{"From"}); + last if $sent; + } + if (!$sent) { + syslog('info', 'Unable to find anyone to send a doublebounce notification'); + } + } + + unlink($tmpfile); +} + +main(); +exit(0); + diff --git a/gnu/dist/sendmail/contrib/etrn.0 b/gnu/dist/sendmail/contrib/etrn.0 new file mode 100644 index 000000000000..66f7975d1393 --- /dev/null +++ b/gnu/dist/sendmail/contrib/etrn.0 @@ -0,0 +1,58 @@ +System Administration Commands etrn(1M) + + +NAME + etrn - start mail queue run + +SYNOPSIS + etrn [-v] server-host [client-hosts] + +DESCRIPTION + SMTP's ETRN command allows an SMTP client and server to + interact, giving the server an opportunity to start the pro­ + cessing of its queues for messages to go to a given host. + This is meant to be used in start-up conditions, as well as + for mail nodes that have transient connections to their ser­ + vice providers. + + The etrn utility initiates an SMTP session with the host + server-host and sends one or more ETRN commands as follows: + If no client-hosts are specified, etrn looks up every host + name for which sendmail(1M) accepts email and, for each + name, sends an ETRN command with that name as the argument. + If any client-hosts are specified, etrn uses each of these + as arguments for successive ETRN commands. + +OPTIONS + The following option is supported: + + -v The normal mode of operation for etrn is to do all of + its work silently. The -v option makes it verbose, + which causes etrn to display its conversations with + the remote SMTP server. + +ENVIRONMENT + No environment variables are used. + +FILES + /etc/mail/sendmail.cf + sendmail configuration file + +SEE ALSO + sendmail(1M), RFC 1985. + +CAVEATS + Not all SMTP servers support ETRN. + +CREDITS + Leveraged from David Muir Sharnoff's expn.pl script. Chris­ + tian von Roques added support for args and fixed a couple of + bugs. + +AVAILABILITY + The latest version of etrn is available in the contrib + directory of the sendmail distribution through anonymous ftp + at ftp://ftp.sendmail.org/ucb/src/sendmail/. + +AUTHOR + John T. Beck diff --git a/gnu/dist/sendmail/contrib/link_hash.sh b/gnu/dist/sendmail/contrib/link_hash.sh index 21f1c2cfc9a1..9a7213244af3 100644 --- a/gnu/dist/sendmail/contrib/link_hash.sh +++ b/gnu/dist/sendmail/contrib/link_hash.sh @@ -3,7 +3,7 @@ ## Copyright (c) 2000 Sendmail, Inc. and its suppliers. ## All rights reserved. ## -## Id: link_hash.sh,v 1.1.2.1 2000/04/25 00:10:47 ca Exp +## Id: link_hash.sh,v 1.2 2000/04/25 00:12:28 ca Exp ## # # ln a certificate to its hash diff --git a/gnu/dist/sendmail/contrib/smcontrol.pl b/gnu/dist/sendmail/contrib/smcontrol.pl index 3ecfee1dc49b..4987460e4d4e 100755 --- a/gnu/dist/sendmail/contrib/smcontrol.pl +++ b/gnu/dist/sendmail/contrib/smcontrol.pl @@ -1,9 +1,11 @@ #!/usr/local/bin/perl -w +use strict; +use Getopt::Std; use FileHandle; use Socket; -$sendmailDaemon = "/usr/sbin/sendmail -q30m -bd"; +my $sendmailDaemon = "/usr/sbin/sendmail -q30m -bd"; ########################################################################## # @@ -70,6 +72,7 @@ sub do_command my $command = shift; my $proto = getprotobyname('ip'); my @reply; + my $i; socket(SOCK, PF_UNIX, SOCK_STREAM, $proto) or return undef; @@ -216,7 +219,7 @@ sub start_daemon } elsif (defined $pid) { - exec($main::sendmailDaemon); + exec($sendmailDaemon); die "Unable to start sendmail daemon: $!.\n"; } else @@ -272,6 +275,29 @@ sub restart_daemon return &do_command($control, "RESTART"); } +########################################################################## +# +# &memdump -- get memdump from the daemon using the control socket +# +# Parameters: +# control -- control socket name +# +# Returns: +# Error message or status message +# + +sub memdump +{ + my $control = shift; + my $status; + + if (not defined $control) + { + return "The control socket is not configured so the daemon can not be queried for memdump."; + } + return &do_command($control, "MEMDUMP"); +} + ########################################################################## # # &help -- get help from the daemon using the control socket @@ -295,10 +321,14 @@ sub help return &do_command($control, "HELP"); } -my $command = shift; -my $control = &get_controlname; my $status = undef; my $daemonStatus = undef; +my $opts = {}; + +getopts('f:', $opts) || die "Usage: $0 [-f /path/to/control/socket] command\n"; + +my $control = $opts->{f} || &get_controlname; +my $command = shift; if (not defined $control) { @@ -306,7 +336,7 @@ if (not defined $control) } if (not defined $command) { - die "Usage: $0 command\n"; + die "Usage: $0 [-f /path/to/control/socket] command\n"; } if ($command eq "status") { @@ -341,10 +371,30 @@ elsif (lc($command) eq "start") { $status = &start_daemon($control); } +elsif (lc($command) eq "memdump") +{ + $status = &memdump($control); +} elsif (lc($command) eq "help") { $status = &help($control); } +elsif (lc($command) eq "mstat") +{ + $status = &do_command($control, "mstat"); + if (not defined $status) + { + # Not responding on control channel, query via SMTP + if (&sendmail_running) + { + $daemonStatus = "Sendmail is running but not answering status queries."; + } + else + { + $daemonStatus = "Sendmail does not appear to be running."; + } + } +} else { die "Unrecognized command $command\n"; diff --git a/gnu/dist/sendmail/devtools/M4/UNIX/sm-test.m4 b/gnu/dist/sendmail/devtools/M4/UNIX/sm-test.m4 new file mode 100644 index 000000000000..4a91fc89ab4a --- /dev/null +++ b/gnu/dist/sendmail/devtools/M4/UNIX/sm-test.m4 @@ -0,0 +1,28 @@ +divert(-1) +# +# Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. +# 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. +# +# Compile/run a test program for libsm. +# +# Id: sm-test.m4,v 1.7 2002/02/01 17:38:07 ca Exp +# +define(`smtest', +`bldPUSH_TARGET($1)dnl +bldLIST_PUSH_ITEM(`bldC_PRODUCTS', $1)dnl +bldPUSH_CLEAN_TARGET($1`-clean')dnl +divert(bldTARGETS_SECTION) +$1`'SRCS=$1.c +$1: ${BEFORE} $1.o ifdef(`confREQUIRE_LIBSM', `libsm.a') + ${CC} -o $1 ${LDOPTS} ${LIBDIRS} $1.o ifdef(`confREQUIRE_LIBSM', `libsm.a') ${LIBS} +ifelse(len(X`'$2), `1', `', ` + @echo ============================================================ + ./$1 + @echo ============================================================') +$1-clean: + rm -f $1 $1.o +divert(0)') diff --git a/gnu/dist/sendmail/devtools/OS/AIX.5.0 b/gnu/dist/sendmail/devtools/OS/AIX.5.0 index 840d56bad940..c2019aec2f70 100644 --- a/gnu/dist/sendmail/devtools/OS/AIX.5.0 +++ b/gnu/dist/sendmail/devtools/OS/AIX.5.0 @@ -1,6 +1,10 @@ -# Id: AIX.5.0,v 1.1.2.1 2000/12/09 03:31:23 ca Exp +# Id: AIX.5.0,v 1.6 2002/03/21 23:59:25 gshapiro Exp + +dnl DO NOT EDIT THIS FILE. +dnl Place personal settings in devtools/Site/site.config.m4 + define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') -define(`confENVDEF', `-D_AIX4=40300 -D_AIX5=50000 -DSM_OS=sm_os_aix') +define(`confENVDEF', `-D_AIX5=50000') define(`confOPTIMIZE', `-O3 -qstrict') define(`confCC', `/usr/vac/bin/xlc') define(`confLIBS', `-ldbm') @@ -9,6 +13,8 @@ define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confDEPEND_TYPE', `AIX') define(`confLDOPTS', `-blibpath:/usr/lib:/lib') +define(`confSM_OS_HEADER', `sm_os_aix') +define(`confMTCCOPTS', `-D_THREAD_SAFE') define(`confMTLDOPTS', `-lpthread') define(`confLDOPTS_SO', `-Wl,-G -Wl,-bexpall') diff --git a/gnu/dist/sendmail/devtools/OS/AIX.5.1 b/gnu/dist/sendmail/devtools/OS/AIX.5.1 new file mode 100644 index 000000000000..76b1268fdc65 --- /dev/null +++ b/gnu/dist/sendmail/devtools/OS/AIX.5.1 @@ -0,0 +1,20 @@ +# Id: AIX.5.1,v 1.2 2002/03/21 23:59:25 gshapiro Exp + +dnl DO NOT EDIT THIS FILE. +dnl Place personal settings in devtools/Site/site.config.m4 + +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-D_AIX5=50100') +define(`confOPTIMIZE', `-O3 -qstrict') +define(`confCC', `/usr/vac/bin/xlc') +define(`confLIBS', `-ldbm') +define(`confINSTALL', `/usr/ucb/install') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `system') +define(`confDEPEND_TYPE', `AIX') +define(`confLDOPTS', `-blibpath:/usr/lib:/lib') +define(`confSM_OS_HEADER', `sm_os_aix') + +define(`confMTCCOPTS', `-D_THREAD_SAFE') +define(`confMTLDOPTS', `-lpthread') +define(`confLDOPTS_SO', `-Wl,-G -Wl,-bexpall') diff --git a/gnu/dist/sendmail/devtools/OS/Interix b/gnu/dist/sendmail/devtools/OS/Interix new file mode 100644 index 000000000000..b76637ddd3bc --- /dev/null +++ b/gnu/dist/sendmail/devtools/OS/Interix @@ -0,0 +1,17 @@ +# Id: Interix,v 1.1.2.1 2002/08/29 00:07:53 gshapiro Exp +# Contributed by Nedelcho Stanev + +dnl DO NOT EDIT THIS FILE. +dnl Place personal settings in devtools/Site/site.config.m4 + +define(`confCC', `/usr/local/bin/gcc') +define(`confOPTIMIZE', `-O2') +APPENDDEF(`confMAPDEF', `-DMAP_REGEX') +APPENDDEF(`confENVDEF', `-D__INTERIX -D_ALL_SOURCE') +APPENDDEF(`confINCDIRS', `-I/usr/local/include/bind') +APPENDDEF(`confLIBDIRS', `-L/usr/local/lib/bind') +APPENDDEF(`confLIBS', `-lbind') +APPENDDEF(`confLIBS', `-ll') +define(`confMAN1EXT', `0') +define(`confMAN5EXT', `0') +define(`confMAN8EXT', `0') diff --git a/gnu/dist/sendmail/devtools/OS/MPE-iX b/gnu/dist/sendmail/devtools/OS/MPE-iX new file mode 100644 index 000000000000..b54c18a9f5ea --- /dev/null +++ b/gnu/dist/sendmail/devtools/OS/MPE-iX @@ -0,0 +1,36 @@ +# Id: MPE-iX,v 1.2 2002/03/21 23:59:25 gshapiro Exp + +dnl DO NOT EDIT THIS FILE. +dnl Place personal settings in devtools/Site/site.config.m4 + +define(`confCC', `gcc') +define(`confOPTIMIZE', `-O') +define(`confMAPDEF', `-DNEWDB -DMAP_REGEX') +define(`confENVDEF', `-DMPE -D_SOCKET_SOURCE -D_POSIX_SOURCE -DIS_SOCKET_CLIB_ITSELF') +APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_DOTTED_USERNAMES -D_FFR_DROP_TRUSTUSER_WARNING -D_FFR_TRUSTED_QF') +define(`confINCDIRS', `-I/BINDFW/CURRENT/include -I/SYSLOG/PUB -I/${HPACCOUNT}/${HPGROUP}/include -I/usr/contrib/include') +define(`confLIBDIRS', `-L/BINDFW/CURRENT/lib -L/SYSLOG/PUB -L/${HPACCOUNT}/${HPGROUP}/lib') +define(`confLIBS', `-lsyslog -ldb -lsocket -lsvipc') +define(`confSM_OS_HEADER', `sm_os_mpeix') +define(`conf_sendmail_LIB_POST', `--for-linker="-WL,cap=ia,ba,ph,pm"') +define(`confINSTALL', `${BUILDBIN}/install.sh') + +define(`confEBINDIR', `/${HPACCOUNT}/${HPGROUP}/sbin') +define(`confGBINGRP', `${HPACCOUNT}') +define(`confGBINOWN', `MGR.${HPACCOUNT}') +define(`confMSPQOWN', `SERVER.${HPACCOUNT}') +define(`confMANROOT', `/${HPACCOUNT}/${HPGROUP}/man/cat') +define(`confMANROOTMAN', `/${HPACCOUNT}/${HPGROUP}/man/man') +define(`confMANGRP', `${HPACCOUNT}') +define(`confMANOWN', `MGR.${HPACCOUNT}') +define(`confMBINDIR', `/${HPACCOUNT}/${HPGROUP}/sbin') +define(`confMBINGRP', `${HPACCOUNT}') +define(`confMBINMODE', `555') +define(`confMBINOWN', `MGR.${HPACCOUNT}') +define(`confSBINDIR', `/${HPACCOUNT}/${HPGROUP}/sbin') +define(`confSBINGRP', `${HPACCOUNT}') +define(`confSBINMODE', `6555') +define(`confSBINOWN', `MGR.${HPACCOUNT}') +define(`confUBINDIR', `/${HPACCOUNT}/${HPGROUP}/bin') +define(`confUBINGRP', `${HPACCOUNT}') +define(`confUBINOWN', `MGR.${HPACCOUNT}') diff --git a/gnu/dist/sendmail/devtools/OS/OSF1.V5.x b/gnu/dist/sendmail/devtools/OS/OSF1.V5.x index a6ec8d9fbcfd..c35d239628b2 100644 --- a/gnu/dist/sendmail/devtools/OS/OSF1.V5.x +++ b/gnu/dist/sendmail/devtools/OS/OSF1.V5.x @@ -1,12 +1,18 @@ -# Id: OSF1.V5.x,v 8.1.2.1 2001/02/26 21:09:00 gshapiro Exp +# Id: OSF1.V5.x,v 8.4 2002/03/21 23:59:25 gshapiro Exp + +dnl DO NOT EDIT THIS FILE. +dnl Place personal settings in devtools/Site/site.config.m4 + define(`confCC', `cc -std1 -Olimit 1000') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') -define(`confENVDEF', `-DHASSNPRINTF=1') +define(`confENVDEF', `') define(`confLIBS', `-ldbm') +define(`confSM_OS_HEADER', `sm_os_osf1') define(`confSTDIR', `/var/adm/sendmail') define(`confINSTALL', `installbsd') define(`confEBINDIR', `/usr/lbin') define(`confUBINDIR', `${BINDIR}') define(`confDEPEND_TYPE', `CC-M') +define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') diff --git a/gnu/dist/sendmail/devtools/OS/OpenUNIX.5.i386 b/gnu/dist/sendmail/devtools/OS/OpenUNIX.5.i386 new file mode 100644 index 000000000000..f4b597c20114 --- /dev/null +++ b/gnu/dist/sendmail/devtools/OS/OpenUNIX.5.i386 @@ -0,0 +1,22 @@ +# Id: OpenUNIX.5.i386,v 1.3 2002/03/21 23:59:25 gshapiro Exp + +dnl DO NOT EDIT THIS FILE. +dnl Place personal settings in devtools/Site/site.config.m4 + +# +# System V Rel 5.x (a.k.a OpenUNIX) +# +define(`confSM_OS_HEADER', `sm_os_openunix') +define(`confCC', `/usr/ccs/bin/cc') +define(`confMAPDEF', `-DNDBM -DMAP_REGEX') +define(`confENVDEF', `-D__svr5__') +define(`confLIBS', `-lsocket -lnsl -lelf') +define(`confSHELL', `/usr/bin/sh') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/etc/mail') +define(`confUBINDIR', `/etc/mail') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') +define(`confMTCCOPTS', `-Kpthread') +define(`confMTLDOPTS', `-lpthread') diff --git a/gnu/dist/sendmail/devtools/OS/SunOS.5.10 b/gnu/dist/sendmail/devtools/OS/SunOS.5.10 new file mode 100644 index 000000000000..6b504b01bbba --- /dev/null +++ b/gnu/dist/sendmail/devtools/OS/SunOS.5.10 @@ -0,0 +1,26 @@ +# Id: SunOS.5.10,v 1.1.2.1 2002/11/09 03:04:19 ca Exp + +dnl DO NOT EDIT THIS FILE. +dnl Place personal settings in devtools/Site/site.config.m4 + +define(`confCC', `gcc') +define(`confLDOPTS_SO', `-G') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') +define(`confENVDEF', `-DSOLARIS=21000 -DNETINET6') +define(`confSM_OS_HEADER', `sm_os_sunos') +define(`confLIBS', `-lsocket -lnsl') +define(`confMTCCOPTS', `-D_REENTRANT') +define(`confMTLDOPTS', `-lpthread') +define(`confMBINDIR', `/usr/lib') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/include/sysexits.h ]; \ + then \ + ln -s /usr/include/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/dist/sendmail/editmap/Build b/gnu/dist/sendmail/editmap/Build new file mode 100644 index 000000000000..2b98a09ab2d6 --- /dev/null +++ b/gnu/dist/sendmail/editmap/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. +# 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. +# +# +# Id: Build,v 1.2 2000/09/17 17:30:02 gshapiro Exp + +exec ../devtools/bin/Build $* diff --git a/gnu/dist/sendmail/editmap/Makefile b/gnu/dist/sendmail/editmap/Makefile new file mode 100644 index 000000000000..156ae69efa2d --- /dev/null +++ b/gnu/dist/sendmail/editmap/Makefile @@ -0,0 +1,17 @@ +# Id: Makefile,v 1.1 2000/08/31 16:19:25 ca Exp + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/dist/sendmail/editmap/Makefile.m4 b/gnu/dist/sendmail/editmap/Makefile.m4 new file mode 100644 index 000000000000..625da23198b9 --- /dev/null +++ b/gnu/dist/sendmail/editmap/Makefile.m4 @@ -0,0 +1,23 @@ +dnl Id: Makefile.m4,v 1.4.6.1 2002/06/21 21:58:27 ca Exp +include(confBUILDTOOLSDIR`/M4/switch.m4') + +define(`confREQUIRE_LIBSM', `true') +# sendmail dir +SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') +PREPENDDEF(`confENVDEF', `confMAPDEF') +PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') + +bldPRODUCT_START(`executable', `editmap') +define(`bldSOURCES', `editmap.c ') +define(`bldINSTALL_DIR', `S') +bldPUSH_SMLIB(`sm') +bldPUSH_SMLIB(`smutil') +bldPUSH_SMLIB(`smdb') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `editmap') +define(`bldSOURCES', `editmap.8') +bldPRODUCT_END + +bldFINISH diff --git a/gnu/dist/sendmail/editmap/editmap.0 b/gnu/dist/sendmail/editmap/editmap.0 new file mode 100644 index 000000000000..282a34425450 --- /dev/null +++ b/gnu/dist/sendmail/editmap/editmap.0 @@ -0,0 +1,132 @@ + + + +EDITMAP(8) EDITMAP(8) + + +NNAAMMEE + eeddiittmmaapp - query and edit single records in database maps + for sendmail + +SSYYNNOOPPSSIISS + eeddiittmmaapp [--CC _f_i_l_e] [--NN] [--ff] [--qq||--uu||--xx] maptype mapname key + [ "value ..." ] + +DDEESSCCRRIIPPTTIIOONN + EEddiittmmaapp queries or edits one record in a database maps + used by the keyed map lookups in sendmail(8). Arguments + are passed on the command line and output (for queries) is + directed to standard output. + + Depending on how it is compiled, eeddiittmmaapp handles up to + three different database formats, selected using the _m_a_p_- + _t_y_p_e parameter. They may be + + dbm DBM format maps. This requires the ndbm(3) + library. + + btree B-Tree format maps. This requires the new Berkeley + DB library. + + hash Hash format maps. This also requires the Berkeley + DB library. + + If the _T_r_u_s_t_e_d_U_s_e_r option is set in the sendmail configu- + ration file and eeddiittmmaapp is invoked as root, the generated + files will be owned by the specified _T_r_u_s_t_e_d_U_s_e_r_. + + FFllaaggss + --CC Use the specified sseennddmmaaiill configuration file for + looking up the TrustedUser option. + + --NN Include the null byte that terminates strings in + the map (for alias maps). + + --ff Normally all upper case letters in the key are + folded to lower case. This flag disables that + behaviour. This is intended to mesh with the -f + flag in the KK line in sendmail.cf. The value is + never case folded. + + --qq Query the map for the specified key. If found, + print value to standard output and exit with 0. If + not found then print an error message to stdout and + exit with EX_UNAVAILABLE. + + --uu Update the record for _k_e_y with _v_a_l_u_e or inserts a + new record if one doesn't exist. Exits with 0 on + success or EX_IOERR on failure. + + --xx Deletes the specific key from the map. Exits with + + + + Date: 2001/06/15 21:33:19 1 + + + + + +EDITMAP(8) EDITMAP(8) + + + 0 on success or EX_IOERR on failure. + + + SSEEEE AALLSSOO + sendmail(8), makemap(8) + +HHIISSTTOORRYY + The eeddiittmmaapp command has no history. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: 2001/06/15 21:33:19 2 + + diff --git a/gnu/dist/sendmail/editmap/editmap.8 b/gnu/dist/sendmail/editmap/editmap.8 new file mode 100644 index 000000000000..c655798f8184 --- /dev/null +++ b/gnu/dist/sendmail/editmap/editmap.8 @@ -0,0 +1,106 @@ +.\" Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. +.\" 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. +.\" +.\" +.\" Id: editmap.8,v 1.8 2001/06/15 21:33:19 ca Exp +.\" +.TH EDITMAP 8 "Date: 2001/06/15 21:33:19" +.SH NAME +.B editmap +\- query and edit single records in database maps for sendmail +.SH SYNOPSIS +.B editmap +.RB [ \-C +.IR file ] +.RB [ \-N ] +.RB [ \-f ] +.RB [ \-q|\-u|\-x ] +maptype mapname +key [ "value ..." ] +.SH DESCRIPTION +.B Editmap +queries or edits one record in a database maps used by the keyed map lookups in +sendmail(8). +Arguments are passed on the command line and output (for queries) is +directed to standard output. +.PP +Depending on how it is compiled, +.B editmap +handles up to three different database formats, +selected using the +.I maptype +parameter. +They may be +.TP +dbm +DBM format maps. +This requires the +ndbm(3) +library. +.TP +btree +B-Tree format maps. +This requires the new Berkeley DB +library. +.TP +hash +Hash format maps. +This also requires the Berkeley DB +library. +.PP +If the +.I TrustedUser +option is set in the sendmail configuration file and +.B editmap +is invoked as root, the generated files will be owned by +the specified +.IR TrustedUser. +.SS Flags +.TP +.B \-C +Use the specified +.B sendmail +configuration file for looking up the TrustedUser option. +.TP +.B \-N +Include the null byte that terminates strings +in the map (for alias maps). +.TP +.B \-f +Normally all upper case letters in the key +are folded to lower case. +This flag disables that behaviour. +This is intended to mesh with the +\-f flag in the +.B K +line in sendmail.cf. +The value is never case folded. +.TP +.B \-q +Query the map for the specified key. If found, print value to standard +output and exit with 0. If not found then print an error +message to stdout and exit with EX_UNAVAILABLE. +.TP +.B \-u +Update the record for +.I key +with +.I value +or inserts a new record if one doesn't exist. Exits with 0 on success +or EX_IOERR on failure. +.TP +.B \-x +Deletes the specific key from the map. Exits with 0 on success or +EX_IOERR on failure. +.TP +.SH SEE ALSO +sendmail(8), +makemap(8) +.SH HISTORY +The +.B editmap +command has no history. diff --git a/gnu/dist/sendmail/editmap/editmap.c b/gnu/dist/sendmail/editmap/editmap.c new file mode 100644 index 000000000000..86b1025eb332 --- /dev/null +++ b/gnu/dist/sendmail/editmap/editmap.c @@ -0,0 +1,420 @@ +/* + * Copyright (c) 1998-2002 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. + * + * 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. + * + */ + +#include +#ifndef lint +SM_UNUSED(static char copyright[]) = +"@(#) Copyright (c) 1998-2001 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 +SM_UNUSED(static char id[]) = "@(#)Id: editmap.c,v 1.23 2002/03/28 17:49:33 gshapiro Exp"; +#endif /* ! lint */ + + +#include +#ifndef ISC_UNIX +# include +#endif /* ! ISC_UNIX */ +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include +#include +#include +#include +#include + +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; + +#define BUFSIZE 1024 +#define ISSEP(c) (isascii(c) && isspace(c)) + + +static void +usage(progname) + char *progname; +{ + fprintf(stderr, + "Usage: %s [-C cffile] [-N] [-f] [-q|-u|-x] maptype mapname key [ \"value ...\" ]\n", + progname); + exit(EX_USAGE); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + char *progname; + char *cfile; + bool verbose = false; + bool query = false; + bool update = false; + bool remove = false; + bool inclnull = false; + bool foldcase = true; + unsigned int nops = 0; + int exitstat; + int opt; + char *typename = NULL; + char *mapname = NULL; + char *keyname = NULL; + char *value = NULL; + int mode; + int smode; + int putflags = 0; + long sff = SFF_ROOTOK|SFF_REGONLY; + struct passwd *pw; + SMDB_DATABASE *database; + SMDB_DBENT db_key, db_val; + SMDB_DBPARAMS params; + SMDB_USER_INFO user_info; +#if HASFCHOWN + FILE *cfp; + char buf[MAXLINE]; +#endif /* HASFCHOWN */ + static char rnamebuf[MAXNAME]; /* holds RealUserName */ + extern char *optarg; + extern int optind; + + 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) + (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf); + else + (void) sm_snprintf(rnamebuf, sizeof rnamebuf, + "Unknown UID %d", (int) RealUid); + RunAsUserName = RealUserName = rnamebuf; + user_info.smdbu_id = RunAsUid; + user_info.smdbu_group_id = RunAsGid; + (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName, + SMDB_MAX_USER_NAME_LEN); + +#define OPTIONS "C:fquxvN" + while ((opt = getopt(argc, argv, OPTIONS)) != -1) + { + switch (opt) + { + case 'C': + cfile = optarg; + break; + + case 'f': + foldcase = false; + break; + + case 'q': + query = true; + nops++; + break; + + case 'u': + update = true; + nops++; + break; + + case 'x': + remove = true; + nops++; + break; + + case 'v': + verbose = true; + break; + + case 'N': + inclnull = true; + break; + + default: + usage(progname); + assert(0); /* NOTREACHED */ + } + } + + if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) + sff |= SFF_NOSLINK; + if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) + sff |= SFF_NOHLINK; + if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) + sff |= SFF_NOWLINK; + + argc -= optind; + argv += optind; + if ((nops != 1) || + (query && argc != 3) || + (remove && argc != 3) || + (update && argc <= 3)) + { + usage(progname); + assert(0); /* NOTREACHED */ + } + + typename = argv[0]; + mapname = argv[1]; + keyname = argv[2]; + if (update) + value = argv[3]; + + if (foldcase) + { + char *p; + + for (p = keyname; *p != '\0'; p++) + { + if (isascii(*p) && isupper(*p)) + *p = tolower(*p); + } + } + + +#if HASFCHOWN + /* Find TrustedUser value in sendmail.cf */ + if ((cfp = fopen(cfile, "r")) == NULL) + { + fprintf(stderr, "%s: %s: %s\n", progname, + cfile, sm_errstring(errno)); + exit(EX_NOINPUT); + } + while (fgets(buf, sizeof(buf), cfp) != NULL) + { + register char *b; + + if ((b = strchr(buf, '\n')) != NULL) + *b = '\0'; + + b = buf; + switch (*b++) + { + case 'O': /* option */ + if (strncasecmp(b, " TrustedUser", 12) == 0 && + !(isascii(b[12]) && isalnum(b[12]))) + { + b = strchr(b, '='); + if (b == NULL) + continue; + while (isascii(*++b) && isspace(*b)) + continue; + if (isascii(*b) && isdigit(*b)) + TrustedUid = atoi(b); + else + { + TrustedUid = 0; + pw = getpwnam(b); + if (pw == NULL) + fprintf(stderr, + "TrustedUser: unknown user %s\n", b); + else + TrustedUid = pw->pw_uid; + } + +# ifdef UID_MAX + if (TrustedUid > UID_MAX) + { + fprintf(stderr, + "TrustedUser: uid value (%ld) > UID_MAX (%ld)", + (long) TrustedUid, + (long) UID_MAX); + TrustedUid = 0; + } +# endif /* UID_MAX */ + break; + } + + + default: + continue; + } + } + (void) fclose(cfp); +#endif /* HASFCHOWN */ + + if (query) + { + mode = O_RDONLY; + smode = S_IRUSR; + } + else + { + mode = O_RDWR | O_CREAT; + sff |= SFF_CREAT|SFF_NOTEXCL; + smode = S_IWUSR; + } + + params.smdbp_num_elements = 4096; + + errno = smdb_open_database(&database, mapname, mode, smode, sff, + typename, &user_info, ¶ms); + if (errno != SMDBE_OK) + { + char *hint; + + 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, + sm_errstring(errno)); + exit(EX_CANTCREAT); + } + + (void) database->smdb_sync(database, 0); + + if (geteuid() == 0 && TrustedUid != 0) + { + errno = database->smdb_set_owner(database, TrustedUid, -1); + if (errno != SMDBE_OK) + { + fprintf(stderr, + "WARNING: ownership change on %s failed %s", + mapname, sm_errstring(errno)); + } + } + + exitstat = EX_OK; + if (query) + { + memset(&db_key, '\0', sizeof db_key); + memset(&db_val, '\0', sizeof db_val); + + db_key.data = keyname; + db_key.size = strlen(keyname); + if (inclnull) + db_key.size++; + + errno = database->smdb_get(database, &db_key, &db_val, 0); + if (errno != SMDBE_OK) + { + /* XXX - Need to distinguish between not found */ + fprintf(stderr, + "%s: couldn't find key %s in map %s\n", + progname, keyname, mapname); + exitstat = EX_UNAVAILABLE; + } + else + { + printf("%.*s\n", (int) db_val.size, + (char *) db_val.data); + } + } + else if (update) + { + memset(&db_key, '\0', sizeof db_key); + memset(&db_val, '\0', sizeof db_val); + + db_key.data = keyname; + db_key.size = strlen(keyname); + if (inclnull) + db_key.size++; + db_val.data = value; + db_val.size = strlen(value); + if (inclnull) + db_val.size++; + + errno = database->smdb_put(database, &db_key, &db_val, + putflags); + if (errno != SMDBE_OK) + { + fprintf(stderr, + "%s: error updating (%s, %s) in map %s: %s\n", + progname, keyname, value, mapname, + sm_errstring(errno)); + exitstat = EX_IOERR; + } + } + else if (remove) + { + memset(&db_key, '\0', sizeof db_key); + memset(&db_val, '\0', sizeof db_val); + + db_key.data = keyname; + db_key.size = strlen(keyname); + if (inclnull) + db_key.size++; + + errno = database->smdb_del(database, &db_key, 0); + + switch (errno) + { + case SMDBE_NOT_FOUND: + fprintf(stderr, + "%s: key %s doesn't exist in map %s\n", + progname, keyname, mapname); + /* Don't set exitstat */ + break; + case SMDBE_OK: + /* All's well */ + break; + default: + fprintf(stderr, + "%s: couldn't remove key %s in map %s (error)\n", + progname, keyname, mapname); + exitstat = EX_IOERR; + break; + } + } + else + { + assert(0); /* NOT REACHED */ + } + + /* + ** Now close the database. + */ + + errno = database->smdb_close(database); + if (errno != SMDBE_OK) + { + fprintf(stderr, "%s: close(%s): %s\n", + progname, mapname, sm_errstring(errno)); + exitstat = EX_IOERR; + } + smdb_free_database(database); + + exit(exitstat); + /* NOTREACHED */ + return exitstat; +} diff --git a/gnu/dist/sendmail/include/libmilter/mfdef.h b/gnu/dist/sendmail/include/libmilter/mfdef.h new file mode 100644 index 000000000000..d7d705baf496 --- /dev/null +++ b/gnu/dist/sendmail/include/libmilter/mfdef.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * + * Id: mfdef.h,v 8.11.2.1 2002/11/11 23:22:28 ca Exp + */ + +/* +** mfdef.h -- Global definitions for mail filter and MTA. +*/ + +#ifndef _LIBMILTER_MFDEF_H +# define _LIBMILTER_MFDEF_H 1 + +/* Shared protocol constants */ +# define MILTER_LEN_BYTES 4 /* length of 32 bit integer in bytes */ +# define MILTER_OPTLEN (MILTER_LEN_BYTES * 3) /* length of options */ +# define MILTER_CHUNK_SIZE 65535 /* body chunk size */ + +/* These apply to SMFIF_* flags */ +#define SMFI_V1_ACTS 0x0000000FL /* The actions of V1 filter */ +#if _FFR_QUARANTINE +# define SMFI_V2_ACTS 0x0000003FL /* The actions of V2 filter */ +#else /* _FFR_QUARANTINE */ +# define SMFI_V2_ACTS 0x0000001FL /* The actions of V2 filter */ +#endif /* _FFR_QUARANTINE */ +#define SMFI_CURR_ACTS SMFI_V2_ACTS /* The current version */ + +/* address families */ +# define SMFIA_UNKNOWN 'U' /* unknown */ +# define SMFIA_UNIX 'L' /* unix/local */ +# define SMFIA_INET '4' /* inet */ +# define SMFIA_INET6 '6' /* inet6 */ + +/* commands: don't use anything smaller than ' ' */ +# define SMFIC_ABORT 'A' /* Abort */ +# define SMFIC_BODY 'B' /* Body chunk */ +# define SMFIC_CONNECT 'C' /* Connection information */ +# define SMFIC_MACRO 'D' /* Define macro */ +# define SMFIC_BODYEOB 'E' /* final body chunk (End) */ +# define SMFIC_HELO 'H' /* HELO/EHLO */ +# define SMFIC_HEADER 'L' /* Header */ +# define SMFIC_MAIL 'M' /* MAIL from */ +# define SMFIC_EOH 'N' /* EOH */ +# define SMFIC_OPTNEG 'O' /* Option negotiation */ +# define SMFIC_QUIT 'Q' /* QUIT */ +# define SMFIC_RCPT 'R' /* RCPT to */ + +/* actions (replies) */ +# define SMFIR_ADDRCPT '+' /* add recipient */ +# define SMFIR_DELRCPT '-' /* remove recipient */ +# define SMFIR_ACCEPT 'a' /* accept */ +# define SMFIR_REPLBODY 'b' /* replace body (chunk) */ +# define SMFIR_CONTINUE 'c' /* continue */ +# define SMFIR_DISCARD 'd' /* discard */ +# define SMFIR_CHGHEADER 'm' /* change header */ +# define SMFIR_PROGRESS 'p' /* progress */ +# define SMFIR_REJECT 'r' /* reject */ +# define SMFIR_TEMPFAIL 't' /* tempfail */ +# if _FFR_MILTER_421 +# define SMFIR_SHUTDOWN '4' /* 421: shutdown (internal to MTA) */ +# endif /* _FFR_MILTER_421 */ +# define SMFIR_ADDHEADER 'h' /* add header */ +# define SMFIR_REPLYCODE 'y' /* reply code etc */ +# if _FFR_QUARANTINE +# define SMFIR_QUARANTINE 'q' /* quarantine */ +# endif /* _FFR_QUARANTINE */ + +/* What the MTA can send/filter wants in protocol */ +# define SMFIP_NOCONNECT 0x00000001L /* MTA should not send connect info */ +# define SMFIP_NOHELO 0x00000002L /* MTA should not send HELO info */ +# define SMFIP_NOMAIL 0x00000004L /* MTA should not send MAIL info */ +# define SMFIP_NORCPT 0x00000008L /* MTA should not send RCPT info */ +# define SMFIP_NOBODY 0x00000010L /* MTA should not send body */ +# define SMFIP_NOHDRS 0x00000020L /* MTA should not send headers */ +# define SMFIP_NOEOH 0x00000040L /* MTA should not send EOH */ + +# define SMFI_V1_PROT 0x0000003FL /* The protocol of V1 filter */ +# define SMFI_V2_PROT 0x0000007FL /* The protocol of V2 filter */ +# define SMFI_CURR_PROT SMFI_V2_PROT /* The current version */ + +#endif /* !_LIBMILTER_MFDEF_H */ diff --git a/gnu/dist/sendmail/include/sm/assert.h b/gnu/dist/sendmail/include/sm/assert.h new file mode 100644 index 000000000000..b7da78f3cc5c --- /dev/null +++ b/gnu/dist/sendmail/include/sm/assert.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: assert.h,v 1.10 2001/06/07 20:04:53 ca Exp + */ + +/* +** libsm abnormal program termination and assertion checking +** See libsm/assert.html for documentation. +*/ + +#ifndef SM_ASSERT_H +# define SM_ASSERT_H + +# include +# include + +/* +** abnormal program termination +*/ + +typedef void (*SM_ABORT_HANDLER_T) __P((const char *, int, const char *)); + +extern SM_DEAD(void +sm_abort_at __P(( + const char *, + int, + const char *))); + +extern void +sm_abort_sethandler __P(( + SM_ABORT_HANDLER_T)); + +extern SM_DEAD(void PRINTFLIKE(1, 2) +sm_abort __P(( + char *, + ...))); + +/* +** assertion checking +*/ + +# ifndef SM_CHECK_ALL +# define SM_CHECK_ALL 1 +# endif /* ! SM_CHECK_ALL */ + +# ifndef SM_CHECK_REQUIRE +# define SM_CHECK_REQUIRE SM_CHECK_ALL +# endif /* ! SM_CHECK_REQUIRE */ + +# ifndef SM_CHECK_ENSURE +# define SM_CHECK_ENSURE SM_CHECK_ALL +# endif /* ! SM_CHECK_ENSURE */ + +# ifndef SM_CHECK_ASSERT +# define SM_CHECK_ASSERT SM_CHECK_ALL +# endif /* ! SM_CHECK_ASSERT */ + +# if SM_CHECK_REQUIRE +# if defined(__STDC__) || defined(__cplusplus) +# define SM_REQUIRE(cond) \ + ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ + "SM_REQUIRE(" #cond ") failed"), 0))) +# else /* defined(__STDC__) || defined(__cplusplus) */ +# define SM_REQUIRE(cond) \ + ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ + "SM_REQUIRE(cond) failed"), 0))) +# endif /* defined(__STDC__) || defined(__cplusplus) */ +# else /* SM_CHECK_REQUIRE */ +# define SM_REQUIRE(cond) ((void) 0) +# endif /* SM_CHECK_REQUIRE */ + +# define SM_REQUIRE_ISA(obj, magic) \ + SM_REQUIRE((obj) != NULL && (obj)->sm_magic == (magic)) + +# if SM_CHECK_ENSURE +# if defined(__STDC__) || defined(__cplusplus) +# define SM_ENSURE(cond) \ + ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ + "SM_ENSURE(" #cond ") failed"), 0))) +# else /* defined(__STDC__) || defined(__cplusplus) */ +# define SM_ENSURE(cond) \ + ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ + "SM_ENSURE(cond) failed"), 0))) +# endif /* defined(__STDC__) || defined(__cplusplus) */ +# else /* SM_CHECK_ENSURE */ +# define SM_ENSURE(cond) ((void) 0) +# endif /* SM_CHECK_ENSURE */ + +# if SM_CHECK_ASSERT +# if defined(__STDC__) || defined(__cplusplus) +# define SM_ASSERT(cond) \ + ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ + "SM_ASSERT(" #cond ") failed"), 0))) +# else /* defined(__STDC__) || defined(__cplusplus) */ +# define SM_ASSERT(cond) \ + ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ + "SM_ASSERT(cond) failed"), 0))) +# endif /* defined(__STDC__) || defined(__cplusplus) */ +# else /* SM_CHECK_ASSERT */ +# define SM_ASSERT(cond) ((void) 0) +# endif /* SM_CHECK_ASSERT */ + +extern SM_DEBUG_T SmExpensiveRequire; +extern SM_DEBUG_T SmExpensiveEnsure; +extern SM_DEBUG_T SmExpensiveAssert; + +#endif /* ! SM_ASSERT_H */ diff --git a/gnu/dist/sendmail/include/sm/bdb.h b/gnu/dist/sendmail/include/sm/bdb.h new file mode 100644 index 000000000000..dd976677121d --- /dev/null +++ b/gnu/dist/sendmail/include/sm/bdb.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002 Sendmail, Inc. and its suppliers. + * 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. + * + * + * Id: bdb.h,v 1.1.2.3 2002/12/05 05:07:44 ca Exp + */ + +#ifndef SM_BDB_H +#define SM_BDB_H + +#if NEWDB +# include +# ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +# endif /* ! DB_VERSION_MAJOR */ + +# if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1 + +# define DBTXN NULL , + +/* +** Always turn on DB_FCNTL_LOCKING for DB 4.1.x since its +** "workaround" for accepting an empty (locked) file depends on +** this flag. Notice: this requires 4.1.24 + patch (which should be +** part of 4.1.25). +*/ + +# define SM_DB_FLAG_ADD(flag) (flag) |= DB_FCNTL_LOCKING + +# else /* DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1 */ + +# define DBTXN +# if !HASFLOCK +# define SM_DB_FLAG_ADD(flag) (flag) |= DB_FCNTL_LOCKING +# else /* !HASFLOCK */ +# define SM_DB_FLAG_ADD(flag) ((void) 0) +# endif /* !HASFLOCK */ + +# endif /* DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1 */ +#endif /* NEWDB */ + +#endif /* ! SM_BDB_H */ diff --git a/gnu/dist/sendmail/include/sm/bitops.h b/gnu/dist/sendmail/include/sm/bitops.h new file mode 100644 index 000000000000..61d09ef2a3a9 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/bitops.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1998-2001 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. + * + * 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. + * + * + * Id: bitops.h,v 1.2 2001/09/22 22:05:42 ca Exp + */ + +#ifndef SM_BITOPS_H +# define SM_BITOPS_H + +/* +** Data structure for bit maps. +** +** Each bit in this map can be referenced by an ascii character. +** This is 256 possible bits, or 32 8-bit bytes. +*/ + +# define BITMAPBITS 256 /* number of bits in a bit map */ +# define BYTEBITS 8 /* number of bits in a byte */ +# define BITMAPBYTES (BITMAPBITS / BYTEBITS) /* number of bytes in bit map */ +# define BITMAPMAX ((BITMAPBYTES / sizeof (int)) - 1) + +/* internal macros */ + +/* make sure this index never leaves the allowed range: 0 to BITMAPMAX */ +# define _BITWORD(bit) (((unsigned char)(bit) / (BYTEBITS * sizeof (int))) & BITMAPMAX) +# define _BITBIT(bit) ((unsigned int)1 << ((unsigned char)(bit) % (BYTEBITS * sizeof (int)))) + +typedef unsigned int BITMAP256[BITMAPBYTES / sizeof (int)]; + +/* properly case and truncate bit */ +# define bitidx(bit) ((unsigned int) (bit) & 0xff) + +/* test bit number N */ +# define bitnset(bit, map) ((map)[_BITWORD(bit)] & _BITBIT(bit)) + +/* set bit number N */ +# define setbitn(bit, map) (map)[_BITWORD(bit)] |= _BITBIT(bit) + +/* clear bit number N */ +# define clrbitn(bit, map) (map)[_BITWORD(bit)] &= ~_BITBIT(bit) + +/* clear an entire bit map */ +# define clrbitmap(map) memset((char *) map, '\0', BITMAPBYTES) + +/* bit hacking */ +# define bitset(bit, word) (((word) & (bit)) != 0) + +#endif /* ! SM_BITOPS_H */ diff --git a/gnu/dist/sendmail/include/sm/cdefs.h b/gnu/dist/sendmail/include/sm/cdefs.h new file mode 100644 index 000000000000..45879a444548 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/cdefs.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: cdefs.h,v 1.15 2002/01/16 18:30:11 ca Exp + */ + +/* +** libsm C language portability macros +** See libsm/cdefs.html for documentation. +*/ + +#ifndef SM_CDEFS_H +# define SM_CDEFS_H + +# include + +/* +** BSD and Linux have which defines a set of C language +** portability macros that are a defacto standard in the open source +** community. +*/ + +# if SM_CONF_SYS_CDEFS_H +# include +# endif /* SM_CONF_SYS_CDEFS_H */ + +/* +** Define the standard C language portability macros +** for platforms that lack . +*/ + +# if !SM_CONF_SYS_CDEFS_H +# if defined(__cplusplus) +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS }; +# else /* defined(__cplusplus) */ +# define __BEGIN_DECLS +# define __END_DECLS +# endif /* defined(__cplusplus) */ +# if defined(__STDC__) || defined(__cplusplus) +# ifndef __P +# define __P(protos) protos +# endif /* __P */ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +# else /* defined(__STDC__) || defined(__cplusplus) */ +# define __P(protos) () +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +# define const +# define signed +# define volatile +# endif /* defined(__STDC__) || defined(__cplusplus) */ +# endif /* !SM_CONF_SYS_CDEFS_H */ + +/* +** Define SM_DEAD, a macro used to declare functions that do not return +** to their caller. +*/ + +# ifndef SM_DEAD +# if __GNUC__ >= 2 +# if __GNUC__ == 2 && __GNUC_MINOR__ < 5 +# define SM_DEAD(proto) volatile proto +# else /* __GNUC__ == 2 && __GNUC_MINOR__ < 5 */ +# define SM_DEAD(proto) proto __attribute__((__noreturn__)) +# endif /* __GNUC__ == 2 && __GNUC_MINOR__ < 5 */ +# else /* __GNUC__ >= 2 */ +# define SM_DEAD(proto) proto +# endif /* __GNUC__ >= 2 */ +# endif /* SM_DEAD */ + +/* +** Define SM_UNUSED, a macro used to declare variables that may be unused. +*/ + +# ifndef SM_UNUSED +# if __GNUC__ >= 2 +# if __GNUC__ == 2 && __GNUC_MINOR__ < 7 +# define SM_UNUSED(decl) decl +# else /* __GNUC__ == 2 && __GNUC_MINOR__ < 7 */ +# define SM_UNUSED(decl) decl __attribute__((__unused__)) +# endif /* __GNUC__ == 2 && __GNUC_MINOR__ < 7 */ +# else /* __GNUC__ >= 2 */ +# define SM_UNUSED(decl) decl +# endif /* __GNUC__ >= 2 */ +# endif /* SM_UNUSED */ + +/* +** The SM_NONVOLATILE macro is used to declare variables that are not +** volatile, but which must be declared volatile when compiling with +** gcc -O -Wall in order to suppress bogus warning messages. +** +** Variables that actually are volatile should be declared volatile +** using the "volatile" keyword. If a variable actually is volatile, +** then SM_NONVOLATILE should not be used. +** +** To compile sendmail with gcc and see all non-bogus warnings, +** you should use +** gcc -O -Wall -DSM_OMIT_BOGUS_WARNINGS ... +** Do not use -DSM_OMIT_BOGUS_WARNINGS when compiling the production +** version of sendmail, because there is a performance hit. +*/ + +# ifdef SM_OMIT_BOGUS_WARNINGS +# define SM_NONVOLATILE volatile +# else /* SM_OMIT_BOGUS_WARNINGS */ +# define SM_NONVOLATILE +# endif /* SM_OMIT_BOGUS_WARNINGS */ + +/* +** Turn on format string argument checking. +*/ + +# ifndef SM_CONF_FORMAT_TEST +# if __GNUC__ == 2 && __GNUC_MINOR__ >= 7 +# define SM_CONF_FORMAT_TEST 1 +# else /* __GNUC__ == 2 && __GNUC_MINOR__ >= 7 */ +# define SM_CONF_FORMAT_TEST 0 +# endif /* __GNUC__ == 2 && __GNUC_MINOR__ >= 7 */ +# endif /* SM_CONF_FORMAT_TEST */ + +# ifndef PRINTFLIKE +# if SM_CONF_FORMAT_TEST +# define PRINTFLIKE(x,y) __attribute__ ((__format__ (__printf__, x, y))) +# else /* SM_CONF_FORMAT_TEST */ +# define PRINTFLIKE(x,y) +# endif /* SM_CONF_FORMAT_TEST */ +# endif /* ! PRINTFLIKE */ + +# ifndef SCANFLIKE +# if SM_CONF_FORMAT_TEST +# define SCANFLIKE(x,y) __attribute__ ((__format__ (__scanf__, x, y))) +# else /* SM_CONF_FORMAT_TEST */ +# define SCANFLIKE(x,y) +# endif /* SM_CONF_FORMAT_TEST */ +# endif /* ! SCANFLIKE */ + +#endif /* ! SM_CDEFS_H */ diff --git a/gnu/dist/sendmail/include/sm/cf.h b/gnu/dist/sendmail/include/sm/cf.h new file mode 100644 index 000000000000..26eb2344e99c --- /dev/null +++ b/gnu/dist/sendmail/include/sm/cf.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: cf.h,v 1.2 2001/03/08 03:23:07 ca Exp + */ + +#ifndef SM_CF_H +# define SM_CF_H + +#include + +typedef struct +{ + char *opt_name; + char *opt_val; +} SM_CF_OPT_T; + +extern int +sm_cf_getopt __P(( + char *path, + int optc, + SM_CF_OPT_T *optv)); + +#endif /* ! SM_CF_H */ diff --git a/gnu/dist/sendmail/include/sm/clock.h b/gnu/dist/sendmail/include/sm/clock.h new file mode 100644 index 000000000000..8a12270b3ca5 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/clock.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1998-2001 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. + * + * 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. + * + * Id: clock.h,v 1.11 2001/05/14 23:25:37 gshapiro Exp + */ + +/* +** CLOCK.H -- for co-ordinating timed events +*/ + +#ifndef _SM_CLOCK_H +# define _SM_CLOCK_H 1 + +# include +# if SM_CONF_SETITIMER +# include +# endif /* SM_CONF_SETITIMER */ + +/* +** STRUCT SM_EVENT -- event queue. +** +** Maintained in sorted order. +** +** We store the pid of the process that set this event to insure +** that when we fork we will not take events intended for the parent. +*/ + +struct sm_event +{ +# if SM_CONF_SETITIMER + struct timeval ev_time; /* time of the call (microseconds) */ +# else /* SM_CONF_SETITIMER */ + time_t ev_time; /* time of the call (seconds) */ +# endif /* SM_CONF_SETITIMER */ + void (*ev_func)__P((int)); + /* function to call */ + int ev_arg; /* argument to ev_func */ + pid_t ev_pid; /* pid that set this event */ + struct sm_event *ev_link; /* link to next item */ +}; + +typedef struct sm_event SM_EVENT; + +/* functions */ +extern void sm_clrevent __P((SM_EVENT *)); +extern void sm_clear_events __P((void)); +extern SM_EVENT *sm_setevent __P((time_t, void(*)(), int)); +extern SM_EVENT *sm_seteventm __P((int, void(*)(), int)); +extern SM_EVENT *sm_sigsafe_seteventm __P((int, void(*)(), int)); +extern SIGFUNC_DECL sm_tick __P((int)); + +/* +** SM_SETEVENT -- set an event to happen at a specific time in seconds. +** +** Translates the seconds into millseconds and calls sm_seteventm() +** to get a specific event to happen in the future at a specific time. +** +** Parameters: +** t -- intvl until next event occurs (seconds). +** f -- function to call on event. +** a -- argument to func on event. +** +** Returns: +** result of sm_seteventm(). +** +** Side Effects: +** Any that sm_seteventm() have. +*/ + +#define sm_setevent(t, f, a) sm_seteventm((int)((t) * 1000), (f), (a)) +#define sm_sigsafe_setevent(t, f, a) sm_sigsafe_seteventm((int)((t) * 1000), (f), (a)) + +#endif /* _SM_CLOCK_H */ diff --git a/gnu/dist/sendmail/include/sm/conf.h b/gnu/dist/sendmail/include/sm/conf.h new file mode 100644 index 000000000000..76ab90a1cb3d --- /dev/null +++ b/gnu/dist/sendmail/include/sm/conf.h @@ -0,0 +1,2853 @@ +/* + * Copyright (c) 1998-2002 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. + * + * 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. + * + * + * Id: conf.h,v 1.90.2.13 2002/12/10 03:08:56 ca Exp + */ + +/* +** CONF.H -- All user-configurable parameters for sendmail +** +** Send updates to sendmail@Sendmail.ORG so they will be +** included in the next release. +*/ + +#ifndef SM_CONF_H +# define SM_CONF_H 1 + + +# include +# include + +/* +** General "standard C" defines. +** +** These may be undone later, to cope with systems that claim to +** be Standard C but aren't. Gcc is the biggest offender -- it +** doesn't realize that the library is part of the language. +** +** Life would be much easier if we could get rid of this sort +** of bozo problems. +*/ + +# ifdef __STDC__ +# define HASSETVBUF 1 /* we have setvbuf(3) in libc */ +# endif /* __STDC__ */ + +/* +** Assume you have standard calls; can be #undefed below if necessary. +*/ + +# ifndef HASLSTAT +# define HASLSTAT 1 /* has lstat(2) call */ +# endif /* ! HASLSTAT */ + +# ifndef HASNICE +# define HASNICE 1 /* has nice(2) call */ +# endif /* ! HASNICE */ + +# ifndef HASRRESVPORT +# define HASRRESVPORT 1 /* has rrsevport(3) call */ +# endif /* ! HASRRESVPORT */ + +/********************************************************************** +** "Hard" compilation options. +** #define these if they are available; comment them out otherwise. +** These cannot be overridden from the Makefile, and should really not +** be turned off unless absolutely necessary. +**********************************************************************/ + +#define LOG 1 /* enable logging -- don't turn off */ + +/********************************************************************** +** Operating system configuration. +** +** Unless you are porting to a new OS, you shouldn't have to +** change these. +**********************************************************************/ + +/* +** HP-UX -- tested for 8.07, 9.00, and 9.01. +** +** If V4FS is defined, compile for HP-UX 10.0. +** 11.x support from Richard Allen . +*/ + +# ifdef __hpux + /* common definitions for HP-UX 9.x and 10.x */ +# undef m_flags /* conflict between Berkeley DB 1.85 db.h & sys/sysmacros.h on HP 300 */ +# 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 usable seteuid(2) call */ +# define HASSETRESGID 1 /* use setresgid(2) to set saved gid */ +# 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 */ +# define LA_TYPE LA_HPUX +# define SPT_TYPE SPT_PSTAT +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# define GIDSET_T gid_t +# define LDA_USE_LOCKF 1 +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ +# endif /* ! HASGETUSERSHELL */ +# ifdef HPUX10 +# define _PATH_SENDMAIL "/usr/sbin/sendmail" +# define SMRSH_CMDDIR "/var/adm/sm.bin" +# endif /* HPUX10 */ +# ifdef HPUX11 +# define HASSETREUID 1 /* setreuid(2) works on HP-UX 11.x */ +# define HASFCHOWN 1 /* has fchown(2) */ +# ifndef BROKEN_RES_SEARCH +# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ +# endif /* ! BROKEN_RES_SEARCH */ +# define SMRSH_CMDDIR "/var/adm/sm.bin" +# define _PATH_SENDMAIL "/usr/sbin/sendmail" +# 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 + /* HP-UX 10.x */ +# define _PATH_UNIX "/stand/vmunix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# ifndef IDENTPROTO +# define IDENTPROTO 1 /* TCP/IP implementation fixed in 10.0 */ +# endif /* ! IDENTPROTO */ +# include /* 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 /* ! _PATH_VENDOR_CF */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# ifdef __STDC__ +extern void hard_syslog(int, char *, ...); +# else /* __STDC__ */ +extern void hard_syslog(); +# endif /* __STDC__ */ +# define FDSET_CAST (int *) /* cast for fd_set parameters to select */ +# endif /* V4FS */ + +# endif /* __hpux */ + +/* +** IBM AIX 5.x +*/ + +# ifdef _AIX5 +# define _AIX4 40300 +# endif /* _AIX5 */ + +/* +** IBM AIX 4.x +*/ + +# 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 /* _AIX4 >= 40200 */ +# if defined(_ILS_MACROS) /* IBM versions aren't side-effect clean */ +# undef isascii +# define isascii(c) !(c & ~0177) +# undef isdigit +# define isdigit(__a) (_IS(__a,_ISDIGIT)) +# undef isspace +# define isspace(__a) (_IS(__a,_ISSPACE)) +# endif /* defined(_ILS_MACROS) */ +# endif /* _AIX4 */ + + +/* +** IBM AIX 3.x -- actually tested for 3.2.3 +*/ + +# ifdef _AIX3 +# include +# include /* to get byte order */ +# include +# 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 */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ +# define GIDSET_T gid_t +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# define LA_TYPE LA_INT +# define FSHIFT 16 +# define LA_AVENRUN "avenrun" +# if !defined(_AIX4) || _AIX4 < 40300 +# ifndef __BIT_TYPES_DEFINED__ +# define SM_INT32 int +# endif /* __BIT_TYPES_DEFINED__ */ +# endif /* !defined(_AIX4) || _AIX4 < 40300 */ +# if !defined(_AIX4) || _AIX4 < 40200 +# define SM_CONF_SYSLOG 0 +# endif /* !defined(_AIX4) || _AIX4 < 40200 */ +# endif /* _AIX3 */ + + +/* +** IBM AIX 2.2.1 -- actually tested for osupdate level 2706+1773 +** +** From Mark Whetzel . +*/ + +# ifdef AIX /* AIX/RT compiler pre-defines this */ +# include +# include /* AIX/RT resource.h does NOT include this */ +# 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 */ +# define HASFCHMOD 0 /* does not have fchmod(2) syscall */ +# define HASSETREUID 1 /* use setreuid(2) -lbsd system call */ +# define HASSETVBUF 1 /* use setvbuf(2) system call */ +# define HASSETRLIMIT 0 /* does not have setrlimit call */ +# define HASFLOCK 0 /* does not have flock call - use fcntl */ +# define HASULIMIT 1 /* use ulimit instead of setrlimit call */ +# define SM_CONF_GETOPT 0 /* Do we need theirs or ours */ +# define SYS5SETPGRP 1 /* don't have setpgid on AIX/RT */ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ +# define BSD4_3 1 /* NOT bsd 4.4 or posix signals */ +# define GIDSET_T int +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# define LA_TYPE LA_SUBR /* use our ported loadavgd daemon */ +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# define ARBPTR_T int * +# define void int +typedef int pid_t; +/* RTisms for BSD compatibility, specified in the Makefile + define BSD 1 + define BSD_INCLUDES 1 + define BSD_REMAP_SIGNAL_TO_SIGVEC + RTisms needed above */ +/* make this sendmail in a completely different place */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/local/newmail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/usr/local/newmail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# endif /* AIX */ + +# if defined(_AIX) +# define LDA_USE_LOCKF 1 +# define LDA_USE_SETEUID 1 +# endif /* defined(_AIX) */ + +/* +** Silicon Graphics IRIX +** +** Compiles on 4.0.1. +** +** Use IRIX64 instead of IRIX for 64-bit IRIX (6.0). +** Use IRIX5 instead of IRIX for IRIX 5.x. +** +** IRIX64 changes from Mark R. Levinson . +** IRIX5 changes from Kari E. Hurtta . +*/ + +# ifdef IRIX +# define SYSTEM5 1 /* this is a System-V derived system */ +# define HASSETREUID 1 /* has setreuid(2) call */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define IP_SRCROUTE 1 /* can check IP source routing */ +# define setpgid BSDsetpgrp +# define GIDSET_T gid_t +# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define SYSLOG_BUFSIZE 512 +# if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) + /* _SC_NPROC_ONLN is 'mpadmin -u', total # of unrestricted processors */ +# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN +# endif /* if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) */ +# ifdef IRIX6 +# 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 /* IRIX6 */ +# define LA_TYPE LA_INT + +# ifdef IRIX64 +# define STAT64 1 +# define QUAD_T unsigned long long +# define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */ +# else /* IRIX64 */ +# define STAT64 0 +# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */ +# endif /* IRIX64 */ +# endif /* IRIX6 */ +# if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# include +# include +# 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 HASSTRERROR 1 /* has strerror(3) */ +# else /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ +# define ARGV_T const char ** +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ +# endif /* IRIX */ + + +/* +** SunOS and Solaris +** +** Tested on SunOS 4.1.x (a.k.a. Solaris 1.1.x) and +** Solaris 2.4 (a.k.a. SunOS 5.4). +*/ + +# if defined(sun) && !defined(BSD) + +# include +# 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 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 __svr4__ +# define LDA_USE_LOCKF 1 +# define LDA_USE_SETEUID 1 +# define _PATH_MAILDIR "/var/mail" +# endif /* __svr4__ */ + +# ifdef SOLARIS_2_3 +# define SOLARIS 20300 /* for back compat only -- use -DSOLARIS=20300 */ +# endif /* SOLARIS_2_3 */ + +# if defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# define SOLARIS 1 /* unknown Solaris version */ +# 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 Release 4 defines below */ +# endif /* ! __svr4__ */ +# define GIDSET_T gid_t +# define USE_SA_SIGACTION 1 /* use sa_sigaction field */ +# define BROKEN_PTHREAD_SLEEP 1 /* sleep after pthread_create() fails */ +# define HASSTRERROR 1 /* has strerror(3) */ +# ifndef _PATH_UNIX +# define _PATH_UNIX "/dev/ksyms" +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# ifndef _PATH_HOSTS +# define _PATH_HOSTS "/etc/inet/hosts" +# endif /* ! _PATH_HOSTS */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ +# endif /* ! SYSLOG_BUFSIZE */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME +# endif /* ! TZ_TYPE */ +# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) +# define USESETEUID 1 /* seteuid works as of 2.3 */ +# define LDA_CONTENTLENGTH 1 /* Needs the Content-Length header */ +# endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ +# if SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) +# define HASSETREUID 1 /* setreuid works as of 2.5 */ +# define HASSETREGID 1 /* use setregid(2) to set saved gid */ +# if SOLARIS < 207 || (SOLARIS > 10000 && SOLARIS < 20700) +# ifndef LA_TYPE +# define LA_TYPE LA_KSTAT /* use kstat(3k) -- may work in < 2.5 */ +# 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 > 10000 && SOLARIS < 20600) || SOLARIS < 206 +# define SM_INT32 int /* 32bit integer */ +# endif /* (SOLARIS > 10000 && SOLARIS < 20600) || SOLARIS < 206 */ +# if SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) +# ifndef LA_TYPE +# include +# if SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) +# include +# define LA_TYPE LA_PSET /* pset_getloadavg(3c) appears in 2.9 */ +# else /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ +# define LA_TYPE LA_SUBR /* getloadavg(3c) appears in 2.7 */ +# endif /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ +# endif /* ! LA_TYPE */ +# define HASGETUSERSHELL 1 /* getusershell(3c) bug fixed in 2.7 */ +# endif /* SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) */ +# if SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) +# undef _PATH_SENDMAILPID /* tmpfs /var/run added in 2.8 */ +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# define SMRSH_CMDDIR "/var/adm/sm.bin" +# define SL_FUDGE 34 /* fudge offset for SyslogPrefixLen */ +# endif /* SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) */ +# if SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) +# define HASURANDOMDEV 1 /* /dev/[u]random added in S9 */ +# endif /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */ +# endif /* ! HASGETUSERSHELL */ + +# 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 /* ! HASFLOCK */ +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ +# include +# include +# ifdef __GNUC__ +# define strtoul strtol /* gcc library bogosity */ +# endif /* __GNUC__ */ +# define memmove(d, s, l) (bcopy((s), (d), (l))) +# define atexit(f) on_exit((f), 0) /* ugly hack for SunOS */ +# define SM_INT32 int /* 32bit integer */ +# define SM_ALIGN_SIZE (sizeof(long)) +# define GIDSET_T int +# define SM_CONF_SYSLOG 0 + +# ifdef SUNOS403 + /* special tweaking for SunOS 4.0.3 */ +# include +# define BSD4_3 1 /* 4.3 BSD-based */ +# define NEEDSTRSTR 1 /* need emulation of strstr(3) routine */ +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# undef WIFEXITED +# undef WEXITSTATUS +# undef HASUNAME +# define setpgid setpgrp +# define MODE_T int +typedef int pid_t; +extern char *getenv(); + +# else /* SUNOS403 */ + /* 4.1.x specifics */ +# define HASSETSID 1 /* has Posix setsid(2) call */ +# define HASSETVBUF 1 /* we have setvbuf(3) in libc */ + +# endif /* SUNOS403 */ +# endif /* SOLARIS */ + +# ifndef LA_TYPE +# define LA_TYPE LA_INT +# endif /* ! LA_TYPE */ + +# endif /* defined(sun) && !defined(BSD) */ + +/* +** DG/UX +** +** Tested on 5.4.2 and 5.4.3. Use DGUX_5_4_2 to get the +** older support. +** 5.4.3 changes from Mark T. Robinson . +*/ + +# ifdef DGUX_5_4_2 +# define DGUX 1 +# endif /* DGUX_5_4_2 */ + +# ifdef DGUX +# define SYSTEM5 1 +# define LA_TYPE LA_DGUX +# define HASSETREUID 1 /* has setreuid(2) call */ +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASSETSID 1 /* has Posix setsid(2) call */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define IP_SRCROUTE 0 /* does not have */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# define SPT_TYPE SPT_NONE /* don't use setproctitle */ +# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define LDA_USE_LOCKF 1 + +/* these include files must be included early on DG/UX */ +# include +# include + +/* compiler doesn't understand const? */ +# define const + +# ifdef DGUX_5_4_2 +# define inet_addr dgux_inet_addr +extern long dgux_inet_addr(); +# endif /* DGUX_5_4_2 */ +# endif /* DGUX */ + + +/* +** Digital Ultrix 4.2 - 4.5 +** +** Apparently, fcntl locking is broken on 4.2A, in that locks are +** not dropped when the process exits. This causes major problems, +** so flock is the only alternative. +*/ + +# ifdef ultrix +# define HASSETREUID 1 /* has setreuid(2) call */ +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# 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 /* ! 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 /* ! 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 /* vax */ +# define LA_TYPE LA_INT +# define LA_AVENRUN "avenrun" +# endif /* vax */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* pre-4.4 TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# define SYSLOG_BUFSIZE 256 +# define SM_CONF_SYSLOG 0 +# endif /* ultrix */ + + +/* +** OSF/1 for KSR. +** +** Contributed by Todd C. Miller +*/ + +# ifdef __ksr__ +# define __osf__ 1 /* get OSF/1 defines below */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# endif /* ! TZ_TYPE */ +# endif /* __ksr__ */ + + +/* +** OSF/1 for Intel Paragon. +** +** Contributed by Jeff A. Earickson +** of Intel Scalable Systems Divison. +*/ + +# ifdef __PARAGON__ +# define __osf__ 1 /* get OSF/1 defines below */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# endif /* ! TZ_TYPE */ +# define GIDSET_T gid_t +# define MAXNAMLEN NAME_MAX +# endif /* __PARAGON__ */ + + +/* +** 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 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 +# define SM_INT32 int /* 32bit integer */ +# ifndef HASFLOCK +# include +# if _XOPEN_SOURCE+0 >= 400 +# define HASFLOCK 0 /* 5.0 and later has bad flock(2) call */ +# else /* _XOPEN_SOURCE+0 >= 400 */ +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* _XOPEN_SOURCE+0 >= 400 */ +# endif /* ! HASFLOCK */ +# define LA_TYPE LA_ALPHAOSF +# define SFS_TYPE SFS_STATVFS /* use statfs() impl */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# if _FFR_DIGUNIX_SAFECHOWN +/* +** Testing on a Digital UNIX 4.0a system showed this to be the correct +** setting but given the security consequences, more testing and +** verification is needed. Unfortunately, the man page offers no +** assistance. +*/ +# define IS_SAFE_CHOWN >= 0 +# endif /* _FFR_DIGUNIX_SAFECHOWN */ +# endif /* __osf__ */ + + +/* +** NeXTstep +*/ + +# ifdef NeXT +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define NEEDPUTENV 2 /* need putenv(3) call; no setenv(3) call */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# define UID_T int /* compiler gripes on uid_t */ +# define GID_T int /* ditto for gid_t */ +# define MODE_T int /* and mode_t */ +# define setpgid setpgrp +# ifndef NOT_SENDMAIL +# define sleep sleepX +# endif /* ! NOT_SENDMAIL */ +# ifndef LA_TYPE +# define LA_TYPE LA_MACH +# endif /* ! LA_TYPE */ +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# ifdef _POSIX_SOURCE +extern struct passwd *getpwent(); +# else /* _POSIX_SOURCE */ +# define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ +# define WAITUNION 1 /* use "union wait" as wait argument type */ +typedef int pid_t; +# undef WEXITSTATUS +# undef WIFEXITED +# undef WIFSTOPPED +# undef WTERMSIG +# endif /* _POSIX_SOURCE */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/sendmail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# define SM_INT32 int /* 32bit integer */ + +# ifdef TCPWRAPPERS +# ifndef HASUNSETENV +# define HASUNSETENV 1 +# endif /* ! HASUNSETENV */ +# undef NEEDPUTENV +# endif /* TCPWRAPPERS */ +# ifndef __APPLE__ +# include +# ifndef S_IRUSR +# define S_IRUSR S_IREAD +# endif /* ! S_IRUSR */ +# ifndef S_IWUSR +# define S_IWUSR S_IWRITE +# endif /* ! S_IWUSR */ +# define _PATH_MAILDIR "/usr/spool/mail" +# endif /* ! __APPLE__ */ +# ifndef isascii +# define isascii(c) ((unsigned)(c) <= 0177) +# endif /* ! isascii */ +# endif /* NeXT */ + +/* +** Apple Darwin (aka Rhapsody) +** +** Contributed by Wilfredo Sanchez +*/ + +# if defined(DARWIN) +# define HASFCHMOD 1 /* has fchmod(2) */ +# define HASFCHOWN 1 /* has fchown(2) */ +# define HASFLOCK 1 /* has flock(2) */ +# define HASUNAME 1 /* has uname(2) */ +# define HASUNSETENV 1 /* has unsetenv(3) */ +# define HASSETSID 1 /* has the setsid(2) */ +# define HASINITGROUPS 1 /* has initgroups(3) */ +# define HASSETVBUF 1 /* has setvbuf (3) */ +# define HASSETREUID 0 /* setreuid(2) unusable */ +# define HASSETEUID 1 /* has seteuid(2) */ +# define USESETEUID 1 /* has seteuid(2) */ +# define HASSETEGID 1 /* has setegid(2) */ +# define HASSETREGID 1 /* has setregid(2) */ +# define HASSETRESGID 0 /* no setresgid(2) */ +# define HASLSTAT 1 /* has lstat(2) */ +# define HASSETRLIMIT 1 /* has setrlimit(2) */ +# define HASWAITPID 1 /* has waitpid(2) */ +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) */ +# define HAS_ST_GEN 1 /* has st_gen field in struct stat */ +# define HASURANDOMDEV 1 /* has urandom(4) */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HASGETUSERSHELL 1 /* had getusershell(3) */ +# define GIDSET_T gid_t /* getgroups(2) takes gid_t */ +# define LA_TYPE LA_SUBR /* use getloadavg(3) */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# define SPT_TYPE SPT_PSSTRINGS /* use magic PS_STRINGS pointer for setproctitle */ +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* struct sockaddr has sa_len */ +# define SAFENFSPATHCONF 0 /* unverified: pathconf(2) doesn't work on NFS */ +# define HAS_IN_H 1 +# define NETLINK 1 /* supports AF_LINK */ +# ifndef NOT_SENDMAIL +# define sleep sleepX +extern unsigned int sleepX __P((unsigned int seconds)); +# endif /* ! NOT_SENDMAIL */ +# endif /* defined(DARWIN) */ + + +/* +** 4.4 BSD +** +** See also BSD defines. +*/ + +# if defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) +# include +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASFCHOWN 1 /* has fchown(2) syscall */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# include +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NEED_PRINTF_PERCENTQ 1 /* doesn't have %lld */ +# define NETLINK 1 /* supports AF_LINK */ +# ifndef LA_TYPE +# define LA_TYPE LA_SUBR +# endif /* ! LA_TYPE */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# define SPT_TYPE SPT_PSSTRINGS /* use PS_STRINGS pointer */ +# endif /* defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) */ + + +/* +** BSD/OS (was BSD/386) (all versions) +** From Tony Sanders, BSDI +*/ + +# ifdef __bsdi__ +# include +# define HASUNSETENV 1 /* has the unsetenv(3) call */ +# define HASSETREUID 0 /* BSD-OS has broken setreuid(2) emulation */ +# 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 HASSETLOGIN 1 /* has setlogin(2) */ +# define HASUNAME 1 /* has uname(2) syscall */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# include +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NETLINK 1 /* supports AF_LINK */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# ifndef LA_TYPE +# define LA_TYPE LA_SUBR +# 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 /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 */ + /* version 1.0 or earlier */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 */ +# if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701 /* on 3.x */ +# define HASSETUSERCONTEXT 1 /* has setusercontext */ +# endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701 */ +# if defined(_BSDI_VERSION) && _BSDI_VERSION <= 199701 /* 3.1 and earlier */ +# define MODE_T int /* va_arg() can't handle less than int */ +# endif /* defined(_BSDI_VERSION) && _BSDI_VERSION <= 199701 */ +# if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199910 /* on 4.x */ +# define HASURANDOMDEV 1 /* has /dev/urandom(4) */ +# endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199910 */ +# endif /* __bsdi__ */ + + +/* +** QNX 4.2x +** Contributed by Glen McCready . +** +** Should work with all versions of QNX. +*/ + +# if defined(__QNX__) +# include +# include +# undef NGROUPS_MAX +# 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 SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ +# 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 _FILE_H_INCLUDED +# endif /* defined(__QNX__) */ + + +/* +** FreeBSD / NetBSD / OpenBSD (all architectures, all versions) +** +** 4.3BSD clone, closer to 4.4BSD for FreeBSD 1.x and NetBSD 0.9x +** 4.4BSD-Lite based for FreeBSD 2.x and NetBSD 1.x +** +** See also BSD defines. +*/ + +# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# include +# define HASUNSETENV 1 /* has unsetenv(3) 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 HASFCHOWN 1 /* fchown(2) */ +# define HASUNAME 1 /* has uname(2) syscall */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# define NEED_PRINTF_PERCENTQ 1 /* doesn't have %lld */ +# include +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NETLINK 1 /* supports AF_LINK */ +# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ +# define GIDSET_T gid_t +# define QUAD_T unsigned long long +# ifndef LA_TYPE +# define LA_TYPE LA_SUBR +# endif /* ! LA_TYPE */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# if defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) +# undef SPT_TYPE +# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ +# 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 +# if __FreeBSD_version >= 199512 /* 2.2-current when it appeared */ +# include +# define SPT_TYPE SPT_BUILTIN +# endif /* __FreeBSD_version >= 199512 */ +# if __FreeBSD_version >= 222000 /* 2.2.2-release and later */ +# define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ +# endif /* __FreeBSD_version >= 222000 */ +# if __FreeBSD_version >= 330000 /* 3.3.0-release and later */ +# define SMRSH_CMDDIR "/usr/libexec/sm.bin" +# define SMRSH_PATH "/bin:/usr/bin" +# endif /* __FreeBSD_version >= 330000 */ +# define USESYSCTL 1 /* use sysctl(3) for getting ncpus */ +# include +# endif /* __FreeBSD__ >= 2 */ +# ifndef SPT_TYPE +# define SPT_TYPE SPT_REUSEARGV +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# endif /* ! SPT_TYPE */ +# endif /* defined(__FreeBSD__) */ +# if defined(__OpenBSD__) +# undef SPT_TYPE +# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ +# define HASSETLOGIN 1 /* has setlogin(2) */ +# define HASSETREUID 0 /* OpenBSD has broken setreuid(2) emulation */ +# define HASSETEGID 1 /* use setegid(2) to set saved gid */ +# define HASURANDOMDEV 1 /* has /dev/urandom(4) */ +# if OpenBSD >= 200006 +# define HASSRANDOMDEV 1 /* has srandomdev(3) */ +# endif /* OpenBSD >= 200006 */ +# if OpenBSD >= 200012 +# define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ +# endif /* OpenBSD >= 200012 */ +# endif /* defined(__OpenBSD__) */ +# endif /* defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) */ + + +/* +** Mach386 +** +** For mt Xinu's Mach386 system. +*/ + +# if defined(MACH) && defined(i386) && !defined(__GNU__) +# define MACH386 1 +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# define SM_CONF_GETOPT 0 /* 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 /* ! LA_TYPE */ +# define SFS_TYPE SFS_VFS /* use 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 /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# endif /* defined(MACH) && defined(i386) && !defined(__GNU__) */ + + + +/* +** GNU OS (hurd) +** Largely BSD & posix compatible. +** Port contributed by Miles Bader . +** Updated by Mark Kettenis . +*/ + +# if defined(__GNU__) && !defined(NeXT) +# include +# 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 HASSTRERROR 1 /* has strerror(3) */ +# define GIDSET_T gid_t +# 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 /* (__GLIBC__ == 2 && __GLIBC_MINOR__ > 1) || __GLIBC__ > 2 */ +# define LA_TYPE LA_MACH + /* GNU uses mach[34], which renames some rpcs from mach2.x. */ +# define host_self mach_host_self +# endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ > 1) || __GLIBC__ > 2 */ +# define SFS_TYPE SFS_STATFS +# define SPT_TYPE SPT_CHANGEARGV +# 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 +# endif /* defined(__GNU__) && !defined(NeXT) */ + +/* +** 4.3 BSD -- this is for very old systems +** +** Should work for mt Xinu MORE/BSD and Mips UMIPS-BSD 2.1. +** +** You'll also have to install a new resolver library. +** I don't guarantee that support for this environment is complete. +*/ + +# if defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) +# define NEEDVPRINTF 1 /* need a replacement for vprintf(3) */ +# define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ +# define ARBPTR_T char * +# define setpgid setpgrp +# ifndef LA_TYPE +# define LA_TYPE LA_FLOAT +# endif /* ! LA_TYPE */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# undef WEXITSTATUS +# undef WIFEXITED +typedef short pid_t; +# endif /* defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) */ + + +/* +** SCO Unix +** +** This includes three parts: +** +** The first is for SCO OpenServer 5. +** (Contributed by Keith Reynolds ). +** +** SCO OpenServer 5 has a compiler version number macro, +** which we can use to figure out what version we're on. +** This may have to change in future releases. +** +** The second is for SCO UNIX 3.2v4.2/Open Desktop 3.0. +** (Contributed by Philippe Brand ). +** +** The third is for SCO UNIX 3.2v4.0/Open Desktop 2.0 and earlier. +*/ + +/* SCO OpenServer 5 */ +# if _SCO_DS >= 1 +# include +# define SIOCGIFNUM_IS_BROKEN 1 /* SIOCGIFNUM returns bogus value */ +# 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 */ +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ +# define RLIMIT_NEEDS_SYS_TIME_H 1 +# define LDA_USE_LOCKF 1 +# ifndef LA_TYPE +# define LA_TYPE LA_DEVSHORT +# endif /* ! LA_TYPE */ +# define _PATH_AVENRUN "/dev/table/avenrun" +# ifndef _SCO_unix_4_2 +# define _SCO_unix_4_2 +# 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 /* ! _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 /* _SCO_unix_4_2 */ + +/* SCO UNIX 3.2v4.0 Open Desktop 2.0 and earlier */ +# ifdef _SCO_unix_ +# include /* needed for IP_SRCROUTE */ +# define SYSTEM5 1 /* include all the System V defines */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define NOFTRUNCATE 0 /* has (simulated) ftruncate call */ +# ifndef USE_SIGLONGJMP +# define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ +# endif /* ! USE_SIGLONGJMP */ +# define MAXPATHLEN PATHSIZE +# define SFS_TYPE SFS_4ARGS /* use 4-arg impl */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define SPT_TYPE SPT_SCO /* write kernel u. area */ +# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */ +# define UID_T uid_t +# define GID_T gid_t +# define GIDSET_T gid_t +# define _PATH_UNIX "/unix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ + +/* stuff fixed in later releases */ +# ifndef _SCO_unix_4_2 +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# 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 /* ! _SCO_DS */ + +# endif /* _SCO_unix_ */ + +/* +** ISC (SunSoft) Unix. +** +** Contributed by J.J. Bailey +*/ + +# ifdef ISC_UNIX +# include +# include /* needed for IP_SRCROUTE */ +# include +# define SYSTEM5 1 /* include all the System V defines */ +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define HASSETREUID 1 /* has setreuid(2) call */ +# define NEEDFSYNC 1 /* needs the fsync(2) call stub */ +# define NETUNIX 0 /* no unix domain socket support */ +# define MAXPATHLEN 1024 +# define LA_TYPE LA_SHORT +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define _PATH_UNIX "/unix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# endif /* ISC_UNIX */ + + +/* +** Altos System V (5.3.1) +** Contributed by Tim Rice . +*/ + +# ifdef ALTOS_SYSTEM_V +# include +# include +# define SYSTEM5 1 /* include all the System V defines */ +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# define NEEDFSYNC 1 /* no fsync(2) in system library */ +# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ +# define NOFTRUNCATE 1 /* do not have ftruncate(2) */ +# define MAXPATHLEN PATH_MAX +# define LA_TYPE LA_SHORT +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# define NETUNIX 0 /* no unix domain socket support */ +# undef WIFEXITED +# undef WEXITSTATUS +# define strtoul strtol /* gcc library bogosity */ + +typedef unsigned short uid_t; +typedef unsigned short gid_t; +typedef short pid_t; +typedef unsigned long mode_t; + +/* some stuff that should have been in the include files */ +extern char *malloc(); +extern struct passwd *getpwent(); +extern struct passwd *getpwnam(); +extern struct passwd *getpwuid(); +extern char *getenv(); +extern struct group *getgrgid(); +extern struct group *getgrnam(); + +# endif /* ALTOS_SYSTEM_V */ + + +/* +** ConvexOS 11.0 and later +** +** "Todd C. Miller" claims this +** works on 9.1 as well. +** +** ConvexOS 11.5 and later, should work on 11.0 as defined. +** For pre-ConvexOOS 11.0, define SM_CONF_GETOPT=0, undef IDENTPROTO +** +** Eric Schnoebelen (eric@cirr.com) For CONVEX Computer Corp. +** (now the CONVEX Technologies Center of Hewlett Packard) +*/ + +# ifdef _CONVEX_SOURCE +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) */ +# define HASINITGROUPS 1 /* has initgroups(3) */ +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASSETSID 1 /* has POSIX setsid(2) call */ +# define HASUNSETENV 1 /* has unsetenv(3) */ +# define HASFLOCK 1 /* has flock(2) */ +# define HASSETRLIMIT 1 /* has setrlimit(2) */ +# define HASSETREUID 1 /* has setreuid(2) */ +# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_error=0 */ +# define NEEDPUTENV 1 /* needs putenv (written in terms of setenv) */ +# define SM_CONF_GETOPT 1 /* need a replacement for getopt(3) */ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ +# define LA_TYPE LA_FLOAT +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef S_IREAD +# define S_IREAD _S_IREAD +# define S_IWRITE _S_IWRITE +# define S_IEXEC _S_IEXEC +# define S_IFMT _S_IFMT +# define S_IFCHR _S_IFCHR +# define S_IFBLK _S_IFBLK +# endif /* ! S_IREAD */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TIMEZONE +# endif /* ! TZ_TYPE */ +# ifndef IDENTPROTO +# define IDENTPROTO 1 +# endif /* ! IDENTPROTO */ +# ifndef SHARE_V1 +# define SHARE_V1 1 /* version 1 of the fair share scheduler */ +# 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 /* !defined(__GNUC__ ) */ +# if SECUREWARE +# define FORK fork /* SecureWare wants the real fork! */ +# else /* SECUREWARE */ +# define FORK vfork /* the rest of the OS versions don't care */ +# endif /* SECUREWARE */ +# endif /* _CONVEX_SOURCE */ + + +/* +** RISC/os 4.52 +** +** Gives a ton of warning messages, but otherwise compiles. +*/ + +# ifdef RISCOS + +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ +# define NEEDPUTENV 1 /* need putenv(3) call */ +# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# define LA_TYPE LA_INT +# define LA_AVENRUN "avenrun" +# define _PATH_UNIX "/unix" +# undef WIFEXITED + +# define setpgid setpgrp + +typedef int pid_t; +# define SIGFUNC_DEFINED +# define SIGFUNC_RETURN (0) +# define SIGFUNC_DECL int +typedef int (*sigfunc_t)(); +extern char *getenv(); +extern void *malloc(); + +/* added for RISC/os 4.01...which is dumber than 4.50 */ +# ifdef RISCOS_4_0 +# ifndef ARBPTR_T +# define ARBPTR_T char * +# endif /* ! ARBPTR_T */ +# undef HASFLOCK +# define HASFLOCK 0 +# endif /* RISCOS_4_0 */ + +# include + +# endif /* RISCOS */ + + +/* +** Linux 0.99pl10 and above... +** +** Thanks to, in reverse order of contact: +** +** John Kennedy +** Andrew Pam +** Florian La Roche +** Karl London +** +** NOTE: Override HASFLOCK as you will but, as of 1.99.6, mixed-style +** 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 +# if !defined(KERNEL_VERSION) /* not defined in 2.0.x kernel series */ +# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +# endif /* !defined(KERNEL_VERSION) */ +# define BSD 1 /* include BSD defines */ +# define HASSETREGID 1 /* use setregid(2) to set saved gid */ +# ifndef REQUIRES_DIR_FSYNC +# define REQUIRES_DIR_FSYNC 1 /* requires fsync() on directory */ +# endif /* REQUIRES_DIR_FSYNC */ +# ifndef USESETEUID +# define USESETEUID 0 /* has it due to POSIX, but doesn't work */ +# endif /* USESETEUID */ +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define GIDSET_T gid_t /* from */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */ +# endif /* HASGETUSERSHELL */ +# 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 */ +# ifndef USE_SIGLONGJMP +# define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ +# endif /* ! USE_SIGLONGJMP */ +# ifndef HASFLOCK +# if LINUX_VERSION_CODE < 66399 +# define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */ +# else /* LINUX_VERSION_CODE < 66399 */ +# define HASFLOCK 1 /* flock(2) fixed after 1.3.95 */ +# endif /* LINUX_VERSION_CODE < 66399 */ +# endif /* ! HASFLOCK */ +# ifndef LA_TYPE +# define LA_TYPE LA_PROCSTR +# endif /* ! LA_TYPE */ +# define SFS_TYPE SFS_VFS /* use 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 >= KERNEL_VERSION(2,0,0)) */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_NONE /* no standard for Linux */ +# endif /* ! TZ_TYPE */ +# if (__GLIBC__ >= 2) +# include +# endif /* (__GLIBC__ >= 2) */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# include +# undef atol /* wounded in */ +# 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 . IPv6 support is native + ** in 2.1 and later, but the APIs appear before the functions. + */ +# if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define HASSTRERROR 1 /* has strerror(3) */ +# define GLIBC_VERSION ((__GLIBC__ << 8) + __GLIBC_MINOR__) +# if (GLIBC_VERSION >= 0x201) +# undef IPPROTO_ICMPV6 /* linux #defines, glibc enums */ +# else /* (GLIBC_VERSION >= 0x201) */ +# include /* IPv6 support */ +# endif /* (GLIBC_VERSION >= 0x201) */ +# if (GLIBC_VERSION >= 0x201 && !defined(NEEDSGETIPNODE)) + /* Have APIs in , but no support in glibc */ +# define NEEDSGETIPNODE 1 +# endif /* (GLIBC_VERSION >= 0x201 && !defined(NEEDSGETIPNODE)) */ +# undef GLIBC_VERSION +# endif /* defined(__GLIBC__) && defined(__GLIBC_MINOR__) */ +# endif /* NETINET6 */ +# ifndef HASFCHOWN +# define HASFCHOWN 1 /* fchown(2) */ +# endif /* ! HASFCHOWN */ +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,36)) && !defined(HASFCHMOD) +# define HASFCHMOD 1 /* fchmod(2) */ +# endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,36)) && !defined(HASFCHMOD) */ +# endif /* __linux__ */ + + +/* +** DELL SVR4 Issue 2.2, and others +** From Kimmo Suominen +** +** It's on #ifdef DELL_SVR4 because Solaris also gets __svr4__ +** defined, and the definitions conflict. +** +** Peter Wemm claims that the setreuid +** trick works on DELL 2.2 (SVR4.0/386 version 4.0) and ESIX 4.0.3A +** (SVR4.0/386 version 3.0). +*/ + +# ifdef DELL_SVR4 + /* no changes necessary */ + /* see general __svr4__ defines below */ +# endif /* DELL_SVR4 */ + + +/* +** Apple A/UX 3.0 +*/ + +# ifdef _AUX_SOURCE +# include +# define BSD /* has BSD routines */ +# define HASSETRLIMIT 0 /* ... but not setrlimit(2) */ +# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ +# define BOGUS_O_EXCL 1 /* exclusive open follows symlinks */ +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASSETVBUF 1 /* has setvbuf(3) in libc */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define SIGFUNC_DEFINED /* sigfunc_t already defined */ +# define SIGFUNC_RETURN /* POSIX-mode */ +# define SIGFUNC_DECL void /* POSIX-mode */ +# define ERRLIST_PREDEFINED 1 +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# ifndef LA_TYPE +# define LA_TYPE LA_INT +# define FSHIFT 16 +# endif /* ! LA_TYPE */ +# define LA_AVENRUN "avenrun" +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# define TZ_TYPE TZ_TZNAME +# ifndef _PATH_UNIX +# define _PATH_UNIX "/unix" /* should be in */ +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# undef WIFEXITED +# undef WEXITSTATUS +# endif /* _AUX_SOURCE */ + + +/* +** Encore UMAX V +** +** Not extensively tested. +*/ + +# ifdef UMAXV +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASSETVBUF 1 /* we have setvbuf(3) in libc */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */ +# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define MAXPATHLEN PATH_MAX +extern struct passwd *getpwent(), *getpwnam(), *getpwuid(); +extern struct group *getgrent(), *getgrnam(), *getgrgid(); +# undef WIFEXITED +# undef WEXITSTATUS +# endif /* UMAXV */ + + +/* +** Stardent Titan 3000 running TitanOS 4.2. +** +** Must be compiled in "cc -43" mode. +** +** From Kate Hedstrom . +** +** Note the tweaking below after the BSD defines are set. +*/ + +# ifdef titan +# define setpgid setpgrp +typedef int pid_t; +# undef WIFEXITED +# undef WEXITSTATUS +# endif /* titan */ + + +/* +** Sequent DYNIX 3.2.0 +** +** From Jim Davis . +*/ + +# ifdef sequent + +# define BSD 1 +# define HASUNSETENV 1 +# define BSD4_3 1 /* to get signal() in conf.c */ +# define WAITUNION 1 +# define LA_TYPE LA_FLOAT +# ifdef _POSIX_VERSION +# undef _POSIX_VERSION /* set in */ +# endif /* _POSIX_VERSION */ +# undef HASSETVBUF /* don't actually have setvbuf(3) */ +# define setpgid setpgrp + +/* Have to redefine WIFEXITED to take an int, to work with waitfor() */ +# undef WIFEXITED +# define WIFEXITED(s) (((union wait*)&(s))->w_stopval != WSTOPPED && \ + ((union wait*)&(s))->w_termsig == 0) +# define WEXITSTATUS(s) (((union wait*)&(s))->w_retcode) +typedef int pid_t; +# define isgraph(c) (isprint(c) && (c != ' ')) + +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ + +# ifndef _PATH_UNIX +# define _PATH_UNIX "/dynix" +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# endif /* sequent */ + + +/* +** Sequent DYNIX/ptx v2.0 (and higher) +** +** For DYNIX/ptx v1.x, undefine HASSETREUID. +** +** From Tim Wright . +** Update from Jack Woolley , 26 Dec 1995, +** for DYNIX/ptx 4.0.2. +*/ + +# ifdef _SEQUENT_ +# include +# define SYSTEM5 1 /* include all the System V defines */ +# define HASSETSID 1 /* has POSIX setsid(2) call */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASSETREUID 1 /* has setreuid(2) call */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define GIDSET_T gid_t +# define LA_TYPE LA_INT +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SPT_TYPE SPT_NONE /* don't use setproctitle */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# endif /* _SEQUENT_ */ + + +/* +** Cray Unicos +** +** Ported by David L. Kensiski, Sterling Sofware +*/ + +# ifdef UNICOS +# define SYSTEM5 1 /* include all the System V defines */ +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define MAXPATHLEN PATHSIZE +# define LA_TYPE LA_ZERO +# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# endif /* UNICOS */ + + +/* +** Apollo DomainOS +** +** From Todd Martin & Don Lewis +** +** 15 Jan 1994; updated 2 Aug 1995 +** +*/ + +# ifdef apollo +# define HASSETREUID 1 /* has setreuid(2) call */ +# define HASINITGROUPS 1 /* has initgroups(2) call */ +# define IP_SRCROUTE 0 /* does not have */ +# define SPT_TYPE SPT_NONE /* don't use setproctitle */ +# define LA_TYPE LA_SUBR /* use getloadavg.c */ +# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define TZ_TYPE TZ_TZNAME +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# 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 /* ! IDENTPROTO */ +# define RLIMIT_NEEDS_SYS_TIME_H 1 +# if defined(NGROUPS_MAX) && !NGROUPS_MAX +# undef NGROUPS_MAX +# endif /* defined(NGROUPS_MAX) && !NGROUPS_MAX */ +# endif /* apollo */ + +/* +** MPE-iX +** +** Requires MPE 6.0 or greater. See sendmail/README for more info. +** +** From Mark Bixby or . +*/ + +# ifdef MPE + +# include +# include + +/* Sendmail stuff */ +# define HASFCHOWN 0 /* lacks fchown() */ +# define HASGETUSERSHELL 0 /* lacks getusershell() */ +# ifdef HASNICE +# undef HASNICE +# endif /* HASNICE */ +# define HASNICE 0 /* lacks nice() */ +# define HASRANDOM 0 /* lacks random() */ +# ifdef HASRRESVPORT +# undef HASRRESVPORT +# endif /* HASRRESVPORT */ +# define HASRRESVPORT 0 /* lacks rresvport() */ +# define IP_SRCROUTE 0 /* lacks IP source routing fields */ +# ifdef MATCHGECOS +# undef MATCHGECOS +# endif /* MATCHGECOS */ +# define MATCHGECOS 0 /* lacks an initialized GECOS field */ +# define NEEDFSYNC 1 /* use sendmail's fsync() */ +# define NEEDLINK 1 /* use sendmail's link() */ +# define NOFTRUNCATE 1 /* lacks ftruncate() */ +# define SFS_TYPE SFS_NONE /* can't determine disk space */ +# define SM_CONF_SYSLOG 0 /* use sendmail decl of syslog() */ +# define USE_DOUBLE_FORK 0 /* don't fork an intermediate zombie */ +# define USE_ENVIRON 1 /* use environ instead of envp */ + +/* Missing header stuff */ +# define AF_UNSPEC 0 +# define AF_MAX AF_INET +# define IFF_LOOPBACK 0x8 +# define IN_LOOPBACKNET 127 +# define MAXNAMLEN NAME_MAX +# define S_IEXEC S_IXUSR +# define S_IREAD S_IRUSR +# define S_IWRITE S_IWUSR + +/* Present header stuff that needs to be missing */ +# undef NGROUPS_MAX + +/* Shadow functions */ +# define bind sendmail_mpe_bind +# define _exit sendmail_mpe__exit +# define exit sendmail_mpe_exit +# define fcntl sendmail_mpe_fcntl +# define getegid sendmail_mpe_getegid +# define geteuid sendmail_mpe_geteuid +# define getpwnam sendmail_mpe_getpwnam +# define getpwuid sendmail_mpe_getpwuid +# define setgid sendmail_mpe_setgid +# define setuid sendmail_mpe_setuid +extern int sendmail_mpe_fcntl __P((int, int, ...)); +extern struct passwd * sendmail_mpe_getpwnam __P((const char *)); +extern struct passwd * sendmail_mpe_getpwuid __P((uid_t)); +# endif /* MPE */ + +/* +** System V Rel 5.x (a.k.a Unixware7 w/o BSD-Compatibility Libs ie. native) +** +** Contributed by Paul Gampe +*/ + +# ifdef __svr5__ +# include +# define __svr4__ +# define SYS5SIGNALS 1 +# define HASFCHOWN 1 /* has fchown(2) call */ +# define HASSETSID 1 +# define HASSETREUID 1 +# define HASWAITPID 1 +# define HASGETDTABLESIZE 1 +# define GIDSET_T gid_t +# define SOCKADDR_LEN_T size_t +# define SOCKOPT_LEN_T size_t +# ifndef _PATH_UNIX +# define _PATH_UNIX "/stand/unix" +# endif /* ! _PATH_UNIX */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 /* unsure */ +# endif /* ! SYSLOG_BUFSIZE */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# undef offsetof /* avoid stddefs.h, sys/sysmacros.h conflict */ +#if !defined(SM_SET_H_ERRNO) && defined(_REENTRANT) +# define SM_SET_H_ERRNO(err) set_h_errno((err)) +#endif /* ! SM_SET_H_ERRNO && _REENTRANT */ +# endif /* __svr5__ */ + +/* ###################################################################### */ + +/* +** UnixWare 2.x +*/ + +# ifdef UNIXWARE2 +# define UNIXWARE 1 +# undef offsetof /* avoid stddefs.h, sys/sysmacros.h conflict */ +# endif /* UNIXWARE2 */ + + +/* +** UnixWare 1.1.2. +** +** Updated by Petr Lampa . +** From Evan Champion . +*/ + +# ifdef UNIXWARE +# include +# define SYSTEM5 1 +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define HASSETREUID 1 +# define HASSETSID 1 +# define HASINITGROUPS 1 +# define GIDSET_T gid_t +# define SLEEP_T unsigned +# define SFS_TYPE SFS_STATVFS +# define LA_TYPE LA_ZERO +# undef WIFEXITED +# undef WEXITSTATUS +# ifndef _PATH_UNIX +# define _PATH_UNIX "/unix" +# endif /* ! _PATH_UNIX */ +# 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 */ +# define SYSLOG_BUFSIZE 128 +# endif /* UNIXWARE */ + + +/* +** Intergraph CLIX 3.1 +** +** From Paul Southworth +*/ + +# ifdef CLIX +# define SYSTEM5 1 /* looks like System V */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# 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 /* CLIX */ + + +/* +** NCR MP-RAS 2.x (SysVr4) with Wollongong TCP/IP +** +** From Kevin Darcy . +*/ + +# ifdef NCR_MP_RAS2 +# include +# define __svr4__ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ +# define SYSLOG_BUFSIZE 1024 +# define SPT_TYPE SPT_NONE +# endif /* NCR_MP_RAS2 */ + + +/* +** NCR MP-RAS 3.x (SysVr4) with STREAMware TCP/IP +** +** From Tom Moore +*/ + +# ifdef NCR_MP_RAS3 +# define __svr4__ +# define HASFCHOWN 1 /* has fchown(2) call */ +# define LDA_USE_LOCKF 1 +# 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 +# define _PATH_MAILDIR "/var/mail" +# ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE +# define _XOPEN_SOURCE_EXTENDED 1 +# include +# undef _XOPEN_SOURCE +# undef _XOPEN_SOURCE_EXTENDED +# endif /* ! _XOPEN_SOURCE */ +# endif /* NCR_MP_RAS3 */ + + +/* +** Tandem NonStop-UX SVR4 +** +** From Rick McCarty . +*/ + +# ifdef NonStop_UX_BXX +# define __svr4__ +# endif /* NonStop_UX_BXX */ + + +/* +** Hitachi 3050R/3050RX and 3500 Workstations running HI-UX/WE2. +** +** Tested for 1.04, 1.03 +** From Akihiro Hashimoto ("Hash") . +** +** Tested for 4.02, 6.10 and 7.10 +** From Motonori NAKAMURA . +*/ + +# 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 statfs() implementation */ +# ifndef HASSETVBUF +# define HASSETVBUF /* HI-UX has no setlinebuf */ +# endif /* ! HASSETVBUF */ +# ifndef GIDSET_T +# define GIDSET_T gid_t +# endif /* ! GIDSET_T */ +# ifndef _PATH_UNIX +# define _PATH_UNIX "/HI-UX" +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ +# 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 +** on HIUX 3050 +*/ +# undef m_flags + +# define SM_CONF_SYSLOG 0 + +# endif /* !defined(__hpux) && (defined(_H3050R) || defined(_HIUX_SOURCE)) */ + + +/* +** Amdahl UTS System V 2.1.5 (SVr3-based) +** +** From: Janet Jackson . +*/ + +# ifdef _UTS +# include +# undef HASLSTAT /* has symlinks, but they cause problems */ +# define NEEDFSYNC 1 /* system fsync(2) fails on non-EFS filesys */ +# define SYS5SIGNALS 1 /* System V signal semantics */ +# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */ +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASINITGROUPS 1 /* has initgroups(3) function */ +# define HASSETVBUF 1 /* has setvbuf(3) function */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* does not have getusershell(3) function */ +# 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() */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define _PATH_UNIX "/unix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# endif /* _UTS */ + +/* +** Cray Computer Corporation's CSOS +** +** From Scott Bolte . +*/ + +# ifdef _CRAYCOM +# define SYSTEM5 1 /* include all the System V defines */ +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define NEEDFSYNC 1 /* no fsync in system library */ +# define MAXPATHLEN PATHSIZE +# define LA_TYPE LA_ZERO +# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define _POSIX_CHOWN_RESTRICTED -1 +extern struct group *getgrent(), *getgrnam(), *getgrgid(); +# endif /* _CRAYCOM */ + + +/* +** Sony NEWS-OS 4.2.1R and 6.0.3 +** +** From Motonori NAKAMURA . +*/ + +# ifdef sony_news +# ifndef __svr4 + /* NEWS-OS 4.2.1R */ +# ifndef BSD +# define BSD /* has BSD routines */ +# 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 */ +# define LA_TYPE LA_INT +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# define setpgid setpgrp +# undef WIFEXITED +# undef WEXITSTATUS +# define MODE_T int /* system include files have no mode_t */ +typedef int pid_t; +typedef int (*sigfunc_t)(); +# define SIGFUNC_DEFINED +# define SIGFUNC_RETURN (0) +# define SIGFUNC_DECL int + +# else /* ! __svr4 */ + /* NEWS-OS 6.0.3 with /bin/cc */ +# ifndef __svr4__ +# 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 /* ! SPT_TYPE */ +# define GIDSET_T gid_t +# undef WIFEXITED +# undef WEXITSTATUS +# ifndef SYSLOG_BUFSIZE +# 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 /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ + +# endif /* ! __svr4 */ +# endif /* sony_news */ + + +/* +** Omron LUNA/UNIOS-B 3.0, LUNA2/Mach and LUNA88K Mach +** +** From Motonori NAKAMURA . +*/ + +# ifdef luna +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# define HASUNSETENV 1 /* has unsetenv(2) call */ +# define NEEDPUTENV 1 /* need putenv(3) call */ +# define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ +# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# ifdef uniosb +# include +# 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 /* uniosb */ +# ifdef luna2 +# define LA_TYPE LA_SUBR +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ +# endif /* luna2 */ +# ifdef luna88k +# define LA_TYPE LA_INT +# endif /* luna88k */ +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# define setpgid setpgrp +# undef WIFEXITED +# undef WEXITSTATUS +typedef int pid_t; +typedef int (*sigfunc_t)(); +# define SIGFUNC_DEFINED +# define SIGFUNC_RETURN (0) +# define SIGFUNC_DECL int +extern char *getenv(); +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# endif /* luna */ + + +/* +** NEC EWS-UX/V 4.2 (with /usr/ucb/cc) +** +** From Motonori NAKAMURA . +*/ + +# if defined(nec_ews_svr4) || defined(_nec_ews_svr4) +# ifndef __svr4__ +# 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 */ +# define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */ +# define GIDSET_T gid_t +# 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 /* ! SYSLOG_BUFSIZE */ +# endif /* defined(nec_ews_svr4) || defined(_nec_ews_svr4) */ + + +/* +** Fujitsu/ICL UXP/DS (For the DS/90 Series) +** +** From Diego R. Lopez . +** Additional changes from Fumio Moriya and Toshiaki Nomura of the +** Fujitsu Fresoftware group . +*/ + +# ifdef __uxp__ +# include +# include +# include +# define __svr4__ +# define HASGETUSERSHELL 0 +# define HASFLOCK 0 +# define _PATH_UNIX "/stand/unix" +# 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 */ +# endif /* __uxp__ */ + +/* +** Pyramid DC/OSx +** +** From Earle Ake . +*/ + +# ifdef DCOSx +# define GIDSET_T gid_t +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# endif /* DCOSx */ + +/* +** Concurrent Computer Corporation Maxion +** +** From Donald R. Laster Jr. . +*/ + +# ifdef __MAXION__ + +# include +# define __svr4__ 1 /* SVR4.2MP */ +# define HASSETREUID 1 /* have setreuid(2) */ +# define HASLSTAT 1 /* have lstat(2) */ +# define HASSETRLIMIT 1 /* have setrlimit(2) */ +# define HASGETDTABLESIZE 1 /* have getdtablesize(2) */ +# define HASGETUSERSHELL 1 /* have getusershell(3) */ +# define NOFTRUNCATE 1 /* do not have ftruncate(2) */ +# define SLEEP_T unsigned +# define SFS_TYPE SFS_STATVFS +# define SFS_BAVAIL f_bavail +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 256 /* Use 256 bytes */ +# endif /* ! SYSLOG_BUFSIZE */ + +# undef WUNTRACED +# undef WIFEXITED +# undef WIFSIGNALED +# undef WIFSTOPPED +# undef WEXITSTATUS +# undef WTERMSIG +# undef WSTOPSIG + +# endif /* __MAXION__ */ + +/* +** Harris Nighthawk PowerUX (nh6000 box) +** +** Contributed by Bob Miorelli, Pratt & Whitney +*/ + +# ifdef _PowerUX +# ifndef __svr4__ +# define __svr4__ +# endif /* ! __svr4__ */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# define SYSLOG_BUFSIZE 1024 +# define LA_TYPE LA_ZERO +typedef struct msgb mblk_t; +# undef offsetof /* avoid stddefs.h and sys/sysmacros.h conflict */ +# endif /* _PowerUX */ + +/* +** Siemens Nixdorf Informationssysteme AG SINIX +** +** Contributed by Gerald Rinske of Siemens Business Services VAS. +*/ +# ifdef sinix +# define HASRANDOM 0 /* has random(3) */ +# define SYSLOG_BUFSIZE 1024 +# define SM_INT32 int /* 32bit integer */ +# endif /* sinix */ + +/* +** CRAY T3E +** +** Contributed by Manu Mahonen +** of Center for Scientific Computing. +*/ +# ifdef _CRAY +# define GET_IPOPT_DST(dst) *(struct in_addr *)&(dst) +# define _PATH_MAILDIR "/usr/spool/mail" +# if !defined(MAXPATHLEN) +# define MAXPATHLEN PATHSIZE +# endif /* !defined(MAXPATHLEN) */ +# endif /* _CRAY */ + +/* +** Motorola 922, MC88110, UNIX SYSTEM V/88 Release 4.0 Version 4.3 +** +** Contributed by Sergey Rusanov +*/ + +# 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 */ + +/* +** Interix +** Contributed by Nedelcho Stanev +** +** Used for Interix support. +*/ + +# if defined(__INTERIX) +# define HASURANDOMDEV 1 +# define HASGETUSERSHELL 0 +# define HASSTRERROR 1 +# define HASUNSETENV 1 +# define HASFCHOWN 1 +# undef HAVE_SYS_ERRLIST +# define sys_errlist __sys_errlist +# define sys_nerr __sys_nerr +# define major(dev) ((int)(((dev) >> 8) & 0xff) +# define minor(dev) ((int)((dev) & 0xff) +# endif /* defined(__INTERIX) */ + + +/********************************************************************** +** End of Per-Operating System defines +**********************************************************************/ +/********************************************************************** +** More general defines +**********************************************************************/ + +/* general BSD defines */ +# ifdef BSD +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ +# ifndef HASSETREUID +# define HASSETREUID 1 /* has setreuid(2) call */ +# endif /* ! HASSETREUID */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# ifndef IP_SRCROUTE +# define IP_SRCROUTE 1 /* can check IP source routing */ +# endif /* ! IP_SRCROUTE */ +# ifndef HASSETRLIMIT +# define HASSETRLIMIT 1 /* has setrlimit(2) call */ +# endif /* ! HASSETRLIMIT */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone variable */ +# endif /* ! TZ_TYPE */ +# endif /* BSD */ + +/* general System V Release 4 defines */ +# ifdef __svr4__ +# define SYSTEM5 1 +# 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 /* ! HASSETRLIMIT */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# endif /* ! HASGETUSERSHELL */ +# ifndef HASFCHMOD +# define HASFCHMOD 1 /* most (all?) SVr4s seem to have fchmod(2) */ +# endif /* ! HASFCHMOD */ + +# ifndef _PATH_UNIX +# define _PATH_UNIX "/unix" +# endif /* ! _PATH_UNIX */ +# 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 128 +# endif /* ! SYSLOG_BUFSIZE */ +# ifndef SFS_TYPE +# define SFS_TYPE SFS_STATVFS +# endif /* ! SFS_TYPE */ + +# ifndef USE_SIGLONGJMP +# define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ +# endif /* ! USE_SIGLONGJMP */ +# endif /* __svr4__ */ + +# ifdef __SVR4 +# define LDA_USE_LOCKF 1 +# define LDA_USE_SETEUID 1 +# define _PATH_MAILDIR "/var/mail" +# endif /* __SVR4 */ + +/* general System V defines */ +# ifdef SYSTEM5 +# include +# define HASUNAME 1 /* use System V uname(2) system call */ +# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */ +# define HASSETVBUF 1 /* we have setvbuf(3) in libc */ +# ifndef HASULIMIT +# define HASULIMIT 1 /* has the ulimit(2) syscall */ +# endif /* ! HASULIMIT */ +# ifndef LA_TYPE +# ifdef MIOC_READKSYM +# define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */ +# else /* MIOC_READKSYM */ +# define LA_TYPE LA_INT /* assume integer load average */ +# endif /* MIOC_READKSYM */ +# endif /* ! LA_TYPE */ +# ifndef SFS_TYPE +# define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */ +# endif /* ! SFS_TYPE */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# 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 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). +*/ + +# ifdef titan +# undef HASINITGROUPS /* doesn't have initgroups(3) call */ +# endif /* titan */ + +# ifdef _CRAYCOM +# undef HASSETSID /* despite POSIX claim, doesn't have setsid */ +# endif /* _CRAYCOM */ + +# ifdef MOTO +# undef USESETEUID +# endif /* MOTO */ + +/* +** Due to a "feature" in some operating systems such as Ultrix 4.3 and +** HPUX 8.0, if you receive a "No route to host" message (ICMP message +** ICMP_UNREACH_HOST) on _any_ connection, all connections to that host +** are closed. Some firewalls return this error if you try to connect +** to the IDENT port (113), so you can't receive email from these hosts +** on these systems. The firewall really should use a more specific +** message such as ICMP_UNREACH_PROTOCOL or _PORT or _FILTER_PROHIB. If +** not explicitly set to zero above, default it on. +*/ + +# ifndef IDENTPROTO +# define IDENTPROTO 1 /* use IDENT proto (RFC 1413) */ +# endif /* ! IDENTPROTO */ + +# ifndef IP_SRCROUTE +# define IP_SRCROUTE 1 /* Detect IP source routing */ +# endif /* ! IP_SRCROUTE */ + +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 1 /* libc has getusershell(3) call */ +# endif /* ! HASGETUSERSHELL */ + +# ifndef NETUNIX +# define NETUNIX 1 /* include unix domain support */ +# endif /* ! NETUNIX */ + +# ifndef HASRANDOM +# define HASRANDOM 1 /* has random(3) support */ +# endif /* ! HASRANDOM */ + +# ifndef HASFLOCK +# define HASFLOCK 0 /* assume no flock(2) support */ +# endif /* ! HASFLOCK */ + +# ifndef HASSETREUID +# define HASSETREUID 0 /* assume no setreuid(2) call */ +# endif /* ! HASSETREUID */ + +# ifndef HASFCHMOD +# define HASFCHMOD 0 /* assume no fchmod(2) syscall */ +# endif /* ! HASFCHMOD */ + +# ifndef USESETEUID +# define USESETEUID 0 /* assume no seteuid(2) call or no saved ids */ +# endif /* ! USESETEUID */ + +# ifndef HASSETRLIMIT +# define HASSETRLIMIT 0 /* assume no setrlimit(2) support */ +# endif /* ! HASSETRLIMIT */ + +# ifndef HASULIMIT +# define HASULIMIT 0 /* assume no ulimit(2) support */ +# endif /* ! HASULIMIT */ + +# ifndef SECUREWARE +# define SECUREWARE 0 /* assume no SecureWare C2 auditing hooks */ +# endif /* ! SECUREWARE */ + +# ifndef USE_DOUBLE_FORK +# define USE_DOUBLE_FORK 1 /* avoid intermediate zombies */ +# endif /* ! USE_DOUBLE_FORK */ + +# ifndef USE_ENVIRON +# define USE_ENVIRON 0 /* use main() envp instead of extern environ */ +# endif /* ! USE_ENVIRON */ + +# ifndef USE_SIGLONGJMP +# define USE_SIGLONGJMP 0 /* assume setjmp handles signals properly */ +# endif /* ! USE_SIGLONGJMP */ + +# ifndef FDSET_CAST +# define FDSET_CAST /* (empty) cast for fd_set arg to select */ +# 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 +** it's an integer -- unfortunately, there seem to be several choices +** here. +*/ + +# ifndef GIDSET_T +# define GIDSET_T int +# endif /* ! GIDSET_T */ + +# ifndef UID_T +# define UID_T uid_t +# endif /* ! UID_T */ + +# ifndef GID_T +# define GID_T gid_t +# endif /* ! GID_T */ + +# ifndef MODE_T +# define MODE_T mode_t +# endif /* ! MODE_T */ + +# ifndef ARGV_T +# define ARGV_T char ** +# endif /* ! ARGV_T */ + +# ifndef SOCKADDR_LEN_T +# define SOCKADDR_LEN_T int +# endif /* ! SOCKADDR_LEN_T */ + +# ifndef SOCKOPT_LEN_T +# define SOCKOPT_LEN_T int +# endif /* ! SOCKOPT_LEN_T */ + +# ifndef QUAD_T +# define QUAD_T unsigned long +# endif /* ! QUAD_T */ +/********************************************************************** +** Remaining definitions should never have to be changed. They are +** primarily to provide back compatibility for older systems -- for +** example, it includes some POSIX compatibility definitions +**********************************************************************/ + +/* System 5 compatibility */ +# ifndef S_ISREG +# define S_ISREG(foo) ((foo & S_IFMT) == S_IFREG) +# endif /* ! S_ISREG */ +# ifndef S_ISDIR +# define S_ISDIR(foo) ((foo & S_IFMT) == S_IFDIR) +# endif /* ! S_ISDIR */ +# if !defined(S_ISLNK) && defined(S_IFLNK) +# define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK) +# 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 /* ! S_IRUSR */ +# ifndef S_IWUSR +# define S_IWUSR 0200 +# endif /* ! S_IWUSR */ +# ifndef S_IRGRP +# define S_IRGRP 0040 +# endif /* ! S_IRGRP */ +# ifndef S_IWGRP +# define S_IWGRP 0020 +# endif /* ! S_IWGRP */ +# ifndef S_IROTH +# define S_IROTH 0004 +# endif /* ! S_IROTH */ +# ifndef S_IWOTH +# define S_IWOTH 0002 +# 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 +# define EX_CONFIG 78 /* configuration error */ +# endif /* ! EX_CONFIG */ + +/* 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 */ + +#ifndef EX_NOTFOUND +# define EX_NOTFOUND EX_NOHOST +#endif /* ! EX_NOTFOUND */ + +/* pseudo-code used for mci_setstat */ +# define EX_NOTSTICKY -5 /* don't save persistent status */ + + +/* +** An "impossible" file mode to indicate that the file does not exist. +*/ + +# define ST_MODE_NOFILE 0171147 /* unlikely to occur */ + + +/* type of arbitrary pointer */ +# ifndef ARBPTR_T +# define ARBPTR_T void * +# endif /* ! ARBPTR_T */ + +# ifndef __P +# include "sm/cdefs.h" +# endif /* ! __P */ + +# if HESIOD && !defined(NAMED_BIND) +# define NAMED_BIND 1 /* not one without the other */ +# endif /* HESIOD && !defined(NAMED_BIND) */ + +# if NAMED_BIND && !defined( __ksr__ ) && !defined( h_errno ) +extern int h_errno; +# endif /* NAMED_BIND && !defined( __ksr__ ) && !defined( h_errno ) */ + +# if NEEDPUTENV +extern int putenv __P((char *)); +# endif /* NEEDPUTENV */ + +#if !HASUNSETENV +extern void unsetenv __P((char *)); +#endif /* !HASUNSETENV */ + +# ifdef LDAPMAP +# include +# include +# include + +/* 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 */ + +# if HASUNAME +# include +# ifdef newstr +# undef newstr +# endif /* newstr */ +# else /* HASUNAME */ +# define NODE_LENGTH 32 +struct utsname +{ + 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 /* !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V) */ + +# if !defined(SIGCHLD) && defined(SIGCLD) +# define SIGCHLD SIGCLD +# endif /* !defined(SIGCHLD) && defined(SIGCLD) */ + +# ifndef STDIN_FILENO +# define STDIN_FILENO 0 +# endif /* ! STDIN_FILENO */ + +# ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +# endif /* ! STDOUT_FILENO */ + +# ifndef STDERR_FILENO +# define STDERR_FILENO 2 +# 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 /* ! LOCK_SH */ + +# ifndef S_IXOTH +# define S_IXOTH (S_IEXEC >> 6) +# endif /* ! S_IXOTH */ + +# ifndef S_IXGRP +# define S_IXGRP (S_IEXEC >> 3) +# endif /* ! S_IXGRP */ + +# ifndef S_IXUSR +# define S_IXUSR (S_IEXEC) +# endif /* ! S_IXUSR */ + +#ifndef O_ACCMODE +# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif /* ! O_ACCMODE */ + +# ifndef SEEK_SET +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +# endif /* ! SEEK_SET */ + +# ifndef SIG_ERR +# define SIG_ERR ((void (*)()) -1) +# endif /* ! SIG_ERR */ + +# ifndef WEXITSTATUS +# define WEXITSTATUS(st) (((st) >> 8) & 0377) +# endif /* ! WEXITSTATUS */ +# ifndef WIFEXITED +# define WIFEXITED(st) (((st) & 0377) == 0) +# 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 /* ! SIGFUNC_DEFINED */ +# ifndef SIGFUNC_RETURN +# define SIGFUNC_RETURN +# endif /* ! SIGFUNC_RETURN */ +# ifndef SIGFUNC_DECL +# define SIGFUNC_DECL void +# endif /* ! SIGFUNC_DECL */ + +/* size of syslog buffer */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 +# endif /* ! SYSLOG_BUFSIZE */ + +/* for FD_SET() */ +#ifndef FD_SETSIZE +# define FD_SETSIZE 256 +#endif /* ! FD_SETSIZE */ + +/* +** Size of prescan buffer. +** Despite comments in the _sendmail_ book, this probably should +** not be changed; there are some hard-to-define dependencies. +*/ + +# define PSBUFSIZE (MAXNAME + MAXATOM) /* size of prescan buffer */ + +/* fork routine -- set above using #ifdef _osname_ or in Makefile */ +# ifndef FORK +# define FORK fork /* function to call to fork mailer */ +# endif /* ! FORK */ + +/* setting h_errno */ +# ifndef SM_SET_H_ERRNO +# define SM_SET_H_ERRNO(err) h_errno = (err) +# endif /* SM_SET_H_ERRNO */ + +# ifndef SM_CONF_GETOPT +# define SM_CONF_GETOPT 1 +# endif /* ! SM_CONF_GETOPT */ + +/* 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. +*/ + +# ifndef SCANF +# define SCANF 1 +# endif /* ! SCANF */ + +/* XXX 32 bit type */ +# ifndef SM_INT32 +# define SM_INT32 int32_t +# endif /* ! SM_INT32 */ + +/* +** SVr4 and similar systems use different routines for setjmp/longjmp +** with signal support +*/ + +# if USE_SIGLONGJMP +# ifdef jmp_buf +# undef jmp_buf +# endif /* jmp_buf */ +# define jmp_buf sigjmp_buf +# ifdef setjmp +# undef setjmp +# endif /* setjmp */ +# define setjmp(env) sigsetjmp(env, 1) +# ifdef longjmp +# undef longjmp +# endif /* longjmp */ +# define longjmp(env, val) siglongjmp(env, val) +# endif /* USE_SIGLONGJMP */ + +# if !defined(NGROUPS_MAX) && defined(NGROUPS) +# define NGROUPS_MAX NGROUPS /* POSIX naming convention */ +# 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. +*/ + +# if !LOG +# define LOG_EMERG 0 /* system is unusable */ +# define LOG_ALERT 1 /* action must be taken immediately */ +# define LOG_CRIT 2 /* critical conditions */ +# define LOG_ERR 3 /* error conditions */ +# define LOG_WARNING 4 /* warning conditions */ +# define LOG_NOTICE 5 /* normal but significant condition */ +# define LOG_INFO 6 /* informational */ +# define LOG_DEBUG 7 /* debug-level messages */ +# endif /* !LOG */ + +# ifndef SM_CONF_SYSLOG +# define SM_CONF_SYSLOG 1 /* syslog.h has prototype for syslog() */ +# endif /* SM_CONF_SYSLOG */ + +# if !SM_CONF_SYSLOG +# ifdef __STDC__ +extern void syslog(int, const char *, ...); +# else /* __STDC__ */ +extern void syslog(); +# endif /* __STDC__ */ +# endif /* !SM_CONF_SYSLOG */ + +/* portable(?) definition for alignment */ +# ifndef SM_ALIGN_SIZE +struct sm_align +{ + char al_c; + union + { + long al_l; + void *al_p; + double al_d; + void (*al_f)(); + } al_u; +}; +# define SM_ALIGN_SIZE offsetof(struct sm_align, al_u) +# endif /* ! SM_ALIGN_SIZE */ +# define SM_ALIGN_BITS (SM_ALIGN_SIZE - 1) + +#endif /* ! SM_CONF_H */ diff --git a/gnu/dist/sendmail/include/sm/config.h b/gnu/dist/sendmail/include/sm/config.h new file mode 100644 index 000000000000..64d06733ca6f --- /dev/null +++ b/gnu/dist/sendmail/include/sm/config.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: config.h,v 1.44 2002/01/23 17:47:15 gshapiro Exp + */ + +/* +** libsm configuration macros. +** The values of these macros are platform dependent. +** The default values are given here. +** If the default is incorrect, then the correct value can be specified +** in the m4 configuration file in devtools/OS. +*/ + +#ifndef SM_CONFIG_H +# define SM_CONFIG_H + +# include "sm_os.h" + +/* +** SM_CONF_STDBOOL_H is 1 if exists +*/ + +# ifndef SM_CONF_STDBOOL_H +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define SM_CONF_STDBOOL_H 1 +# else /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ +# define SM_CONF_STDBOOL_H 0 +# endif /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ +# endif /* ! SM_CONF_STDBOOL_H */ + +/* +** Configuration macros that specify how __P is defined. +*/ + +# ifndef SM_CONF_SYS_CDEFS_H +# define SM_CONF_SYS_CDEFS_H 0 +# endif /* ! SM_CONF_SYS_CDEFS_H */ + +/* +** SM_CONF_STDDEF_H is 1 if exists +*/ + +# ifndef SM_CONF_STDDEF_H +# define SM_CONF_STDDEF_H 1 +# endif /* ! SM_CONF_STDDEF_H */ + +/* +** Configuration macro that specifies whether strlcpy/strlcat are available. +** Note: this is the default so that the libsm version (optimized) will +** be used by default (sm_strlcpy/sm_strlcat). +*/ + +# ifndef SM_CONF_STRL +# define SM_CONF_STRL 0 +# endif /* ! SM_CONF_STRL */ + +/* +** Configuration macro indicating that setitimer is available +*/ + +# ifndef SM_CONF_SETITIMER +# define SM_CONF_SETITIMER 1 +# endif /* ! SM_CONF_SETITIMER */ + +/* +** Does define uid_t and gid_t? +*/ + +# ifndef SM_CONF_UID_GID +# define SM_CONF_UID_GID 1 +# endif /* ! SM_CONF_UID_GID */ + +/* +** Does define ssize_t? +*/ +# ifndef SM_CONF_SSIZE_T +# define SM_CONF_SSIZE_T 1 +# endif /* ! SM_CONF_SSIZE_T */ + +/* +** Does the C compiler support long long? +*/ + +# ifndef SM_CONF_LONGLONG +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define SM_CONF_LONGLONG 1 +# else /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ +# if defined(__GNUC__) +# define SM_CONF_LONGLONG 1 +# else /* defined(__GNUC__) */ +# define SM_CONF_LONGLONG 0 +# endif /* defined(__GNUC__) */ +# endif /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ +# endif /* ! SM_CONF_LONGLONG */ + +/* +** Does define quad_t and u_quad_t? +** We only care if long long is not available. +*/ + +# ifndef SM_CONF_QUAD_T +# define SM_CONF_QUAD_T 0 +# endif /* ! SM_CONF_QUAD_T */ + +/* +** Configuration macro indicating that shared memory is available +*/ + +# ifndef SM_CONF_SHM +# define SM_CONF_SHM 0 +# endif /* ! SM_CONF_SHM */ + +/* +** Does define sigsetjmp? +*/ + +# ifndef SM_CONF_SIGSETJMP +# define SM_CONF_SIGSETJMP 1 +# endif /* ! SM_CONF_SIGSETJMP */ + +/* +** Does exist, and define the EX_* macros with values +** that differ from the default BSD values in ? +*/ + +# ifndef SM_CONF_SYSEXITS_H +# define SM_CONF_SYSEXITS_H 0 +# endif /* ! SM_CONF_SYSEXITS_H */ + +/* has memchr() prototype? (if not: needs memory.h) */ +# ifndef SM_CONF_MEMCHR +# define SM_CONF_MEMCHR 1 +# endif /* ! SM_CONF_MEMCHR */ + +/* try LLONG tests in libsm/t-types.c? */ +# ifndef SM_CONF_TEST_LLONG +# define SM_CONF_TEST_LLONG 1 +# endif /* !SM_CONF_TEST_LLONG */ + +/* Does LDAP library have ldap_memfree()? */ +# ifndef SM_CONF_LDAP_MEMFREE + +/* +** The new LDAP C API (draft-ietf-ldapext-ldap-c-api-04.txt) includes +** ldap_memfree() in the API. That draft states to use LDAP_API_VERSION +** of 2004 to identify the API. +*/ + +# if USING_NETSCAPE_LDAP || LDAP_API_VERSION >= 2004 +# define SM_CONF_LDAP_MEMFREE 1 +# else /* USING_NETSCAPE_LDAP || LDAP_API_VERSION >= 2004 */ +# define SM_CONF_LDAP_MEMFREE 0 +# endif /* USING_NETSCAPE_LDAP || LDAP_API_VERSION >= 2004 */ +# endif /* ! SM_CONF_LDAP_MEMFREE */ + +#endif /* ! SM_CONFIG_H */ diff --git a/gnu/dist/sendmail/include/sm/debug.h b/gnu/dist/sendmail/include/sm/debug.h new file mode 100644 index 000000000000..8e8ce16ebfa0 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/debug.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: debug.h,v 1.15 2001/03/08 03:23:07 ca Exp + */ + +/* +** libsm debugging and tracing +** See libsm/debug.html for documentation. +*/ + +#ifndef SM_DEBUG_H +# define SM_DEBUG_H + +# include +# include + +/* +** abstractions for printing trace messages +*/ + +extern SM_FILE_T * +sm_debug_file __P((void)); + +extern void +sm_debug_setfile __P(( + SM_FILE_T *)); + +extern void PRINTFLIKE(1, 2) +sm_dprintf __P(( + char *_fmt, + ...)); + +extern void +sm_dflush __P((void)); + +/* +** abstractions for setting and testing debug activation levels +*/ + +extern void +sm_debug_addsettings_x __P(( + const char *)); + +extern void +sm_debug_addsetting_x __P(( + const char *, + int)); + +# define SM_DEBUG_UNKNOWN ((SM_ATOMIC_UINT_T)(-1)) + +extern const char SmDebugMagic[]; + +typedef struct sm_debug SM_DEBUG_T; +struct sm_debug +{ + const char *sm_magic; /* points to SmDebugMagic */ + + /* + ** debug_level is the activation level of this debug + ** object. Level 0 means no debug activity. + ** It is initialized to SM_DEBUG_UNKNOWN, which indicates + ** that the true value is unknown. If debug_level == + ** SM_DEBUG_UNKNOWN, then the access functions will look up + ** its true value in the internal table of debug settings. + */ + + SM_ATOMIC_UINT_T debug_level; + + /* + ** debug_name is the name used to reference this SM_DEBUG + ** structure via the sendmail -d option. + */ + + char *debug_name; + + /* + ** debug_desc is a literal character string of the form + ** "@(#)$Debug: - $" + */ + + char *debug_desc; + + /* + ** We keep a linked list of initialized SM_DEBUG structures + ** so that when sm_debug_addsetting is called, we can reset + ** them all back to the uninitialized state. + */ + + SM_DEBUG_T *debug_next; +}; + +# ifndef SM_DEBUG_CHECK +# define SM_DEBUG_CHECK 1 +# endif /* ! SM_DEBUG_CHECK */ + +# if SM_DEBUG_CHECK +/* +** This macro is cleverly designed so that if the debug object is below +** the specified level, then the only overhead is a single comparison +** (except for the first time this macro is invoked). +*/ + +# define sm_debug_active(debug, level) \ + ((debug)->debug_level >= (level) && \ + ((debug)->debug_level != SM_DEBUG_UNKNOWN || \ + sm_debug_loadactive(debug, level))) + +# define sm_debug_level(debug) \ + ((debug)->debug_level == SM_DEBUG_UNKNOWN \ + ? sm_debug_loadlevel(debug) : (debug)->debug_level) + +# define sm_debug_unknown(debug) ((debug)->debug_level == SM_DEBUG_UNKNOWN) +# else /* SM_DEBUG_CHECK */ +# define sm_debug_active(debug, level) 0 +# define sm_debug_level(debug) 0 +# define sm_debug_unknown(debug) 0 +# endif /* SM_DEBUG_CHECK */ + +extern bool +sm_debug_loadactive __P(( + SM_DEBUG_T *, + int)); + +extern int +sm_debug_loadlevel __P(( + SM_DEBUG_T *)); + +# define SM_DEBUG_INITIALIZER(name, desc) { \ + SmDebugMagic, \ + SM_DEBUG_UNKNOWN, \ + name, \ + desc, \ + NULL} + +#endif /* ! SM_DEBUG_H */ diff --git a/gnu/dist/sendmail/include/sm/errstring.h b/gnu/dist/sendmail/include/sm/errstring.h new file mode 100644 index 000000000000..15e8cd4d5893 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/errstring.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * + * Id: errstring.h,v 1.4 2001/06/07 20:04:53 ca Exp + */ + +/* +** Error codes. +*/ + +#ifndef SM_ERRSTRING_H +# define SM_ERRSTRING_H + +#include +extern int errno; + +/* +** 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 sm_errstring. +*/ + +#ifndef E_PSEUDOBASE +# define E_PSEUDOBASE 256 +#endif /* ! E_PSEUDOBASE */ + +#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_SM_GRFILE (E_PSEUDOBASE + 10) /* g readable file */ +#define E_SM_WRFILE (E_PSEUDOBASE + 11) /* o readable file */ +#define E_DNSBASE (E_PSEUDOBASE + 20) /* base for DNS h_errno */ +#define E_SMDBBASE (E_PSEUDOBASE + 40) /* base for libsmdb errors */ +#define E_LDAPBASE (E_PSEUDOBASE + 70) /* base for LDAP errors */ + +/* libsmdb */ +#define SMDBE_OK 0 +#define SMDBE_MALLOC (E_SMDBBASE + 1) +#define SMDBE_GDBM_IS_BAD (E_SMDBBASE + 2) +#define SMDBE_UNSUPPORTED (E_SMDBBASE + 3) +#define SMDBE_DUPLICATE (E_SMDBBASE + 4) +#define SMDBE_BAD_OPEN (E_SMDBBASE + 5) +#define SMDBE_NOT_FOUND (E_SMDBBASE + 6) +#define SMDBE_UNKNOWN_DB_TYPE (E_SMDBBASE + 7) +#define SMDBE_UNSUPPORTED_DB_TYPE (E_SMDBBASE + 8) +#define SMDBE_INCOMPLETE (E_SMDBBASE + 9) +#define SMDBE_KEY_EMPTY (E_SMDBBASE + 10) +#define SMDBE_KEY_EXIST (E_SMDBBASE + 11) +#define SMDBE_LOCK_DEADLOCK (E_SMDBBASE + 12) +#define SMDBE_LOCK_NOT_GRANTED (E_SMDBBASE + 13) +#define SMDBE_LOCK_NOT_HELD (E_SMDBBASE + 14) +#define SMDBE_RUN_RECOVERY (E_SMDBBASE + 15) +#define SMDBE_IO_ERROR (E_SMDBBASE + 16) +#define SMDBE_READ_ONLY (E_SMDBBASE + 17) +#define SMDBE_DB_NAME_TOO_LONG (E_SMDBBASE + 18) +#define SMDBE_INVALID_PARAMETER (E_SMDBBASE + 19) +#define SMDBE_ONLY_SUPPORTS_ONE_CURSOR (E_SMDBBASE + 20) +#define SMDBE_NOT_A_VALID_CURSOR (E_SMDBBASE + 21) +#define SMDBE_LAST_ENTRY (E_SMDBBASE + 22) +#define SMDBE_OLD_VERSION (E_SMDBBASE + 23) + +extern const char * +sm_errstring __P(( + int _errno)); + +#endif /* SM_ERRSTRING_H */ diff --git a/gnu/dist/sendmail/include/sm/exc.h b/gnu/dist/sendmail/include/sm/exc.h new file mode 100644 index 000000000000..d1a758747827 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/exc.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: exc.h,v 1.23 2001/06/07 20:04:53 ca Exp + */ + +/* +** libsm exception handling +** See libsm/exc.html for documentation. +*/ + +#ifndef SM_EXC_H +# define SM_EXC_H + +#include +#include +#include +#include + +typedef struct sm_exc SM_EXC_T; +typedef struct sm_exc_type SM_EXC_TYPE_T; +typedef union sm_val SM_VAL_T; + +/* +** Exception types +*/ + +extern const char SmExcTypeMagic[]; + +struct sm_exc_type +{ + const char *sm_magic; + const char *etype_category; + const char *etype_argformat; + void (*etype_print) __P((SM_EXC_T *, SM_FILE_T *)); + const char *etype_printcontext; +}; + +extern const SM_EXC_TYPE_T SmEtypeOs; +extern const SM_EXC_TYPE_T SmEtypeErr; + +extern void +sm_etype_printf __P(( + SM_EXC_T *_exc, + SM_FILE_T *_stream)); + +/* +** Exception objects +*/ + +extern const char SmExcMagic[]; + +union sm_val +{ + int v_int; + long v_long; + char *v_str; + SM_EXC_T *v_exc; +}; + +struct sm_exc +{ + const char *sm_magic; + size_t exc_refcount; + const SM_EXC_TYPE_T *exc_type; + SM_VAL_T *exc_argv; +}; + +# define SM_EXC_INITIALIZER(type, argv) \ + { \ + SmExcMagic, \ + 0, \ + type, \ + argv, \ + } + +extern SM_EXC_T * +sm_exc_new_x __P(( + const SM_EXC_TYPE_T *_type, + ...)); + +extern SM_EXC_T * +sm_exc_addref __P(( + SM_EXC_T *_exc)); + +extern void +sm_exc_free __P(( + SM_EXC_T *_exc)); + +extern bool +sm_exc_match __P(( + SM_EXC_T *_exc, + const char *_pattern)); + +extern void +sm_exc_write __P(( + SM_EXC_T *_exc, + SM_FILE_T *_stream)); + +extern void +sm_exc_print __P(( + SM_EXC_T *_exc, + SM_FILE_T *_stream)); + +extern SM_DEAD(void +sm_exc_raise_x __P(( + SM_EXC_T *_exc))); + +extern SM_DEAD(void +sm_exc_raisenew_x __P(( + const SM_EXC_TYPE_T *_type, + ...))); + +/* +** Exception handling +*/ + +typedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *)); + +extern void +sm_exc_newthread __P(( + SM_EXC_DEFAULT_HANDLER_T _handle)); + +typedef struct sm_exc_handler SM_EXC_HANDLER_T; +struct sm_exc_handler +{ + SM_EXC_T *eh_value; + SM_JMPBUF_T eh_context; + SM_EXC_HANDLER_T *eh_parent; + int eh_state; +}; + +/* values for eh_state */ +enum +{ + SM_EH_PUSHED = 2, + SM_EH_POPPED = 0, + SM_EH_HANDLED = 1 +}; + +extern SM_EXC_HANDLER_T *SmExcHandler; + +# define SM_TRY { SM_EXC_HANDLER_T _h; \ + do { \ + _h.eh_value = NULL; \ + _h.eh_parent = SmExcHandler; \ + _h.eh_state = SM_EH_PUSHED; \ + SmExcHandler = &_h; \ + if (sm_setjmp_nosig(_h.eh_context) == 0) { + +# define SM_FINALLY SM_ASSERT(SmExcHandler == &_h); \ + } \ + if (sm_setjmp_nosig(_h.eh_context) == 0) { + +# define SM_EXCEPT(e,pat) } \ + if (_h.eh_state == SM_EH_HANDLED) \ + break; \ + if (_h.eh_state == SM_EH_PUSHED) { \ + SM_ASSERT(SmExcHandler == &_h); \ + SmExcHandler = _h.eh_parent; \ + } \ + _h.eh_state = sm_exc_match(_h.eh_value,pat) \ + ? SM_EH_HANDLED : SM_EH_POPPED; \ + if (_h.eh_state == SM_EH_HANDLED) { \ + SM_UNUSED(SM_EXC_T *e) = _h.eh_value; + +# define SM_END_TRY } \ + } while (0); \ + if (_h.eh_state == SM_EH_PUSHED) { \ + SM_ASSERT(SmExcHandler == &_h); \ + SmExcHandler = _h.eh_parent; \ + if (_h.eh_value != NULL) \ + sm_exc_raise_x(_h.eh_value); \ + } else if (_h.eh_state == SM_EH_POPPED) { \ + if (_h.eh_value != NULL) \ + sm_exc_raise_x(_h.eh_value); \ + } else \ + sm_exc_free(_h.eh_value); \ + } + +#endif /* SM_EXC_H */ diff --git a/gnu/dist/sendmail/include/sm/fdset.h b/gnu/dist/sendmail/include/sm/fdset.h new file mode 100644 index 000000000000..5c7115432267 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/fdset.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2001, 2002 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: fdset.h,v 1.3.10.2 2002/12/10 04:02:25 ca Exp + */ + +#ifndef SM_FDSET_H +# define SM_FDSET_H + +/* +** Note: SM_FD_OK_SELECT(fd) requires that ValidSocket(fd) has been checked +** before. +*/ + +# define SM_FD_SET(fd, pfdset) FD_SET(fd, pfdset) +# define SM_FD_ISSET(fd, pfdset) FD_ISSET(fd, pfdset) +# define SM_FD_SETSIZE FD_SETSIZE +# define SM_FD_OK_SELECT(fd) (FD_SETSIZE <= 0 || (fd) < FD_SETSIZE) + +#endif /* SM_FDSET_H */ diff --git a/gnu/dist/sendmail/include/sm/gen.h b/gnu/dist/sendmail/include/sm/gen.h new file mode 100644 index 000000000000..d5cd008c0649 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/gen.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: gen.h,v 1.22 2002/04/03 00:40:42 ca Exp + */ + +/* +** libsm general definitions +** See libsm/gen.html for documentation. +*/ + +#ifndef SM_GEN_H +# define SM_GEN_H + +# include +# include +# include + +/* +** Define SM_RCSID and SM_IDSTR, +** macros used to embed RCS and SCCS identification strings in object files. +*/ + +# ifdef lint +# define SM_RCSID(str) +# define SM_IDSTR(id,str) +# else /* lint */ +# define SM_RCSID(str) SM_UNUSED(static const char RcsId[]) = str; +# define SM_IDSTR(id,str) SM_UNUSED(static const char id[]) = str; +# endif /* lint */ + +/* +** Define NULL and offsetof (from the C89 standard) +*/ + +# if SM_CONF_STDDEF_H +# include +# else /* SM_CONF_STDDEF_H */ +# ifndef NULL +# define NULL 0 +# endif +# define offsetof(type, member) ((size_t)(&((type *)0)->member)) +# endif /* SM_CONF_STDDEF_H */ + +/* +** Define bool, true, false (from the C99 standard) +*/ + +# if SM_CONF_STDBOOL_H +# include +# else /* SM_CONF_STDBOOL_H */ +# ifndef __cplusplus + typedef int bool; +# define false 0 +# define true 1 +# endif +# endif /* SM_CONF_STDBOOL_H */ + +/* +** Define SM_MAX and SM_MIN +*/ + +# define SM_MAX(a, b) ((a) > (b) ? (a) : (b)) +# define SM_MIN(a, b) ((a) < (b) ? (a) : (b)) + +/* Define SM_SUCCESS and SM_FAILURE */ +# define SM_SUCCESS 0 +# define SM_FAILURE (-1) + +/* XXX This needs to be fixed when we start to use threads: */ +typedef int SM_ATOMIC_INT_T; +typedef unsigned int SM_ATOMIC_UINT_T; + +#endif /* SM_GEN_H */ diff --git a/gnu/dist/sendmail/include/sm/heap.h b/gnu/dist/sendmail/include/sm/heap.h new file mode 100644 index 000000000000..bebf69551330 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/heap.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: heap.h,v 1.22 2001/09/04 22:41:55 ca Exp + */ + +/* +** Sendmail debugging memory allocation package. +** See libsm/heap.html for documentation. +*/ + +#ifndef SM_HEAP_H +# define SM_HEAP_H + +# include +# include +# include +# include + +/* change default to 0 for production? */ +# ifndef SM_HEAP_CHECK +# define SM_HEAP_CHECK 1 +# endif /* ! SM_HEAP_CHECK */ + +# if SM_HEAP_CHECK +# define sm_malloc_x(sz) sm_malloc_tagged_x(sz, __FILE__, __LINE__, SmHeapGroup) +# define sm_malloc(size) sm_malloc_tagged(size, __FILE__, __LINE__, SmHeapGroup) +# define sm_free(ptr) sm_free_tagged(ptr, __FILE__, __LINE__) + +extern void *sm_malloc_tagged __P((size_t, char *, int, int)); +extern void *sm_malloc_tagged_x __P((size_t, char *, int, int)); +extern void sm_free_tagged __P((void *, char *, int)); +extern void *sm_realloc_x __P((void *, size_t)); +extern bool sm_heap_register __P((void *, size_t, char *, int, int)); +extern void sm_heap_checkptr_tagged __P((void *, char *, int)); +extern void sm_heap_report __P((SM_FILE_T *, int)); + +# else /* SM_HEAP_CHECK */ +# define sm_malloc_tagged(size, file, line, grp) sm_malloc(size) +# define sm_malloc_tagged_x(size, file, line, grp) sm_malloc_x(size) +# define sm_free_tagged(ptr, file, line) sm_free(ptr) +# define sm_heap_register(ptr, size, file, line, grp) (true) +# define sm_heap_checkptr_tagged(ptr, tag, num) ((void)0) +# define sm_heap_report(file, verbose) ((void)0) + +extern void *sm_malloc __P((size_t)); +extern void *sm_malloc_x __P((size_t)); +extern void *sm_realloc_x __P((void *, size_t)); +extern void sm_free __P((void *)); +# endif /* SM_HEAP_CHECK */ + +extern void *sm_realloc __P((void *, size_t)); + +# define sm_heap_checkptr(ptr) sm_heap_checkptr_tagged(ptr, __FILE__, __LINE__) + +#if 0 +/* +** sm_f[mc]alloc are plug in replacements for malloc and calloc +** which can be used in a context requiring a function pointer, +** and which are compatible with sm_free. Warning: sm_heap_report +** cannot report where storage leaked by sm_f[mc]alloc was allocated. +*/ + +/* XXX unused right now */ + +extern void * +sm_fmalloc __P(( + size_t)); + +extern void * +sm_fcalloc __P(( + size_t, + size_t)); +#endif /* 0 */ + +/* +** Allocate 'permanent' storage that can be freed but may still be +** allocated when the process exits. sm_heap_report will not complain +** about a storage leak originating from a call to sm_pmalloc. +*/ + +# define sm_pmalloc(size) sm_malloc_tagged(size, __FILE__, __LINE__, 0) +# define sm_pmalloc_x(size) sm_malloc_tagged_x(size, __FILE__, __LINE__, 0) + +# define sm_heap_group() SmHeapGroup +# define sm_heap_setgroup(g) (SmHeapGroup = (g)) +# define sm_heap_newgroup() (SmHeapGroup = ++SmHeapMaxGroup) + +extern int SmHeapGroup; +extern int SmHeapMaxGroup; + +extern SM_DEBUG_T SmHeapTrace; +extern SM_DEBUG_T SmHeapCheck; +extern SM_EXC_T SmHeapOutOfMemory; + +#endif /* ! SM_HEAP_H */ diff --git a/gnu/dist/sendmail/include/sm/io.h b/gnu/dist/sendmail/include/sm/io.h new file mode 100644 index 000000000000..8f7ee562023e --- /dev/null +++ b/gnu/dist/sendmail/include/sm/io.h @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + * + * Id: io.h,v 1.23 2002/02/23 19:32:17 gshapiro Exp + */ + +/*- + * @(#)stdio.h 5.17 (Berkeley) 6/3/91 + */ + +#ifndef SM_IO_H +#define SM_IO_H + +#include +#include +#include + +/* mode for sm io (exposed) */ +#define SM_IO_RDWR 1 /* read-write */ +#define SM_IO_RDONLY 2 /* read-only */ +#define SM_IO_WRONLY 3 /* write-only */ +#define SM_IO_APPEND 4 /* write-only from eof */ +#define SM_IO_APPENDRW 5 /* read-write from eof */ +#define SM_IO_RDWRTR 6 /* read-write with truncation indicated */ + +/* for sm_io_fseek, et al api's (exposed) */ +#define SM_IO_SEEK_SET 0 +#define SM_IO_SEEK_CUR 1 +#define SM_IO_SEEK_END 2 + +/* flags for info what's with different types (exposed) */ +#define SM_IO_WHAT_MODE 1 +#define SM_IO_WHAT_VECTORS 2 +#define SM_IO_WHAT_FD 3 +#define SM_IO_WHAT_TYPE 4 +#define SM_IO_WHAT_ISTYPE 5 +#define SM_IO_IS_READABLE 6 +#define SM_IO_WHAT_TIMEOUT 7 +#define SM_IO_WHAT_SIZE 8 + +/* info flags (exposed) */ +#define SM_IO_FTYPE_CREATE 1 +#define SM_IO_FTYPE_MODIFY 2 +#define SM_IO_FTYPE_DELETE 3 + +#define SM_IO_SL_PRIO 1 + +#define SM_IO_OPEN_MAX 20 + +/* for internal buffers */ +struct smbuf +{ + unsigned char *smb_base; + int smb_size; +}; + +/* +** sm I/O state variables (internal only). +** +** The following always hold: +** +** if (flags&(SMLBF|SMWR)) == (SMLBF|SMWR), +** lbfsize is -bf.size, else lbfsize is 0 +** if flags&SMRD, w is 0 +** if flags&SMWR, r is 0 +** +** This ensures that the getc and putc macros (or inline functions) never +** try to write or read from a file that is in `read' or `write' mode. +** (Moreover, they can, and do, automatically switch from read mode to +** write mode, and back, on "r+" and "w+" files.) +** +** lbfsize is used only to make the inline line-buffered output stream +** code as compact as possible. +** +** ub, up, and ur are used when ungetc() pushes back more characters +** than fit in the current bf, or when ungetc() pushes back a character +** that does not match the previous one in bf. When this happens, +** ub.base becomes non-nil (i.e., a stream has ungetc() data iff +** ub.base!=NULL) and up and ur save the current values of p and r. +*/ + +typedef struct sm_file SM_FILE_T; + +struct sm_file +{ + const char *sm_magic; /* This SM_FILE_T is free when NULL */ + unsigned char *f_p; /* current position in (some) buffer */ + int f_r; /* read space left for getc() */ + int f_w; /* write space left for putc() */ + long f_flags; /* flags, below */ + short f_file; /* fileno, if Unix fd, else -1 */ + struct smbuf f_bf; /* the buffer (>= 1 byte, if !NULL) */ + int f_lbfsize; /* 0 or -bf.size, for inline putc */ + + /* These can be used for any purpose by a file type implementation: */ + void *f_cookie; + int f_ival; + + /* operations */ + int (*f_close) __P((SM_FILE_T *)); + ssize_t (*f_read) __P((SM_FILE_T *, char *, size_t)); + off_t (*f_seek) __P((SM_FILE_T *, off_t, int)); + ssize_t (*f_write) __P((SM_FILE_T *, const char *, size_t)); + int (*f_open) __P((SM_FILE_T *, const void *, int, + const void *)); + int (*f_setinfo) __P((SM_FILE_T *, int , void *)); + int (*f_getinfo) __P((SM_FILE_T *, int , void *)); + int f_timeout; + int f_timeoutstate; /* either blocking or non-blocking */ + char *f_type; /* for by-type lookups */ + struct sm_file *f_flushfp; /* flush this before reading parent */ + struct sm_file *f_modefp; /* sync mode with this fp */ + + /* separate buffer for long sequences of ungetc() */ + struct smbuf f_ub; /* ungetc buffer */ + unsigned char *f_up; /* saved f_p when f_p is doing ungetc */ + int f_ur; /* saved f_r when f_r is counting ungetc */ + + /* tricks to meet minimum requirements even when malloc() fails */ + unsigned char f_ubuf[3]; /* guarantee an ungetc() buffer */ + unsigned char f_nbuf[1]; /* guarantee a getc() buffer */ + + /* Unix stdio files get aligned to block boundaries on fseek() */ + int f_blksize; /* stat.st_blksize (may be != bf.size) */ + off_t f_lseekoff; /* current lseek offset */ + int f_dup_cnt; /* count file dup'd */ +}; + +__BEGIN_DECLS +extern SM_FILE_T SmIoF[]; +extern const char SmFileMagic[]; +extern SM_FILE_T SmFtStdio_def; +extern SM_FILE_T SmFtStdiofd_def; +extern SM_FILE_T SmFtString_def; +extern SM_FILE_T SmFtSyslog_def; +extern SM_FILE_T SmFtRealStdio_def; + +#define SMIOIN_FILENO 0 +#define SMIOOUT_FILENO 1 +#define SMIOERR_FILENO 2 +#define SMIOSTDIN_FILENO 3 +#define SMIOSTDOUT_FILENO 4 +#define SMIOSTDERR_FILENO 5 + +/* Common predefined and already (usually) open files (exposed) */ +#define smioin (&SmIoF[SMIOIN_FILENO]) +#define smioout (&SmIoF[SMIOOUT_FILENO]) +#define smioerr (&SmIoF[SMIOERR_FILENO]) +#define smiostdin (&SmIoF[SMIOSTDIN_FILENO]) +#define smiostdout (&SmIoF[SMIOSTDOUT_FILENO]) +#define smiostderr (&SmIoF[SMIOSTDERR_FILENO]) + +#define SmFtStdio (&SmFtStdio_def) +#define SmFtStdiofd (&SmFtStdiofd_def) +#define SmFtString (&SmFtString_def) +#define SmFtSyslog (&SmFtSyslog_def) +#define SmFtRealStdio (&SmFtRealStdio_def) + +#ifdef __STDC__ +# define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \ + (f) = {SmFileMagic, (unsigned char *) 0, 0, 0, 0L, -1, {0}, 0, (void *) 0,\ + 0, (close), (read), (seek), (write), (open), (set), (get), (timeout),\ + 0, (name)} +# define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout) + +#else /* __STDC__ */ +# define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) (f) +# define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \ + (f).sm_magic = SmFileMagic; \ + (f).f_p = (unsigned char *) 0; \ + (f).f_r = 0; \ + (f).f_w = 0; \ + (f).f_flags = 0L; \ + (f).f_file = 0; \ + (f).f_bf.smb_base = (unsigned char *) 0; \ + (f).f_bf.smb_size = 0; \ + (f).f_lbfsize = 0; \ + (f).f_cookie = (void *) 0; \ + (f).f_ival = 0; \ + (f).f_close = (close); \ + (f).f_read = (read); \ + (f).f_seek = (seek); \ + (f).f_write = (write); \ + (f).f_open = (open); \ + (f).f_setinfo = (set); \ + (f).f_getinfo = (get); \ + (f).f_timeout = (timeout); \ + (f).f_timeoutstate = 0; \ + (f).f_type = (name); + +#endif /* __STDC__ */ + +__END_DECLS + +/* Internal flags */ +#define SMFBF 0x000001 /* XXXX fully buffered */ +#define SMLBF 0x000002 /* line buffered */ +#define SMNBF 0x000004 /* unbuffered */ +#define SMNOW 0x000008 /* Flush each write; take read now */ +#define SMRD 0x000010 /* OK to read */ +#define SMWR 0x000020 /* OK to write */ + /* RD and WR are never simultaneously asserted */ +#define SMRW 0x000040 /* open for reading & writing */ +#define SMFEOF 0x000080 /* found EOF */ +#define SMERR 0x000100 /* found error */ +#define SMMBF 0x000200 /* buf is from malloc */ +#define SMAPP 0x000400 /* fdopen()ed in append mode */ +#define SMSTR 0x000800 /* this is an snprintf string */ +#define SMOPT 0x001000 /* do fseek() optimisation */ +#define SMNPT 0x002000 /* do not do fseek() optimisation */ +#define SMOFF 0x004000 /* set iff offset is in fact correct */ +#define SMALC 0x010000 /* allocate string space dynamically */ + +#define SMMODEMASK 0x0070 /* read/write mode */ + +/* defines for timeout constants */ +#define SM_TIME_IMMEDIATE (0) +#define SM_TIME_FOREVER (-1) +#define SM_TIME_DEFAULT (-2) + +/* timeout state for blocking */ +#define SM_TIME_BLOCK (0) /* XXX just bool? */ +#define SM_TIME_NONBLOCK (1) + +/* Exposed buffering type flags */ +#define SM_IO_FBF 0 /* setvbuf should set fully buffered */ +#define SM_IO_LBF 1 /* setvbuf should set line buffered */ +#define SM_IO_NBF 2 /* setvbuf should set unbuffered */ + +/* setvbuf buffered, but through at lower file type layers */ +#define SM_IO_NOW 3 + +/* +** size of buffer used by setbuf. +** If underlying filesystem blocksize is discoverable that is used instead +*/ + +#define SM_IO_BUFSIZ 4096 + +#define SM_IO_EOF (-1) + +/* Functions defined in ANSI C standard. */ +__BEGIN_DECLS +SM_FILE_T *sm_io_autoflush __P((SM_FILE_T *, SM_FILE_T *)); +void sm_io_automode __P((SM_FILE_T *, SM_FILE_T *)); +void sm_io_clearerr __P((SM_FILE_T *)); +int sm_io_close __P((SM_FILE_T *, int SM_NONVOLATILE)); +SM_FILE_T *sm_io_dup __P((SM_FILE_T *)); +int sm_io_eof __P((SM_FILE_T *)); +int sm_io_error __P((SM_FILE_T *)); +char *sm_io_fgets __P((SM_FILE_T *, int, char *, int)); +int sm_io_flush __P((SM_FILE_T *, int SM_NONVOLATILE)); + +int PRINTFLIKE(3, 4) +sm_io_fprintf __P((SM_FILE_T *, int, const char *, ...)); + +int sm_io_fputs __P((SM_FILE_T *, int, const char *)); + +int SCANFLIKE(3, 4) +sm_io_fscanf __P((SM_FILE_T *, int, const char *, ...)); + +int sm_io_getc __P((SM_FILE_T *, int)); +int sm_io_getinfo __P((SM_FILE_T *, int, void *)); +SM_FILE_T *sm_io_open __P((const SM_FILE_T *, int SM_NONVOLATILE, const void *, + int, const void *)); +int sm_io_purge __P((SM_FILE_T *)); +int sm_io_putc __P((SM_FILE_T *, int, int)); +size_t sm_io_read __P((SM_FILE_T *, int, void *, size_t)); +SM_FILE_T *sm_io_reopen __P((const SM_FILE_T *, int SM_NONVOLATILE, + const void *, int, const void *, SM_FILE_T *)); +void sm_io_rewind __P((SM_FILE_T *, int)); +int sm_io_seek __P((SM_FILE_T *, int SM_NONVOLATILE, long SM_NONVOLATILE, + int SM_NONVOLATILE)); +int sm_io_setinfo __P((SM_FILE_T *, int, void *)); +int sm_io_setvbuf __P((SM_FILE_T *, int, char *, int, size_t)); + +int SCANFLIKE(2, 3) +sm_io_sscanf __P((const char *, char const *, ...)); + +long sm_io_tell __P((SM_FILE_T *, int SM_NONVOLATILE)); +int sm_io_ungetc __P((SM_FILE_T *, int, int)); +int sm_io_vfprintf __P((SM_FILE_T *, int, const char *, va_list)); +size_t sm_io_write __P((SM_FILE_T *, int, const void *, size_t)); + +void sm_strio_init __P((SM_FILE_T *, char *, size_t)); + +extern SM_FILE_T * +sm_io_fopen __P(( + char *_pathname, + int _flags, + ...)); + +extern SM_FILE_T * +sm_io_stdioopen __P(( + FILE *_stream, + char *_mode)); + +extern int +sm_vasprintf __P(( + char **_str, + const char *_fmt, + va_list _ap)); + +extern int +sm_vsnprintf __P(( + char *, + size_t, + const char *, + va_list)); + +extern void +sm_perror __P(( + const char *)); + +__END_DECLS + +/* +** Functions internal to the implementation. +*/ + +__BEGIN_DECLS +int sm_rget __P((SM_FILE_T *, int)); +int sm_vfscanf __P((SM_FILE_T *, int SM_NONVOLATILE, const char *, + va_list SM_NONVOLATILE)); +int sm_wbuf __P((SM_FILE_T *, int, int)); +__END_DECLS + +/* +** The macros are here so that we can +** define function versions in the library. +*/ + +#define sm_getc(f, t) \ + (--(f)->f_r < 0 ? \ + sm_rget(f, t) : \ + (int)(*(f)->f_p++)) + +/* +** This has been tuned to generate reasonable code on the vax using pcc. +** (It also generates reasonable x86 code using gcc.) +*/ + +#define sm_putc(f, t, c) \ + (--(f)->f_w < 0 ? \ + (f)->f_w >= (f)->f_lbfsize ? \ + (*(f)->f_p = (c)), *(f)->f_p != '\n' ? \ + (int)*(f)->f_p++ : \ + sm_wbuf(f, t, '\n') : \ + sm_wbuf(f, t, (int)(c)) : \ + (*(f)->f_p = (c), (int)*(f)->f_p++)) + +#define sm_eof(p) (((p)->f_flags & SMFEOF) != 0) +#define sm_error(p) (((p)->f_flags & SMERR) != 0) +#define sm_clearerr(p) ((void)((p)->f_flags &= ~(SMERR|SMFEOF))) + +#define sm_io_eof(p) sm_eof(p) +#define sm_io_error(p) sm_error(p) + +#define sm_io_clearerr(p) sm_clearerr(p) + +#ifndef lint +# ifndef _POSIX_SOURCE +# define sm_io_getc(fp, t) sm_getc(fp, t) +# define sm_io_putc(fp, t, x) sm_putc(fp, t, x) +# endif /* _POSIX_SOURCE */ +#endif /* lint */ + +#endif /* SM_IO_H */ diff --git a/gnu/dist/sendmail/include/sm/ldap.h b/gnu/dist/sendmail/include/sm/ldap.h new file mode 100644 index 000000000000..6ebc8ba246a8 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/ldap.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: ldap.h,v 1.22 2002/03/05 02:17:26 ca Exp + */ + +#ifndef SM_LDAP_H +# define SM_LDAP_H + +# include +# include + +/* +** NOTE: These should be changed from LDAPMAP_* to SM_LDAP_* +** in the next major release (8.13) of sendmail. +*/ + +# ifndef LDAPMAP_MAX_ATTR +# define LDAPMAP_MAX_ATTR 64 +# endif /* ! LDAPMAP_MAX_ATTR */ +# ifndef LDAPMAP_MAX_FILTER +# define LDAPMAP_MAX_FILTER 1024 +# endif /* ! LDAPMAP_MAX_FILTER */ +# ifndef LDAPMAP_MAX_PASSWD +# define LDAPMAP_MAX_PASSWD 256 +# endif /* ! LDAPMAP_MAX_PASSWD */ + +# if LDAPMAP + +# if _FFR_LDAP_RECURSION + +/* Attribute types */ +# define SM_LDAP_ATTR_NONE (-1) +# define SM_LDAP_ATTR_OBJCLASS 0 +# define SM_LDAP_ATTR_NORMAL 1 +# define SM_LDAP_ATTR_DN 2 +# define SM_LDAP_ATTR_FILTER 3 +# define SM_LDAP_ATTR_URL 4 + +/* sm_ldap_results() flags */ +# define SM_LDAP_SINGLEMATCH 0x0001 +# define SM_LDAP_MATCHONLY 0x0002 +# define SM_LDAP_USE_ALLATTR 0x0004 + +# endif /* _FFR_LDAP_RECURSION */ + +struct sm_ldap_struct +{ + /* needed for ldap_open or ldap_init */ + char *ldap_target; + int ldap_port; +# if _FFR_LDAP_URI + bool ldap_uri; +# endif /* _FFR_LDAP_URI */ +# if _FFR_LDAP_SETVERSION + int ldap_version; +# endif /* _FFR_LDAP_SETVERSION */ + pid_t ldap_pid; + + /* options set in ld struct before ldap_bind_s */ + int ldap_deref; + time_t ldap_timelimit; + int ldap_sizelimit; + int ldap_options; + + /* args for ldap_bind_s */ + LDAP *ldap_ld; + char *ldap_binddn; + char *ldap_secret; + int ldap_method; + + /* args for ldap_search */ + char *ldap_base; + int ldap_scope; + char *ldap_filter; + char *ldap_attr[LDAPMAP_MAX_ATTR + 1]; +# if _FFR_LDAP_RECURSION + int ldap_attr_type[LDAPMAP_MAX_ATTR + 1]; + char *ldap_attr_needobjclass[LDAPMAP_MAX_ATTR + 1]; +# endif /* _FFR_LDAP_RECURSION */ + bool ldap_attrsonly; + + /* args for ldap_result */ + struct timeval ldap_timeout; + LDAPMessage *ldap_res; + + /* ldapmap_lookup options */ + char ldap_attrsep; + + /* Linked list of maps sharing the same LDAP binding */ + void *ldap_next; +}; + +typedef struct sm_ldap_struct SM_LDAP_STRUCT; + +# if _FFR_LDAP_RECURSION +struct sm_ldap_recurse_entry +{ + char *lr_search; + int lr_type; + bool lr_done; +}; + +struct sm_ldap_recurse_list +{ + int lr_size; + int lr_cnt; + struct sm_ldap_recurse_entry **lr_data; +}; + +typedef struct sm_ldap_recurse_entry SM_LDAP_RECURSE_ENTRY; +typedef struct sm_ldap_recurse_list SM_LDAP_RECURSE_LIST; +# endif /* _FFR_LDAP_RECURSION */ + +/* functions */ +extern void sm_ldap_clear __P((SM_LDAP_STRUCT *)); +extern bool sm_ldap_start __P((char *, SM_LDAP_STRUCT *)); +extern int sm_ldap_search __P((SM_LDAP_STRUCT *, char *)); +# if _FFR_LDAP_RECURSION +extern int sm_ldap_results __P((SM_LDAP_STRUCT *, int, int, int, + SM_RPOOL_T *, char **, int *, int *, + SM_LDAP_RECURSE_LIST *)); +# endif /* _FFR_LDAP_RECURSION */ +extern void sm_ldap_setopts __P((LDAP *, SM_LDAP_STRUCT *)); +extern int sm_ldap_geterrno __P((LDAP *)); +extern void sm_ldap_close __P((SM_LDAP_STRUCT *)); + +/* Portability defines */ +# if !SM_CONF_LDAP_MEMFREE +# define ldap_memfree(x) ((void) 0) +# endif /* !SM_CONF_LDAP_MEMFREE */ + +# endif /* LDAPMAP */ +#endif /* ! SM_LDAP_H */ diff --git a/gnu/dist/sendmail/include/sm/limits.h b/gnu/dist/sendmail/include/sm/limits.h new file mode 100644 index 000000000000..aaf65d27d848 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/limits.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: limits.h,v 1.6 2001/03/08 03:23:08 ca Exp + */ + +/* +** +** This header file is a portability wrapper for . +** It includes , then it ensures that the following macros +** from the C 1999 standard for are defined: +** LLONG_MIN, LLONG_MAX +** ULLONG_MAX +*/ + +#ifndef SM_LIMITS_H +# define SM_LIMITS_H + +# include +# include +# include + +/* +** The following assumes two's complement binary arithmetic. +*/ + +# ifndef LLONG_MIN +# define LLONG_MIN ((LONGLONG_T)(~(ULLONG_MAX >> 1))) +# endif /* ! LLONG_MIN */ +# ifndef LLONG_MAX +# define LLONG_MAX ((LONGLONG_T)(ULLONG_MAX >> 1)) +# endif /* ! LLONG_MAX */ +# ifndef ULLONG_MAX +# define ULLONG_MAX ((ULONGLONG_T)(-1)) +# endif /* ! ULLONG_MAX */ + +/* +** PATH_MAX is defined by the POSIX standard. All modern systems +** provide it. Older systems define MAXPATHLEN in instead. +*/ + +# ifndef PATH_MAX +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# else /* MAXPATHLEN */ +# define PATH_MAX 2048 +# endif /* MAXPATHLEN */ +# endif /* ! PATH_MAX */ + +#endif /* ! SM_LIMITS_H */ diff --git a/gnu/dist/sendmail/include/sm/mbdb.h b/gnu/dist/sendmail/include/sm/mbdb.h new file mode 100644 index 000000000000..bc38f7d52b80 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/mbdb.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: mbdb.h,v 1.6 2002/05/24 20:50:14 gshapiro Exp + */ + +#ifndef SM_MBDB_H +# define SM_MBDB_H + +#include +#include +#include + +/* +** This is an abstract interface for looking up local mail recipients. +*/ + +#define MBDB_MAXNAME 256 +#define SM_NO_UID ((uid_t)(-1)) +#define SM_NO_GID ((gid_t)(-1)) + +typedef struct +{ + uid_t mbdb_uid; + gid_t mbdb_gid; + char mbdb_name[MBDB_MAXNAME]; + char mbdb_fullname[MBDB_MAXNAME]; + char mbdb_homedir[PATH_MAX]; + char mbdb_shell[PATH_MAX]; +} SM_MBDB_T; + +extern int sm_mbdb_initialize __P((char *)); +extern void sm_mbdb_terminate __P((void)); +extern int sm_mbdb_lookup __P((char *, SM_MBDB_T *)); +extern void sm_mbdb_frompw __P((SM_MBDB_T *, struct passwd *)); +extern void sm_pwfullname __P((char *, char *, char *, size_t)); + +#endif /* ! SM_MBDB_H */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_aix.h b/gnu/dist/sendmail/include/sm/os/sm_os_aix.h new file mode 100644 index 000000000000..e27ecabff091 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_aix.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_aix.h,v 1.9 2001/10/09 23:12:13 ca Exp + */ + +/* +** sm_os_aix.h -- platform definitions for AIX +*/ + +#define SM_OS_NAME "aix" + +#ifndef SM_CONF_SHM +# define SM_CONF_SHM 1 +#endif /* SM_CONF_SHM */ +#ifndef SM_CONF_SEM +# define SM_CONF_SEM 2 +#endif /* SM_CONF_SEM */ +#ifndef SM_CONF_MSG +# define SM_CONF_MSG 1 +#endif /* SM_CONF_MSG */ + +/* AIX 3 doesn't have a prototype for syslog()? */ +#ifdef _AIX3 +# ifndef _AIX4 +# ifndef SM_CONF_SYSLOG +# define SM_CONF_SYSLOG 0 +# endif /* SM_CONF_SYSLOG */ +# endif /* ! _AIX4 */ +#endif /* _AIX3 */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_freebsd.h b/gnu/dist/sendmail/include/sm/os/sm_os_freebsd.h new file mode 100644 index 000000000000..5b9d03406acd --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_freebsd.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_freebsd.h,v 1.11 2002/04/15 17:17:05 gshapiro Exp + */ + +/* +** Platform definitions for FreeBSD +*/ + +#define SM_OS_NAME "freebsd" + +#define SM_CONF_SYS_CDEFS_H 1 + +#if __FreeBSD__ >= 2 +# include /* defines __FreeBSD_version */ +# if __FreeBSD_version >= 199512 /* 2.2-current when it appeared */ +# define MI_SOMAXCONN -1 /* listen() max backlog for milter */ +# endif /* __FreeBSD_version >= 199512 */ +# if __FreeBSD_version >= 330000 + /* 3.3.0-release and later have strlcpy()/strlcat() */ +# ifndef SM_CONF_STRL +# define SM_CONF_STRL 1 +# endif +# endif +#endif + +#ifndef SM_CONF_SHM +# define SM_CONF_SHM 1 +#endif /* SM_CONF_SHM */ +#ifndef SM_CONF_SEM +# define SM_CONF_SEM 1 +#endif /* SM_CONF_SEM */ +#ifndef SM_CONF_MSG +# define SM_CONF_MSG 1 +#endif /* SM_CONF_MSG */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_hp.h b/gnu/dist/sendmail/include/sm/os/sm_os_hp.h new file mode 100644 index 000000000000..3081427f1d6c --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_hp.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_hp.h,v 1.8 2001/10/31 15:36:56 ca Exp + */ + +/* +** sm_os_hp.h -- platform definitions for HP +*/ + +#define SM_OS_NAME "hp" + +#ifndef SM_CONF_SHM +# define SM_CONF_SHM 1 +#endif /* SM_CONF_SHM */ +#ifndef SM_CONF_SEM +# define SM_CONF_SEM 2 +#endif /* SM_CONF_SEM */ +#ifndef SM_CONF_MSG +# define SM_CONF_MSG 1 +#endif /* SM_CONF_MSG */ + +/* max/min buffer size of other than regular files */ +#ifndef SM_IO_MAX_BUF +# define SM_IO_MAX_BUF 8192 +#endif /* SM_IO_MAX_BUF */ +#ifndef SM_IO_MIN_BUF +# define SM_IO_MIN_BUF 4096 +#endif /* SM_IO_MIN_BUF */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_irix.h b/gnu/dist/sendmail/include/sm/os/sm_os_irix.h new file mode 100644 index 000000000000..ca16aac159f1 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_irix.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_irix.h,v 1.7 2001/10/09 23:12:13 ca Exp + */ + +/* +** Silicon Graphics IRIX +** +** Compiles on 4.0.1. +** +** 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 == _ABIN32 (= 2) Abi: -n32 on IRIX 6.2 +** _MIPS_SIM == _ABI64 (= 3) Abi: -64 on IRIX 6.2 +** +** _MIPS_SIM is 1 also on IRIX 5.3 +** +** IRIX64 changes from Mark R. Levinson . +** IRIX5 changes from Kari E. Hurtta . +** Adaptive changes from Kari E. Hurtta . +*/ + +#ifndef IRIX +# define IRIX +#endif /* ! IRIX */ +#if _MIPS_SIM > 0 && !defined(IRIX5) +# define IRIX5 /* IRIX5 or IRIX6 */ +#endif /* _MIPS_SIM > 0 && !defined(IRIX5) */ +#if _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64) +# define IRIX6 /* IRIX6 */ +#endif /* _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64) */ + +#define SM_OS_NAME "irix" + +#if defined(IRIX6) || defined(IRIX64) +# define SM_CONF_LONGLONG 1 +#endif /* defined(IRIX6) || defined(IRIX64) */ + +#if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# define SM_CONF_SYS_CDEFS_H 1 +#endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ + +/* try LLONG tests in libsm/t-types.c? */ +#ifndef SM_CONF_TEST_LLONG +# define SM_CONF_TEST_LLONG 0 +#endif /* !SM_CONF_TEST_LLONG */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_linux.h b/gnu/dist/sendmail/include/sm/os/sm_os_linux.h new file mode 100644 index 000000000000..9fccb6053510 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_linux.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_linux.h,v 1.12 2001/10/05 01:52:41 ca Exp + */ + +/* +** Platform definitions for Linux +*/ + +#define SM_OS_NAME "linux" + +/* to get version number */ +#include + +# 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 */ + +/* doesn't seem to work on Linux */ +#ifndef SM_CONF_SETITIMER +# define SM_CONF_SETITIMER 0 +#endif /* SM_CONF_SETITIMER */ + +#ifndef SM_CONF_SHM +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,19)) +# define SM_CONF_SHM 1 +# endif /* LINUX_VERSION_CODE */ +#endif /* SM_CONF_SHM */ + +#define SM_CONF_SYS_CDEFS_H 1 +#ifndef SM_CONF_SEM +# define SM_CONF_SEM 2 +#endif /* SM_CONF_SEM */ +#ifndef SM_CONF_MSG +# define SM_CONF_MSG 1 +#endif /* SM_CONF_MSG */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_mpeix.h b/gnu/dist/sendmail/include/sm/os/sm_os_mpeix.h new file mode 100644 index 000000000000..c3ffe929a275 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_mpeix.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_mpeix.h,v 1.2 2001/12/14 00:23:02 ca Exp + */ + +/* +** sm_os_mpeix.h -- platform definitions for HP MPE/iX +*/ + +#define SM_OS_NAME "mpeix" + +#ifndef SM_CONF_SHM +# define SM_CONF_SHM 1 +#endif /* SM_CONF_SHM */ + +#ifndef SM_CONF_SEM +# define SM_CONF_SEM 2 +#endif /* SM_CONF_SEM */ + +#ifndef SM_CONF_MSG +# define SM_CONF_MSG 1 +#endif /* SM_CONF_MSG */ + +#define SM_CONF_SETITIMER 0 + +#ifndef SM_CONF_CANT_SETRGID +# define SM_CONF_CANT_SETRGID 1 +#endif /* SM_CONF_CANT_SETRGID */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_next.h b/gnu/dist/sendmail/include/sm/os/sm_os_next.h new file mode 100644 index 000000000000..0655a2967bf3 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_next.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_next.h,v 1.7 2001/04/03 01:53:06 gshapiro Exp + */ + +/* +** Platform definitions for NeXT +*/ + +#define SM_OS_NAME "next" + +#define SM_CONF_SIGSETJMP 0 +#define SM_CONF_SSIZE_T 0 +#define SM_CONF_FORMAT_TEST 0 + +/* doesn't seem to work on NeXT 3.x */ +#define SM_DEAD(proto) proto +#define SM_UNUSED(decl) decl + +/* try LLONG tests in libsm/t-types.c? */ +#ifndef SM_CONF_TEST_LLONG +# define SM_CONF_TEST_LLONG 0 +#endif /* !SM_CONF_TEST_LLONG */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_openbsd.h b/gnu/dist/sendmail/include/sm/os/sm_os_openbsd.h new file mode 100644 index 000000000000..06bfa9843720 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_openbsd.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2000 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_openbsd.h,v 1.7 2000/12/05 19:00:47 dmoen Exp + */ + +/* +** sm_os_openbsd.h -- platform definitions for OpenBSD +** +** Note: this header file cannot be called OpenBSD.h +** because defines the macro OpenBSD. +*/ + +#define SM_OS_NAME "openbsd" + +#define SM_CONF_SYS_CDEFS_H 1 +#ifndef SM_CONF_SHM +# define SM_CONF_SHM 1 +#endif /* SM_CONF_SHM */ +#ifndef SM_CONF_SEM +# define SM_CONF_SEM 1 +#endif /* SM_CONF_SEM */ +#ifndef SM_CONF_MSG +# define SM_CONF_MSG 1 +#endif /* SM_CONF_MSG */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_openunix.h b/gnu/dist/sendmail/include/sm/os/sm_os_openunix.h new file mode 100644 index 000000000000..cc6d83d5d842 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_openunix.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_openunix.h,v 1.5 2001/11/11 16:32:00 ca Exp + */ + +#define SM_OS_NAME "openunix" + +/* needs alarm(), our sleep() otherwise hangs. */ +#define SM_CONF_SETITIMER 0 + +/* long long seems to work */ +#define SM_CONF_LONGLONG 1 + +/* don't use flock() in mail.local.c */ +#define LDA_USE_LOCKF 1 + +#ifndef SM_CONF_SHM +# define SM_CONF_SHM 1 +#endif /* SM_CONF_SHM */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_osf1.h b/gnu/dist/sendmail/include/sm/os/sm_os_osf1.h new file mode 100644 index 000000000000..d615c03723a8 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_osf1.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_osf1.h,v 1.3 2001/10/09 23:12:13 ca Exp + */ + +/* +** platform definitions for Digital UNIX +*/ + +#define SM_OS_NAME "osf1" + +#define SM_CONF_SETITIMER 0 diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_sunos.h b/gnu/dist/sendmail/include/sm/os/sm_os_sunos.h new file mode 100644 index 000000000000..76aac8a2c7bf --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_sunos.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_sunos.h,v 1.14 2001/08/14 18:09:42 ca Exp + */ + +/* +** platform definitions for SunOS 4.0.3, SunOS 4.1.x and Solaris 2.x +*/ + +#define SM_OS_NAME "sunos" + +#ifdef SOLARIS +/* +** Solaris 2.x (aka SunOS 5.x) +** M4 config file is devtools/OS/SunOS.5.x, which defines the SOLARIS macro. +*/ + +# define SM_CONF_LONGLONG 1 +# ifndef SM_CONF_SHM +# define SM_CONF_SHM 1 +# endif /* SM_CONF_SHM */ +# ifndef SM_CONF_SEM +# define SM_CONF_SEM 2 +# endif /* SM_CONF_SEM */ +# ifndef SM_CONF_MSG +# define SM_CONF_MSG 1 +# endif /* SM_CONF_MSG */ + +#else /* SOLARIS */ + +/* +** SunOS 4.0.3 or 4.1.x +*/ + +# define SM_CONF_SSIZE_T 0 +# ifndef SM_CONF_BROKEN_SIZE_T +# define SM_CONF_BROKEN_SIZE_T 1 /* size_t is signed? */ +# endif /* SM_CONF_BROKEN_SIZE_T */ + +# ifndef SM_CONF_BROKEN_STRTOD +# define SM_CONF_BROKEN_STRTOD 1 +# endif /* ! SM_CONF_BROKEN_STRTOD */ + +/* has memchr() prototype? (if not: needs memory.h) */ +# ifndef SM_CONF_MEMCHR +# define SM_CONF_MEMCHR 0 +# endif /* ! SM_CONF_MEMCHR */ + +# ifdef SUNOS403 + +/* +** SunOS 4.0.3 +** M4 config file is devtools/OS/SunOS4.0, which defines the SUNOS403 macro. +*/ + +# else /* SUNOS403 */ + +/* +** SunOS 4.1.x +** M4 config file is devtools/OS/SunOS, which defines no macros. +*/ + +# endif /* SUNOS403 */ +#endif /* SOLARIS */ diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_ultrix.h b/gnu/dist/sendmail/include/sm/os/sm_os_ultrix.h new file mode 100644 index 000000000000..e79cce684dc9 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_ultrix.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_ultrix.h,v 1.3 2001/10/09 23:12:13 ca Exp + */ + +/* +** platform definitions for Ultrix +*/ + +#define SM_OS_NAME "ultrix" + +#define SM_CONF_SSIZE_T 0 diff --git a/gnu/dist/sendmail/include/sm/os/sm_os_unixware.h b/gnu/dist/sendmail/include/sm/os/sm_os_unixware.h new file mode 100644 index 000000000000..f34c800567fc --- /dev/null +++ b/gnu/dist/sendmail/include/sm/os/sm_os_unixware.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2001, 2002 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: sm_os_unixware.h,v 1.7.2.1 2002/10/24 18:02:14 ca Exp + */ + +#define SM_OS_NAME "unixware" + +#ifndef SM_CONF_LONGLONG +# if defined(__SCO_VERSION__) && __SCO_VERSION__ > 400000000L +# define SM_CONF_LONGLONG 1 +# define SM_CONF_TEST_LLONG 1 +# define SM_CONF_BROKEN_SIZE_T 0 +# endif /* defined(__SCO_VERSION__) && __SCO_VERSION__ > 400000000L */ +#endif /* !SM_CONF_LONGLONG */ + +/* try LLONG tests in libsm/t-types.c? */ +#ifndef SM_CONF_TEST_LLONG +# define SM_CONF_TEST_LLONG 0 +#endif /* !SM_CONF_TEST_LLONG */ + +/* needs alarm(), our sleep() otherwise hangs. */ +#define SM_CONF_SETITIMER 0 + +#ifndef SM_CONF_SHM +# define SM_CONF_SHM 1 +#endif /* SM_CONF_SHM */ + +/* size_t seems to be signed */ +#ifndef SM_CONF_BROKEN_SIZE_T +# define SM_CONF_BROKEN_SIZE_T 1 +#endif /* SM_CONF_BROKEN_SIZE_T */ + +/* don't use flock() in mail.local.c */ +#ifndef LDA_USE_LOCKF +# define LDA_USE_LOCKF 1 +#endif /* LDA_USE_LOCKF */ diff --git a/gnu/dist/sendmail/include/sm/path.h b/gnu/dist/sendmail/include/sm/path.h new file mode 100644 index 000000000000..eca3299dce76 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/path.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: path.h,v 1.6 2001/04/03 01:53:00 gshapiro Exp + */ + +/* +** Portable names for standard filesystem paths +** and macros for directories. +*/ + +#ifndef SM_PATH_H +# define SM_PATH_H + +# include + +# define SM_PATH_DEVNULL "/dev/null" +# define SM_IS_DIR_DELIM(c) ((c) == '/') +# define SM_FIRST_DIR_DELIM(s) strchr(s, '/') +# define SM_LAST_DIR_DELIM(s) strrchr(s, '/') + +/* Warning: this must be accessible as array */ +# define SM_IS_DIR_START(s) ((s)[0] == '/') + +# define sm_path_isdevnull(path) (strcmp(path, "/dev/null") == 0) + +#endif /* ! SM_PATH_H */ diff --git a/gnu/dist/sendmail/include/sm/rpool.h b/gnu/dist/sendmail/include/sm/rpool.h new file mode 100644 index 000000000000..fef870f40626 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/rpool.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: rpool.h,v 1.15 2001/09/04 22:41:55 ca Exp + */ + +/* +** libsm resource pools +** See libsm/rpool.html for documentation. +*/ + +#ifndef SM_RPOOL_H +# define SM_RPOOL_H + +# include +# include +# include + +/* +** Each memory pool object consists of an SM_POOLLINK_T, +** followed by a platform specific amount of padding, +** followed by 'poolsize' bytes of pool data, +** where 'poolsize' is the value of rpool->sm_poolsize at the time +** the pool is allocated. +*/ + +typedef struct sm_poollink SM_POOLLINK_T; +struct sm_poollink +{ + SM_POOLLINK_T *sm_pnext; +}; + +typedef void (*SM_RPOOL_RFREE_T) __P((void *_rcontext)); + +typedef SM_RPOOL_RFREE_T *SM_RPOOL_ATTACH_T; + +typedef struct sm_resource SM_RESOURCE_T; +struct sm_resource +{ + /* + ** Function for freeing this resource. It may be NULL, + ** meaning that this resource has already been freed. + */ + + SM_RPOOL_RFREE_T sm_rfree; + void *sm_rcontext; /* resource data */ +}; + +# define SM_RLIST_MAX 511 + +typedef struct sm_rlist SM_RLIST_T; +struct sm_rlist +{ + SM_RESOURCE_T sm_rvec[SM_RLIST_MAX]; + SM_RLIST_T *sm_rnext; +}; + +typedef struct +{ + /* Points to SmRpoolMagic, or is NULL if rpool is freed. */ + const char *sm_magic; + + /* + ** If this rpool object has no parent, then sm_parentlink + ** is NULL. Otherwise, we set *sm_parentlink = NULL + ** when this rpool is freed, so that it isn't freed a + ** second time when the parent is freed. + */ + + SM_RPOOL_RFREE_T *sm_parentlink; + + /* + ** Memory pools + */ + + /* Size of the next pool to be allocated, not including the header. */ + size_t sm_poolsize; + + /* + ** If an sm_rpool_malloc_x request is too big to fit + ** in the current pool, and the request size > bigobjectsize, + ** then the object will be given its own malloc'ed block. + ** sm_bigobjectsize <= sm_poolsize. The maximum wasted space + ** at the end of a pool is maxpooledobjectsize - 1. + */ + + size_t sm_bigobjectsize; + + /* Points to next free byte in the current pool. */ + char *sm_poolptr; + + /* + ** Number of bytes available in the current pool. + ** Initially 0. Set to 0 by sm_rpool_free. + */ + + size_t sm_poolavail; + + /* Linked list of memory pools. Initially NULL. */ + SM_POOLLINK_T *sm_pools; + + /* + ** Resource lists + */ + + SM_RESOURCE_T *sm_rptr; /* Points to next free resource slot. */ + + /* + ** Number of available resource slots in current list. + ** Initially 0. Set to 0 by sm_rpool_free. + */ + + size_t sm_ravail; + + /* Linked list of resource lists. Initially NULL. */ + SM_RLIST_T *sm_rlists; + +#if _FFR_PERF_RPOOL + int sm_nbigblocks; + int sm_npools; +#endif /* _FFR_PERF_RPOOL */ + +} SM_RPOOL_T; + +extern SM_RPOOL_T * +sm_rpool_new_x __P(( + SM_RPOOL_T *_parent)); + +extern void +sm_rpool_free __P(( + SM_RPOOL_T *_rpool)); + +# if SM_HEAP_CHECK +extern void * +sm_rpool_malloc_tagged_x __P(( + SM_RPOOL_T *_rpool, + size_t _size, + char *_file, + int _line, + int _group)); +# define sm_rpool_malloc_x(rpool, size) \ + sm_rpool_malloc_tagged_x(rpool, size, __FILE__, __LINE__, SmHeapGroup) +extern void * +sm_rpool_malloc_tagged __P(( + SM_RPOOL_T *_rpool, + size_t _size, + char *_file, + int _line, + int _group)); +# define sm_rpool_malloc(rpool, size) \ + sm_rpool_malloc_tagged(rpool, size, __FILE__, __LINE__, SmHeapGroup) +# else /* SM_HEAP_CHECK */ +extern void * +sm_rpool_malloc_x __P(( + SM_RPOOL_T *_rpool, + size_t _size)); +extern void * +sm_rpool_malloc __P(( + SM_RPOOL_T *_rpool, + size_t _size)); +# endif /* SM_HEAP_CHECK */ + +# define sm_rpool_strdup_x(rpool, str) \ + strcpy(sm_rpool_malloc_x(rpool, strlen(str) + 1), str) + +extern SM_RPOOL_ATTACH_T +sm_rpool_attach_x __P(( + SM_RPOOL_T *_rpool, + SM_RPOOL_RFREE_T _rfree, + void *_rcontext)); + +# define sm_rpool_detach(a) ((void)(*(a) = NULL)) + +extern void +sm_rpool_setsizes __P(( + SM_RPOOL_T *_rpool, + size_t _poolsize, + size_t _bigobjectsize)); + +#endif /* ! SM_RPOOL_H */ diff --git a/gnu/dist/sendmail/include/sm/setjmp.h b/gnu/dist/sendmail/include/sm/setjmp.h new file mode 100644 index 000000000000..8303481c0469 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/setjmp.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: setjmp.h,v 1.3 2001/03/08 03:23:08 ca Exp + */ + +#ifndef SM_SETJMP_H +# define SM_SETJMP_H + +# include +# include + +/* +** sm_setjmp_sig is a setjmp that saves the signal mask. +** sm_setjmp_nosig is a setjmp that does *not* save the signal mask. +** SM_JMPBUF_T is used with both of the above macros. +** +** On most systems, these can be implemented using sigsetjmp. +** Some old BSD systems do not have sigsetjmp, but they do have +** setjmp and _setjmp, which are just as good. +*/ + +# if SM_CONF_SIGSETJMP + +typedef sigjmp_buf SM_JMPBUF_T; +# define sm_setjmp_sig(buf) sigsetjmp(buf, 1) +# define sm_setjmp_nosig(buf) sigsetjmp(buf, 0) +# define sm_longjmp_sig(buf, val) siglongjmp(buf, val) +# define sm_longjmp_nosig(buf, val) siglongjmp(buf, val) + +# else /* SM_CONF_SIGSETJMP */ + +typedef jmp_buf SM_JMPBUF_T; +# define sm_setjmp_sig(buf) setjmp(buf) +# define sm_longjmp_sig(buf, val) longjmp(buf, val) +# define sm_setjmp_nosig(buf) _setjmp(buf) +# define sm_longjmp_nosig(buf, val) _longjmp(buf, val) + +# endif /* SM_CONF_SIGSETJMP */ + +#endif /* ! SM_SETJMP_H */ diff --git a/gnu/dist/sendmail/include/sm/shm.h b/gnu/dist/sendmail/include/sm/shm.h new file mode 100644 index 000000000000..6b798fb892d5 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/shm.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: shm.h,v 1.8 2002/04/10 23:11:35 ca Exp + */ + +#ifndef SM_SHM_H +# define SM_SHM_H + +# if SM_CONF_SHM +# include +# include +# include + +/* # include "def.h" */ + +/* key for shared memory */ +# define SM_SHM_KEY ((key_t) 42) + +/* return value for failed shmget() */ +# define SM_SHM_NULL ((void *) -1) +# define SM_SHM_NO_ID (-2) + +extern void *sm_shmstart __P((key_t, int , int , int *, bool)); +extern int sm_shmstop __P((void *, int, bool)); + +/* for those braindead systems... (e.g., SunOS 4) */ +# ifndef SHM_R +# define SHM_R 0400 +# endif /* SHM_R */ +# ifndef SHM_W +# define SHM_W 0200 +# endif /* SHM_W */ + +# endif /* SM_CONF_SHM */ +#endif /* ! SM_SHM_H */ diff --git a/gnu/dist/sendmail/include/sm/signal.h b/gnu/dist/sendmail/include/sm/signal.h new file mode 100644 index 000000000000..1835e8e9ac2a --- /dev/null +++ b/gnu/dist/sendmail/include/sm/signal.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1998-2001 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. + * + * 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. + * + * Id: signal.h,v 1.16 2001/07/20 19:48:21 gshapiro Exp + */ + +/* +** SIGNAL.H -- libsm (and sendmail) signal facilities +** Extracted from sendmail/conf.h and focusing +** on signal configuration. +*/ + +#ifndef SM_SIGNAL_H +#define SM_SIGNAL_H 1 + +#include +#include +#include +#include +#include + +/* +** Critical signal sections +*/ + +#define PEND_SIGHUP 0x0001 +#define PEND_SIGINT 0x0002 +#define PEND_SIGTERM 0x0004 +#define PEND_SIGUSR1 0x0008 + +#define ENTER_CRITICAL() InCriticalSection++ + +#define LEAVE_CRITICAL() \ +do \ +{ \ + if (InCriticalSection > 0) \ + InCriticalSection--; \ +} while (0) + +#define CHECK_CRITICAL(sig) \ +do \ +{ \ + if (InCriticalSection > 0 && (sig) != 0) \ + { \ + pend_signal((sig)); \ + return SIGFUNC_RETURN; \ + } \ +} while (0) + +/* variables */ +extern unsigned int volatile InCriticalSection; /* >0 if in critical section */ +extern int volatile PendingSignal; /* pending signal to resend */ + +/* functions */ +extern void pend_signal __P((int)); + +/* reset signal in case System V semantics */ +#ifdef SYS5SIGNALS +# define FIX_SYSV_SIGNAL(sig, handler) \ +{ \ + if ((sig) != 0) \ + (void) sm_signal((sig), (handler)); \ +} +#else /* SYS5SIGNALS */ +# define FIX_SYSV_SIGNAL(sig, handler) { /* EMPTY */ } +#endif /* SYS5SIGNALS */ + +extern void sm_allsignals __P((bool)); +extern int sm_blocksignal __P((int)); +extern int sm_releasesignal __P((int)); +extern sigfunc_t sm_signal __P((int, sigfunc_t)); +extern SIGFUNC_DECL sm_signal_noop __P((int)); +#endif /* SM_SIGNAL_H */ diff --git a/gnu/dist/sendmail/include/sm/string.h b/gnu/dist/sendmail/include/sm/string.h new file mode 100644 index 000000000000..ceee0c2b3b13 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/string.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: string.h,v 1.36 2001/06/17 21:31:11 ca Exp + */ + +/* +** libsm string manipulation +*/ + +#ifndef SM_STRING_H +# define SM_STRING_H + +# include +# include +# include /* strlc{py,at}, strerror */ + +/* return number of bytes left in a buffer */ +#define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf)) + +extern int PRINTFLIKE(3, 4) +sm_snprintf __P(( + char *, + size_t, + const char *, + ...)); + +extern bool +sm_match __P(( + const char *_str, + const char *_pattern)); + +extern char * +sm_strdup __P(( + char *)); + +extern char * +sm_strndup_x __P(( + const char *_str, + size_t _len)); + +/* for "normal" data (free'd before end of process) */ +# define sm_strdup_x(str) strcpy(sm_malloc_x(strlen(str) + 1), str) + +/* for data that is supposed to be persistent. */ +# define sm_pstrdup_x(str) strcpy(sm_pmalloc_x(strlen(str) + 1), str) + +# define sm_strdup_tagged_x(str, file, line, group) \ + strcpy(sm_malloc_tagged_x(strlen(str) + 1, file, line, group), str) + +extern char * +sm_stringf_x __P(( + const char *_fmt, + ...)); + +extern char * +sm_vstringf_x __P(( + const char *_fmt, + va_list _ap)); + +extern size_t +sm_strlcpy __P(( + char *_dst, + const char *_src, + ssize_t _len)); + +extern size_t +sm_strlcat __P(( + char *_dst, + const char *_src, + ssize_t _len)); + +extern size_t +sm_strlcat2 __P(( + char *, + const char *, + const char *, + ssize_t)); + +extern size_t +#ifdef __STDC__ +sm_strlcpyn(char *dst, ssize_t len, int n, ...); +#else /* __STDC__ */ +sm_strlcpyn __P((char *, + ssize_t, + int, + va_dcl)); +#endif /* __STDC__ */ + +# if !HASSTRERROR +extern char * +strerror __P(( + int _errno)); +# endif /* !HASSTRERROR */ + +extern int +sm_strrevcmp __P(( + const char *, + const char *)); + +extern int +sm_strrevcasecmp __P(( + const char *, + const char *)); + +extern int +sm_strcasecmp __P(( + const char *, + const char *)); + +extern int +sm_strncasecmp __P(( + const char *, + const char *, + size_t)); + +extern LONGLONG_T +sm_strtoll __P(( + const char *, + char**, int)); + +extern ULONGLONG_T +sm_strtoull __P(( + const char *, + char**, int)); + +extern void +stripquotes __P((char *)); + +#endif /* SM_STRING_H */ diff --git a/gnu/dist/sendmail/include/sm/sysexits.h b/gnu/dist/sendmail/include/sm/sysexits.h new file mode 100644 index 000000000000..fca898e3d5c4 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/sysexits.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1987, 1993 + * 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. + * + * Id: sysexits.h,v 1.5 2001/03/10 17:30:01 ca Exp + * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef SM_SYSEXITS_H +# define SM_SYSEXITS_H + +# include + +/* +** SYSEXITS.H -- Exit status codes for system programs. +** +** This include file attempts to categorize possible error +** exit statuses for system programs, notably delivermail +** and the Berkeley network. +** +** Error numbers begin at EX__BASE to reduce the possibility of +** clashing with other exit statuses that random programs may +** already return. The meaning of the codes is approximately +** as follows: +** +** EX_USAGE -- The command was used incorrectly, e.g., with +** the wrong number of arguments, a bad flag, a bad +** syntax in a parameter, or whatever. +** EX_DATAERR -- The input data was incorrect in some way. +** This should only be used for user's data & not +** system files. +** EX_NOINPUT -- An input file (not a system file) did not +** exist or was not readable. This could also include +** errors like "No message" to a mailer (if it cared +** to catch it). +** EX_NOUSER -- The user specified did not exist. This might +** be used for mail addresses or remote logins. +** EX_NOHOST -- The host specified did not exist. This is used +** in mail addresses or network requests. +** EX_UNAVAILABLE -- A service is unavailable. This can occur +** if a support program or file does not exist. This +** can also be used as a catchall message when something +** you wanted to do doesn't work, but you don't know +** why. +** EX_SOFTWARE -- An internal software error has been detected. +** This should be limited to non-operating system related +** errors as possible. +** EX_OSERR -- An operating system error has been detected. +** This is intended to be used for such things as "cannot +** fork", "cannot create pipe", or the like. It includes +** things like getuid returning a user that does not +** exist in the passwd file. +** EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, +** etc.) does not exist, cannot be opened, or has some +** sort of error (e.g., syntax error). +** EX_CANTCREAT -- A (user specified) output file cannot be +** created. +** EX_IOERR -- An error occurred while doing I/O on some file. +** EX_TEMPFAIL -- temporary failure, indicating something that +** is not really an error. In sendmail, this means +** that a mailer (e.g.) could not create a connection, +** and the request should be reattempted later. +** EX_PROTOCOL -- the remote system returned something that +** was "not possible" during a protocol exchange. +** EX_NOPERM -- You did not have sufficient permission to +** perform the operation. This is not intended for +** file system problems, which should use NOINPUT or +** CANTCREAT, but rather for higher level permissions. +*/ + +# if SM_CONF_SYSEXITS_H +# include +# else /* SM_CONF_SYSEXITS_H */ + +# define EX_OK 0 /* successful termination */ + +# define EX__BASE 64 /* base value for error messages */ + +# define EX_USAGE 64 /* command line usage error */ +# define EX_DATAERR 65 /* data format error */ +# define EX_NOINPUT 66 /* cannot open input */ +# define EX_NOUSER 67 /* addressee unknown */ +# define EX_NOHOST 68 /* host name unknown */ +# define EX_UNAVAILABLE 69 /* service unavailable */ +# define EX_SOFTWARE 70 /* internal software error */ +# define EX_OSERR 71 /* system error (e.g., can't fork) */ +# define EX_OSFILE 72 /* critical OS file missing */ +# define EX_CANTCREAT 73 /* can't create (user) output file */ +# define EX_IOERR 74 /* input/output error */ +# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ +# define EX_PROTOCOL 76 /* remote error in protocol */ +# define EX_NOPERM 77 /* permission denied */ +# define EX_CONFIG 78 /* configuration error */ + +# define EX__MAX 78 /* maximum listed value */ + +# endif /* SM_CONF_SYSEXITS_H */ + +extern char *sm_strexit __P((int)); +extern char *sm_sysexitmsg __P((int)); +extern char *sm_sysexmsg __P((int)); + +#endif /* ! SM_SYSEXITS_H */ diff --git a/gnu/dist/sendmail/include/sm/test.h b/gnu/dist/sendmail/include/sm/test.h new file mode 100644 index 000000000000..cbc7f927b8e5 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/test.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: test.h,v 1.6 2001/04/03 01:53:01 gshapiro Exp + */ + +/* +** Abstractions for writing a libsm test program. +*/ + +#ifndef SM_TEST_H +# define SM_TEST_H + +# include + +# if defined(__STDC__) || defined(__cplusplus) +# define SM_TEST(cond) sm_test(cond, #cond, __FILE__, __LINE__) +# else /* defined(__STDC__) || defined(__cplusplus) */ +# define SM_TEST(cond) sm_test(cond, "cond", __FILE__, __LINE__) +# endif /* defined(__STDC__) || defined(__cplusplus) */ + +extern int SmTestIndex; +extern int SmTestNumErrors; + +extern void +sm_test_begin __P(( + int _argc, + char **_argv, + char *_testname)); + +extern bool +sm_test __P(( + bool _success, + char *_expr, + char *_filename, + int _lineno)); + +extern int +sm_test_end __P((void)); + +#endif /* ! SM_TEST_H */ diff --git a/gnu/dist/sendmail/include/sm/types.h b/gnu/dist/sendmail/include/sm/types.h new file mode 100644 index 000000000000..94615394f6a4 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/types.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: types.h,v 1.13 2001/04/03 01:53:01 gshapiro Exp + */ + +/* +** This header file defines standard integral types. +** - It includes , and fixes portability problems that +** exist on older Unix platforms. +** - It defines LONGLONG_T and ULONGLONG_T, which are portable locutions +** for 'long long' and 'unsigned long long'. +*/ + +#ifndef SM_TYPES_H +# define SM_TYPES_H + +# include + +/* +** On BSD 4.2 systems, was not idempotent. +** This problem is circumvented by replacing all occurrences +** of with , which is idempotent. +*/ + +# include + +/* +** On some old Unix platforms, some of the standard types are missing. +** We fix that here. +*/ + +# if !SM_CONF_UID_GID +# define uid_t int +# define gid_t int +# endif /* !SM_CONF_UID_GID */ + +# if !SM_CONF_SSIZE_T +# define ssize_t int +# endif /* !SM_CONF_SSIZE_T */ + +/* +** Define LONGLONG_T and ULONGLONG_T, which are portable locutions +** for 'long long' and 'unsigned long long' from the C 1999 standard. +*/ + +# if SM_CONF_LONGLONG + typedef long long LONGLONG_T; + typedef unsigned long long ULONGLONG_T; +# else /* SM_CONF_LONGLONG */ +# if SM_CONF_QUAD_T + typedef quad_t LONGLONG_T; + typedef u_quad_t ULONGLONG_T; +# else /* SM_CONF_QUAD_T */ + typedef long LONGLONG_T; + typedef unsigned long ULONGLONG_T; +# endif /* SM_CONF_QUAD_T */ +# endif /* SM_CONF_LONGLONG */ + +#endif /* ! SM_TYPES_H */ diff --git a/gnu/dist/sendmail/include/sm/varargs.h b/gnu/dist/sendmail/include/sm/varargs.h new file mode 100644 index 000000000000..056a6fea1c29 --- /dev/null +++ b/gnu/dist/sendmail/include/sm/varargs.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: varargs.h,v 1.7.2.1 2002/07/29 21:43:20 gshapiro Exp + */ + +/* +** libsm variable argument lists +*/ + +#ifndef SM_VARARGS_H +# define SM_VARARGS_H + +# if defined(__STDC__) || defined(__cplusplus) +# define SM_VA_STD 1 +# include +# define SM_VA_START(ap, f) va_start(ap, f) +# else /* defined(__STDC__) || defined(__cplusplus) */ +# define SM_VA_STD 0 +# include +# define SM_VA_START(ap, f) va_start(ap) +# endif /* defined(__STDC__) || defined(__cplusplus) */ + +# if defined(va_copy) +# define SM_VA_COPY(dst, src) va_copy((dst), (src)) +# elif defined(__va_copy) +# define SM_VA_COPY(dst, src) __va_copy((dst), (src)) +# else +# define SM_VA_COPY(dst, src) memcpy(&(dst), &(src), sizeof((dst))) +# endif + +/* +** The following macros are useless, but are provided for symmetry. +*/ + +# define SM_VA_LOCAL_DECL va_list ap; +# define SM_VA_ARG(ap, type) va_arg(ap, type) +# define SM_VA_END(ap) va_end(ap) + +#endif /* ! SM_VARARGS_H */ diff --git a/gnu/dist/sendmail/include/sm/xtrap.h b/gnu/dist/sendmail/include/sm/xtrap.h new file mode 100644 index 000000000000..e60b631106db --- /dev/null +++ b/gnu/dist/sendmail/include/sm/xtrap.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + * Id: xtrap.h,v 1.7 2001/04/03 01:53:01 gshapiro Exp + */ + +/* +** scaffolding for testing exception handler code +*/ + +#ifndef SM_XTRAP_H +# define SM_XTRAP_H + +# include +# include + +extern SM_ATOMIC_UINT_T SmXtrapCount; +extern SM_DEBUG_T SmXtrapDebug; +extern SM_DEBUG_T SmXtrapReport; + +# if SM_DEBUG_CHECK +# define sm_xtrap_check() (++SmXtrapCount == sm_debug_level(&SmXtrapDebug)) +# else /* SM_DEBUG_CHECK */ +# define sm_xtrap_check() (0) +# endif /* SM_DEBUG_CHECK */ + +# define sm_xtrap_raise_x(exc) \ + if (sm_xtrap_check()) \ + { \ + sm_exc_raise_x(exc); \ + } else + +#endif /* ! SM_XTRAP_H */ diff --git a/gnu/dist/sendmail/libmilter/Makefile.m4 b/gnu/dist/sendmail/libmilter/Makefile.m4 index 19381a48f96c..d2e7566dfdb5 100644 --- a/gnu/dist/sendmail/libmilter/Makefile.m4 +++ b/gnu/dist/sendmail/libmilter/Makefile.m4 @@ -1,5 +1,8 @@ +dnl Id: Makefile.m4,v 8.30.2.1 2002/06/21 21:58:28 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +dnl only required for compilation of EXTRAS +define(`confREQUIRE_LIBSM', `true') define(`confMT', `true') # sendmail dir @@ -8,17 +11,30 @@ PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`library', `libmilter') define(`bldINSTALLABLE', `true') -define(`bldSOURCES', `main.c engine.c listener.c handler.c comm.c smfi.c signal.c sm_gethost.c ') -bldPUSH_SMLIB(`smutil') +define(`LIBMILTER_EXTRAS', `errstring.c strl.c') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL -Dsm_snprintf=snprintf') +define(`bldSOURCES', `main.c engine.c listener.c handler.c comm.c smfi.c signal.c sm_gethost.c LIBMILTER_EXTRAS ') +define(`confBEFORE', `LIBMILTER_EXTRAS') bldPUSH_INSTALL_TARGET(`install-mfapi') bldPRODUCT_END -APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') + +PUSHDIVERT(3) +errstring.c: + ${LN} ${LNOPTS} ${SRCDIR}/libsm/errstring.c . + +strl.c: + ${LN} ${LNOPTS} ${SRCDIR}/libsm/strl.c . +POPDIVERT + divert(bldTARGETS_SECTION) -# Install the API header file +# Install the API header files MFAPI= ${SRCDIR}/inc`'lude/libmilter/mfapi.h +MFDEF= ${SRCDIR}/inc`'lude/libmilter/mfdef.h install-mfapi: ${MFAPI} - ${INSTALL} -c -o ${INCOWN} -g ${INCGRP} -m ${INCMODE} ${MFAPI} ${DESTDIR}${INCLUDEDIR} + if [ ! -d ${DESTDIR}${INCLUDEDIR}/libmilter ]; then mkdir -p ${DESTDIR}${INCLUDEDIR}/libmilter; else :; fi + ${INSTALL} -c -o ${INCOWN} -g ${INCGRP} -m ${INCMODE} ${MFAPI} ${DESTDIR}${INCLUDEDIR}/libmilter/mfapi.h + ${INSTALL} -c -o ${INCOWN} -g ${INCGRP} -m ${INCMODE} ${MFDEF} ${DESTDIR}${INCLUDEDIR}/libmilter/mfdef.h divert(0) bldFINISH diff --git a/gnu/dist/sendmail/libmilter/docs/api.html b/gnu/dist/sendmail/libmilter/docs/api.html new file mode 100644 index 000000000000..af714efd3097 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/api.html @@ -0,0 +1,194 @@ + +Milter API + +

Milter API

+ +

Contents

+
    +
  • Library Control Functions +
  • Data Access Functions +
  • Message Modification Functions +
  • Callbacks +
+ +

Library Control Functions

+ +Before handing control to libmilter (by calling smfi_main), a filter may call the following +functions to set libmilter parameters. In particular, the filter must +call smfi_register to register its +callbacks. Each function will return either MI_SUCCESS or MI_FAILURE to +indicate the status of the operation. +

+None of these functions communicate with the MTA. All alter the +library's state, some of which is communicated to the MTA inside smfi_main. +

+ + + + + + + + + + +
FunctionDescription
smfi_registerRegister a filter.
smfi_setconnSpecify socket to use.
smfi_settimeoutSet timeout.
smfi_mainHand control to libmilter.
+ +

Data Access Functions

+ +The following functions may be called from within the filter-defined callbacks +to access information about the current connection or message. +

+ + + + + + + + + +
FunctionDescription
smfi_getsymvalReturn the value +of a symbol.
smfi_getprivGet the private data +pointer.
smfi_setprivSet the private data +pointer.
smfi_setreplySet the specific +reply code to be used.
+ +

Message Modification Functions

+ +The following functions change a message's contents and attributes. +They may only be called in xxfi_eom. +All of these functions may invoke additional communication with the MTA. +They will return either MI_SUCCESS or MI_FAILURE to indicate the status of +the operation. + +

+A filter must have set the appropriate flag (listed below) in the +description passed to smfi_register +to call any message modification function. Failure to do so will +cause the MTA to treat a call to the function as a failure of the +filter, terminating its connection. + +

+Note that the status returned indicates only whether or not the +filter's message was successfully sent to the MTA, not whether or not +the MTA performed the requested operation. For example, smfi_addheader, when called with an +illegal header name, will return MI_SUCCESS even though the MTA may +later refuse to add the illegal header. +

+ + + + + + + + + + + +
FunctionDescriptionSMFIF_* flag
smfi_addheaderAdd a header to +the message.SMFIF_ADDHDRS
smfi_chgheaderChange or delete a header.SMFIF_CHGHDRS
smfi_addrcptAdd a recipient to +the envelope.SMFIF_ADDRCPT
smfi_delrcptDelete a recipient +from the envelope.SMFIF_DELRCPT
smfi_replacebodyReplace the +body of the message.SMFIF_CHGBODY
+ +

Callbacks

+ +The filter should implement one or more of the following callbacks, +which are registered via smfi_register: +

+ + + + + + + + + + + + + + + + + + + + + + +
FunctionDescription
xxfi_connectconnection info
xxfi_heloSMTP HELO/EHLO command
xxfi_envfromenvelope sender
xxfi_envrcptenvelope recipient
xxfi_headerheader
xxfi_eohend of header
xxfi_bodybody block
xxfi_eomend of message
xxfi_abortmessage aborted
xxfi_closeconnection cleanup
+ +

+The above callbacks should all return one of the following return values, +having the indicated meanings. Any return other than one of the below +values constitutes an error, and will cause sendmail to terminate its +connection to the offending filter. + +

Milter distinguishes between recipient-, +message-, and connection-oriented routines. Recipient-oriented +callbacks may affect the processing of a single message recipient; +message-oriented callbacks, a single message; connection-oriented +callbacks, an entire connection (during which multiple messages may be +delivered to multiple sets of recipients). +xxfi_envrcpt is recipient-oriented. +xxfi_connect, +xxfi_helo and +xxfi_close are connection-oriented. All +other callbacks are message-oriented. + +

+ + + + + + + + + + + + + + + + + + + + + + +
Return valueDescription
SMFIS_CONTINUEContinue processing the current connection, message, or recipient. +
SMFIS_REJECTFor a connection-oriented routine, reject this connection; call xxfi_close.
+ For a message-oriented routine (except + xxfi_eom or + xxfi_abort), reject this message.
+ For a recipient-oriented routine, reject the current recipient (but continue processing the current message). +
SMFIS_DISCARDFor a message- or recipient-oriented routine, accept this message, but silently discard it.
+ SMFIS_DISCARD should not be returned by a connection-oriented routine. +
SMFIS_ACCEPTFor a connection-oriented routine, accept this connection without further filter processing; call xxfi_close.
+ For a message- or recipient-oriented routine, accept this message without further filtering.
+
SMFIS_TEMPFAILReturn a temporary failure, i.e., the corresponding SMTP command will return an appropriate 4xx status code. + For a message-oriented routine (except xxfi_envfrom), fail for this message.
+ For a connection-oriented routine, fail for this connection; call xxfi_close.
+ For a recipient-oriented routine, only fail for the current recipient; continue message processing. +
+ +


+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/design.html b/gnu/dist/sendmail/libmilter/docs/design.html new file mode 100644 index 000000000000..fbc74e65fd2a --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/design.html @@ -0,0 +1,144 @@ + + +Architecture + + + +

Architecture

+ +

Contents

+ +
    +
  • Design Goals +
  • Implementing Filtering Policies +
  • MTA - Filter Communication +
+ +

Goals

+ +The Sendmail Content Management API (Milter) provides an interface for +third-party software to validate and modify messages as they pass +through the mail transport system. Filters can process messages' +connection (IP) information, envelope protocol elements, message +headers, and/or message body contents, and modify a message's +recipients, headers, and body. The MTA configuration file specifies +which filters are to be applied, and in what order, allowing an +administrator to combine multiple independently-developed filters. + +

+We expect to see both vendor-supplied, configurable mail filtering +applications and a multiplicity of script-like filters designed by and +for MTA administrators. A certain degree of coding sophistication and +domain knowledge on the part of the filter provider is assumed. This +allows filters to exercise fine-grained control at the SMTP level. +However, as will be seen in the example, many filtering applications +can be written with relatively little protocol knowledge. + +

+Given these expectations, the API is designed to achieve the following +goals: + +

    +
  1. Safety/security. + Filter processes should not need to run as root + (of course, they can if required, but that is a local issue); + this will simplify coding + and limit the impact of security flaws in the filter program. +

    +

  2. Reliability. + Coding failures in a Milter process that cause that process + to hang or core-dump + should not stop mail delivery. + Faced with such a failure, + sendmail should use a default mechanism, + either behaving as if the filter were not present + or as if a required resource were unavailable. + The latter failure mode will generally have sendmail return + a 4xx SMTP code (although in later phases of the SMTP protocol + it may cause the mail to be queued for later processing). +

    +

  3. Simplicity. + The API should make implementation of a new filter + no more difficult than absolutely necessary. + Subgoals include: +
      +
    • Encourage good thread practice + by defining thread-clean interfaces including local data hooks. +
    • Provide all interfaces required + while avoiding unnecessary pedanticism. +
    +

    +

  4. Performance. + Simple filters should not seriously impact overall MTA performance. +
+ +

Implementing Filtering Policies

+ +Milter is designed to allow a server administrator to combine +third-party filters to implement a desired mail filtering policy. For +example, if a site wished to scan incoming mail for viruses on several +platforms, eliminate unsolicited commercial email, and append a mandated +footer to selected incoming messages, the administrator could configure +the MTA to filter messages first through a server based anti-virus +engine, then via a large-scale spam-catching service, and finally +append the desired footer if the message still met requisite criteria. +Any of these filters could be added or changed independently. + +

+Thus the site administrator, not the filter writer, controls the +overall mail filtering environment. In particular, he/she must decide +which filters are run, in what order they are run, and how they +communicate with the MTA. These parameters, as well as the +actions to be taken if a filter becomes unavailable, are selectable +during MTA configuration. Further +details are available later in this document. + +

MTA - Filter communication

+ +Filters run as separate processes, outside of the sendmail address +space. The benefits of this are threefold: + +
    +
  1. The filter need not run with "root" permissions, thereby + avoiding a large family of potential security problems.
  2. + +
  3. Failures in a particular filter will not affect the MTA or + other filters.
  4. + +
  5. The filter can potentially have higher performance because of + the parallelism inherent in multiple processes.
  6. +
+ +

+Each filter may communicate with multiple MTAs at the same time over +local or remote connections, using multiple threads of execution. Figure 1 illustrates a possible network of +communication channels between a site's filters, its MTAs, and other +MTAs on the network: +

+
+
+Figure 1: A set of MTA's interacting with a set of filters. +
+

+The Milter library (libmilter) implements the communication protocol. +It accepts connections from various MTAs, passes the relevant data to +the filter through callbacks, then makes appropriate responses based +on return codes. A filter may also send data to the MTA as a result +of library calls. Figure 2 shows a single +filter process processing messages from two MTAs: +

+
+
+Figure 2: A filter handling simultaneous requests from two MTA's. +
+
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/figure1.fig b/gnu/dist/sendmail/libmilter/docs/figure1.fig new file mode 100644 index 000000000000..e0cbdc8e8aa2 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/figure1.fig @@ -0,0 +1,56 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 975 225 5025 3375 +6 1500 1275 2700 2025 +2 2 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 5 + 1650 1425 2550 1425 2550 1875 1650 1875 1650 1425 +4 0 1 50 0 0 20 0.0000 4 195 645 1800 1725 MTA\001 +-6 +6 1950 2625 3150 3375 +2 2 0 2 4 7 50 0 -1 0.000 0 0 7 0 0 5 + 2100 2775 3000 2775 3000 3225 2100 3225 2100 2775 +4 0 4 50 0 0 20 0.0000 4 195 645 2250 3075 MTA\001 +-6 +6 1050 225 2250 975 +2 2 0 2 14 7 50 0 -1 0.000 0 0 7 0 0 5 + 1200 375 2100 375 2100 825 1200 825 1200 375 +4 0 14 50 0 0 20 0.0000 4 195 645 1350 675 MTA\001 +-6 +2 1 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 2 + 2550 1575 3750 2625 +2 1 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 2 + 2550 1575 3750 1575 +2 1 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 2 + 2550 1575 3750 825 +2 1 0 2 4 7 50 0 -1 0.000 0 0 7 0 0 2 + 3000 2925 3750 2625 +2 1 0 2 14 7 50 0 -1 0.000 0 0 7 0 0 2 + 2100 525 3750 825 +2 1 0 2 14 7 50 0 -1 0.000 0 0 7 0 0 2 + 2100 525 3750 2625 +2 1 0 4 0 7 50 0 -1 0.000 0 0 7 0 0 2 + 1050 3075 2100 3075 +2 1 0 4 0 7 50 0 -1 0.000 0 0 7 0 0 2 + 1050 1725 1650 1725 +2 1 0 4 0 7 50 0 -1 0.000 0 0 7 0 0 2 + 1050 675 1200 675 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3750 2475 4950 2475 4950 2925 3750 2925 3750 2475 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3750 1425 4950 1425 4950 1875 3750 1875 3750 1425 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3750 525 4950 525 4950 975 3750 975 3750 525 +4 0 0 50 0 1 20 0.0000 4 210 795 3900 2775 Filter 3\001 +4 0 0 50 0 1 20 0.0000 4 210 795 3900 1725 Filter 2\001 +4 0 0 50 0 1 20 0.0000 4 210 795 3900 825 Filter 1\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 300 525 1050 525 1050 3225 300 3225 300 525 +4 0 0 50 0 2 24 1.5708 4 255 1950 825 2850 INTERNET\001 diff --git a/gnu/dist/sendmail/libmilter/docs/figure1.jpg b/gnu/dist/sendmail/libmilter/docs/figure1.jpg new file mode 100644 index 000000000000..1a5f1dec386a Binary files /dev/null and b/gnu/dist/sendmail/libmilter/docs/figure1.jpg differ diff --git a/gnu/dist/sendmail/libmilter/docs/figure1.ps b/gnu/dist/sendmail/libmilter/docs/figure1.ps new file mode 100644 index 000000000000..ae317607e4d2 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/figure1.ps @@ -0,0 +1,173 @@ +%!PS-Adobe-2.0 +%%Title: figure1.fig +%%Creator: fig2dev Version 3.2.3 Patchlevel +%%CreationDate: Tue Jun 6 14:00:04 2000 +%%For: sean@host232.Sendmail.COM (Sean O'rourke,5400) +%%Orientation: Landscape +%%Pages: 1 +%%BoundingBox: 0 0 612 792 +%%BeginSetup +%%IncludeFeature: *PageSize Letter +%%EndSetup +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 792 moveto 0 0 lineto 612 0 lineto 612 792 lineto closepath clip newpath +198.0 238.0 translate + 90 rotate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +%%Page: 1 1 +10 setmiterlimit + 0.06000 0.06000 sc +%%Page: 1 1 +/Times-Bold ff 360.00 scf sf +825 2850 m +gs 1 -1 sc 90.0 rot (INTERNET) col0 sh gr +/Times-Roman ff 300.00 scf sf +1800 1725 m +gs 1 -1 sc (MTA) col1 sh gr +% Polyline +15.000 slw +n 2100 2775 m 3000 2775 l 3000 3225 l 2100 3225 l + cp gs col4 s gr +/Times-Roman ff 300.00 scf sf +2250 3075 m +gs 1 -1 sc (MTA) col4 sh gr +% Polyline +n 1200 375 m 2100 375 l 2100 825 l 1200 825 l + cp gs col14 s gr +/Times-Roman ff 300.00 scf sf +1350 675 m +gs 1 -1 sc (MTA) col14 sh gr +% Polyline +n 2550 1575 m + 3750 2625 l gs col1 s gr +% Polyline +n 2550 1575 m + 3750 1575 l gs col1 s gr +% Polyline +n 2550 1575 m + 3750 825 l gs col1 s gr +% Polyline +n 3000 2925 m + 3750 2625 l gs col4 s gr +% Polyline +n 2100 525 m + 3750 825 l gs col14 s gr +% Polyline +n 2100 525 m + 3750 2625 l gs col14 s gr +% Polyline +45.000 slw +n 1050 3075 m + 2100 3075 l gs col0 s gr +% Polyline +n 1050 1725 m + 1650 1725 l gs col0 s gr +% Polyline +n 1050 675 m + 1200 675 l gs col0 s gr +% Polyline +15.000 slw +n 3750 2475 m 4950 2475 l 4950 2925 l 3750 2925 l + cp gs col0 s gr +% Polyline +n 3750 1425 m 4950 1425 l 4950 1875 l 3750 1875 l + cp gs col0 s gr +% Polyline +n 3750 525 m 4950 525 l 4950 975 l 3750 975 l + cp gs col0 s gr +/Times-Italic ff 300.00 scf sf +3900 2775 m +gs 1 -1 sc (Filter 3) col0 sh gr +/Times-Italic ff 300.00 scf sf +3900 1725 m +gs 1 -1 sc (Filter 2) col0 sh gr +/Times-Italic ff 300.00 scf sf +3900 825 m +gs 1 -1 sc (Filter 1) col0 sh gr +% Polyline +7.500 slw +n 300 525 m 1050 525 l 1050 3225 l 300 3225 l + cp gs col0 s gr +% Polyline +15.000 slw +n 1650 1425 m 2550 1425 l 2550 1875 l 1650 1875 l + cp gs col1 s gr +$F2psEnd +rs +showpage diff --git a/gnu/dist/sendmail/libmilter/docs/figure2.fig b/gnu/dist/sendmail/libmilter/docs/figure2.fig new file mode 100644 index 000000000000..c93bfe3d5e58 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/figure2.fig @@ -0,0 +1,67 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +5 1 0 1 0 7 50 0 -1 0.000 0 0 1 0 2981.250 1200.000 2700 1050 3300 1200 2700 1350 + 1 1 1.00 60.00 120.00 +6 4200 900 6450 1350 +2 2 0 1 1 7 50 0 -1 0.000 0 0 7 0 0 5 + 4200 900 6450 900 6450 1350 4200 1350 4200 900 +4 0 1 50 0 0 16 0.0000 4 195 2040 4350 1200 xxfi_header callback\001 +-6 +6 4200 2250 6450 2700 +2 2 0 1 4 7 50 0 -1 0.000 0 0 7 0 0 5 + 4200 2250 6450 2250 6450 2700 4200 2700 4200 2250 +4 0 4 50 0 0 16 0.0000 4 195 2040 4350 2550 xxfi_header callback\001 +-6 +6 600 2100 1800 2850 +2 2 0 2 4 7 50 0 -1 0.000 0 0 7 0 0 5 + 750 2250 1650 2250 1650 2700 750 2700 750 2250 +4 0 4 50 0 0 20 0.0000 4 195 645 900 2550 MTA\001 +-6 +6 600 750 1800 1500 +2 2 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 5 + 750 900 1650 900 1650 1350 750 1350 750 900 +4 0 1 50 0 0 20 0.0000 4 195 645 900 1200 MTA\001 +-6 +2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4200 1200 3600 1200 +2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 3450 900 4050 900 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2400 300 6600 300 6600 3300 2400 3300 2400 300 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2550 750 3450 750 3450 2700 2550 2700 2550 750 +2 1 0 2 4 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 3450 2700 4050 2700 +2 1 0 2 4 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4200 2400 3600 2400 +2 1 0 2 4 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 1650 2700 2250 2700 +2 1 0 2 4 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 2400 2400 1800 2400 +2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 1650 900 2250 900 +2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 2400 1200 1800 1200 +4 0 0 50 0 0 20 0.0000 4 195 630 3900 600 Filter\001 +4 0 4 50 0 0 12 0.0000 4 180 1620 3450 3000 callback (arguments)\001 +4 0 4 50 0 0 12 0.0000 4 180 1575 3900 1950 optional library calls,\001 +4 0 4 50 0 0 12 0.0000 4 135 855 3900 2175 return code\001 +4 0 4 50 0 0 12 0.0000 4 135 780 1500 2100 responses\001 +4 0 0 50 0 0 16 0.0000 4 165 645 2700 2085 Milter\001 +4 0 0 50 0 0 16 0.0000 4 225 675 2700 2400 library\001 +4 0 4 50 0 0 12 0.0000 4 135 510 1500 3000 header\001 diff --git a/gnu/dist/sendmail/libmilter/docs/figure2.jpg b/gnu/dist/sendmail/libmilter/docs/figure2.jpg new file mode 100644 index 000000000000..8b11485cde9d Binary files /dev/null and b/gnu/dist/sendmail/libmilter/docs/figure2.jpg differ diff --git a/gnu/dist/sendmail/libmilter/docs/figure2.ps b/gnu/dist/sendmail/libmilter/docs/figure2.ps new file mode 100644 index 000000000000..861a193c6f0a --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/figure2.ps @@ -0,0 +1,242 @@ +%!PS-Adobe-2.0 +%%Title: figure2.fig +%%Creator: fig2dev Version 3.2.3 Patchlevel +%%CreationDate: Tue Jun 6 13:57:47 2000 +%%For: sean@host232.Sendmail.COM (Sean O'rourke,5400) +%%Orientation: Landscape +%%Pages: 1 +%%BoundingBox: 0 0 612 792 +%%BeginSetup +%%IncludeFeature: *PageSize Letter +%%EndSetup +%%Magnification: 1.5000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 792 moveto 0 0 lineto 612 0 lineto 612 792 lineto closepath clip newpath +144.0 65.5 translate + 90 rotate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +%%Page: 1 1 +10 setmiterlimit + 0.09000 0.09000 sc +%%Page: 1 1 +/Times-Roman ff 180.00 scf sf +1500 3000 m +gs 1 -1 sc (header) col4 sh gr +/Times-Roman ff 240.00 scf sf +4350 1200 m +gs 1 -1 sc (xxfi_header callback) col1 sh gr +% Polyline +7.500 slw +n 4200 2250 m 6450 2250 l 6450 2700 l 4200 2700 l + cp gs col4 s gr +/Times-Roman ff 240.00 scf sf +4350 2550 m +gs 1 -1 sc (xxfi_header callback) col4 sh gr +% Polyline +15.000 slw +n 750 2250 m 1650 2250 l 1650 2700 l 750 2700 l + cp gs col4 s gr +/Times-Roman ff 300.00 scf sf +900 2550 m +gs 1 -1 sc (MTA) col4 sh gr +% Polyline +n 750 900 m 1650 900 l 1650 1350 l 750 1350 l + cp gs col1 s gr +/Times-Roman ff 300.00 scf sf +900 1200 m +gs 1 -1 sc (MTA) col1 sh gr +% Arc +7.500 slw +gs clippath +2713 1319 m 2667 1357 l 2761 1475 l 2710 1363 l 2808 1437 l cp +eoclip +n 2981.2 1200.0 318.8 -151.9 151.9 arc +gs col0 s gr + gr + +% arrowhead +n 2808 1437 m 2710 1363 l 2761 1475 l 2808 1437 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +3585 1140 m 3585 1260 l 3872 1260 l 3632 1200 l 3872 1140 l cp +eoclip +n 4200 1200 m + 3600 1200 l gs col1 s gr gr + +% arrowhead +n 3872 1140 m 3632 1200 l 3872 1260 l 3872 1140 l cp gs col1 1.00 shd ef gr col1 s +% Polyline +gs clippath +4065 960 m 4065 840 l 3778 840 l 4018 900 l 3778 960 l cp +eoclip +n 3450 900 m + 4050 900 l gs col1 s gr gr + +% arrowhead +n 3778 960 m 4018 900 l 3778 840 l 3778 960 l cp gs col1 1.00 shd ef gr col1 s +% Polyline +n 2400 300 m 6600 300 l 6600 3300 l 2400 3300 l + cp gs col0 s gr +% Polyline +7.500 slw +n 2550 750 m 3450 750 l 3450 2700 l 2550 2700 l + cp gs col0 s gr +% Polyline +15.000 slw +gs clippath +4065 2760 m 4065 2640 l 3778 2640 l 4018 2700 l 3778 2760 l cp +eoclip +n 3450 2700 m + 4050 2700 l gs col4 s gr gr + +% arrowhead +n 3778 2760 m 4018 2700 l 3778 2640 l 3778 2760 l cp gs col4 1.00 shd ef gr col4 s +% Polyline +gs clippath +3585 2340 m 3585 2460 l 3872 2460 l 3632 2400 l 3872 2340 l cp +eoclip +n 4200 2400 m + 3600 2400 l gs col4 s gr gr + +% arrowhead +n 3872 2340 m 3632 2400 l 3872 2460 l 3872 2340 l cp gs col4 1.00 shd ef gr col4 s +% Polyline +gs clippath +2265 2760 m 2265 2640 l 1978 2640 l 2218 2700 l 1978 2760 l cp +eoclip +n 1650 2700 m + 2250 2700 l gs col4 s gr gr + +% arrowhead +n 1978 2760 m 2218 2700 l 1978 2640 l 1978 2760 l cp gs col4 1.00 shd ef gr col4 s +% Polyline +gs clippath +1785 2340 m 1785 2460 l 2072 2460 l 1832 2400 l 2072 2340 l cp +eoclip +n 2400 2400 m + 1800 2400 l gs col4 s gr gr + +% arrowhead +n 2072 2340 m 1832 2400 l 2072 2460 l 2072 2340 l cp gs col4 1.00 shd ef gr col4 s +% Polyline +gs clippath +2265 960 m 2265 840 l 1978 840 l 2218 900 l 1978 960 l cp +eoclip +n 1650 900 m + 2250 900 l gs col1 s gr gr + +% arrowhead +n 1978 960 m 2218 900 l 1978 840 l 1978 960 l cp gs col1 1.00 shd ef gr col1 s +% Polyline +gs clippath +1785 1140 m 1785 1260 l 2072 1260 l 1832 1200 l 2072 1140 l cp +eoclip +n 2400 1200 m + 1800 1200 l gs col1 s gr gr + +% arrowhead +n 2072 1140 m 1832 1200 l 2072 1260 l 2072 1140 l cp gs col1 1.00 shd ef gr col1 s +/Times-Roman ff 300.00 scf sf +3900 600 m +gs 1 -1 sc (Filter) col0 sh gr +/Times-Roman ff 180.00 scf sf +3450 3000 m +gs 1 -1 sc (callback \(arguments\)) col4 sh gr +/Times-Roman ff 180.00 scf sf +3900 1950 m +gs 1 -1 sc (optional library calls,) col4 sh gr +/Times-Roman ff 180.00 scf sf +3900 2175 m +gs 1 -1 sc (return code) col4 sh gr +/Times-Roman ff 180.00 scf sf +1500 2100 m +gs 1 -1 sc (responses) col4 sh gr +/Times-Roman ff 240.00 scf sf +2700 2085 m +gs 1 -1 sc (Milter) col0 sh gr +/Times-Roman ff 240.00 scf sf +2700 2400 m +gs 1 -1 sc (library) col0 sh gr +% Polyline +7.500 slw +n 4200 900 m 6450 900 l 6450 1350 l 4200 1350 l + cp gs col1 s gr +$F2psEnd +rs +showpage diff --git a/gnu/dist/sendmail/libmilter/docs/index.html b/gnu/dist/sendmail/libmilter/docs/index.html new file mode 100644 index 000000000000..a6b11dde359d --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/index.html @@ -0,0 +1,92 @@ + + +Filtering Mail with Sendmail + + + + +

Filtering Mail with Sendmail

+ + + +

Introduction

+ +

+Sendmail's Content Management API (milter) provides third-party +programs to access mail messages as they are being processed by the +Mail Transfer Agent (MTA), allowing them to examine and modify message +content and meta-information. Filtering policies implemented by +Milter-conformant filters may then be centrally configured and +composed in an end-user's MTA configuration file. + +

+Possible uses for filters include spam rejection, virus +filtering, and content control. In general, Milter seeks to address +site-wide filtering concerns in a scalable way. Individual users' mail +filtering needs (e.g. sorting messages by subject) are left to +client-level programs such as Procmail. + +

+This document is a technical introduction intended for those +interested in developing Milter filters. It includes: +

    +
  • A description of Milter's design goals. + +
  • An explanation of Milter application architecture, including +interactions between the support library and user code, and between +filters and the MTA. + +
  • A specification of the C application programming interface. +
  • An example of a simple Milter filter. +
+ +

Contents

+ + + +
+ +Copyright (c) 2000, 2001 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/installation.html b/gnu/dist/sendmail/libmilter/docs/installation.html new file mode 100644 index 000000000000..8ce8611e6d09 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/installation.html @@ -0,0 +1,170 @@ + +Installation and Configuration + + +

Installation

+

Contents

+ + +

Compiling and Installing Your Filter

+ +To compile a filter, modify the Makefile provided with the sample program, or: +
    +
  • Put the include and Sendmail directories in your include path + (e.g. -I/path/to/include -I/path/to/sendmail). + +
  • Make sure libmilter.so is in your library path, and link your + application with it (e.g. "-lmilter"). + +
  • Compile with pthreads, either by using -pthread for gcc, or + linking with a pthreads support library (-lpthread). +
+Your compile command line will look like +
+cc -I/path/to/include -I/path/to/sendmail -c myfile.c
+
+and your linking command line will look something like +
+cc -o myfilter [object-files] -L[library-location] -lmilter -pthread
+
+ +

+To run the filter, the Milter shared library must be available to the +run-time linker. + +

Configuring Sendmail

+ +First, you must compile sendmail with MILTER defined. +If you use a sendmail version older than 8.12 please see +the instructions for your version. +To do this, add the following lines to your build +configuration file (devtools/Site/config.site.m4) +
+APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER')
+
+ +then type ./Build -c in your sendmail directory. + +

+Next, you must add the desired filters to your sendmail configuration +(.mc) file. +Mail filters have three equates: +The required S= equate specifies the socket where +sendmail should look for the filter; The optional F= and +T= equates specify flags and timeouts, respectively. All +equates names, equate field names, and flag values are case sensitive. + +

+The current flags (F=) are: +

+ + + + + + + + + + +
Flag Meaning
R Reject connection if filter unavailable
T Temporary fail connection if filter unavailable
+ +If a filter is unavailable or unresponsive and no flags have been +specified, the MTA will continue normal handling of the current +connection. The MTA will try to contact the filter again on each new +connection. + +

+There are three fields inside of the T= equate: S, R, and +E. Note the separator between each is a ";" (semicolon), as "," +(comma) already separates equates. The value of each field is a +decimal number followed by a single letter designating the units ("s" +for seconds, "m" for minutes). The fields have the following +meanings: +

+ + + + + + + + + + + + + + + + +
Flag Meaning
C Timeout for connecting to a filter. If set to 0, the + system's connect() timeout will be used. + Default: 5m
S Timeout for sending information from the MTA to a + filter. Default: 10s
R Timeout for reading reply from the filter. Default: 10s
E Overall timeout between sending end-of-message to + filter and waiting for the final acknowledgment. Default: 5m
+ +

+The following sendmail.mc example specifies three filters. The first +two rendezvous on Unix-domain sockets in the /var/run directory; the +third uses an IP socket on port 999. +

+	INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/f1.sock, F=R')
+	INPUT_MAIL_FILTER(`filter2', `S=unix:/var/run/f2.sock, F=T, T=S:1s;R:1s;E:5m')
+	INPUT_MAIL_FILTER(`filter3', `S=inet:999@localhost, T=C:2m')
+
+	define(`confINPUT_MAIL_FILTERS', `filter2,filter1,filter3')
+
+ m4 ../m4/cf.m4 myconfig.mc > myconfig.cf +
+By default, the filters would be run in the order declared, +i.e. "filter1, filter2, filter3"; however, since +confINPUT_MAIL_FILTERS is defined, the filters will be +run "filter2, filter1, filter3". Also note that a filter can be +defined without adding it to the input filter list by using +MAIL_FILTER() instead of INPUT_MAIL_FILTER(). + +

+The above macros will result in the following lines being added to +your .cf file: +

+        Xfilter1, S=unix:/var/run/f1.sock, F=R
+        Xfilter2, S=unix:/var/run/f2.sock, F=T, T=S:1s;R:1s;E:5m
+        Xfilter3, S=inet:999@localhost, T=C:2m
+
+        O InputMailFilters=filter2,filter1,filter3
+
+

+Finally, the sendmail macros accessible via smfi_getsymval can be configured by +defining the following m4 variables (or cf options): + + + + + + + + + + + + + +
In .mc file In .cf fileDefault Value
confMILTER_MACROS_CONNECTMilter.macros.connectj, _, {daemon_name}, {if_name}, {if_addr}
confMILTER_MACROS_HELOMilter.macros.helo{tls_version}, {cipher}, {cipher_bits}, {cert_subject}, +{cert_issuer}
confMILTER_MACROS_ENVFROMMilter.macros.envfromi, {auth_type}, {auth_authen}, {auth_ssf}, {auth_author}, +{mail_mailer}, {mail_host}, {mail_addr}
confMILTER_MACROS_ENVRCPTMilter.macros.envrcpt{rcpt_mailer}, {rcpt_host}, {rcpt_addr}
+For information about available macros and their meanings, please +consult the sendmail documentation. +


+ +Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ diff --git a/gnu/dist/sendmail/libmilter/docs/other.html b/gnu/dist/sendmail/libmilter/docs/other.html new file mode 100644 index 000000000000..8ec9ffdb00e5 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/other.html @@ -0,0 +1,15 @@ + +Other Resources + + +FAQ? Mailing list? More sample filters? +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/overview.html b/gnu/dist/sendmail/libmilter/docs/overview.html new file mode 100644 index 000000000000..76e2fb5f7c1d --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/overview.html @@ -0,0 +1,194 @@ + + +Technical Overview + + + + +

Technical Overview

+ +

Contents

+ +
    +
  • Initialization +
  • Control flow +
  • Multithreading +
  • Resource Management +
  • Signal Handling +
+ +

Initialization

+ +In addition to its own initialization, libmilter expects a filter to initialize several parameters before calling smfi_main: +
    +
  • The callbacks the filter wishes to be called, and the types of + message modification it intends to perform (required, see smfi_register). + +
  • The socket address to be used when communicating with the MTA + (required, see smfi_setconn). + +
  • The number of seconds to wait for MTA connections before + timing out (optional, see smfi_settimeout). +
+

+If the filter fails to initialize libmilter, or if one or more of the +parameters it has passed are invalid, a subsequent call to smfi_main +will fail. + +

Control flow

+ +

+The following pseudocode describes the filtering process from the +perspective of a set of N MTA's, each corresponding to a +connection. Callbacks are shown beside the processing stages in which +they are invoked; if no callbacks are defined for a particular stage, +that stage may be bypassed. Though it is not shown, processing may be +aborted at any time during a message, in which case the xxfi_abort callback is invoked and control +returns to MESSAGE. +

+

+For each of N connections
+{
+	For each filter
+		process connection/helo (xxfi_connect, xxfi_helo)
+MESSAGE:For each message in this connection (sequentially)
+	{
+		For each filter
+			process sender (xxfi_envfrom)
+		For each recipient
+		{
+			For each filter
+				process recipient (xxfi_envrcpt)
+		}
+		For each filter
+		{
+			For each header
+				process header (xxfi_header)
+			process end of headers (xxfi_eoh)
+			For each body block
+				process this body block (xxfi_body)
+			process end of message (xxfi_eom)
+		}
+	}
+	For each filter
+		process end of connection (xxfi_close)
+}
+
+ +

Note: Filters are contacted in order defined in config file.

+ +

+To write a filter, a vendor supplies callbacks to process relevant +parts of a message transaction. The library then controls all +sequencing, threading, and protocol exchange with the MTA. Figure 3 outlines control flow for a filter +process, showing where different callbacks are invoked. +

+
+ + + + + + + + + + + + + + + + +
SMTP CommandsMilter Callbacks
(open SMTP connection)xxfi_connect
HELO ...xxfi_helo
MAIL From: ...xxfi_envfrom
RCPT To: ...xxfi_envrcpt
[more RCPTs][xxfi_envrcpt]
DATA 
Header: ...xxfi_header
[more headers][xxfi_header]
 xxfi_eoh
body... xxfi_body
[more body...][xxfi_body]
.xxfi_eom
QUITxxfi_close
(close SMTP connection) 
+Figure 3: Milter callbacks related to an SMTP transaction. +
+

+Note that although only a single message is shown above, multiple +messages may be sent in a single connection. Note also that a message +and/or connection may be aborted by either the remote host or the MTA +at any point during the SMTP transaction. If this occurs during a +message (between the MAIL command and the final "."), the filter's xxfi_abort routine will be called. xxfi_close is called any time the +connection closes. + +

Multithreading

+ +

+A single filter process may handle any number of connections +simultaneously. All filtering callbacks must therefore be reentrant, +and use some appropriate external synchronization methods to access +global data. Furthermore, since there is not a one-to-one +correspondence between threads and connections (N connections mapped +onto M threads, M <= N), connection-specific data must be accessed +through the handles provided by the Milter library. The programmer +cannot rely on library-supplied thread-specific data blocks +(e.g. pthread_getspecific()) to store connection-specific data. See +the API documentation for smfi_setpriv and smfi_getpriv for details. + +

Resource management

+ +Since filters are likely to be long-lived, and to handle many +connections, proper deallocation of per-connection resources is +important. The lifetime of a connection is bracketed by calls to the +callbacks xxfi_connect and xxfi_close. Therefore connection-specific +resources (accessed via smfi_getpriv +and smfi_setpriv) may be allocated in +xxfi_connect, and should be freed in +xxfi_close. For further information see +the discussion of message- versus +connection-oriented routines. In particular, note that there is only +one connection-specific data pointer per connection. +

+ +Each message is bracketed by calls to xxfi_envfrom and xxfi_eom (or xxfi_abort), implying that message-specific +resources can be allocated and reclaimed in these routines. Since the +messages in a connection are processed sequentially by each filter, +there will be only one active message associated with a given +connection and filter (and connection-private data block). These +resources must still be accessed through smfi_getpriv and smfi_setpriv, and must be reclaimed +in xxfi_abort. + +

Signal Handling

+ +libmilter takes care of signal handling, the filters are +not influenced directly by signals. +There are basically two types of signal handlers: + +
    +
  1. Stop: no new connections from the MTA will be accepted, +but existing connections are allowed to continue. +
  2. Abort: all filters will be stopped as soon as the next +communication with the MTA happens. +
+ +Filters are not terminated asynchronously (except by +signals that can't be caught). +In the case of Abort the +xxfi_abort callback is invoked. + +
+ +Copyright (c) 2000, 2001 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/sample.html b/gnu/dist/sendmail/libmilter/docs/sample.html new file mode 100644 index 000000000000..879258c39df0 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/sample.html @@ -0,0 +1,490 @@ + +A Sample Filter + +

A Sample Filter

+ +The following sample logs each message to a separate temporary file, +adds a recipient given with the -a flag, and rejects a disallowed +recipient address given with the -r flag. It recognizes the following +options: +

+

+ + + + + +
-p portThe port through which the MTA will connect to the filter.
-t secThe timeout value.
-r addrA recipient to reject.
-a addrA recipient to add.
+
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "libmilter/mfapi.h"
+
+#ifndef bool
+# define bool	int
+# define TRUE	1
+# define FALSE	0
+#endif /* ! bool */
+
+
+struct mlfiPriv
+{
+	char	*mlfi_fname;
+	char	*mlfi_connectfrom;
+	char	*mlfi_helofrom;
+	FILE	*mlfi_fp;
+};
+
+#define MLFIPRIV	((struct mlfiPriv *) smfi_getpriv(ctx))
+
+extern sfsistat		mlfi_cleanup(SMFICTX *, bool);
+
+/* recipients to add and reject (set with -a and -r options) */
+char *add = NULL;
+char *reject = NULL;
+
+sfsistat
+mlfi_connect(ctx, hostname, hostaddr)
+	 SMFICTX *ctx;
+	 char *hostname;
+	 _SOCK_ADDR *hostaddr;
+{
+	struct mlfiPriv *priv;
+	char *ident;
+
+	/* allocate some private memory */
+	priv = malloc(sizeof *priv);
+	if (priv == NULL)
+	{
+		/* can't accept this message right now */
+		return SMFIS_TEMPFAIL;
+	}
+	memset(priv, '\0', sizeof *priv);
+
+	/* save the private data */
+	smfi_setpriv(ctx, priv);
+
+	ident = smfi_getsymval(ctx, "_");
+	if (ident == NULL)
+		ident = "???";
+	if ((priv->mlfi_connectfrom = strdup(ident)) == NULL)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	/* continue processing */
+	return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_helo(ctx, helohost)
+	 SMFICTX *ctx;
+	 char *helohost;
+{
+	size_t len;
+	char *tls;
+	char *buf;
+	struct mlfiPriv *priv = MLFIPRIV;
+
+	tls = smfi_getsymval(ctx, "{tls_version}");
+	if (tls == NULL)
+		tls = "No TLS";
+	if (helohost == NULL)
+		helohost = "???";
+	len = strlen(tls) + strlen(helohost) + 3;
+	if ((buf = (char*) malloc(len)) == NULL)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+	snprintf(buf, len, "%s, %s", helohost, tls);
+	if (priv->mlfi_helofrom != NULL)
+		free(priv->mlfi_helofrom);
+	priv->mlfi_helofrom = buf;
+
+	/* continue processing */
+	return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_envfrom(ctx, argv)
+	 SMFICTX *ctx;
+	 char **argv;
+{
+	struct mlfiPriv *priv = MLFIPRIV;
+	char *mailaddr = smfi_getsymval(ctx, "{mail_addr}");
+	int argc = 0;
+
+	/* open a file to store this message */
+	if ((priv->mlfi_fname = strdup("/tmp/msg.XXXXXX")) == NULL)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	if (mkstemp(priv->mlfi_fname) == -1)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	if ((priv->mlfi_fp = fopen(priv->mlfi_fname, "w+")) == NULL)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	/* count the arguments */
+	while (*argv++ != NULL)
+		++argc;
+
+	/* log the connection information we stored earlier: */
+	if (fprintf(priv->mlfi_fp, "Connect from %s (%s)\n\n",
+		    priv->mlfi_helofrom, priv->mlfi_connectfrom) == EOF)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+	/* log the sender */
+	if (fprintf(priv->mlfi_fp, "FROM %s (%d argument%s)\n",
+		    mailaddr ? mailaddr : "???", argc,
+		    (argc == 1) ? "" : "s") == EOF)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	/* continue processing */
+	return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_envrcpt(ctx, argv)
+	 SMFICTX *ctx;
+	 char **argv;
+{
+	struct mlfiPriv *priv = MLFIPRIV;
+	char *rcptaddr = smfi_getsymval(ctx, "{rcpt_addr}");
+	int argc = 0;
+
+	/* count the arguments */
+	while (*argv++ != NULL)
+		++argc;
+
+	/* log this recipient */
+	if (reject != NULL && rcptaddr != NULL &&
+	    (strcasecmp(rcptaddr, reject) == 0))
+	{
+		if (fprintf(priv->mlfi_fp, "RCPT %s -- REJECTED\n",
+			    rcptaddr) == EOF)
+		{
+			(void) mlfi_cleanup(ctx, FALSE);
+			return SMFIS_TEMPFAIL;
+		}
+		return SMFIS_REJECT;
+	}
+	if (fprintf(priv->mlfi_fp, "RCPT %s (%d argument%s)\n",
+		    rcptaddr ? rcptaddr : "???", argc,
+		    (argc == 1) ? "" : "s") == EOF)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	/* continue processing */
+	return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_header(ctx, headerf, headerv)
+	 SMFICTX *ctx;
+	 char *headerf;
+	 unsigned char *headerv;
+{
+	/* write the header to the log file */
+	if (fprintf(MLFIPRIV->mlfi_fp, "%s: %s\n", headerf, headerv) == EOF)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	/* continue processing */
+	return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_eoh(ctx)
+	 SMFICTX *ctx;
+{
+	/* output the blank line between the header and the body */
+	if (fprintf(MLFIPRIV->mlfi_fp, "\n") == EOF)
+	{
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	/* continue processing */
+	return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_body(ctx, bodyp, bodylen)
+	 SMFICTX *ctx;
+	 unsigned char *bodyp;
+	 size_t bodylen;
+{
+        struct mlfiPriv *priv = MLFIPRIV;
+
+	/* output body block to log file */
+	if (fwrite(bodyp, bodylen, 1, priv->mlfi_fp) != 1)
+	{
+		/* write failed */
+		fprintf(stderr, "Couldn't write file %s: %s\n",
+			priv->mlfi_fname, strerror(errno));
+		(void) mlfi_cleanup(ctx, FALSE);
+		return SMFIS_TEMPFAIL;
+	}
+
+	/* continue processing */
+	return SMFIS_CONTINUE;
+}
+
+sfsistat
+mlfi_eom(ctx)
+	 SMFICTX *ctx;
+{
+	bool ok = TRUE;
+
+	/* change recipients, if requested */
+	if (add != NULL)
+		ok = (smfi_addrcpt(ctx, add) == MI_SUCCESS);
+	return mlfi_cleanup(ctx, ok);
+}
+
+sfsistat
+mlfi_abort(ctx)
+	 SMFICTX *ctx;
+{
+	return mlfi_cleanup(ctx, FALSE);
+}
+
+sfsistat
+mlfi_cleanup(ctx, ok)
+	 SMFICTX *ctx;
+	 bool ok;
+{
+	sfsistat rstat = SMFIS_CONTINUE;
+	struct mlfiPriv *priv = MLFIPRIV;
+	char *p;
+	char host[512];
+	char hbuf[1024];
+
+	if (priv == NULL)
+		return rstat;
+
+	/* close the archive file */
+	if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF)
+	{
+		/* failed; we have to wait until later */
+		fprintf(stderr, "Couldn't close archive file %s: %s\n",
+			priv->mlfi_fname, strerror(errno));
+		rstat = SMFIS_TEMPFAIL;
+		(void) unlink(priv->mlfi_fname);
+	}
+	else if (ok)
+	{
+		/* add a header to the message announcing our presence */
+		if (gethostname(host, sizeof host) < 0)
+			snprintf(host, sizeof host, "localhost");
+		p = strrchr(priv->mlfi_fname, '/');
+		if (p == NULL)
+			p = priv->mlfi_fname;
+		else
+			p++;
+		snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
+		if (smfi_addheader(ctx, "X-Archived", hbuf) != MI_SUCCESS)
+		{
+			/* failed; we have to wait until later */
+			fprintf(stderr,
+				"Couldn't add header: X-Archived: %s\n",
+				hbuf);
+			ok = FALSE;
+			rstat = SMFIS_TEMPFAIL;
+			(void) unlink(priv->mlfi_fname);
+		}
+	}
+	else
+	{
+		/* message was aborted -- delete the archive file */
+		fprintf(stderr, "Message aborted.  Removing %s\n",
+			priv->mlfi_fname);
+		rstat = SMFIS_TEMPFAIL;
+		(void) unlink(priv->mlfi_fname);
+	}
+
+	/* release private memory */
+	if (priv->mlfi_fname != NULL)
+		free(priv->mlfi_fname);
+
+	/* return status */
+	return rstat;
+}
+
+sfsistat
+mlfi_close(ctx)
+	 SMFICTX *ctx;
+{
+	struct mlfiPriv *priv = MLFIPRIV;
+
+	if (priv == NULL)
+		return SMFIS_CONTINUE;
+	if (priv->mlfi_connectfrom != NULL)
+		free(priv->mlfi_connectfrom);
+	if (priv->mlfi_helofrom != NULL)
+		free(priv->mlfi_helofrom);
+	free(priv);
+	smfi_setpriv(ctx, NULL);
+	return SMFIS_CONTINUE;
+}
+
+struct smfiDesc smfilter =
+{
+	"SampleFilter",	/* filter name */
+	SMFI_VERSION,	/* version code -- do not change */
+	SMFIF_ADDHDRS,	/* flags */
+	mlfi_connect,	/* connection info filter */
+	mlfi_helo,	/* SMTP HELO command filter */
+	mlfi_envfrom,	/* envelope sender filter */
+	mlfi_envrcpt,	/* envelope recipient filter */
+	mlfi_header,	/* header filter */
+	mlfi_eoh,	/* end of header */
+	mlfi_body,	/* body block filter */
+	mlfi_eom,	/* end of message */
+	mlfi_abort,	/* message aborted */
+	mlfi_close,	/* connection cleanup */
+};
+
+static void
+usage(prog)
+	char *prog;
+{
+	fprintf(stderr,
+		"Usage: %s [-p socket-addr] [-t timeout] [-r reject-addr] [-a add-addr]\n",
+		prog);
+}
+
+int
+main(argc, argv)
+	 int argc;
+	 char **argv;
+{
+	int c;
+	const char *args = "p:t:r:a:h";
+	extern char *optarg;
+
+	/* Process command line options */
+	while ((c = getopt(argc, argv, args)) != -1)
+	{
+		switch (c)
+		{
+		  case 'p':
+			if (optarg == NULL || *optarg == '\0')
+			{
+				(void) fprintf(stderr, "Illegal conn: %s\n",
+					       optarg);
+				exit(EX_USAGE);
+			}
+			if (smfi_setconn(optarg) == MI_FAILURE)
+			{
+				(void) fprintf(stderr,
+					       "smfi_setconn failed\n");
+				exit(EX_SOFTWARE);
+			}
+
+			/*
+			**  If we're using a local socket, make sure it
+			**  doesn't already exist.  Don't ever run this
+			**  code as root!!
+			*/
+
+			if (strncasecmp(optarg, "unix:", 5) == 0)
+				unlink(optarg + 5);
+			else if (strncasecmp(optarg, "local:", 6) == 0)
+				unlink(optarg + 6);
+			break;
+
+		  case 't':
+			if (optarg == NULL || *optarg == '\0')
+			{
+				(void) fprintf(stderr, "Illegal timeout: %s\n",
+					       optarg);
+				exit(EX_USAGE);
+			}
+			if (smfi_settimeout(atoi(optarg)) == MI_FAILURE)
+			{
+				(void) fprintf(stderr,
+					       "smfi_settimeout failed\n");
+				exit(EX_SOFTWARE);
+			}
+			break;
+
+		  case 'r':
+			if (optarg == NULL)
+			{
+				(void) fprintf(stderr,
+					       "Illegal reject rcpt: %s\n",
+					       optarg);
+				exit(EX_USAGE);
+			}
+			reject = optarg;
+			break;
+
+		  case 'a':
+			if (optarg == NULL)
+			{
+				(void) fprintf(stderr,
+					       "Illegal add rcpt: %s\n",
+					       optarg);
+				exit(EX_USAGE);
+			}
+			add = optarg;
+			smfilter.xxfi_flags |= SMFIF_ADDRCPT;
+			break;
+
+		  case 'h':
+		  default:
+			usage(argv[0]);
+			exit(EX_USAGE);
+		}
+	}
+	if (smfi_register(smfilter) == MI_FAILURE)
+	{
+		fprintf(stderr, "smfi_register failed\n");
+		exit(EX_UNAVAILABLE);
+	}
+	return smfi_main();
+}
+
+/* eof */
+
+
+
+ +Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_addheader.html b/gnu/dist/sendmail/libmilter/docs/smfi_addheader.html new file mode 100644 index 000000000000..6f852aebf6ec --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_addheader.html @@ -0,0 +1,115 @@ + +smfi_addheader + +

smfi_addheader

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_addheader(
+	SMFICTX *ctx,
+	char *headerf,
+	char *headerv
+);
+
+Add a header to the current message. +
DESCRIPTION + + + + + + + + + +
Called WhenCalled only from xxfi_eom.
EffectsAdds a header to the current message.
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
headerfThe header name, a non-NULL, null-terminated string. +
headervThe header value to be added, a non-NULL, null-terminated string. This may be the empty string. +
+
RETURN VALUESsmfi_addheader returns MI_FAILURE if: +
  • headerf or headerv is NULL. +
  • Adding headers in the current connection state is invalid. +
  • Memory allocation fails. +
  • A network error occurs. +
  • SMFIF_ADDHDRS was not set when smfi_register was called. +
+Otherwise, it returns MI_SUCCESS. +
NOTES +
  • smfi_addheader does not change a message's existing headers. +To change a header's current value, use smfi_chgheader. +
  • A filter which calls smfi_addheader must have set the SMFIF_ADDHDRS flag in the smfiDesc_str passed to smfi_register. +
  • For smfi_chgheader, filter order is important. Later filters will see the header changes made by earlier ones. +
  • Neither the name nor the value of the header is checked for + standards compliance. However, each line of the header must be under + 2048 characters and should be under 998 characters. If longer headers + are needed, make them multi-line. To make a multi-line header, insert + a line feed (ASCII 0x0a, or \n in C) followed by at least + one whitespace character such as a space (ASCII 0x20) or tab (ASCII 0x09, + or \t in C). The line feed should NOT be preceded by a + carriage return (ASCII 0x0d); the MTA will add this automatically. + It is the filter writer's responsibility to ensure that no standards + are violated. +
+
EXAMPLE +
+  int ret;
+  SMFICTX *ctx;
+
+  ...
+
+  ret = smfi_addheader(ctx, "Content-Type",
+                       "multipart/mixed;\n\tboundary=\"foobar\"");
+ 
+
+ +
+ +Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_addrcpt.html b/gnu/dist/sendmail/libmilter/docs/smfi_addrcpt.html new file mode 100644 index 000000000000..d0a59638eb25 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_addrcpt.html @@ -0,0 +1,80 @@ + +smfi_addrcpt + +

smfi_addrcpt

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_addrcpt(
+	SMFICTX *ctx,
+	char *rcpt
+);
+
+Add a recipient for the current message. +
DESCRIPTION + + + + + + + + + +
Called WhenCalled only from xxfi_eom.
EffectsAdd a recipient to the message envelope.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
rcptThe new recipient's address. +
+
RETURN VALUESsmfi_addrcpt will fail and return MI_FAILURE if: +
  • rcpt is NULL. +
  • Adding headers in the current connection state is invalid. +
  • A network error occurs. +
  • SMFIF_ADDRCPT was not set when smfi_register was called. +
+Otherwise, it will return MI_SUCCESS. +
NOTES +A filter which calls smfi_addrcpt must have set the SMFIF_ADDRCPT flag +in the smfiDesc_str passed to +smfi_register. +
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_chgheader.html b/gnu/dist/sendmail/libmilter/docs/smfi_chgheader.html new file mode 100644 index 000000000000..89ce6f26ebfa --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_chgheader.html @@ -0,0 +1,117 @@ + +smfi_chgheader + +

smfi_chgheader

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_chgheader(
+	SMFICTX *ctx,
+	char *headerf,
+	mi_int32 hdridx,
+	char *headerv
+);
+
+Change or delete a message header. +
DESCRIPTION + + + + + + + + + +
Called WhenCalled only from xxfi_eom.
EffectsChanges a header's value for the current message.
+ + +
ARGUMENTS + + + + + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
headerfThe header name, a non-NULL, null-terminated string. +
hdridxHeader index value (1-based). A hdridx value of 1 will modify the first occurrence of a header named headerf. If hdridx is greater than the number of times headerf appears, a new copy of headerf will be added. +
headervThe new value of the given header. headerv == NULL implies that the header should be deleted. +
+
RETURN VALUES +smfi_chgheader will return MI_FAILURE if +
  • headerf is NULL +
  • Modifying headers in the current connection state is invalid. +
  • Memory allocation fails. +
  • A network error occurs. +
  • SMFIF_CHGHDRS was not set when smfi_register was called. +
+Otherwise, it returns MI_SUCCESS. +
NOTES +
  • While smfi_chgheader may be used to add new headers, it is more efficient and far safer to use smfi_addheader. +
  • A filter which calls smfi_chgheader must have set the SMFIF_CHGHDRS flag in the smfiDesc_str passed to smfi_register. +
  • For smfi_chgheader, filter order is important. Later filters will see the header changes made by earlier ones. +
  • Neither the name nor the value of the header is checked for + standards compliance. However, each line of the header must be under + 2048 characters and should be under 998 characters. If longer headers + are needed, make them multi-line. To make a multi-line header, insert + a line feed (ASCII 0x0a, or \n in C) followed by at least + one whitespace character such as a space (ASCII 0x20) or tab (ASCII 0x09, + or \t in C). The line feed should NOT be preceded by a + carriage return (ASCII 0x0d); the MTA will add this automatically. + It is the filter writer's responsibility to ensure that no standards + are violated. +
+
EXAMPLE +
+  int ret;
+  SMFICTX *ctx;
+
+  ...
+
+  ret = smfi_chgheader(ctx, "Content-Type",
+                       "multipart/mixed;\n\tboundary=\"foobar\"");
+ 
+
+ +
+ +Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_delrcpt.html b/gnu/dist/sendmail/libmilter/docs/smfi_delrcpt.html new file mode 100644 index 000000000000..f86fd2efc394 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_delrcpt.html @@ -0,0 +1,79 @@ + +smfi_delrcpt + +

smfi_delrcpt

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_delrcpt(
+	SMFICTX *ctx;
+	char *rcpt;
+);
+
+Remove a recipient from the current message's envelope. +
DESCRIPTION + + + + + + + + + +
Called WhenCalled only from xxfi_eom.
Effectssmfi_delrcpt removes the named recipient from the current message's envelope.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
rcptThe recipient address to be removed, a non-NULL, null-terminated string. +
+
RETURN VALUESsmfi_delrcpt will fail and return MI_FAILURE if: +
    +
  • rcpt is NULL. +
  • Adding headers in the current connection state is invalid. +
  • A network error occurs. +
  • SMFIF_DELRCPT was not set when smfi_register was called. +
+Otherwise, it will return MI_SUCCESS +
NOTES +The addresses to be removed must match exactly. For example, an address and its expanded form do not match. +
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_getpriv.html b/gnu/dist/sendmail/libmilter/docs/smfi_getpriv.html new file mode 100644 index 000000000000..8bb6efae9538 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_getpriv.html @@ -0,0 +1,59 @@ + +smfi_getpriv + +

smfi_getpriv

+ + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+void* smfi_getpriv(
+	SMFICTX *ctx
+);
+
+Get the connection-specific data pointer for this connection. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_getpriv may be called in any of the xxfi_* callbacks.
EffectsNone.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
ctxOpaque context structure. +
+
RETURN VALUESsmfi_getpriv returns the private data pointer stored by a prior call to smfi_setpriv, or NULL if none has been set.
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_getsymval.html b/gnu/dist/sendmail/libmilter/docs/smfi_getsymval.html new file mode 100644 index 000000000000..8cbde7d7cb79 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_getsymval.html @@ -0,0 +1,96 @@ + +smfi_getsymval + +

smfi_getsymval

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+char* smfi_getsymval(
+	SMFICTX *ctx,
+	char *symname
+);
+
+Get the value of a sendmail macro. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_getsymval may be called from within any of the xxfi_* callbacks. Which macros are defined will depend on when it is called.
EffectsNone.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
ctxThe opaque context structure. +
symnameThe name of a sendmail macro. + Single letter macros can optionally be enclosed in braces ("{" and "}"), + longer macro names must be enclosed in braces, just as in a + sendmail.cf file. + See below for default macros. +
+
RETURN VALUESsmfi_getsymval returns the value of the given macro as a null-terminated string, or NULL if the macro is not defined.
NOTES +By default, the following macros are valid in the given contexts: + + + + + + + +
Sent WithMacros
xxfi_connect daemon_name, if_name, if_addr, j, _
xxfi_helo tls_version, cipher, cipher_bits, cert_subject, cert_issuer
xxfi_envfrom i, auth_type, auth_authen, auth_ssf, auth_author, + mail_mailer, mail_host, mail_addr
xxfi_envrcpt rcpt_mailer, rcpt_host, rcpt_addr
+

+All macros stay in effect from the point they are received until the +end of the connection for the first two sets, the end of the message +for the third (xxfi_envfrom), and just for each recipient for the +final set (xxfi_envrcpt). +

+The macro list can be changed using the confMILTER_MACROS_* options in +sendmail.mc. The scopes of such macros will be determined by when +they are set by sendmail. For descriptions of macros' values, please +see the "Sendmail Installation and Operation Guide" provided with your +sendmail distribution. + +

+ +
+ +Copyright (c) 2000, 2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_main.html b/gnu/dist/sendmail/libmilter/docs/smfi_main.html new file mode 100644 index 000000000000..9652eaa48550 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_main.html @@ -0,0 +1,48 @@ + +smfi_main + +

smfi_main

+ + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_main(
+);
+
+Hand control to libmilter event loop. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_main is called after a filter's initialization is complete.
Effectssmfi_main hands control to the Milter event loop.
+ + +
RETURN VALUESsmfi_main will return MI_FAILURE if it fails to establish a connection. This may occur for any of a variety of reasons (e.g. invalid address passed to smfi_setconn). The reason for the failure will be logged. Otherwise, smfi_main will return MI_SUCCESS.
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_register.html b/gnu/dist/sendmail/libmilter/docs/smfi_register.html new file mode 100644 index 000000000000..705b3a4a9dae --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_register.html @@ -0,0 +1,160 @@ + +smfi_register + +

smfi_register

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_register(
+	smfiDesc_str descr
+);
+
+Register a set of filter callbacks. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_register must be called before smfi_main
Effectssmfi_register creates a filter using the information given in the +smfiDesc_str argument. Multiple calls to smfi_register within a +single process are not allowed.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
descr +A filter descriptor of type smfiDesc_str describing the filter's +functions. The structure has the following members: +
+struct smfiDesc
+{
+	char		*xxfi_name;	/* filter name */
+	int		xxfi_version;	/* version code -- do not change */
+	unsigned long	xxfi_flags;	/* flags */
+
+	/* connection info filter */
+	sfsistat	(*xxfi_connect)(SMFICTX *, char *, _SOCK_ADDR *);
+	/* SMTP HELO command filter */
+	sfsistat	(*xxfi_helo)(SMFICTX *, char *);
+	/* envelope sender filter */
+	sfsistat	(*xxfi_envfrom)(SMFICTX *, char **);
+	/* envelope recipient filter */
+	sfsistat	(*xxfi_envrcpt)(SMFICTX *, char **);
+	/* header filter */
+	sfsistat	(*xxfi_header)(SMFICTX *, char *, char *);
+	/* end of header */
+	sfsistat	(*xxfi_eoh)(SMFICTX *);
+	/* body block */
+	sfsistat	(*xxfi_body)(SMFICTX *, unsigned char *, size_t);
+	/* end of message */
+	sfsistat	(*xxfi_eom)(SMFICTX *);
+	/* message aborted */
+	sfsistat	(*xxfi_abort)(SMFICTX *);
+	/* connection cleanup */
+	sfsistat	(*xxfi_close)(SMFICTX *);
+};
+
+ +A NULL value for any callback function indicates that the filter does +not wish to process the given type of information, simply returning +SMFIS_CONTINUE. +
+
RETURN VALUES +smfi_register may return MI_FAILURE for any of the following reasons: +
    +
  • memory allocation failed. +
  • incompatible version or illegal flags value. +
+ +
NOTES + + +The xxfi_flags field should contain the bitwise OR of zero or more of +the following values, describing the actions the filter may take: + + + + + + + + + + + + + + + + + + + + + + +
FlagDescription
+ SMFIF_ADDHDRS + + This filter may add headers. +
+ SMFIF_CHGHDRS + + This filter may change and/or delete headers. +
+ SMFIF_CHGBODY + + This filter may replace the body during filtering. + This may have significant performance impact + if other filters do body filtering after this filter. +
+ SMFIF_ADDRCPT + + This filter may add recipients to the message. +
+ SMFIF_DELRCPT + + This filter may remove recipients from the message. +
+ +
+ +
+ +Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_replacebody.html b/gnu/dist/sendmail/libmilter/docs/smfi_replacebody.html new file mode 100644 index 000000000000..204c2dc0eb31 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_replacebody.html @@ -0,0 +1,90 @@ + +smfi_replacebody + +

smfi_replacebody

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_replacebody(
+	SMFICTX *ctx,
+	unsigned char *bodyp,
+	int bodylen
+);
+
+Replace message-body data. +
DESCRIPTION + + + + + + + + + +
Called WhenCalled only from xxfi_eom. smfi_replacebody may be called more than once.
Effectssmfi_replacebody replaces the body of the current message. If called +more than once, subsequent calls result in data being appended to the new +body. +
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
bodypA pointer to the start of the new body data, which does not have to be null-terminated. If bodyp is NULL, it is treated as having length == 0. Body data should be in CR/LF form. +
bodylenThe number of data bytes pointed to by bodyp. +
+
RETURN VALUESsmfi_replacebody fails and returns MI_FAILURE if: +
    +
  • bodyp == NULL and bodylen > 0. +
  • Changing the body in the current connection state is invalid. +
  • A network error occurs. +
  • SMFIF_CHGBODY was not set when smfi_register was called. +
+Otherwise, it will return MI_SUCCESS. +
NOTES +
    +
  • Since the message body may be very large, setting SMFIF_CHGBODY may significantly affect filter performance. +
  • If a filter sets SMFIF_CHGBODY but does not call smfi_replacebody, the original body remains unchanged. +
  • For smfi_replacebody, filter order is important. Later filters will see the new body contents created by earlier ones. +
+
+ +
+ +Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_setbacklog.html b/gnu/dist/sendmail/libmilter/docs/smfi_setbacklog.html new file mode 100644 index 000000000000..79f0fd02adeb --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_setbacklog.html @@ -0,0 +1,60 @@ + +smfi_setbacklog + +

smfi_setbacklog

+ + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_setbacklog(
+	int obacklog
+);
+
+Set the filter's listen backlog value. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_setbacklog should only be called before smfi_main.
EffectsSets the incoming socket backlog used by listen(). If smfi_setbacklog is not called, the operating system default is used.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
obacklogThe number of incoming connections to allow in the listen queue. +
+
RETURN VALUESsmfi_setbacklog returns MI_FAILURE if obacklog is less than or equal +to zero.
+ +
+ +Copyright (c) 2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_setconn.html b/gnu/dist/sendmail/libmilter/docs/smfi_setconn.html new file mode 100644 index 000000000000..0d46a5bc48e8 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_setconn.html @@ -0,0 +1,77 @@ + +smfi_setconn + +

smfi_setconn

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_setconn(
+	char *oconn;
+);
+
+Set the socket through which this filter should communicate with sendmail. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_setconn must be called once before smfi_main.
EffectsSets the socket through which the filter communicates with sendmail.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
oconnThe address of the desired communication socket. + The address should be a NULL-terminated string in "proto:address" + format: +
    +
  • {unix|local}:/path/to/file -- A named pipe. +
  • inet:port@{hostname|ip-address} -- An IPV4 socket. +
  • inet6:port@{hostname|ip-address} -- An IPV6 socket. +
+
+
RETURN VALUESsmfi_setconn will not fail on an invalid address. The failure will +only be detected in smfi_main
NOTES +
  • If possible, filters should not run as root when communicating over unix/local domain sockets. +
  • Unix/local sockets should have their permissions set to 0600 (read/write permission only for the socket's owner). +
+
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_setpriv.html b/gnu/dist/sendmail/libmilter/docs/smfi_setpriv.html new file mode 100644 index 000000000000..e800cc8dcc0c --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_setpriv.html @@ -0,0 +1,77 @@ + +smfi_setpriv + +

smfi_setpriv

+ + + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_setpriv(
+	SMFICTX *ctx,
+	void *privatedata
+);
+
+Set the private data pointer for this connection. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_setpriv may be called in any of the xxfi_* callbacks.
EffectsSets the private data pointer for the context ctx.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
privatedataPointer to private data. This value will be returned by subsequent calls to smfi_getpriv using ctx. +
+
RETURN VALUESsmfi_setpriv returns MI_FAILURE if ctx is an invalid context. +Otherwise, it returns MI_SUCCESS.
NOTESThere is only one private data pointer per connection; multiple +calls to smfi_setpriv with different values will cause previous values +to be lost. +

+Before a filter terminates it should release the private data +and set the pointer to NULL. +

+ +
+ +Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_setreply.html b/gnu/dist/sendmail/libmilter/docs/smfi_setreply.html new file mode 100644 index 000000000000..73852f21c4d3 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_setreply.html @@ -0,0 +1,97 @@ + +smfi_setreply + +

smfi_setreply

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_setreply(
+	SMFICTX *ctx,
+	char *rcode,
+	char *xcode,
+	char *message
+);
+
+Set the default SMTP error reply code. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_setreply may be called from any of the xxfi_ callbacks +other than xxfi_connect.
EffectsDirectly set the SMTP error reply code for this connection. This code +will be used on subsequent error replies resulting from actions taken by +this filter.
+ + +
ARGUMENTS + + + + + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
rcodeThe three-digit (RFC 821) SMTP reply code, as a null-terminated string. rcode cannot be NULL, and must be a valid reply code. +
xcodeThe extended (RFC 2034) reply code. If xcode is NULL, no extended code is used. Otherwise, xcode must conform to RFC 2034. +
messageThe text part of the SMTP reply. If message is NULL, an empty message is used. +
+
RETURN VALUESsmfi_setreply will fail and return MI_FAILURE if: +
    +
  • The rcode or xcode argument is invalid. +
  • A memory-allocation failure occurs. +
+Otherwise, it return MI_SUCCESS. +
NOTES +
    +
  • Values passed to smfi_setreply are not checked for standards compliance. +
  • For details about reply codes and their meanings, please see RFC's +821 +and 2034. +
  • If the reply code (rcode) given is a '4XX' code but SMFI_REJECT is used +for the message, the custom reply is not used. +
  • Similarly, if the reply code (rcode) given is a '5XX' code but +SMFI_TEMPFAIL is used for the message, the custom reply is not used. +
+
+ +
+ +Copyright (c) 2000, 2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/smfi_settimeout.html b/gnu/dist/sendmail/libmilter/docs/smfi_settimeout.html new file mode 100644 index 000000000000..6fee16621d7c --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/smfi_settimeout.html @@ -0,0 +1,63 @@ + +smfi_settimeout + +

smfi_settimeout

+ + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_settimeout(
+	int otimeout
+);
+
+Set the filter's connection timeout value. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_settimeout should only be called before smfi_main.
EffectsSets the number of seconds libmilter will wait for an MTA connection before +timing out a socket. +If smfi_settimeout is not called, a default timeout of 7210 seconds is used. +
+ + +
ARGUMENTS + + + + +
ArgumentDescription
otimeoutThe number of seconds to wait before timing out (> 0). Zero means +no wait, not "wait forever". +
+
RETURN VALUESsmfi_settimeout always returns MI_SUCCESS.
+ +
+ +Copyright (c) 2000, 2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_abort.html b/gnu/dist/sendmail/libmilter/docs/xxfi_abort.html new file mode 100644 index 000000000000..aeddf6f37d34 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_abort.html @@ -0,0 +1,80 @@ + +xxfi_abort + +

xxfi_abort

+ + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_abort)(
+	SMFICTX * ctx
+);
+
+Handle the current message's being aborted. +
DESCRIPTION + + + + + + + + + +
Called Whenxxfi_abort may be called at any time during message processing (i.e. between some message-oriented routine and xxfi_eom).
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
ctxOpaque context structure. +
+
NOTES +
    +
  • xxfi_abort must reclaim any resources allocated on a per-message +basis, and must be tolerant of being called between any two +message-oriented callbacks. + +
  • Calls to xxfi_abort and xxfi_eom are +mutually exclusive. + +
  • xxfi_abort is not responsible for reclaiming connection-specific +data, since xxfi_close is always called +when a connection is closed. + +
  • Since the current message is already being aborted, the return +value is currently ignored. + +
  • xxfi_abort is only called if the message is aborted outside the +filter's control and the filter has not completed its +message-oriented processing. For example, if a filter has already +returned SMFIS_ACCEPT, SMFIS_REJECT, or SMFIS_DISCARD from a +message-oriented routine, xxfi_abort will not be called even if the +message is later aborted outside its control. +
+
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_body.html b/gnu/dist/sendmail/libmilter/docs/xxfi_body.html new file mode 100644 index 000000000000..b19e0d4913d2 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_body.html @@ -0,0 +1,80 @@ + +xxfi_body + +

xxfi_body

+ + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_body)(
+	SMFICTX * ctx,
+	unsigned char * bodyp,
+	size_t len
+);
+
+Handle a piece of a message's body. +
DESCRIPTION + + + + + + + + + +
Called Whenxxfi_body is called zero or more times between xxfi_eoh and xxfi_eom.
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
bodypPointer to the start of this block of body data. bodyp is not valid outside this call to xxfi_body. +
lenThe amount of data pointed to by bodyp. +
+
NOTES +
    +
  • bodyp points to a sequence of bytes. +It is not a C string (a sequence of characters that is terminated by '\0'). +Therefore, do not use the usual C string functions like strlen() on this byte block. +Moreover, the byte sequence may contain '\0' characters inside the block. +Hence even if a trailing '\0' is added, C string functions may still fail +to work as expected. +
  • Since message bodies can be very large, defining xxfi_body can +significantly impact filter performance. +
  • End-of-lines are represented as received from SMTP (normally CR/LF). +
  • Later filters will see body changes made by earlier ones. +
  • Message bodies may be sent in multiple chunks, with one call to + xxfi_body per chunk. +
+
+ +
+ +Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_close.html b/gnu/dist/sendmail/libmilter/docs/xxfi_close.html new file mode 100644 index 000000000000..07742be7682f --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_close.html @@ -0,0 +1,66 @@ + +xxfi_close + +

xxfi_close

+ + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_close)(
+	SMFICTX * ctx
+);
+
+The current connection is being closed. +
DESCRIPTION + + + + + + + + + +
Called Whenxxfi_close is always called once at the end of each connection.
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
ctxOpaque context structure. +
+
NOTES +
    +
  • xxfi_close is called on close even if the previous mail +transaction was aborted. +
  • xxfi_close is responsible for freeing any resources allocated on a +per-connection basis. +
  • Since the connection is already closing, the return value is +currently ignored. +
+
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_connect.html b/gnu/dist/sendmail/libmilter/docs/xxfi_connect.html new file mode 100644 index 000000000000..17102856ba26 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_connect.html @@ -0,0 +1,90 @@ + +xxfi_connect + +

xxfi_connect

+ + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_connect)(
+        SMFICTX    *ctx, 
+        char       *hostname,
+        _SOCK_ADDR *hostaddr);
+
+
DESCRIPTION + + + + + + + + + +
Called WhenOnce, at the start of each SMTP connection.
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
ctxthe opaque context structure. +
hostnamethe host name of the message sender, as determined by a + reverse lookup on the host address. If the reverse lookup + fails, hostname will contain the message sender's IP + address enclosed in square brackets (e.g. `[a.b.c.d]'). +
hostaddrthe host address, as determined by a getpeername() call on the SMTP socket. + NULL if the type is not supported in the current version or if + the SMTP connection is made via stdin. +
+
NOTESIf an earlier filter rejects the connection in its xxfi_connect() +routine, this filter's xxfi_connect() will not be called.
+ +
+ +Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_envfrom.html b/gnu/dist/sendmail/libmilter/docs/xxfi_envfrom.html new file mode 100644 index 000000000000..d023c404768e --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_envfrom.html @@ -0,0 +1,92 @@ + +xxfi_envfrom + +

xxfi_envfrom

+ + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_envfrom)(
+	SMFICTX * ctx,
+	char **	argv
+);
+
+Handle the envelope FROM command. +
DESCRIPTION + + + + + + + + + +
Called Whenxxfi_envfrom is called once at the beginning of each message, before xxfi_envrcpt.
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
argvNull-terminated SMTP command arguments; + argv[0] is guaranteed to be the sender address. + Later arguments are the ESMTP arguments. +
+
SPECIAL RETURN VALUES + + + + + + + + + + + + + + + + + +
Return valueDescription
SMFIS_TEMPFAILReject this sender and message with a temporary error; a new sender (and hence a new message) may subsequently be specified. xxfi_abort is not called. +
SMFIS_REJECTReject this sender and message; a new sender/message may be specified. xxfi_abort is not called. +
SMFIS_DISCARDAccept and silently discard this message. xxfi_abort is not called. +
SMFIS_ACCEPTAccept this message. xxfi_abort is not called. +
+
NOTESFor more details on ESTMP responses, please see RFC +1869.
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_envrcpt.html b/gnu/dist/sendmail/libmilter/docs/xxfi_envrcpt.html new file mode 100644 index 000000000000..f13626a2191f --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_envrcpt.html @@ -0,0 +1,94 @@ + +xxfi_envrcpt + +

xxfi_envrcpt

+ + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_envrcpt)(
+	SMFICTX * ctx,
+	char ** argv
+);
+
+Handle the envelope RCPT command. +
DESCRIPTION + + + + + + + + + +
Called Whenxxfi_envrcpt is called once per recipient, hence one or more times per message, immediately after xxfi_envfrom.
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
argvNull-terminated SMTP command arguments; + argv[0] is guaranteed to be the recipient address. + Later arguments are the ESMTP arguments. +
+
SPECIAL RETURN VALUES + + + + + + + + + + + + + + + + + +
Return valueDescription
SMFIS_TEMPFAILTemporarily fail for this particular recipient; further recipients + maystill be sent. xxfi_abort is not called. +
SMFIS_REJECTReject this particular recipient; further recipients maystill be sent. + xxfi_abort is not called. +
SMFIS_DISCARDAccept and discard the message. xxfi_abort will be called. +
SMFIS_ACCEPTAccept recipient. xxfi_abort will not be called. +
+
NOTESFor more details on ESTMP responses, please see RFC +1869.
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_eoh.html b/gnu/dist/sendmail/libmilter/docs/xxfi_eoh.html new file mode 100644 index 000000000000..46c7925f3080 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_eoh.html @@ -0,0 +1,53 @@ + +xxfi_eoh + +

xxfi_eoh

+ + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_eoh)(
+	SMFICTX * ctx
+);
+
+Handle the end of message headers. +
DESCRIPTION + + + + + + + + + +
Called Whenxxfi_eoh is called once after all headers have been sent and processed. +
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
ctxOpaque context structure. +
+
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_eom.html b/gnu/dist/sendmail/libmilter/docs/xxfi_eom.html new file mode 100644 index 000000000000..40f6deec02a6 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_eom.html @@ -0,0 +1,58 @@ + +xxfi_eom + +

xxfi_eom

+ + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_eom)(
+	SMFICTX * ctx
+);
+
+End of a message. +
DESCRIPTION + + + + + + + + + +
Called Whenxxfi_eom is called once after all calls to xxfi_body for a given message.
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
ctxOpaque context structure. +
+
NOTESA filter is required to make all its modifications to the message headers, body, and envelope in xxfi_eom. Modifications are made via the smfi_* routines. +
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_header.html b/gnu/dist/sendmail/libmilter/docs/xxfi_header.html new file mode 100644 index 000000000000..a6c6322b13b7 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_header.html @@ -0,0 +1,74 @@ + +xxfi_header + +

xxfi_header

+ + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_header)(
+	SMFICTX * ctx,
+	char * headerf,
+	char * headerv
+);
+
+Handle a message header. +
DESCRIPTION + + + + + + + + + +
Called Whenxxfi_header is called zero or more times between xxfi_envrcpt and xxfi_eoh, once per message header.
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
headerf Header field name. +
headervHeader field value. The + content of the header may include folded white space (i.e. multiple + lines with following white space). The trailing line terminator (CR/LF) + is removed. +
+
NOTES +
    +
  • Later filters will see header changes/additions made by earlier ones. +
  • For much more detail about header format, please see +RFC 822 +
+
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libmilter/docs/xxfi_helo.html b/gnu/dist/sendmail/libmilter/docs/xxfi_helo.html new file mode 100644 index 000000000000..b1aa9e9a8ae9 --- /dev/null +++ b/gnu/dist/sendmail/libmilter/docs/xxfi_helo.html @@ -0,0 +1,59 @@ + +xxfi_helo + +

xxfi_helo

+ + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_helo)(
+	SMFICTX * ctx, 
+	char * helohost
+);
+
+Handle the HELO/EHLO command. +
DESCRIPTION + + + + + + + + +
Called When xxfi_helo is called whenever the client +sends a HELO/EHLO command. It may therefore be called between zero and +three times
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
helohostValue passed to HELO/EHLO command, which should be + the domain name of the sending host (but is, in practice, + anything the sending host wants to send). +
+
+ +
+ +Copyright (c) 2000 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + diff --git a/gnu/dist/sendmail/libsm/Build b/gnu/dist/sendmail/libsm/Build new file mode 100644 index 000000000000..179911619b81 --- /dev/null +++ b/gnu/dist/sendmail/libsm/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. +# 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. +# +# +# Id: Build,v 1.4 2001/02/14 04:39:46 gshapiro Exp + +exec sh ../devtools/bin/Build $* diff --git a/gnu/dist/sendmail/libsm/Makefile b/gnu/dist/sendmail/libsm/Makefile new file mode 100644 index 000000000000..97a2d31e29dc --- /dev/null +++ b/gnu/dist/sendmail/libsm/Makefile @@ -0,0 +1,17 @@ +# Id: Makefile,v 1.1 2000/03/27 19:26:48 dmoen Exp + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/dist/sendmail/libsm/Makefile.m4 b/gnu/dist/sendmail/libsm/Makefile.m4 new file mode 100644 index 000000000000..868a4dd11d79 --- /dev/null +++ b/gnu/dist/sendmail/libsm/Makefile.m4 @@ -0,0 +1,37 @@ +dnl Id: Makefile.m4,v 1.64.2.1 2002/06/21 21:58:29 ca Exp +define(`confREQUIRE_LIBUNIX') +include(confBUILDTOOLSDIR`/M4/switch.m4') + +define(`confREQUIRE_LIBSM', `true') +PREPENDDEF(`confENVDEF', `confMAPDEF') +bldPRODUCT_START(`library', `libsm') +define(`bldSOURCES', ` assert.c debug.c errstring.c exc.c heap.c match.c rpool.c strdup.c strerror.c strl.c clrerr.c fclose.c feof.c ferror.c fflush.c fget.c fpos.c findfp.c flags.c fopen.c fprintf.c fpurge.c fput.c fread.c fscanf.c fseek.c fvwrite.c fwalk.c fwrite.c get.c makebuf.c put.c refill.c rewind.c setvbuf.c smstdio.c snprintf.c sscanf.c stdio.c strio.c ungetc.c vasprintf.c vfprintf.c vfscanf.c vprintf.c vsnprintf.c vsprintf.c vsscanf.c wbuf.c wsetup.c string.c stringf.c xtrap.c strto.c test.c path.c strcasecmp.c strrevcmp.c signal.c clock.c config.c shm.c mbdb.c strexit.c cf.c ldap.c niprop.c mpeix.c ') +bldPRODUCT_END +dnl sem.c msg.c +dnl syslogio.c + +include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/sm-test.m4') +smtest(`t-event', `run') +smtest(`t-exc', `run') +smtest(`t-rpool', `run') +smtest(`t-string', `run') +smtest(`t-smstdio', `run') +smtest(`t-match', `run') +smtest(`t-strio', `run') +smtest(`t-heap', `run') +smtest(`t-fopen', `run') +smtest(`t-strl', `run') +smtest(`t-strrevcmp', `run') +smtest(`t-types', `run') +smtest(`t-path', `run') +smtest(`t-float', `run') +smtest(`t-scanf', `run') +smtest(`t-shm', `run') +dnl smtest(`t-sem', `run') +dnl smtest(`t-msg', `run') +smtest(`t-cf') +smtest(`b-strcmp') +dnl SM_CONF_STRL cannot be turned off +dnl smtest(`b-strl') + +bldFINISH diff --git a/gnu/dist/sendmail/libsm/README b/gnu/dist/sendmail/libsm/README new file mode 100644 index 000000000000..9f8aa740c83a --- /dev/null +++ b/gnu/dist/sendmail/libsm/README @@ -0,0 +1,129 @@ +# Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +# 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. +# +# Id: README,v 1.21 2002/01/23 17:30:48 gshapiro Exp +# + +Libsm is a library of generally useful C abstractions. +For documentation, see index.html. + +Libsm stands alone; it depends on no other sendmail libraries, +and the only sendmail header files it depends on are its own, +which reside in ../include/sm. + +The t-*.c files are regression tests. +These tests are incomplete: we do not yet test all of the APIs, +and we have not yet converted all tests to use the test harness. +If a test fails read the explanation it generates. Sometimes it +is sufficient to change a compile time flag, which are also listed +below. If that does not help, check the sendmail/README files for +problems on your OS. + +The b-*.c files are benchmarks that compare system routines with +those provided by libsm. By default sendmail uses the routines +provided by the OS. In several cases, the routines provided by +libsm are faster than those of the OS. If your OS provides the +routines, you can compare the performance of them with the libsm +versions by running the programs with the option -d (by default +the programs just issue an explanation when/how to use them). +The programs are: + +b-strcmp.c tests strcasecmp(). + ++----------------------+ +| CONFIGURATION MACROS | ++----------------------+ + +Libsm uses a set of C preprocessor macros to specify platform specific +features of the C compiler and standard C libraries. + +If you are porting sendmail to a new platform, you may need to tweak +the values of some of these macros. + +The following macros are given default values in . +If the default value is wrong for a given platform, then a platform +specific value is specified in one of two ways: + + - A -D option is added to the confENVDEF macro; this change can be made + to the platform M4 file in devtools/OS, or to the site.config.m4 + file in devtools/Site. + + - The confSM_OS_HEADER macro in the platform M4 file defines sm_os_foo, + which forces "sm/os/sm_os_foo.h" to be included by "sm/config.h" via a + link that is made from "sm_os.h" to "sm/os/sm_os_foo.h". Platform + specific configuration macro settings are added to . + +SM_CONF_STDBOOL_H + Set to 1 if the header file exists, + and defines true, false and bool. + +SM_CONF_SYS_CDEFS_H + Set to 1 if the header file exists, + and defines __P. You may need to do this to eliminate + warnings about __P being multiply defined. + +SM_CONF_STDDEF_H + Set to 0 if the header file does not exist. + +SM_CONF_SETITIMER + Set to 0 if the setitimer function is not available. + +SM_CONF_SYSEXITS_H + Set to 1 if exists, and sets the EX_* macros + to values different from the default BSD values in . + +SM_CONF_UID_GID + Set to 0 if does not define uid_t and gid_t. + +SM_CONF_SSIZE_T + Set to 0 if does not define ssize_t. + +SM_CONF_BROKEN_SIZE_T + Set to 1 if size_t is not unsigned. + +SM_CONF_LONGLONG + Set to 1 if your C compiler supports the 'long long' type. + This will be set automatically if you use gcc or a C compiler + that conforms to the 1999 ISO C standard. + +SM_CONF_QUAD_T + Set to 1 if your C compiler does not support 'long long', + but defines quad_t as an integral type. + +SM_CONF_SHM + Set to 1 if System V shared memory APIs are available. + +SM_CONF_MSG + Set to 1 if System V message queues are available. + +SM_CONF_SEM + Set to 1 if semaphores are available. + +SM_CONF_BROKEN_STRTOD + Set to 1 if your strtod() does not work properly. + +SM_CONF_GETOPT + Set to 1 if your operating system does not include getopt(3). + +SM_CONF_LDAP_MEMFREE + Set to 1 if your LDAP client libraries include ldap_memfree(3). + +SM_IO_MAX_BUF_FILE + Set this to a useful buffer size for regular files if stat(2) + does not return a value for st_blksize that is the + "optimal blocksize for I/O". + +SM_IO_MAX_BUF + Set this to a useful maximum buffer size for other than + regular files if stat(2) does not return a value for + st_blksize that is the "optimal blocksize for I/O". + +SM_IO_MIN_BUF + Set this to a useful minimum buffer size for other than + regular files if stat(2) does not return a value for + st_blksize that is the "optimal blocksize for I/O". + diff --git a/gnu/dist/sendmail/libsm/assert.c b/gnu/dist/sendmail/libsm/assert.c new file mode 100644 index 000000000000..9d0014c42b3d --- /dev/null +++ b/gnu/dist/sendmail/libsm/assert.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: assert.c,v 1.25 2001/09/11 04:04:47 gshapiro Exp") + +/* +** Abnormal program termination and assertion checking. +** For documentation, see assert.html. +*/ + +#include +#include +#include + +#include +#include +#include +#include + +/* +** Debug categories that are used to guard expensive assertion checks. +*/ + +SM_DEBUG_T SmExpensiveAssert = SM_DEBUG_INITIALIZER("sm_check_assert", + "@(#)$Debug: sm_check_assert - check assertions $"); + +SM_DEBUG_T SmExpensiveRequire = SM_DEBUG_INITIALIZER("sm_check_require", + "@(#)$Debug: sm_check_require - check function preconditions $"); + +SM_DEBUG_T SmExpensiveEnsure = SM_DEBUG_INITIALIZER("sm_check_ensure", + "@(#)$Debug: sm_check_ensure - check function postconditions $"); + +/* +** Debug category: send self SIGSTOP on fatal error, +** so that you can run a debugger on the stopped process. +*/ + +SM_DEBUG_T SmAbortStop = SM_DEBUG_INITIALIZER("sm_abort_stop", + "@(#)$Debug: sm_abort_stop - stop process on fatal error $"); + +/* +** SM_ABORT_DEFAULTHANDLER -- Default procedure for abnormal program +** termination. +** +** The goal is to display an error message without disturbing the +** process state too much, then dump core. +** +** Parameters: +** filename -- filename (can be NULL). +** lineno -- line number. +** msg -- message. +** +** Returns: +** doesn't return. +*/ + +static void +sm_abort_defaulthandler __P(( + const char *filename, + int lineno, + const char *msg)); + +static void +sm_abort_defaulthandler(filename, lineno, msg) + const char *filename; + int lineno; + const char *msg; +{ + if (filename != NULL) + sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s:%d: %s\n", filename, + lineno, msg); + else + sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n", msg); + sm_io_flush(smioerr, SM_TIME_DEFAULT); +#ifdef SIGSTOP + if (sm_debug_active(&SmAbortStop, 1)) + kill(getpid(), SIGSTOP); +#endif /* SIGSTOP */ + abort(); +} + +/* +** This is the action to be taken to cause abnormal program termination. +*/ + +static SM_ABORT_HANDLER_T SmAbortHandler = sm_abort_defaulthandler; + +/* +** SM_ABORT_SETHANDLER -- Set handler for SM_ABORT() +** +** This allows you to set a handler function for causing abnormal +** program termination; it is called when a logic bug is detected. +** +** Parameters: +** f -- handler. +** +** Returns: +** none. +*/ + +void +sm_abort_sethandler(f) + SM_ABORT_HANDLER_T f; +{ + if (f == NULL) + SmAbortHandler = sm_abort_defaulthandler; + else + SmAbortHandler = f; +} + +/* +** SM_ABORT -- Call it when you have detected a logic bug. +** +** Parameters: +** fmt -- format string. +** ... -- arguments. +** +** Returns: +** doesn't. +*/ + +void +#if SM_VA_STD +sm_abort(char *fmt, ...) +#else /* SM_VA_STD */ +sm_abort(fmt, va_alist) + char *fmt; + va_dcl +#endif /* SM_VA_STD */ +{ + char msg[128]; + SM_VA_LOCAL_DECL + + SM_VA_START(ap, fmt); + sm_vsnprintf(msg, sizeof msg, fmt, ap); + SM_VA_END(ap); + sm_abort_at(NULL, 0, msg); +} + +/* +** SM_ABORT_AT -- Initiate abnormal program termination. +** +** This is the low level function that is called to initiate abnormal +** program termination. It prints an error message and terminates the +** program. It is called by sm_abort and by the assertion macros. +** If filename != NULL then filename and lineno specify the line of source +** code at which the bug was detected. +** +** Parameters: +** filename -- filename (can be NULL). +** lineno -- line number. +** msg -- message. +** +** Returns: +** doesn't. +*/ + +void +sm_abort_at(filename, lineno, msg) + const char *filename; + int lineno; + const char *msg; +{ + SM_TRY + (*SmAbortHandler)(filename, lineno, msg); + SM_EXCEPT(exc, "*") + sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "exception raised by abort handler:\n"); + sm_exc_print(exc, smioerr); + sm_io_flush(smioerr, SM_TIME_DEFAULT); + SM_END_TRY + + /* + ** SmAbortHandler isn't supposed to return. + ** Since it has, let's make sure that the program is terminated. + */ + + abort(); +} diff --git a/gnu/dist/sendmail/libsm/assert.html b/gnu/dist/sendmail/libsm/assert.html new file mode 100644 index 000000000000..488afed278ec --- /dev/null +++ b/gnu/dist/sendmail/libsm/assert.html @@ -0,0 +1,359 @@ + + + libsm : Assert and Abort + + + +Back to libsm overview + +
+

libsm : Assert and Abort

+
Id: assert.html,v 1.6 2001/08/27 21:47:03 ca Exp +
+ +

Introduction

+ +This package contains abstractions +for assertion checking and abnormal program termination. + +

Synopsis

+ +
+#include <sm/assert.h>
+
+/*
+**  abnormal program termination
+*/
+
+void sm_abort_at(char *filename, int lineno, char *msg);
+typedef void (*SM_ABORT_HANDLER)(char *filename, int lineno, char *msg);
+void sm_abort_sethandler(SM_ABORT_HANDLER);
+void sm_abort(char *fmt, ...)
+
+/*
+**  assertion checking
+*/
+
+SM_REQUIRE(expression)
+SM_ASSERT(expression)
+SM_ENSURE(expression)
+
+extern SM_DEBUG_T SmExpensiveRequire;
+extern SM_DEBUG_T SmExpensiveAssert;
+extern SM_DEBUG_T SmExpensiveEnsure;
+
+#if SM_CHECK_REQUIRE
+#if SM_CHECK_ASSERT
+#if SM_CHECK_ENSURE
+
+cc -DSM_CHECK_ALL=0 -DSM_CHECK_REQUIRE=1 ...
+
+ +

Abnormal Program Termination

+ +The functions sm_abort and sm_abort_at are used to report a logic +bug and terminate the program. They can be invoked directly, +and they are also used by the assertion checking macros. + +
+
+ void sm_abort_at(char *filename, int lineno, char *msg) +
+ This is the low level interface for causing abnormal program + termination. It is intended to be invoked from a + macro, such as the assertion checking macros. + + If filename != NULL then filename and lineno specify the line + of source code on which the logic bug is detected. These + arguments are normally either set to __FILE__ and __LINE__ + from an assertion checking macro, or they are set to NULL and 0. + + The default action is to print an error message to smioerr + using the arguments, and then call abort(). This default + behaviour can be changed by calling sm_abort_sethandler. +

+

+ void sm_abort_sethandler(SM_ABORT_HANDLER handler) +
+ Install 'handler' as the callback function that is invoked + by sm_abort_at. This callback function is passed the same + arguments as sm_abort_at, and is expected to log an error + message and terminate the program. The callback function should + not raise an exception or perform cleanup: see Rationale. + + sm_abort_sethandler is intended to be called once, from main(), + before any additional threads are created: see Rationale. + You should not use sm_abort_sethandler to + switch back and forth between several handlers; + this is particularly dangerous when there are + multiple threads, or when you are in a library routine. +

+

+ void sm_abort(char *fmt, ...) +
+ This is the high level interface for causing abnormal program + termination. It takes printf arguments. There is no need to + include a trailing newline in the format string; a trailing newline + will be printed if appropriate by the handler function. +
+ +

Assertions

+ + The assertion handling package + supports a style of programming in which assertions are used + liberally throughout the code, both as a form of documentation, + and as a way of detecting bugs in the code by performing runtime checks. +

+ There are three kinds of assertion: +

+
+ SM_REQUIRE(expr) +
+ This is an assertion used at the beginning of a function + to check that the preconditions for calling the function + have been satisfied by the caller. +

+

+ SM_ENSURE(expr) +
+ This is an assertion used just before returning from a function + to check that the function has satisfied all of the postconditions + that it is required to satisfy by its contract with the caller. +

+

+ SM_ASSERT(expr) +
+ This is an assertion that is used in the middle of a function, + to check loop invariants, and for any other kind of check that is + not a "require" or "ensure" check. +
+ If any of the above assertion macros fail, then sm_abort_at + is called. By default, a message is printed to stderr and the + program is aborted. For example, if SM_REQUIRE(arg > 0) fails + because arg <= 0, then the message +
+foo.c:47: SM_REQUIRE(arg > 0) failed
+
+ is printed to stderr, and abort() is called. + You can change this default behaviour using sm_abort_sethandler. + +

How To Disable Assertion Checking At Compile Time

+ + You can use compile time macros to selectively enable or disable + each of the three kinds of assertions, for performance reasons. + For example, you might want to enable SM_REQUIRE checking + (because it finds the most bugs), but disable the other two types. +

+ By default, all three types of assertion are enabled. + You can selectively disable individual assertion types + by setting one or more of the following cpp macros to 0 + before <sm/assert.h> is included for the first time: +

+ SM_CHECK_REQUIRE
+ SM_CHECK_ENSURE
+ SM_CHECK_ASSERT
+
+ Or, you can define SM_CHECK_ALL as 0 to disable all assertion + types, then selectively define one or more of SM_CHECK_REQUIRE, + SM_CHECK_ENSURE or SM_CHECK_ASSERT as 1. For example, + to disable all assertions except for SM_REQUIRE, you can use + these C compiler flags: +
+ -DSM_CHECK_ALL=0 -DSM_CHECK_REQUIRE=1 +
+ + After <sm/assert.h> is included, the macros + SM_CHECK_REQUIRE, SM_CHECK_ENSURE and SM_CHECK_ASSERT + are each set to either 0 or 1. + +

How To Write Complex or Expensive Assertions

+ + Sometimes an assertion check requires more code than a simple + boolean expression. + For example, it might require an entire statement block + with its own local variables. + You can code such assertion checks by making them conditional on + SM_CHECK_REQUIRE, SM_CHECK_ENSURE or SM_CHECK_ASSERT, + and using sm_abort to signal failure. +

+ Sometimes an assertion check is significantly more expensive + than one or two comparisons. + In such cases, it is not uncommon for developers to comment out + the assertion once the code is unit tested. + Please don't do this: it makes it hard to turn the assertion + check back on for the purposes of regression testing. + What you should do instead is make the assertion check conditional + on one of these predefined debug objects: +

+ SmExpensiveRequire
+ SmExpensiveAssert
+ SmExpensiveEnsure +
+ By doing this, you bring the cost of the assertion checking code + back down to a single comparison, unless expensive assertion checking + has been explicitly enabled. + By the way, the corresponding debug category names are +
+ sm_check_require
+ sm_check_assert
+ sm_check_ensure +
+ What activation level should you check for? + Higher levels correspond to more expensive assertion checks. + Here are some basic guidelines: +
+ level 1: < 10 basic C operations
+ level 2: < 100 basic C operations
+ level 3: < 1000 basic C operations
+ ... +
+ +

+ Here's a contrived example of both techniques: +

+void
+w_munge(WIDGET *w)
+{
+    SM_REQUIRE(w != NULL);
+#if SM_CHECK_REQUIRE
+    /*
+    **  We run this check at level 3 because we expect to check a few hundred
+    **  table entries.
+    */
+
+    if (sm_debug_active(&SmExpensiveRequire, 3))
+    {
+        int i;
+
+        for (i = 0; i < WIDGET_MAX; ++i)
+        {
+            if (w[i] == NULL)
+                sm_abort("w_munge: NULL entry %d in widget table", i);
+        }
+    }
+#endif /* SM_CHECK_REQUIRE */
+
+ +

Other Guidelines

+ + You should resist the urge to write SM_ASSERT(0) when the code has + reached an impossible place. It's better to call sm_abort, because + then you can generate a better error message. For example, +
+switch (foo)
+{
+    ...
+  default:
+    sm_abort("impossible value %d for foo", foo);
+}
+
+ Note that I did not bother to guard the default clause of the switch + statement with #if SM_CHECK_ASSERT ... #endif, because there is + probably no performance gain to be had by disabling this particular check. +

+ Avoid including code that has side effects inside of assert macros, + or inside of SM_CHECK_* guards. You don't want the program to stop + working if assertion checking is disabled. + +

Rationale for Logic Bug Handling

+ + When a logic bug is detected, our philosophy is to log an error message + and terminate the program, dumping core if possible. + It is not a good idea to raise an exception, attempt cleanup, + or continue program execution. Here's why. +

+ First of all, to facilitate post-mortem analysis, we want to dump core + on detecting a logic bug, disturbing the process image as little as + possible before dumping core. We don't want to raise an exception + and unwind the stack, executing cleanup code, before dumping core, + because that would obliterate information we need to analyze the cause + of the abort. +

+ Second, it is a bad idea to raise an exception on an assertion failure + because this places unacceptable restrictions on code that uses + the assertion macros. + The reason is this: the sendmail code must be written so that + anywhere it is possible for an assertion to be raised, the code + will catch the exception and clean up if necessary, restoring + data structure invariants and freeing resources as required. + If an assertion failure was signalled by raising an exception, + then every time you added an assertion, you would need to check + both the function containing the assertion and its callers to see + if any exception handling code needed to be added to clean up properly + on assertion failure. That is far too great a burden. +

+ It is a bad idea to attempt cleanup upon detecting a logic bug + for several reasons: +

    +
  • If you need to perform cleanup actions in order to preserve the + integrity of the data that the program is handling, then the + program is not fault tolerant, and needs to be redesigned. + There are several reasons why a program might be terminated unexpectedly: + the system might crash, the program might receive a signal 9, + the program might be terminated by a memory fault (possibly as a + side effect of earlier data structure corruption), and the program + might detect a logic bug and terminate itself. Note that executing + cleanup actions is not feasible in most of the above cases. + If the program has a fault tolerant design, then it will not lose + data even if the system crashes in the middle of an operation. +

    +

  • If the cause of the logic bug is earlier data structure corruption, + then cleanup actions intended to preserve the integrity of the data + that the program is handling might cause more harm than good: they + might cause information to be corrupted or lost. +

    +

  • If the program uses threads, then cleanup is much more problematic. + Suppose that thread A is holding some locks, and is in the middle of + modifying a shared data structure. The locks are needed because the + data structure is currently in an inconsistent state. At this point, + a logic bug is detected deep in a library routine called by A. + How do we get all of the running threads to stop what they are doing + and perform their thread-specific cleanup actions before terminating? + We may not be able to get B to clean up and terminate cleanly until + A has restored the invariants on the data structure it is modifying + and releases its locks. So, we raise an exception and unwind the stack, + restoring data structure invariants and releasing locks at each level + of abstraction, and performing an orderly shutdown. There are certainly + many classes of error conditions for which using the exception mechanism + to perform an orderly shutdown is appropriate and feasible, but there + are also classes of error conditions for which exception handling and + orderly shutdown is dangerous or impossible. The abnormal program + termination system is intended for this second class of error conditions. + If you want to trigger orderly shutdown, don't call sm_abort: + raise an exception instead. +
+

+ Here is a strategy for making sendmail fault tolerant. + Sendmail is structured as a collection of processes. The "root" process + does as little as possible, except spawn children to do all of the real + work, monitor the children, and act as traffic cop. + We use exceptions to signal expected but infrequent error conditions, + so that the process encountering the exceptional condition can clean up + and keep going. (Worker processes are intended to be long lived, in + order to minimize forking and increase performance.) But when a bug + is detected in a sendmail worker process, the worker process does minimal + or no cleanup and then dies. A bug might be detected in several ways: + the process might dereference a NULL pointer, receive a signal 11, + core dump and die, or an assertion might fail, in which case the process + commits suicide. Either way, the root process detects the death of the + worker, logs the event, and spawns another worker. + +

Rationale for Naming Conventions

+ + The names "require" and "ensure" come from the writings of Bertrand Meyer, + a prominent evangelist for assertion checking who has written a number of + papers about the "Design By Contract" programming methodology, + and who created the Eiffel programming language. + Many other assertion checking packages for C also have "require" and + "ensure" assertion types. In short, we are conforming to a de-facto + standard. +

+ We use the names SM_REQUIRE, SM_ASSERT + and SM_ENSURE in preference to to REQUIRE, + ASSERT and ENSURE because at least two other + open source libraries (libisc and libnana) define REQUIRE + and ENSURE macros, and many libraries define ASSERT. + We want to avoid name conflicts with other libraries. + + + diff --git a/gnu/dist/sendmail/libsm/b-strcmp.c b/gnu/dist/sendmail/libsm/b-strcmp.c new file mode 100644 index 000000000000..1676b14eaa86 --- /dev/null +++ b/gnu/dist/sendmail/libsm/b-strcmp.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: b-strcmp.c,v 1.12 2001/09/11 04:04:47 gshapiro Exp") +#include +#include +#include +#include +#include +#include + +#define toseconds(x, y) (x.tv_sec - y.tv_sec) +#define SIZE 512 +#define LOOPS 4000000L /* initial number of loops */ +#define MAXTIME 30L /* "maximum" time to run single test */ + +void +fatal(str) + char *str; +{ + perror(str); + exit(1); +} + +void +purpose() +{ + printf("This program benchmarks the performance differences between\n"); + printf("strcasecmp() and sm_strcasecmp().\n"); + printf("These tests may take several minutes to complete.\n"); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + long a; + int k; + bool doit = false; + long loops; + long j; + long one, two; + struct timeval t1, t2; + char src1[SIZE], src2[SIZE]; + +# define OPTIONS "d" + while ((k = getopt(argc, argv, OPTIONS)) != -1) + { + switch ((char) k) + { + case 'd': + doit = true; + break; + + default: + break; + } + } + + if (!doit) + { + purpose(); + printf("If you want to run it, specify -d as option.\n"); + return 0; + } + + /* Run-time comments to the user */ + purpose(); + printf("\n"); + for (k = 0; k < 3; k++) + { + switch (k) + { + case 0: + (void) sm_strlcpy(src1, "1234567890", SIZE); + (void) sm_strlcpy(src2, "1234567890", SIZE); + break; + case 1: + (void) sm_strlcpy(src1, "1234567890", SIZE); + (void) sm_strlcpy(src2, "1234567891", SIZE); + break; + case 2: + (void) sm_strlcpy(src1, "1234567892", SIZE); + (void) sm_strlcpy(src2, "1234567891", SIZE); + break; + } + printf("Test %d: strcasecmp(%s, %s) versus sm_strcasecmp()\n", + k, src1, src2); + loops = LOOPS; + for (;;) + { + j = 0; + if (gettimeofday(&t1, NULL) < 0) + fatal("gettimeofday"); + for (a = 0; a < loops; a++) + j += strcasecmp(src1, src2); + if (gettimeofday(&t2, NULL) < 0) + fatal("gettimeofday"); + one = toseconds(t2, t1); + printf("\tstrcasecmp() result: %ld seconds [%ld]\n", + one, j); + + j = 0; + if (gettimeofday(&t1, NULL) < 0) + fatal("gettimeofday"); + for (a = 0; a < loops; a++) + j += sm_strcasecmp(src1, src2); + if (gettimeofday(&t2, NULL) < 0) + fatal("gettimeofday"); + two = toseconds(t2, t1); + printf("\tsm_strcasecmp() result: %ld seconds [%ld]\n", + two, j); + + if (abs(one - two) > 2) + break; + loops += loops; + if (loops < 0L || one > MAXTIME) + { + printf("\t\t** results too close: no decision\n"); + break; + } + else + { + printf("\t\t** results too close redoing test %ld times **\n", + loops); + } + } + } + + printf("\n\n"); + printf("Interpreting the results:\n"); + printf("\tFor differences larger than 2 seconds, the lower value is\n"); + printf("\tbetter and that function should be used for performance\n"); + printf("\treasons.\n\n"); + printf("This program will re-run the tests when the difference is\n"); + printf("less than 2 seconds.\n"); + printf("The result will vary depending on the compiler optimization\n"); printf("level used. Compiling the sendmail libsm library with a\n"); + printf("better optimization level can change the results.\n"); + return 0; +} diff --git a/gnu/dist/sendmail/libsm/b-strl.c b/gnu/dist/sendmail/libsm/b-strl.c new file mode 100644 index 000000000000..2cdb941bcced --- /dev/null +++ b/gnu/dist/sendmail/libsm/b-strl.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +/* +** Compile this program using a command line similar to: +** cc -O -L../OBJ/libsm -o b-strl b-strl.c -lsm +** where "OBJ" is the name of the object directory for the platform +** you are compiling on. +** Then run the program: +** ./b-strl +** and read the output for results and how to interpret the results. +*/ + +#include +SM_RCSID("@(#)Id: b-strl.c,v 1.24 2001/09/11 04:04:47 gshapiro Exp") +#include +#include +#include +#include +#include +#include + +#define SRC_SIZE 512 +#define toseconds(x, y) (x.tv_sec - y.tv_sec) +#define LOOPS 4000000L /* initial number of loops */ +#define MAXTIME 30L /* "maximum" time to run single test */ + +void +fatal(str) + char *str; +{ + perror(str); + exit(1); +} + +void +purpose() +{ + printf("This program benchmarks the performance differences between\n"); + printf("strlcpy() and sm_strlcpy(), and strlcat() and sm_strlcat().\n"); + printf("These tests may take several minutes to complete.\n"); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ +#if !SM_CONF_STRL + printf("The configuration indicates the system needs the libsm\n"); + printf("versions of strlcpy(3) and strlcat(3). Thus, performing\n"); + printf("these tests will not be of much use.\n"); + printf("If your OS has strlcpy(3) and strlcat(3) then set the macro\n"); + printf("SM_CONF_STRL to 1 in your site.config.m4 file\n"); + printf("(located in ../devtools/Site) and recompile this program.\n"); +#else /* !SM_CONF_STRL */ + int ch; + long a; + bool doit = false; + long loops = LOOPS; + long one, two; + struct timeval t1, t2; + char dest[SRC_SIZE], source[SRC_SIZE]; + +# define OPTIONS "d" + while ((ch = getopt(argc, argv, OPTIONS)) != -1) + { + switch ((char) ch) + { + case 'd': + doit = true; + break; + + default: + break; + } + } + + if (!doit) + { + purpose(); + printf("If you want to run it, specify -d as option.\n"); + return 0; + } + + /* + ** Let's place a small string at the head of dest for + ** catenation to happen (it'll be ignored for the copy). + */ + (void) sm_strlcpy(dest, "a small string at the start! ", SRC_SIZE - 1); + + /* + ** Let's place a larger string into source for the catenation and + ** the copy. + */ + (void) strlcpy(source, + " This is the longer string that will be used for catenation and copying for the the performace testing. The longer the string being catenated or copied the greater the difference in measureable performance\n", + SRC_SIZE - 1); + + /* Run-time comments to the user */ + purpose(); + printf("\n"); + printf("Test 1: strlcat() versus sm_strlcat()\n"); + +redo_cat: + if (gettimeofday(&t1, NULL) < 0) + fatal("gettimeofday"); + + for (a = 0; a < loops; a++) + strlcat(dest, source, SRC_SIZE - 1); + + if (gettimeofday(&t2, NULL) < 0) + fatal("gettimeofday"); + + printf("\tstrlcat() result: %ld seconds\n", one = toseconds(t2, t1)); + + if (gettimeofday(&t1, NULL) < 0) + fatal("gettimeofday"); + + for (a = 0; a < loops; a++) + sm_strlcat(dest, source, SRC_SIZE - 1); + + if (gettimeofday(&t2, NULL) < 0) + fatal("gettimeofday"); + + printf("\tsm_strlcat() result: %ld seconds\n", two = toseconds(t2, t1)); + + if (one - two >= -2 && one - two <= 2) + { + loops += loops; + if (loops < 0L || one > MAXTIME) + { + printf("\t\t** results too close: no decision\n"); + } + else + { + printf("\t\t** results too close redoing test %ld times **\n", + loops); + goto redo_cat; + } + } + + printf("\n"); + printf("Test 2: strlcpy() versus sm_strlpy()\n"); + loops = LOOPS; +redo_cpy: + if (gettimeofday(&t1, NULL) < 0) + fatal("gettimeofday"); + + for (a = 0; a < loops; a++) + strlcpy(dest, source, SRC_SIZE - 1); + + if (gettimeofday(&t2, NULL) < 0) + fatal("gettimeofday"); + + printf("\tstrlcpy() result: %ld seconds\n", one = toseconds(t2, t1)); + + if (gettimeofday(&t1, NULL) < 0) + fatal("gettimeofday"); + + for (a = 0; a < loops; a++) + sm_strlcpy(dest, source, SRC_SIZE - 1); + + if (gettimeofday(&t2, NULL) < 0) + fatal("gettimeofday"); + + printf("\tsm_strlcpy() result: %ld seconds\n", two = toseconds(t2, t1)); + + if (one - two >= -2 && one - two <= 2) + { + loops += loops; + if (loops < 0L || one > MAXTIME) + { + printf("\t\t** results too close: no decision\n"); + } + else + { + printf("\t\t** results too close redoing test %ld times **\n", + loops); + goto redo_cpy; + } + } + + printf("\n\n"); + printf("Interpreting the results:\n"); + printf("\tFor differences larger than 2 seconds, the lower value is\n"); + printf("\tbetter and that function should be used for performance\n"); + printf("\treasons.\n\n"); + printf("This program will re-run the tests when the difference is\n"); + printf("less than 2 seconds.\n"); + printf("The result will vary depending on the compiler optimization\n"); printf("level used. Compiling the sendmail libsm library with a\n"); + printf("better optimization level can change the results.\n"); +#endif /* !SM_CONF_STRL */ + return 0; +} diff --git a/gnu/dist/sendmail/libsm/cdefs.html b/gnu/dist/sendmail/libsm/cdefs.html new file mode 100644 index 000000000000..c4f252161c51 --- /dev/null +++ b/gnu/dist/sendmail/libsm/cdefs.html @@ -0,0 +1,107 @@ + + + libsm : C Language Portability Macros + + + +Back to libsm overview + +

+

libsm : C Language Portability Macros

+
Id: cdefs.html,v 1.2 2000/12/07 17:33:09 dmoen Exp +
+ +

Description

+ +The header file <sm/cdefs.h> +defines portable interfaces to non-portable features +of various C compilers. +It also assists you in writing C header files that are compatible +with C++. + +
+
+ __P(parameterlist) +
+ This macro is used to write portable function prototypes. + For example, + +
+int foo __P((int));
+
+ +
+ __CONCAT(x,y) +
+ This macro concatenates two tokens x and y, + forming a single token xy. + Warning: make sure there is no white space around the arguments x and y. +

+ +

+ __STRING(x) +
+ This macro converts the token sequence x into a string literal. +

+ +

+ __BEGIN_DECLS, __END_DECLS +
+ These macros are used to write C header files that are compatible + with C++ compilers. + Put __BEGIN_DECLS before the first function or variable + declaration in your header file, + and put __END_DECLS after the last function or variable + declaration. +

+ +

+ const, signed, volatile +
+ For pre-ANSI C compilers, const, signed + and volatile are defined as empty macros. + This means you can use these keywords without introducing + portability problems. +

+ +

+ SM_DEAD(function_declaration) +
+ This macro modifies a prototype of a function + that does not return to its caller. + With some versions of gcc, this will result in slightly better code, + and can suppress some useless warnings produced by gcc -Wall. + For example, + +
+SM_DEAD(void exit __P((int)));
+
+ +
+ SM_UNUSED(variable_declaration) +
+ This macro modifies a definition of an unused + local variable, global variable or function parameter + in order to suppress compiler warnings. + Examples: + +
+SM_UNUSED(static const char Id[]) = "@(#)Id: cdefs.html,v 1.2 2000/12/07 17:33:09 dmoen Exp";
+void
+foo(x)
+	SM_UNUSED(int x);
+{
+	SM_UNUSED(int y) = 0;
+	return 0;
+}
+void
+bar(SM_UNUSED(int x))
+{
+	return 0;
+}
+
+ +
+ + + diff --git a/gnu/dist/sendmail/libsm/cf.c b/gnu/dist/sendmail/libsm/cf.c new file mode 100644 index 000000000000..ee7579c19961 --- /dev/null +++ b/gnu/dist/sendmail/libsm/cf.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: cf.c,v 1.6 2001/09/11 04:04:47 gshapiro Exp") + +#include +#include + +#include +#include +#include +#include + +/* +** SM_CF_GETOPT -- look up option values in the sendmail.cf file +** +** Open the sendmail.cf file and parse all of the 'O' directives. +** Each time one of the options named in the option vector optv +** is found, store a malloced copy of the option value in optv. +** +** Parameters: +** path -- pathname of sendmail.cf file +** optc -- size of option vector +** optv -- pointer to option vector +** +** Results: +** 0 on success, or an errno value on failure. +** An exception is raised on malloc failure. +*/ + +int +sm_cf_getopt(path, optc, optv) + char *path; + int optc; + SM_CF_OPT_T *optv; +{ + SM_FILE_T *cfp; + char buf[2048]; + char *p; + char *id; + char *idend; + char *val; + int i; + + cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, path, SM_IO_RDONLY, NULL); + if (cfp == NULL) + return errno; + + while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL) + { + p = strchr(buf, '\n'); + if (p != NULL) + *p = '\0'; + + if (buf[0] != 'O' || buf[1] != ' ') + continue; + + id = &buf[2]; + val = strchr(id, '='); + if (val == NULL) + val = idend = id + strlen(id); + else + { + idend = val; + ++val; + while (*val == ' ') + ++val; + while (idend > id && idend[-1] == ' ') + --idend; + *idend = '\0'; + } + + for (i = 0; i < optc; ++i) + { + if (sm_strcasecmp(optv[i].opt_name, id) == 0) + { + optv[i].opt_val = sm_strdup_x(val); + break; + } + } + } + if (sm_io_error(cfp)) + { + int save_errno = errno; + + (void) sm_io_close(cfp, SM_TIME_DEFAULT); + errno = save_errno; + return errno; + } + (void) sm_io_close(cfp, SM_TIME_DEFAULT); + return 0; +} diff --git a/gnu/dist/sendmail/libsm/clock.c b/gnu/dist/sendmail/libsm/clock.c new file mode 100644 index 000000000000..2d10ee0edb49 --- /dev/null +++ b/gnu/dist/sendmail/libsm/clock.c @@ -0,0 +1,528 @@ +/* + * Copyright (c) 1998-2002 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. + * + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: clock.c,v 1.35.2.2 2002/06/27 23:24:20 gshapiro Exp") +#include +#include +#include +#if SM_CONF_SETITIMER +# include +#endif /* SM_CONF_SETITIMER */ +#include +#include +#include +#include +#include "local.h" + +#ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +#endif /* ! sigmask */ + +static void sm_endsleep __P((void)); + + +/* +** SM_SETEVENTM -- set an event to happen at a specific time in milliseconds. +** +** Events are stored in a sorted list for fast processing. +** An event only applies to the process that set it. +** Source is #ifdef'd to work with older OS's that don't have setitimer() +** (that is, don't have a timer granularity less than 1 second). +** +** Parameters: +** intvl -- interval until next event occurs (milliseconds). +** func -- function to call on event. +** arg -- argument to func on event. +** +** Returns: +** On success returns the SM_EVENT entry created. +** On failure returns NULL. +** +** Side Effects: +** none. +*/ + +static SM_EVENT *volatile SmEventQueue; /* head of event queue */ +static SM_EVENT *volatile SmFreeEventList; /* list of free events */ + +SM_EVENT * +sm_seteventm(intvl, func, arg) + int intvl; + void (*func)(); + int arg; +{ + ENTER_CRITICAL(); + if (SmFreeEventList == NULL) + { + SmFreeEventList = (SM_EVENT *) sm_pmalloc_x(sizeof *SmFreeEventList); + SmFreeEventList->ev_link = NULL; + } + LEAVE_CRITICAL(); + + return sm_sigsafe_seteventm(intvl, func, arg); +} + +/* +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +SM_EVENT * +sm_sigsafe_seteventm(intvl, func, arg) + int intvl; + void (*func)(); + int arg; +{ + register SM_EVENT **evp; + register SM_EVENT *ev; +#if SM_CONF_SETITIMER + auto struct timeval now, nowi, ival; + auto struct itimerval itime; +#else /* SM_CONF_SETITIMER */ + auto time_t now, nowi; +#endif /* SM_CONF_SETITIMER */ + int wasblocked; + + /* negative times are not allowed */ + if (intvl <= 0) + return NULL; + + wasblocked = sm_blocksignal(SIGALRM); +#if SM_CONF_SETITIMER + ival.tv_sec = intvl / 1000; + ival.tv_usec = (intvl - ival.tv_sec * 1000) * 10; + (void) gettimeofday(&now, NULL); + nowi = now; + timeradd(&now, &ival, &nowi); +#else /* SM_CONF_SETITIMER */ + now = time(NULL); + nowi = now + (time_t)(intvl / 1000); +#endif /* SM_CONF_SETITIMER */ + + /* search event queue for correct position */ + for (evp = (SM_EVENT **) (&SmEventQueue); + (ev = *evp) != NULL; + evp = &ev->ev_link) + { +#if SM_CONF_SETITIMER + if (timercmp(&(ev->ev_time), &nowi, >=)) +#else /* SM_CONF_SETITIMER */ + if (ev->ev_time >= nowi) +#endif /* SM_CONF_SETITIMER */ + break; + } + + ENTER_CRITICAL(); + if (SmFreeEventList == NULL) + { + /* + ** This shouldn't happen. If called from sm_seteventm(), + ** we have just malloced a SmFreeEventList entry. If + ** called from a signal handler, it should have been + ** from an existing event which sm_tick() just added to + ** SmFreeEventList. + */ + + LEAVE_CRITICAL(); + return NULL; + } + else + { + ev = SmFreeEventList; + SmFreeEventList = ev->ev_link; + } + LEAVE_CRITICAL(); + + /* insert new event */ + ev->ev_time = nowi; + ev->ev_func = func; + ev->ev_arg = arg; + ev->ev_pid = getpid(); + ENTER_CRITICAL(); + ev->ev_link = *evp; + *evp = ev; + LEAVE_CRITICAL(); + + (void) sm_signal(SIGALRM, sm_tick); +# if SM_CONF_SETITIMER + timersub(&SmEventQueue->ev_time, &now, &itime.it_value); + itime.it_interval.tv_sec = 0; + itime.it_interval.tv_usec = 0; + if (itime.it_value.tv_sec < 0) + itime.it_value.tv_sec = 0; + if (itime.it_value.tv_sec == 0 && itime.it_value.tv_usec == 0) + itime.it_value.tv_usec = 1000; + (void) setitimer(ITIMER_REAL, &itime, NULL); +# else /* SM_CONF_SETITIMER */ + intvl = SmEventQueue->ev_time - now; + (void) alarm((unsigned) intvl < 1 ? 1 : intvl); +# endif /* SM_CONF_SETITIMER */ + if (wasblocked == 0) + (void) sm_releasesignal(SIGALRM); + return ev; +} +/* +** SM_CLREVENT -- remove an event from the event queue. +** +** Parameters: +** ev -- pointer to event to remove. +** +** Returns: +** none. +** +** Side Effects: +** arranges for event ev to not happen. +*/ + +void +sm_clrevent(ev) + register SM_EVENT *ev; +{ + register SM_EVENT **evp; + int wasblocked; +# if SM_CONF_SETITIMER + struct itimerval clr; +# endif /* SM_CONF_SETITIMER */ + + if (ev == NULL) + return; + + /* find the parent event */ + wasblocked = sm_blocksignal(SIGALRM); + for (evp = (SM_EVENT **) (&SmEventQueue); + *evp != NULL; + evp = &(*evp)->ev_link) + { + if (*evp == ev) + break; + } + + /* now remove it */ + if (*evp != NULL) + { + ENTER_CRITICAL(); + *evp = ev->ev_link; + ev->ev_link = SmFreeEventList; + SmFreeEventList = ev; + LEAVE_CRITICAL(); + } + + /* restore clocks and pick up anything spare */ + if (wasblocked == 0) + (void) sm_releasesignal(SIGALRM); + if (SmEventQueue != NULL) + (void) kill(getpid(), SIGALRM); + else + { + /* nothing left in event queue, no need for an alarm */ +# if SM_CONF_SETITIMER + clr.it_interval.tv_sec = 0; + clr.it_interval.tv_usec = 0; + clr.it_value.tv_sec = 0; + clr.it_value.tv_usec = 0; + (void) setitimer(ITIMER_REAL, &clr, NULL); +# else /* SM_CONF_SETITIMER */ + (void) alarm(0); +# endif /* SM_CONF_SETITIMER */ + } +} +/* +** SM_CLEAR_EVENTS -- remove all events from the event queue. +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +sm_clear_events() +{ + register SM_EVENT *ev; +#if SM_CONF_SETITIMER + struct itimerval clr; +#endif /* SM_CONF_SETITIMER */ + int wasblocked; + + /* nothing will be left in event queue, no need for an alarm */ +#if SM_CONF_SETITIMER + clr.it_interval.tv_sec = 0; + clr.it_interval.tv_usec = 0; + clr.it_value.tv_sec = 0; + clr.it_value.tv_usec = 0; + (void) setitimer(ITIMER_REAL, &clr, NULL); +#else /* SM_CONF_SETITIMER */ + (void) alarm(0); +#endif /* SM_CONF_SETITIMER */ + + if (SmEventQueue == NULL) + return; + + wasblocked = sm_blocksignal(SIGALRM); + + /* find the end of the EventQueue */ + for (ev = SmEventQueue; ev->ev_link != NULL; ev = ev->ev_link) + continue; + + ENTER_CRITICAL(); + ev->ev_link = SmFreeEventList; + SmFreeEventList = SmEventQueue; + SmEventQueue = NULL; + LEAVE_CRITICAL(); + + /* restore clocks and pick up anything spare */ + if (wasblocked == 0) + (void) sm_releasesignal(SIGALRM); +} +/* +** SM_TICK -- take a clock tick +** +** Called by the alarm clock. This routine runs events as needed. +** Always called as a signal handler, so we assume that SIGALRM +** has been blocked. +** +** Parameters: +** One that is ignored; for compatibility with signal handlers. +** +** Returns: +** none. +** +** Side Effects: +** calls the next function in EventQueue. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED */ +SIGFUNC_DECL +sm_tick(sig) + int sig; +{ + register SM_EVENT *ev; + pid_t mypid; + int save_errno = errno; +#if SM_CONF_SETITIMER + struct itimerval clr; + struct timeval now; +#else /* SM_CONF_SETITIMER */ + register time_t now; +#endif /* SM_CONF_SETITIMER */ + +#if SM_CONF_SETITIMER + clr.it_interval.tv_sec = 0; + clr.it_interval.tv_usec = 0; + clr.it_value.tv_sec = 0; + clr.it_value.tv_usec = 0; + (void) setitimer(ITIMER_REAL, &clr, NULL); + gettimeofday(&now, NULL); +#else /* SM_CONF_SETITIMER */ + (void) alarm(0); + now = time(NULL); +#endif /* SM_CONF_SETITIMER */ + + FIX_SYSV_SIGNAL(sig, sm_tick); + errno = save_errno; + CHECK_CRITICAL(sig); + + mypid = getpid(); + while (PendingSignal != 0) + { + int sigbit = 0; + int sig = 0; + + if (bitset(PEND_SIGHUP, PendingSignal)) + { + sigbit = PEND_SIGHUP; + sig = SIGHUP; + } + else if (bitset(PEND_SIGINT, PendingSignal)) + { + sigbit = PEND_SIGINT; + sig = SIGINT; + } + else if (bitset(PEND_SIGTERM, PendingSignal)) + { + sigbit = PEND_SIGTERM; + sig = SIGTERM; + } + else if (bitset(PEND_SIGUSR1, PendingSignal)) + { + sigbit = PEND_SIGUSR1; + sig = SIGUSR1; + } + else + { + /* If we get here, we are in trouble */ + abort(); + } + PendingSignal &= ~sigbit; + kill(mypid, sig); + } + +#if SM_CONF_SETITIMER + gettimeofday(&now, NULL); +#else /* SM_CONF_SETITIMER */ + now = time(NULL); +#endif /* SM_CONF_SETITIMER */ + while ((ev = SmEventQueue) != NULL && + (ev->ev_pid != mypid || +#if SM_CONF_SETITIMER + timercmp(&ev->ev_time, &now, <=) +#else /* SM_CONF_SETITIMER */ + ev->ev_time <= now +#endif /* SM_CONF_SETITIMER */ + )) + { + void (*f)(); + int arg; + pid_t pid; + + /* process the event on the top of the queue */ + ev = SmEventQueue; + SmEventQueue = SmEventQueue->ev_link; + + /* we must be careful in here because ev_func may not return */ + f = ev->ev_func; + arg = ev->ev_arg; + pid = ev->ev_pid; + ENTER_CRITICAL(); + ev->ev_link = SmFreeEventList; + SmFreeEventList = ev; + LEAVE_CRITICAL(); + if (pid != getpid()) + continue; + if (SmEventQueue != NULL) + { +#if SM_CONF_SETITIMER + if (timercmp(&SmEventQueue->ev_time, &now, >)) + { + timersub(&SmEventQueue->ev_time, &now, + &clr.it_value); + clr.it_interval.tv_sec = 0; + clr.it_interval.tv_usec = 0; + if (clr.it_value.tv_sec < 0) + clr.it_value.tv_sec = 0; + if (clr.it_value.tv_sec == 0 && + clr.it_value.tv_usec == 0) + clr.it_value.tv_usec = 1000; + (void) setitimer(ITIMER_REAL, &clr, NULL); + } + else + { + clr.it_interval.tv_sec = 0; + clr.it_interval.tv_usec = 0; + clr.it_value.tv_sec = 3; + clr.it_value.tv_usec = 0; + (void) setitimer(ITIMER_REAL, &clr, NULL); + } +#else /* SM_CONF_SETITIMER */ + if (SmEventQueue->ev_time > now) + (void) alarm((unsigned) (SmEventQueue->ev_time + - now)); + else + (void) alarm(3); +#endif /* SM_CONF_SETITIMER */ + } + + /* call ev_func */ + errno = save_errno; + (*f)(arg); +#if SM_CONF_SETITIMER + clr.it_interval.tv_sec = 0; + clr.it_interval.tv_usec = 0; + clr.it_value.tv_sec = 0; + clr.it_value.tv_usec = 0; + (void) setitimer(ITIMER_REAL, &clr, NULL); + gettimeofday(&now, NULL); +#else /* SM_CONF_SETITIMER */ + (void) alarm(0); + now = time(NULL); +#endif /* SM_CONF_SETITIMER */ + } + if (SmEventQueue != NULL) + { +#if SM_CONF_SETITIMER + timersub(&SmEventQueue->ev_time, &now, &clr.it_value); + clr.it_interval.tv_sec = 0; + clr.it_interval.tv_usec = 0; + if (clr.it_value.tv_sec < 0) + clr.it_value.tv_sec = 0; + if (clr.it_value.tv_sec == 0 && clr.it_value.tv_usec == 0) + clr.it_value.tv_usec = 1000; + (void) setitimer(ITIMER_REAL, &clr, NULL); +#else /* SM_CONF_SETITIMER */ + (void) alarm((unsigned) (SmEventQueue->ev_time - now)); +#endif /* SM_CONF_SETITIMER */ + } + errno = save_errno; + return SIGFUNC_RETURN; +} +/* +** SLEEP -- a version of sleep that works with this stuff +** +** Because Unix sleep uses the alarm facility, I must reimplement +** it here. +** +** Parameters: +** intvl -- time to sleep. +** +** Returns: +** zero. +** +** Side Effects: +** waits for intvl time. However, other events can +** be run during that interval. +*/ + + +static bool volatile SmSleepDone; + +#ifndef SLEEP_T +# define SLEEP_T unsigned int +#endif /* ! SLEEP_T */ + +SLEEP_T +sleep(intvl) + unsigned int intvl; +{ + int was_held; + + if (intvl == 0) + return (SLEEP_T) 0; + SmSleepDone = false; + (void) sm_setevent((time_t) intvl, sm_endsleep, 0); + was_held = sm_releasesignal(SIGALRM); + while (!SmSleepDone) + (void) pause(); + if (was_held > 0) + (void) sm_blocksignal(SIGALRM); + return (SLEEP_T) 0; +} + +static void +sm_endsleep() +{ + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + SmSleepDone = true; +} + diff --git a/gnu/dist/sendmail/libsm/clrerr.c b/gnu/dist/sendmail/libsm/clrerr.c new file mode 100644 index 000000000000..d904896ce3d6 --- /dev/null +++ b/gnu/dist/sendmail/libsm/clrerr.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: clrerr.c,v 1.13 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include "local.h" + +/* +** SM_IO_CLEARERR -- public function to clear a file pointer's error status +** +** Parameters: +** fp -- the file pointer +** +** Returns: +** nothing. +*/ +#undef sm_io_clearerr + +void +sm_io_clearerr(fp) + SM_FILE_T *fp; +{ + SM_REQUIRE_ISA(fp, SmFileMagic); + + sm_clearerr(fp); +} diff --git a/gnu/dist/sendmail/libsm/config.c b/gnu/dist/sendmail/libsm/config.c new file mode 100644 index 000000000000..49891faf6935 --- /dev/null +++ b/gnu/dist/sendmail/libsm/config.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: config.c,v 1.27 2002/01/23 17:30:48 gshapiro Exp") + +#include +#include +#include +#include + +/* +** PUTENV -- emulation of putenv() in terms of setenv() +** +** Not needed on Posix-compliant systems. +** This doesn't have full Posix semantics, but it's good enough +** for sendmail. +** +** Parameter: +** env -- the environment to put. +** +** Returns: +** 0 on success, < 0 on failure. +*/ + +#if NEEDPUTENV + +# if NEEDPUTENV == 2 /* no setenv(3) call available */ + +int +putenv(str) + char *str; +{ + char **current; + int matchlen, envlen = 0; + char *tmp; + char **newenv; + static bool first = true; + extern char **environ; + + /* + ** find out how much of str to match when searching + ** for a string to replace. + */ + + if ((tmp = strchr(str, '=')) == NULL || tmp == str) + matchlen = strlen(str); + else + matchlen = (int) (tmp - str); + ++matchlen; + + /* + ** Search for an existing string in the environment and find the + ** length of environ. If found, replace and exit. + */ + + for (current = environ; *current != NULL; current++) + { + ++envlen; + + if (strncmp(str, *current, matchlen) == 0) + { + /* found it, now insert the new version */ + *current = (char *) str; + return 0; + } + } + + /* + ** 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) + { + newenv = (char **) sm_malloc(sizeof(char *) * (envlen + 2)); + if (newenv == NULL) + return -1; + + first = false; + (void) memcpy(newenv, environ, sizeof(char *) * envlen); + } + else + { + newenv = (char **) sm_realloc((char *) environ, + sizeof(char *) * (envlen + 2)); + if (newenv == NULL) + return -1; + } + + /* actually add in the new entry */ + environ = newenv; + environ[envlen] = (char *) str; + environ[envlen + 1] = NULL; + + return 0; +} + +# else /* NEEDPUTENV == 2 */ + +int +putenv(env) + char *env; +{ + char *p; + int l; + char nbuf[100]; + + p = strchr(env, '='); + if (p == NULL) + return 0; + l = p - env; + if (l > sizeof nbuf - 1) + l = sizeof nbuf - 1; + memmove(nbuf, env, l); + nbuf[l] = '\0'; + return setenv(nbuf, ++p, 1); +} + +# endif /* NEEDPUTENV == 2 */ +#endif /* NEEDPUTENV */ +/* +** UNSETENV -- remove a variable from the environment +** +** Not needed on newer systems. +** +** Parameters: +** name -- the string name of the environment variable to be +** deleted from the current environment. +** +** Returns: +** none. +** +** Globals: +** environ -- a pointer to the current environment. +** +** Side Effects: +** Modifies environ. +*/ + +#if !HASUNSETENV + +void +unsetenv(name) + char *name; +{ + extern char **environ; + register char **pp; + int len = strlen(name); + + for (pp = environ; *pp != NULL; pp++) + { + if (strncmp(name, *pp, len) == 0 && + ((*pp)[len] == '=' || (*pp)[len] == '\0')) + break; + } + + for (; *pp != NULL; pp++) + *pp = pp[1]; +} + +#endif /* !HASUNSETENV */ + +char *SmCompileOptions[] = +{ +#if SM_CONF_BROKEN_STRTOD + "SM_CONF_BROKEN_STRTOD", +#endif /* SM_CONF_BROKEN_STRTOD */ +#if SM_CONF_GETOPT + "SM_CONF_GETOPT", +#endif /* SM_CONF_GETOPT */ +#if SM_CONF_LDAP_MEMFREE + "SM_CONF_LDAP_MEMFREE", +#endif /* SM_CONF_LDAP_MEMFREE */ +#if SM_CONF_LONGLONG + "SM_CONF_LONGLONG", +#endif /* SM_CONF_LONGLONG */ +#if SM_CONF_MEMCHR + "SM_CONF_MEMCHR", +#endif /* SM_CONF_MEMCHR */ +#if SM_CONF_MSG + "SM_CONF_MSG", +#endif /* SM_CONF_MSG */ +#if SM_CONF_QUAD_T + "SM_CONF_QUAD_T", +#endif /* SM_CONF_QUAD_T */ +#if SM_CONF_SEM + "SM_CONF_SEM", +#endif /* SM_CONF_SEM */ +#if SM_CONF_SETITIMER + "SM_CONF_SETITIMER", +#endif /* SM_CONF_SETITIMER */ +#if SM_CONF_SHM + "SM_CONF_SHM", +#endif /* SM_CONF_SHM */ +#if SM_CONF_SHM_DELAY + "SM_CONF_SHM_DELAY", +#endif /* SM_CONF_SHM_DELAY */ +#if SM_CONF_SSIZE_T + "SM_CONF_SSIZE_T", +#endif /* SM_CONF_SSIZE_T */ +#if SM_CONF_STDBOOL_H + "SM_CONF_STDBOOL_H", +#endif /* SM_CONF_STDBOOL_H */ +#if SM_CONF_STDDEF_H + "SM_CONF_STDDEF_H", +#endif /* SM_CONF_STDDEF_H */ + +#if 0 +/* XXX this is always enabled (for now) */ +#if SM_CONF_STRL + "SM_CONF_STRL", +#endif /* SM_CONF_STRL */ +#endif /* 0 */ + +#if SM_CONF_SYS_CDEFS_H + "SM_CONF_SYS_CDEFS_H", +#endif /* SM_CONF_SYS_CDEFS_H */ +#if SM_CONF_SYSEXITS_H + "SM_CONF_SYSEXITS_H", +#endif /* SM_CONF_SYSEXITS_H */ +#if SM_CONF_UID_GID + "SM_CONF_UID_GID", +#endif /* SM_CONF_UID_GID */ +#if SM_HEAP_CHECK + "SM_HEAP_CHECK", +#endif /* SM_HEAP_CHECK */ +#if defined(SM_OS_NAME) && defined(__STDC__) + "SM_OS=sm_os_" SM_OS_NAME, +#endif /* defined(SM_OS_NAME) && defined(__STDC__) */ +#if SM_VA_STD + "SM_VA_STD", +#endif /* SM_VA_STD */ + NULL +}; diff --git a/gnu/dist/sendmail/libsm/debug.c b/gnu/dist/sendmail/libsm/debug.c new file mode 100644 index 000000000000..aa35c341eb4f --- /dev/null +++ b/gnu/dist/sendmail/libsm/debug.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: debug.c,v 1.28 2001/09/25 19:57:05 gshapiro Exp") + +/* +** libsm debugging and tracing +** For documentation, see debug.html. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** Abstractions for printing trace messages. +*/ + +/* +** The output file to which trace output is directed. +** There is a controversy over whether this variable +** should be process global or thread local. +** To make the interface more abstract, we've hidden the +** variable behind access functions. +*/ + +static SM_FILE_T *SmDebugOutput = smioout; + +/* +** SM_DEBUG_FILE -- Returns current debug file pointer. +** +** Parameters: +** none. +** +** Returns: +** current debug file pointer. +*/ + +SM_FILE_T * +sm_debug_file() +{ + return SmDebugOutput; +} + +/* +** SM_DEBUG_SETFILE -- Sets debug file pointer. +** +** Parameters: +** fp -- new debug file pointer. +** +** Returns: +** none. +** +** Side Effects: +** Sets SmDebugOutput. +*/ + +void +sm_debug_setfile(fp) + SM_FILE_T *fp; +{ + SmDebugOutput = fp; +} + +/* +** SM_DPRINTF -- printf() for debug output. +** +** Parameters: +** fmt -- format for printf() +** +** Returns: +** none. +*/ + +void +#if SM_VA_STD +sm_dprintf(char *fmt, ...) +#else /* SM_VA_STD */ +sm_dprintf(fmt, va_alist) + char *fmt; + va_dcl +#endif /* SM_VA_STD */ +{ + SM_VA_LOCAL_DECL + + if (SmDebugOutput == NULL) + return; + SM_VA_START(ap, fmt); + sm_io_vfprintf(SmDebugOutput, SmDebugOutput->f_timeout, fmt, ap); + SM_VA_END(ap); +} + +/* +** SM_DFLUSH -- Flush debug output. +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +sm_dflush() +{ + sm_io_flush(SmDebugOutput, SM_TIME_DEFAULT); +} + +/* +** This is the internal database of debug settings. +** The semantics of looking up a setting in the settings database +** are that the *last* setting specified in a -d option on the sendmail +** command line that matches a given SM_DEBUG structure is the one that is +** used. That is necessary to conform to the existing semantics of +** the sendmail -d option. We store the settings as a linked list in +** reverse order, so when we do a lookup, we take the *first* entry +** that matches. +*/ + +typedef struct sm_debug_setting SM_DEBUG_SETTING_T; +struct sm_debug_setting +{ + const char *ds_pattern; + unsigned int ds_level; + SM_DEBUG_SETTING_T *ds_next; +}; +SM_DEBUG_SETTING_T *SmDebugSettings = NULL; + +/* +** We keep a linked list of SM_DEBUG structures that have been initialized, +** for use by sm_debug_reset. +*/ + +SM_DEBUG_T *SmDebugInitialized = NULL; + +const char SmDebugMagic[] = "sm_debug"; + +/* +** SM_DEBUG_RESET -- Reset SM_DEBUG structures. +** +** Reset all SM_DEBUG structures back to the uninitialized state. +** This is used by sm_debug_addsetting to ensure that references to +** SM_DEBUG structures that occur before sendmail processes its -d flags +** do not cause those structures to be permanently forced to level 0. +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +sm_debug_reset() +{ + SM_DEBUG_T *debug; + + for (debug = SmDebugInitialized; + debug != NULL; + debug = debug->debug_next) + { + debug->debug_level = SM_DEBUG_UNKNOWN; + } + SmDebugInitialized = NULL; +} + +/* +** SM_DEBUG_ADDSETTING_X -- add an entry to the database of debug settings +** +** Parameters: +** pattern -- a shell-style glob pattern (see sm_match). +** WARNING: the storage for 'pattern' will be owned by +** the debug package, so it should either be a string +** literal or the result of a call to sm_strdup_x. +** level -- a non-negative integer. +** +** Returns: +** none. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +void +sm_debug_addsetting_x(pattern, level) + const char *pattern; + int level; +{ + SM_DEBUG_SETTING_T *s; + + SM_REQUIRE(pattern != NULL); + SM_REQUIRE(level >= 0); + s = sm_malloc_x(sizeof(SM_DEBUG_SETTING_T)); + s->ds_pattern = pattern; + s->ds_level = (unsigned int) level; + s->ds_next = SmDebugSettings; + SmDebugSettings = s; + sm_debug_reset(); +} + +/* +** PARSE_NAMED_SETTING_X -- process a symbolic debug setting +** +** Parameters: +** s -- Points to a non-empty \0 or , terminated string, +** of which the initial character is not a digit. +** +** Returns: +** pointer to terminating \0 or , character. +** +** Exceptions: +** F:sm.heap -- out of memory. +** +** Side Effects: +** adds the setting to the database. +*/ + +static const char * +parse_named_setting_x(s) + register const char *s; +{ + const char *pat, *endpat; + int level; + + pat = s; + while (*s != '\0' && *s != ',' && *s != '.') + ++s; + endpat = s; + if (*s == '.') + { + ++s; + level = 0; + while (isascii(*s) && isdigit(*s)) + { + level = level * 10 + (*s - '0'); + ++s; + } + if (level < 0) + level = 0; + } + else + level = 1; + + sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level); + + /* skip trailing junk */ + while (*s != '\0' && *s != ',') + ++s; + + return s; +} + +/* +** SM_DEBUG_ADDSETTINGS_X -- process a list of debug options +** +** Parameters: +** s -- a list of debug settings, eg the argument to the +** sendmail -d option. +** +** The syntax of the string s is as follows: +** +** ::= | "," +** ::= | "." +** ::= [a-zA-Z_*?][a-zA-Z0-9_*?]* +** +** However, note that we skip over anything we don't +** understand, rather than report an error. +** +** Returns: +** none. +** +** Exceptions: +** F:sm.heap -- out of memory +** +** Side Effects: +** updates the database of debug settings. +*/ + +void +sm_debug_addsettings_x(s) + register const char *s; +{ + for (;;) + { + if (*s == '\0') + return; + if (*s == ',') + { + ++s; + continue; + } + s = parse_named_setting_x(s); + } +} + +/* +** SM_DEBUG_LOADLEVEL -- Get activation level of the specified debug object. +** +** Parameters: +** debug -- debug object. +** +** Returns: +** Activation level of the specified debug object. +** +** Side Effects: +** Ensures that the debug object is initialized. +*/ + +int +sm_debug_loadlevel(debug) + SM_DEBUG_T *debug; +{ + if (debug->debug_level == SM_DEBUG_UNKNOWN) + { + SM_DEBUG_SETTING_T *s; + + for (s = SmDebugSettings; s != NULL; s = s->ds_next) + { + if (sm_match(debug->debug_name, s->ds_pattern)) + { + debug->debug_level = s->ds_level; + goto initialized; + } + } + debug->debug_level = 0; + initialized: + debug->debug_next = SmDebugInitialized; + SmDebugInitialized = debug; + } + return (int) debug->debug_level; +} + +/* +** SM_DEBUG_LOADACTIVE -- Activation level reached? +** +** Parameters: +** debug -- debug object. +** level -- level to check. +** +** Returns: +** true iff the activation level of the specified debug +** object >= level. +** +** Side Effects: +** Ensures that the debug object is initialized. +*/ + +bool +sm_debug_loadactive(debug, level) + SM_DEBUG_T *debug; + int level; +{ + return sm_debug_loadlevel(debug) >= level; +} diff --git a/gnu/dist/sendmail/libsm/debug.html b/gnu/dist/sendmail/libsm/debug.html new file mode 100644 index 000000000000..573c6f879393 --- /dev/null +++ b/gnu/dist/sendmail/libsm/debug.html @@ -0,0 +1,272 @@ + + + libsm : Debugging and Tracing + + + +Back to libsm overview + +
+

libsm : Debugging and Tracing

+
Id: debug.html,v 1.9 2002/02/02 16:50:56 ca Exp +
+ +

Introduction

+ +The debug and trace package provides abstractions for writing trace +messages, and abstractions for enabling and disabling debug and +trace code at run time. + +

+Sendmail 8.11 and earlier has a -d option which +lets you turn on debug and trace code. +Debug categories are integers from 0 to 99, with the sole exception +of "ANSI", which is a named debug category. + +

+The libsm debug package supports named debug categories. +Debug category names have the form of C identifiers. +For example, sm_trace_heap controls the output of trace +messages from the sm heap package, while sm_check_heap +controls the argument validity checking and memory leak detection +features of the sm heap package. + +

+In sendmail 8.12, the -d flag is generalized +to support both the original style numeric categories, for backwards +compatibility, and the new style named categories implemented by libsm. +With this change, +"-dANSI" is implemented using a libsm named debug category. +You will be able to set a collection of named debug categories to +the same activation level by specifying a glob pattern. +For example, +

+
+ -dANSI +
+ sets the named category "ANSI" to level 1, +
+ -dfoo_*.3 +
+ sets all named categories matching the glob pattern "foo_*" to level 3, +
+ -d0-99.1 +
+ sets the numeric categories 0 through 99 to level 1, and +
+ -dANSI,foo_*.3,0-99.1 +
+ does all of the above. +
+ +

Synopsis

+ +
+#include <sm/debug.h>
+
+/*
+**  abstractions for printing trace messages
+*/
+void sm_dprintf(char *fmt, ...)
+void sm_dflush()
+void sm_debug_setfile(SM_FILE_T *)
+
+/*
+**  abstractions for setting and testing debug activation levels
+*/
+void sm_debug_addsettings(char *settings)
+void sm_debug_addsetting(char *pattern, int level)
+
+typedef struct sm_debug SM_DEBUG_T;
+SM_DEBUG_T dbg = SM_DEBUG_INITIALIZER("name", "@(#)$Debug: name - description $");
+
+bool sm_debug_active(SM_DEBUG_T *debug, int level)
+int  sm_debug_level(SM_DEBUG_T *debug)
+bool sm_debug_unknown(SM_DEBUG_T *debug)
+
+ +

Naming Conventions

+ +All debug categories defined by libsm have names of the form sm_*. +Debug categories that turn on trace output have names of the form +*_trace_*. +Debug categories that turn on run time checks have names of the form +*_check_*. +Here are all of the libsm debug categories as of March 2000: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Variable nameCategory nameMeaning
SmExpensiveAssertsm_check_assertenable expensive SM_ASSERT checking
SmExpensiveRequiresm_check_requireenable expensive SM_REQUIRE checking
SmExpensiveEnsuresm_check_ensureenable expensive SM_ENSURE checking
SmHeapTracesm_trace_heaptrace sm_{malloc,realloc,free} calls
SmHeapChecksm_check_heapenable checking and memory leak detection in sm_{malloc,realloc,free}
+ +

Function Reference

+ +
+
+ SM_DEBUG_INITIALIZER +
+ To create a new debug category, use the SM_DEBUG_INITIALIZER macro + to initialize a static variable of type SM_DEBUG_T. For example, +
+SM_DEBUG_T ANSI_debug = SM_DEBUG_INITIALIZER("ANSI",
+	    "@(#)$Debug: ANSI - enable reverse video in debug output $");
+
+ There is no centralized table of category names that needs to + be edited in order to add a new debug category. + The sole purpose of the second argument to SM_DEBUG_INITIALIZER + is to provide an easy way to find out what named debug categories + are present in a sendmail binary. You can use: +
+ident /usr/sbin/sendmail | grep Debug
+
+ or: +
+what /usr/sbin/sendmail | grep Debug
+
+ + +
+ void sm_debug_addsetting(char *pattern, int level) +
+ All debug categories default to activation level 0, which means + no activity. + This function updates an internal database of debug settings, + setting all categories whose name matches the specified glob + pattern to the specified activation level. The level argument + must be >= 0. +

+ + +

+ void sm_debug_addsettings(char *settings) +
+ This function is used to process the -d command line + option of Sendmail 9.x, and of other programs that support the + setting of named debug categories. The settings argument is a + comma-separated list of settings; each setting is a glob pattern, + optionally followed by a '.' and a decimal numeral. +

+ + +

+ bool sm_debug_active(SM_DEBUG_T *debug, int level) +
+ This macro returns true if the activation level of + the statically initialized debug structure debug + is >= the specified level. + The test is performed very efficiently: in the most common case, + when the result is false, only a single comparison + operation is performed. +

+ This macro performs a function call only if the debug structure has + an unknown activation level. All debug structures are in this state + at the beginning of program execution, and after a call to + sm_debug_addsetting. +

+ + +

+ int sm_debug_level(SM_DEBUG_T *debug) +
+ This macro returns the activation level of the specified debug structure. + The comparison +
+sm_debug_level(debug) >= level
+
+ is slightly less efficient than, but otherwise semantically + equivalent to +
+sm_debug_active(debug, level)
+
+

+ + +

+ bool sm_debug_unknown(SM_DEBUG_T *debug) +
+ This macro returns true if the activation level of the specified + debug structure is unknown. + Here is an example of how the macro might be used: +
+if (sm_debug_unknown(&FooDebug))
+{
+	if (sm_debug_active(&FooDebug, 1))
+	{
+		... perform some expensive data structure initializations
+		... in order to enable the "foo" debugging mechanism
+	}
+	else
+	{
+		... disable the "foo" debugging mechanism
+	}
+}
+
+ The purpose of using sm_debug_unknown in the above example + is to avoid performing the expensive initializations each time through + the code. So it's a performance hack. + A debug structure is in the "unknown" state at the beginning of + program execution, and after a call to sm_debug_addsetting. + A side effect of calling sm_debug_active is that the + activation level becomes known. +

+ + +

+ void sm_dprintf(char *fmt, ...) +
+ This function is used to print a debug message. + The standard idiom is +
+if (sm_debug_active(&BarDebug, 1))
+	sm_dprintf("bar: about to test tensile strength of bar %d\n", i);
+
+

+ +

+ void sm_dflush() +
+ Flush the debug output stream. +

+ +

+ void sm_debug_setfile(SM_FILE_T *file) +
+ This function lets you specify where debug output is printed. + By default, debug output is written to standard output. +

+ We want to allow you to direct debug output to syslog. + The current plan is to provide a standard interface for + creating an SM_FILE_T object that writes to syslog. + +

+ + + diff --git a/gnu/dist/sendmail/libsm/errstring.c b/gnu/dist/sendmail/libsm/errstring.c new file mode 100644 index 000000000000..ec8558391308 --- /dev/null +++ b/gnu/dist/sendmail/libsm/errstring.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2001 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. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: errstring.c,v 1.12 2001/10/03 16:09:32 ca Exp") + +#include +#include /* sys_errlist, on some platforms */ + +#include /* sm_snprintf */ +#include +#include + +#if NAMED_BIND +# include +#endif + +#if LDAPMAP +# include +# include /* for LDAP error codes */ +#endif /* LDAPMAP */ + +/* +** Notice: this file is used by libmilter. Please try to avoid +** using libsm specific functions. +*/ + +/* +** SM_ERRSTRING -- return string description of error code +** +** Parameters: +** errnum -- the error number to translate +** +** Returns: +** A string description of errnum. +*/ + +const char * +sm_errstring(errnum) + int errnum; +{ + char *ret; + + switch (errnum) + { + case EPERM: + /* SunOS gives "Not owner" -- this is the POSIX message */ + return "Operation not permitted"; + + /* + ** Error messages used internally in sendmail. + */ + + 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"; + + case E_SM_GRFILE: + return "Group readable file"; + + case E_SM_WRFILE: + return "World readable file"; + + /* + ** DNS error messages. + */ + +#if NAMED_BIND + case HOST_NOT_FOUND + E_DNSBASE: + return "Name server: host not found"; + + case TRY_AGAIN + E_DNSBASE: + return "Name server: host name lookup failure"; + + case NO_RECOVERY + E_DNSBASE: + return "Name server: non-recoverable error"; + + case NO_DATA + E_DNSBASE: + return "Name server: no data known"; +#endif /* NAMED_BIND */ + + /* + ** libsmdb error messages. + */ + + case SMDBE_MALLOC: + return "Memory allocation failed"; + + case SMDBE_GDBM_IS_BAD: + return "GDBM is not supported"; + + case SMDBE_UNSUPPORTED: + return "Unsupported action"; + + case SMDBE_DUPLICATE: + return "Key already exists"; + + case SMDBE_BAD_OPEN: + return "Database open failed"; + + case SMDBE_NOT_FOUND: + return "Key not found"; + + case SMDBE_UNKNOWN_DB_TYPE: + return "Unknown database type"; + + case SMDBE_UNSUPPORTED_DB_TYPE: + return "Support for database type not compiled into this program"; + + case SMDBE_INCOMPLETE: + return "DB sync did not finish"; + + case SMDBE_KEY_EMPTY: + return "Key is empty"; + + case SMDBE_KEY_EXIST: + return "Key already exists"; + + case SMDBE_LOCK_DEADLOCK: + return "Locker killed to resolve deadlock"; + + case SMDBE_LOCK_NOT_GRANTED: + return "Lock unavailable"; + + case SMDBE_LOCK_NOT_HELD: + return "Lock not held by locker"; + + case SMDBE_RUN_RECOVERY: + return "Database panic, run recovery"; + + case SMDBE_IO_ERROR: + return "I/O error"; + + case SMDBE_READ_ONLY: + return "Database opened read-only"; + + case SMDBE_DB_NAME_TOO_LONG: + return "Name too long"; + + case SMDBE_INVALID_PARAMETER: + return "Invalid parameter"; + + case SMDBE_ONLY_SUPPORTS_ONE_CURSOR: + return "Only one cursor allowed"; + + case SMDBE_NOT_A_VALID_CURSOR: + return "Invalid cursor"; + + case SMDBE_OLD_VERSION: + return "Berkeley DB file is an old version, recreate it"; + } + + /* + ** LDAP error messages. + */ + +#if LDAPMAP + if (errnum >= E_LDAPBASE) + return ldap_err2string(errnum - E_LDAPBASE); +#endif /* LDAPMAP */ + + ret = strerror(errnum); + if (ret == NULL) + { + static char buf[30]; + + (void) sm_snprintf(buf, sizeof buf, "Error %d", errnum); + return buf; + } + return ret; +} diff --git a/gnu/dist/sendmail/libsm/exc.c b/gnu/dist/sendmail/libsm/exc.c new file mode 100644 index 000000000000..a185489c2036 --- /dev/null +++ b/gnu/dist/sendmail/libsm/exc.c @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: exc.c,v 1.47 2002/01/09 18:51:43 ca Exp") + +/* +** exception handling +** For documentation, see exc.html +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +const char SmExcMagic[] = "sm_exc"; +const char SmExcTypeMagic[] = "sm_exc_type"; + +/* +** SM_ETYPE_PRINTF -- printf for exception types. +** +** Parameters: +** exc -- exception. +** stream -- file for output. +** +** Returns: +** none. +*/ + +/* +** A simple formatted print function that can be used as the print function +** by most exception types. It prints the printcontext string, interpreting +** occurrences of %0 through %9 as references to the argument vector. +** If exception argument 3 is an int or long, then %3 will print the +** argument in decimal, and %o3 or %x3 will print it in octal or hex. +*/ + +void +sm_etype_printf(exc, stream) + SM_EXC_T *exc; + SM_FILE_T *stream; +{ + size_t n = strlen(exc->exc_type->etype_argformat); + const char *p, *s; + char format; + + for (p = exc->exc_type->etype_printcontext; *p != '\0'; ++p) + { + if (*p != '%') + { + (void) sm_io_putc(stream, SM_TIME_DEFAULT, *p); + continue; + } + ++p; + if (*p == '\0') + { + (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%'); + break; + } + if (*p == '%') + { + (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%'); + continue; + } + format = '\0'; + if (isalpha(*p)) + { + format = *p++; + if (*p == '\0') + { + (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%'); + (void) sm_io_putc(stream, SM_TIME_DEFAULT, + format); + break; + } + } + if (isdigit(*p)) + { + size_t i = *p - '0'; + if (i < n) + { + switch (exc->exc_type->etype_argformat[i]) + { + case 's': + case 'r': + s = exc->exc_argv[i].v_str; + if (s == NULL) + s = "(null)"; + sm_io_fputs(stream, SM_TIME_DEFAULT, s); + continue; + case 'i': + sm_io_fprintf(stream, + SM_TIME_DEFAULT, + format == 'o' ? "%o" + : format == 'x' ? "%x" + : "%d", + exc->exc_argv[i].v_int); + continue; + case 'l': + sm_io_fprintf(stream, + SM_TIME_DEFAULT, + format == 'o' ? "%lo" + : format == 'x' ? "%lx" + : "%ld", + exc->exc_argv[i].v_long); + continue; + case 'e': + sm_exc_write(exc->exc_argv[i].v_exc, + stream); + continue; + } + } + } + (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%'); + if (format) + (void) sm_io_putc(stream, SM_TIME_DEFAULT, format); + (void) sm_io_putc(stream, SM_TIME_DEFAULT, *p); + } +} + +/* +** Standard exception types. +*/ + +/* +** SM_ETYPE_OS_PRINT -- Print OS related exception. +** +** Parameters: +** exc -- exception. +** stream -- file for output. +** +** Returns: +** none. +*/ + +static void +sm_etype_os_print __P(( + SM_EXC_T *exc, + SM_FILE_T *stream)); + +static void +sm_etype_os_print(exc, stream) + SM_EXC_T *exc; + SM_FILE_T *stream; +{ + int err = exc->exc_argv[0].v_int; + char *syscall = exc->exc_argv[1].v_str; + char *sysargs = exc->exc_argv[2].v_str; + + if (sysargs) + sm_io_fprintf(stream, SM_TIME_DEFAULT, "%s: %s failed: %s", + sysargs, syscall, sm_errstring(err)); + else + sm_io_fprintf(stream, SM_TIME_DEFAULT, "%s failed: %s", syscall, + sm_errstring(err)); +} + +/* +** SmEtypeOs represents the failure of a Unix system call. +** The three arguments are: +** int errno (eg, ENOENT) +** char *syscall (eg, "open") +** char *sysargs (eg, NULL or "/etc/mail/sendmail.cf") +*/ + +const SM_EXC_TYPE_T SmEtypeOs = +{ + SmExcTypeMagic, + "E:sm.os", + "isr", + sm_etype_os_print, + NULL, +}; + +/* +** SmEtypeErr is a completely generic error which should only be +** used in applications and test programs. Libraries should use +** more specific exception codes. +*/ + +const SM_EXC_TYPE_T SmEtypeErr = +{ + SmExcTypeMagic, + "E:sm.err", + "r", + sm_etype_printf, + "%0", +}; + +/* +** SM_EXC_VNEW_X -- Construct a new exception object. +** +** Parameters: +** etype -- type of exception. +** ap -- varargs. +** +** Returns: +** pointer to exception object. +*/ + +/* +** This is an auxiliary function called by sm_exc_new_x and sm_exc_raisenew_x. +** +** If an exception is raised, then to avoid a storage leak, we must: +** (a) Free all storage we have allocated. +** (b) Free all exception arguments in the varargs list. +** Getting this right is tricky. +** +** To see why (b) is required, consider the code fragment +** SM_EXCEPT(exc, "*") +** sm_exc_raisenew_x(&MyEtype, exc); +** SM_END_TRY +** In the normal case, sm_exc_raisenew_x will allocate and raise a new +** exception E that owns exc. When E is eventually freed, exc is also freed. +** In the exceptional case, sm_exc_raisenew_x must free exc before raising +** an out-of-memory exception so that exc is not leaked. +*/ + +SM_EXC_T * +sm_exc_vnew_x(etype, ap) + const SM_EXC_TYPE_T *etype; + va_list SM_NONVOLATILE ap; +{ + /* + ** All variables that are modified in the SM_TRY clause and + ** referenced in the SM_EXCEPT clause must be declared volatile. + */ + + /* NOTE: Type of si, i, and argc *must* match */ + SM_EXC_T * volatile exc = NULL; + int volatile si = 0; + SM_VAL_T * volatile argv = NULL; + int i, argc; + + SM_REQUIRE_ISA(etype, SmExcTypeMagic); + argc = strlen(etype->etype_argformat); + SM_TRY + { + /* + ** Step 1. Allocate the exception structure. + ** On failure, scan the varargs list and free all + ** exception arguments. + */ + + exc = sm_malloc_x(sizeof(SM_EXC_T)); + exc->sm_magic = SmExcMagic; + exc->exc_refcount = 1; + exc->exc_type = etype; + exc->exc_argv = NULL; + + /* + ** Step 2. Allocate the argument vector. + ** On failure, free exc, scan the varargs list and free all + ** exception arguments. On success, scan the varargs list, + ** and copy the arguments into argv. + */ + + argv = sm_malloc_x(argc * sizeof(SM_VAL_T)); + exc->exc_argv = argv; + for (i = 0; i < argc; ++i) + { + switch (etype->etype_argformat[i]) + { + case 'i': + argv[i].v_int = SM_VA_ARG(ap, int); + break; + case 'l': + argv[i].v_long = SM_VA_ARG(ap, long); + break; + case 'e': + argv[i].v_exc = SM_VA_ARG(ap, SM_EXC_T*); + break; + case 's': + argv[i].v_str = SM_VA_ARG(ap, char*); + break; + case 'r': + SM_REQUIRE(etype->etype_argformat[i+1] == '\0'); + argv[i].v_str = SM_VA_ARG(ap, char*); + break; + default: + sm_abort("sm_exc_vnew_x: bad argformat '%c'", + etype->etype_argformat[i]); + } + } + + /* + ** Step 3. Scan argv, and allocate space for all + ** string arguments. si is the number of elements + ** of argv that have been processed so far. + ** On failure, free exc, argv, all the exception arguments + ** and all of the strings that have been copied. + */ + + for (si = 0; si < argc; ++si) + { + switch (etype->etype_argformat[si]) + { + case 's': + { + char *str = argv[si].v_str; + if (str != NULL) + argv[si].v_str = sm_strdup_x(str); + } + break; + case 'r': + { + char *fmt = argv[si].v_str; + if (fmt != NULL) + argv[si].v_str = sm_vstringf_x(fmt, ap); + } + break; + } + } + } + SM_EXCEPT(e, "*") + { + if (exc == NULL || argv == NULL) + { + /* + ** Failure in step 1 or step 2. + ** Scan ap and free all exception arguments. + */ + + for (i = 0; i < argc; ++i) + { + switch (etype->etype_argformat[i]) + { + case 'i': + (void) SM_VA_ARG(ap, int); + break; + case 'l': + (void) SM_VA_ARG(ap, long); + break; + case 'e': + sm_exc_free(SM_VA_ARG(ap, SM_EXC_T*)); + break; + case 's': + case 'r': + (void) SM_VA_ARG(ap, char*); + break; + } + } + } + else + { + /* + ** Failure in step 3. Scan argv and free + ** all exception arguments and all string + ** arguments that have been duplicated. + ** Then free argv. + */ + + for (i = 0; i < argc; ++i) + { + switch (etype->etype_argformat[i]) + { + case 'e': + sm_exc_free(argv[i].v_exc); + break; + case 's': + case 'r': + if (i < si) + sm_free(argv[i].v_str); + break; + } + } + sm_free(argv); + } + sm_free(exc); + sm_exc_raise_x(e); + } + SM_END_TRY + + return exc; +} + +/* +** SM_EXC_NEW_X -- Construct a new exception object. +** +** Parameters: +** etype -- type of exception. +** ... -- varargs. +** +** Returns: +** pointer to exception object. +*/ + +SM_EXC_T * +#if SM_VA_STD +sm_exc_new_x( + const SM_EXC_TYPE_T *etype, + ...) +#else /* SM_VA_STD */ +sm_exc_new_x(etype, va_alist) + const SM_EXC_TYPE_T *etype; + va_dcl +#endif /* SM_VA_STD */ +{ + SM_EXC_T *exc; + SM_VA_LOCAL_DECL + + SM_VA_START(ap, etype); + exc = sm_exc_vnew_x(etype, ap); + SM_VA_END(ap); + return exc; +} + +/* +** SM_ADDREF -- Add a reference to an exception object. +** +** Parameters: +** exc -- exception object. +** +** Returns: +** exc itself. +*/ + +SM_EXC_T * +sm_addref(exc) + SM_EXC_T *exc; +{ + SM_REQUIRE_ISA(exc, SmExcMagic); + if (exc->exc_refcount != 0) + ++exc->exc_refcount; + return exc; +} + +/* +** SM_EXC_FREE -- Destroy a reference to an exception object. +** +** Parameters: +** exc -- exception object. +** +** Returns: +** none. +*/ + +void +sm_exc_free(exc) + SM_EXC_T *exc; +{ + if (exc == NULL) + return; + SM_REQUIRE(exc->sm_magic == SmExcMagic); + if (exc->exc_refcount == 0) + return; + if (--exc->exc_refcount == 0) + { + int i, c; + + for (i = 0; (c = exc->exc_type->etype_argformat[i]) != '\0'; + ++i) + { + switch (c) + { + case 's': + case 'r': + sm_free(exc->exc_argv[i].v_str); + break; + case 'e': + sm_exc_free(exc->exc_argv[i].v_exc); + break; + } + } + exc->sm_magic = NULL; + sm_free(exc->exc_argv); + sm_free(exc); + } +} + +/* +** SM_EXC_MATCH -- Match exception category against a glob pattern. +** +** Parameters: +** exc -- exception. +** pattern -- glob pattern. +** +** Returns: +** true iff match. +*/ + +bool +sm_exc_match(exc, pattern) + SM_EXC_T *exc; + const char *pattern; +{ + if (exc == NULL) + return false; + SM_REQUIRE(exc->sm_magic == SmExcMagic); + return sm_match(exc->exc_type->etype_category, pattern); +} + +/* +** SM_EXC_WRITE -- Write exception message to a stream (wo trailing newline). +** +** Parameters: +** exc -- exception. +** stream -- file for output. +** +** Returns: +** none. +*/ + +void +sm_exc_write(exc, stream) + SM_EXC_T *exc; + SM_FILE_T *stream; +{ + SM_REQUIRE_ISA(exc, SmExcMagic); + exc->exc_type->etype_print(exc, stream); +} + +/* +** SM_EXC_PRINT -- Print exception message to a stream (with trailing newline). +** +** Parameters: +** exc -- exception. +** stream -- file for output. +** +** Returns: +** none. +*/ + +void +sm_exc_print(exc, stream) + SM_EXC_T *exc; + SM_FILE_T *stream; +{ + SM_REQUIRE_ISA(exc, SmExcMagic); + exc->exc_type->etype_print(exc, stream); + (void) sm_io_putc(stream, SM_TIME_DEFAULT, '\n'); +} + +SM_EXC_HANDLER_T *SmExcHandler = NULL; +static SM_EXC_DEFAULT_HANDLER_T SmExcDefaultHandler = NULL; + +/* +** SM_EXC_NEWTHREAD -- Initialize exception handling for new process/thread. +** +** Parameters: +** h -- default exception handler. +** +** Returns: +** none. +*/ + +/* +** Initialize a new process or a new thread by clearing the +** exception handler stack and optionally setting a default +** exception handler function. Call this at the beginning of main, +** or in a new process after calling fork, or in a new thread. +** +** This function is a luxury, not a necessity. +** If h != NULL then you can get the same effect by +** wrapping the body of main, or the body of a forked child +** or a new thread in SM_TRY ... SM_EXCEPT(e,"*") h(e); SM_END_TRY. +*/ + +void +sm_exc_newthread(h) + SM_EXC_DEFAULT_HANDLER_T h; +{ + SmExcHandler = NULL; + SmExcDefaultHandler = h; +} + +/* +** SM_EXC_RAISE_X -- Raise an exception. +** +** Parameters: +** exc -- exception. +** +** Returns: +** doesn't. +*/ + +void +sm_exc_raise_x(exc) + SM_EXC_T *exc; +{ + SM_REQUIRE_ISA(exc, SmExcMagic); + + if (SmExcHandler == NULL) + { + if (SmExcDefaultHandler != NULL) + { + SM_EXC_DEFAULT_HANDLER_T h; + + /* + ** If defined, the default handler is expected + ** to terminate the current thread of execution + ** using exit() or pthread_exit(). + ** If it instead returns normally, then we fall + ** through to the default case below. If it + ** raises an exception, then sm_exc_raise_x is + ** re-entered and, because we set SmExcDefaultHandler + ** to NULL before invoking h, we will again + ** end up in the default case below. + */ + + h = SmExcDefaultHandler; + SmExcDefaultHandler = NULL; + (*h)(exc); + } + + /* + ** No exception handler, so print the error and exit. + ** To override this behaviour on a program wide basis, + ** call sm_exc_newthread or put an exception handler in main(). + ** + ** XXX TODO: map the exception category to an exit code + ** XXX from . + */ + + sm_exc_print(exc, smioerr); + exit(255); + } + + if (SmExcHandler->eh_value == NULL) + SmExcHandler->eh_value = exc; + else + sm_exc_free(exc); + + sm_longjmp_nosig(SmExcHandler->eh_context, 1); +} + +/* +** SM_EXC_RAISENEW_X -- shorthand for sm_exc_raise_x(sm_exc_new_x(...)) +** +** Parameters: +** etype -- type of exception. +** ap -- varargs. +** +** Returns: +** none. +*/ + +void +#if SM_VA_STD +sm_exc_raisenew_x( + const SM_EXC_TYPE_T *etype, + ...) +#else +sm_exc_raisenew_x(etype, va_alist) + const SM_EXC_TYPE_T *etype; + va_dcl +#endif +{ + SM_EXC_T *exc; + SM_VA_LOCAL_DECL + + SM_VA_START(ap, etype); + exc = sm_exc_vnew_x(etype, ap); + SM_VA_END(ap); + sm_exc_raise_x(exc); +} diff --git a/gnu/dist/sendmail/libsm/exc.html b/gnu/dist/sendmail/libsm/exc.html new file mode 100644 index 000000000000..6fa55bc4d10e --- /dev/null +++ b/gnu/dist/sendmail/libsm/exc.html @@ -0,0 +1,757 @@ + + + libsm : Exception Handling + + + +Back to libsm overview + +
+

libsm : Exception Handling

+
Id: exc.html,v 1.12 2001/02/13 21:21:25 gshapiro Exp +
+ +

Introduction

+ +The exception handling package provides the facilities that +functions in libsm use to report errors. +Here are the basic concepts: + +
    +
  1. + When a function detects an exceptional condition at the library level, + it does not print an error message, or call syslog, or + exit the program. Instead, it reports the error back to its + caller, and lets the caller decide what to do. + This improves modularity, because error handling is separated + from error reporting. +

    +

  2. + Errors are not represented by a single integer error code, + because that you can't represent everything that an error handler + might need to know about an error by a single integer. + Instead, errors are represented by exception objects. + An exception object contains an exception code and an array + of zero or more exception arguments. + The exception code is a string that specifies what kind of exception + this is, and the arguments may be integers, strings or exception objects. +

    +

  3. + Errors are not reported using a special return value, + because if you religiously check for error returns from every + function call that could fail, then most of your code ends up being + error handling code. Errors are reported by raising an exception. + When an exception is raised, we unwind the call stack + until we find an exception handler. If the exception is + not handled, then we print the exception on stderr and + exit the program. +
+ +

Synopsis

+ +
+#include <sm/exc.h>
+
+typedef struct sm_exc_type SM_EXC_TYPE_T;
+typedef struct sm_exc SM_EXC_T;
+typedef union sm_val SM_VAL_T;
+
+/*
+**  Exception types
+*/
+
+extern const char SmExcTypeMagic[];
+
+struct sm_exc_type
+{
+	const char	*sm_magic;
+	const char	*etype_category;
+	const char	*etype_argformat;
+	void 		(*etype_print)(SM_EXC_T *exc, SM_FILE_T *stream);
+	const char	*etype_printcontext;
+};
+
+extern const SM_EXC_TYPE_T SmEtypeOs;
+extern const SM_EXC_TYPE_T SmEtypeErr;
+
+void
+sm_etype_printf(
+	SM_EXC_T *exc,
+	SM_FILE_T *stream);
+
+/*
+**  Exception objects
+*/
+
+extern const char SmExcMagic[];
+
+union sm_val
+{
+	int		v_int;
+	long		v_long;
+	char		*v_str;
+	SM_EXC_T	*v_exc;
+};
+
+struct sm_exc
+{
+	const char		*sm_magic;
+	size_t			exc_refcount;
+	const SM_EXC_TYPE_T	*exc_type;
+	SM_VAL_T		*exc_argv;
+};
+
+SM_EXC_T *
+sm_exc_new_x(
+	const SM_EXC_TYPE_T *type,
+	...);
+
+SM_EXC_T *
+sm_exc_addref(
+	SM_EXC_T *exc);
+
+void
+sm_exc_free(
+	SM_EXC_T *exc);
+
+bool
+sm_exc_match(
+	SM_EXC_T *exc,
+	const char *pattern);
+
+void
+sm_exc_print(
+	SM_EXC_T *exc,
+	SM_FILE_T *stream);
+
+void
+sm_exc_write(
+	SM_EXC_T *exc,
+	SM_FILE_T *stream);
+
+void
+sm_exc_raise_x(
+	SM_EXC_T *exc);
+
+void
+sm_exc_raisenew_x(
+	const SM_EXC_TYPE_T *type,
+	...);
+
+/*
+**  Ensure that cleanup code is executed,
+**  and/or handle an exception.
+*/
+SM_TRY
+	Block of code that may raise an exception.
+SM_FINALLY
+	Cleanup code that may raise an exception.
+	This clause is guaranteed to be executed even if an exception is
+	raised by the SM_TRY clause or by an earlier SM_FINALLY clause.
+	You may have 0 or more SM_FINALLY clauses.
+SM_EXCEPT(exc, pattern)
+	Exception handling code, triggered by an exception
+	whose category matches 'pattern'.
+	You may have 0 or more SM_EXCEPT clauses.
+SM_END_TRY
+
+ +

Overview

+ + An exception is an object which represents an exceptional condition, + which might be an error condition like "out of memory", or might be + a condition like "end of file". +

+ Functions in libsm report errors and other unusual conditions by + raising an exception, rather than by returning an error code or + setting a global variable such as errno. If a libsm function is + capable of raising an exception, its name ends in "_x". + (We do not raise an exception when a bug is detected in the + program; instead, we terminate the program using sm_abort. + See the assertion package + for details.) +

+ When you are using the libsm exception handling package, + you are using a new programming paradigm. + You will need to abandon some of the programming idioms + you are accustomed to, and switch to new idioms. + Here is an overview of some of these idioms. +

    +
  1. + When a function is unable to complete its task because + of an exceptional condition, it reports this condition + by raising an exception. +

    + Here is an example of how to construct an exception object + and raise an exception. + In this example, we convert a Unix system error into an exception. +

    +fd = open(path, O_RDONLY);
    +if (fd == -1)
    +	sm_exc_raise_x(sm_exc_new_x(&SmEtypeOs, errno, "open", "%s", path));
    +
    + + Because the idiom sm_exc_raise_x(sm_exc_new_x(...)) + is so common, it can be abbreviated as sm_exc_raisenew_x(...). +

    +

  2. + When you detect an error at the application level, + you don't call a function like BSD's errx, + which prints an error message on stderr and exits the program. + Instead, you raise an exception. + This causes cleanup code in surrounding exception handlers + to be run before the program exits. + For example, instead of this: +
    +errx(1, "%s:%d: syntax error", filename, lineno);
    +
    + + use this: + +
    +sm_exc_raisenew_x(&SmEtypeErr, "%s:%d: syntax error", filename, lineno);
    +
    + + The latter code raises an exception, unwinding the call stack + and executing cleanup code. + If the exception is not handled, then the exception is printed + to stderr and the program exits. + The end result is substantially the same as a call to errx. +

    +

  3. + The SM_TRY ... SM_FINALLY ... control structure + ensures that cleanup code is executed and resources are released + in the presence of exceptions. +

    + For example, suppose that you have written the following code: + +

    +rpool = sm_rpool_new_x(&SmRpoolRoot, 0);
    +... some code ...
    +sm_rpool_free_x(rpool);
    +
    + + If any of the functions called within "... some code ..." have + names ending in _x, then it is possible that an exception will be + raised, and if that happens, then "rpool" will not be freed. + And that's a bug. To fix this bug, change your code so it looks + like this: + +
    +rpool = sm_rpool_new_x(&SmRpoolRoot, 0);
    +SM_TRY
    +	... some code that can raise an exception ...
    +SM_FINALLY
    +	sm_rpool_free_x(rpool);
    +SM_END_TRY
    +
    + +
  4. + The SM_TRY ... SM_EXCEPT ... control structure handles an exception. + Unhandled exceptions terminate the program. + For example, here is a simple exception handler + that traps all exceptions, and prints the exceptions: + +
    +SM_TRY
    +	/* code that can raise an exception */
    +	...
    +SM_EXCEPT(exc, "*")
    +	/* catch all exceptions */
    +	sm_exc_print(exc, stderr);
    +SM_END_TRY
    +
    + + Exceptions are reference counted. The SM_END_TRY macro contains a + call to sm_exc_free, so you don't normally need to worry about freeing + an exception after handling it. In the rare case that you want an + exception to outlive an exception handler, then you increment its + reference count by calling sm_exc_addref. +

    +

  5. + The second argument of the SM_EXCEPT macro is a glob pattern + which specifies the types of exceptions that are to be handled. + For example, you might want to handle an end-of-file exception + differently from other exceptions. + Here's how you do that: + +
    +SM_TRY
    +	/* code that might raise end-of-file, or some other exception */
    +	...
    +SM_EXCEPT(exc, "E:sm.eof")
    +	/* what to do if end-of-file is encountered */
    +	...
    +SM_EXCEPT(exc, "*")
    +	/* what to do if some other exception is raised */
    +	...
    +SM_END_TRY
    +
    +
+ +

Exception Values

+ +In traditional C code, errors are usually denoted by a single integer, +such as errno. In practice, errno does not carry enough information +to describe everything that an error handler might want to know about +an error. And the scheme is not very extensible: if several different +packages want to add additional error codes, it is hard to avoid +collisions. + +

+In libsm, an exceptional condition is described +by an object of type SM_EXC_T. +An exception object is created by specifying an exception type +and a list of exception arguments. + +

+The exception arguments are an array of zero or more values. +The values may be a mixture of ints, longs, strings, and exceptions. +In the SM_EXC_T structure, the argument vector is represented +by SM_VAL_T *exc_argv, where SM_VAL_T +is a union of the possible argument types. +The number and types of exception arguments is determined by +the exception type. + +

+An exception type is a statically initialized const object +of type SM_EXC_TYPE_T, which has the following members: + +

+
+ const char *sm_magic +
+ A pointer to SmExcTypeMagic. +

+

+ const char *etype_category +
+ This is a string of the form + "class:name". +

+ The class is used to assign the exception type to + one of a number of broad categories of exceptions on which an + exception handler might want to discriminate. + I suspect that what we want is a hierarchical taxonomy, + but I don't have a full design for this yet. + For now, I am recommending the following classes: +

+
"F" +
A fatal error has occurred. + This is an error that prevents the application + from making any further progress, so the only + recourse is to raise an exception, execute cleanup code + as the stack is unwound, then exit the application. + The out-of-memory exception raised by sm_malloc_x + has category "F:sm.heap" because sendmail commits suicide + (after logging the error and cleaning up) when it runs out + of memory. + +
"E" +
The function could not complete its task because an error occurred. + (It might be useful to define subclasses of this category, + in which case our taxonony becomes a tree, and 'F' becomes + a subclass of 'E'.) + +
"J" +
This exception is being raised in order to effect a + non-local jump. No error has occurred; we are just + performing the non-local equivalent of a continue, + break or return. + +
"S" +
The function was interrupted by a signal. + Signals are not errors because they occur asynchronously, + and they are semantically unrelated to the function that + happens to be executing when the signal arrives. + Note that it is extremely dangerous to raise an exception + from a signal handler. For example, if you are in the middle + of a call to malloc, you might corrupt the heap. +
+ Eric's libsm paper defines "W", "D" and "I" + for Warning, Debug and Informational: + I suspect these categories only make sense in the context of + Eric's 1985 exception handling system which allowed you to + raise conditions without terminating the calling function. +

+ The name uniquely identifies the exception type. + I recommend a string of the form + library.package.detail. +

+

+ const char *etype_argformat +
+ This is an array of single character codes. + Each code indicates the type of one of the exception arguments. + sm_exc_new_x uses this string to decode its variable + argument list into an exception argument vector. + The following type codes are supported: +
+
i +
+ The exception argument has type int. +
l +
+ The exception argument has type long. +
e +
+ The exception argument has type SM_EXC_T*. + The value may either be NULL or a pointer + to an exception. The pointer value is simply copied + into the exception argument vector. +
s +
+ The exception argument has type char*. + The value may either be NULL or a pointer + to a character string. In the latter case, + sm_exc_new_x will make a copy of the string. +
r +
+ The exception argument has type char*. + sm_exc_new_x will read a printf-style + format string argument followed by a list of printf + arguments from its variable argument list, and convert + these into a string. + This type code can only occur as the last element + of exc_argformat. +
+

+

+ void (*etype_print)(SM_EXC_T *exc, SM_FILE_T *stream) +
+ This function prints an exception of the specified type + onto an output stream. + The final character printed is not a newline. +
+ +

Standard Exceptions and Exception Types

+ +Libsm defines one standard exception value, SmHeapOutOfMemory. +This is a statically initialized const variable, because it seems +like a bad idea to dynamically allocate an exception object to +report a low memory condition. +This exception has category "F:sm.heap". +If you need to, you can explicitly raise this exception +with sm_exc_raise_x(&SmHeapOutOfMemory). + +

+Statically initialized exception values cannot contain any +run-time parameters, so the normal case is to dynamically allocate +a new exception object whenever you raise an exception. +Before you can create an exception, you need an exception type. +Libsm defines the following standard exception types. + +

+
+ SmEtypeOs +
+ This represents a generic operating system error. + The category is "E:sm.os". + The argformat is "isr", + where argv[0] is the value of errno + after a system call has failed, + argv[1] is the name of the function (usually a system call) that failed, + and argv[2] is either NULL + or a character string which describes some of the arguments + to the failing system call (usually it is just a file name). + Here's an example of raising an exception: + +
+fd = open(filename, O_RDONLY);
+if (fd == -1)
+	sm_exc_raisenew_x(&SmEtypeOs, errno, "open", "%s", filename);
+
+ + If errno is ENOENT and filename is "/etc/mail/snedmail.cf", + then the exception raised by the above code will be printed as + +
+/etc/mail/snedmail.cf: open failed: No such file or directory
+
+ +
+ SmEtypeErr +
+ This represents a generic error. + The category is "E:sm.err", + and the argformat is "r". + You can use it + in application contexts where you are raising an exception + for the purpose of terminating the program. + You know the exception won't be handled, + so you don't need to worry about packaging the error for + later analysis by an exception handler. + All you need to specify is the message string that + will be printed to stderr before the program exits. + For example, + +
+sm_exc_raisenew_x(&SmEtypeErr, "name lookup failed: %s", name);
+
+
+ +

Custom Exception Types

+ +If you are writing a library package, and you need to raise +exceptions that are not standard Unix system errors, +then you need to define one or more new exception types. + +

+Every new exception type needs a print function. +The standard print function sm_etype_printf +is all you need in the majority of cases. +It prints the etype_printcontext string of the exception type, +substituting occurrences of %0 through %9 with the corresponding +exception argument. +If exception argument 3 is an int or long, +then %3 will print the argument in decimal, +and %o3 or %x3 will print it in octal or hex. + +

+In the following example, I will assume that your library +package implements regular expressions, and can raise 5 different exceptions. +When compiling a regular expression, 3 different syntax errors +can be reported: +

    +
  • unbalanced parenthesis +
  • unbalanced bracket +
  • missing argument for repetition operator +
+Whenever one of these errors is reported, you will also report +the index of the character within the regex string at which the +syntax error was detected. +The fourth exception is raised if a compiled regular expression +is invalid: this exception has no arguments. +The fifth exception is raised if the package runs out of memory: +for this, you use the standard SmHeapOutOfMemory exception. + +

+The obvious approach is to define 4 separate exception types. +Here they are: + +

+/* print a regular expression syntax error */
+void
+rx_esyntax_print(SM_EXC_T *exc, SM_FILE_T *stream)
+{
+	sm_io_fprintf(stream, "rx syntax error at character %d: %s",
+		exc->exc_argv[0].v_int,
+		exc->exc_type->etype_printcontext);
+}
+SM_EXC_TYPE_T RxSyntaxParen = {
+	SmExcTypeMagic,
+	"E:mylib.rx.syntax.paren",
+	"i",
+	rx_esyntax_print,
+	"unbalanced parenthesis"
+};
+SM_EXC_TYPE_T RxSyntaxBracket = {
+	SmExcTypeMagic,
+	"E:mylib.rx.syntax.bracket",
+	"i",
+	rx_esyntax_print,
+	"unbalanced bracket"
+};
+SM_EXC_TYPE_T RxSyntaxMissingArg = {
+	SmExcTypeMagic,
+	"E:mylib.rx.syntax.missingarg",
+	"i",
+	rx_esyntax_print,
+	"missing argument for repetition operator"
+};
+
+SM_EXC_TYPE_T RxRunCorrupt = {
+	SmExcTypeMagic,
+	"E:mylib.rx.run.corrupt",
+	"",
+	sm_etype_printf,
+	"rx runtime error: compiled regular expression is corrupt"
+};
+
+ +

+With the above definitions, you can raise a syntax error reporting +an unbalanced parenthesis at string offset i using: +

+sm_exc_raisenew_x(&RxSyntaxParen, i);
+
+ +If i==42 then this exception will be printed as: +
+rx syntax error at character 42: unbalanced parenthesis
+
+ +An exception handler can provide special handling for regular +expression syntax errors using this code: +
+SM_TRY
+	... code that might raise an exception ...
+SM_EXCEPT(exc, "E:mylib.rx.syntax.*")
+	int i = exc->exc_argv[0].v_int;
+	... handle a regular expression syntax error ...
+SM_END_TRY
+
+ +

+External requirements may force you to define an integer code +for each error reported by your package. Or you may be wrapping +an existing package that works this way. In this case, it might +make sense to define a single exception type, patterned after SmEtypeOs, +and include the integer code as an exception argument. + +

+Your package might intercept an exception E generated by a lower +level package, and then reclassify it as a different expression E'. +For example, a package for reading a configuration file might +reclassify one of the regular expression syntax errors from the +previous example as a configuration file syntax error. +When you do this, the new exception E' should include the original +exception E as an exception parameter, and the print function for +exception E' should print the high level description of the exception +(eg, "syntax error in configuration file %s at line %d\n"), +then print the subexception that is stored as an exception parameter. + +

Function Reference

+ +
+
+ SM_EXC_T *sm_exc_new_x(const SM_EXC_TYPE_T *type, ...) +
+ Create a new exception. Raise an exception on heap exhaustion. + The new exception has a reference count of 1. +

+ + A list of zero or more exception arguments follows the exception type; + these are copied into the new exception object. + The number and types of these arguments is determined + by type->etype_argformat. +

+ + Note that there is no rpool argument to sm_exc_new_x. + Exceptions are allocated directly from the heap. + This is because exceptions are normally raised at low levels + of abstraction and handled at high levels. Because the low + level code typically has no idea of how or at what level the + exception will be handled, it also has no idea of which resource + pool, if any, should own the exception. +

+

+ SM_EXC_T *sm_exc_addref(SM_EXC_T *exc) +
+ Increment the reference count of an exception. + Return the first argument. +

+

+ void sm_exc_free(SM_EXC_T *exc) +
+ Decrement the reference count of an exception. + If it reaches 0, free the exception object. +

+

+ bool sm_exc_match(SM_EXC_T *exc, const char *pattern) +
+ Compare the exception's category to the specified glob pattern, + return true if they match. +

+

+ void sm_exc_print(SM_EXC_T *exc, SM_FILE_T *stream) +
+ Print the exception on the stream + as a sequence of one or more newline terminated lines. +

+

+ void sm_exc_write(SM_EXC_T *exc, SM_FILE_T *stream) +
+ Write the exception on the stream without a terminating newline. +

+

+ void sm_exc_raise_x(SM_EXC_T *exc) +
+ Raise the exception. This function does not return to its caller. +

+

+ void sm_exc_raisenew_x(const SM_EXC_TYPE_T *type, ...) +
+ A short form for sm_exc_raise_x(sm_exc_new_x(type,...)). +
+ +

Macro Reference

+ +The SM_TRY ... SM_END_TRY control structure +ensures that cleanup code is executed in the presence of exceptions, +and permits exceptions to be handled. + +
+SM_TRY
+	A block of code that may raise an exception.
+SM_FINALLY
+	Cleanup code that may raise an exception.
+	This code is guaranteed to be executed whether or not
+	an exception was raised by a previous clause.
+	You may have 0 or more SM_FINALLY clauses.
+SM_EXCEPT(e, pat)
+	Exception handling code, which is triggered by an exception
+	whose category matches the glob pattern 'pat'.
+	The exception value is bound to the local variable 'e'.
+	You may have 0 or more SM_EXCEPT clauses.
+SM_END_TRY
+
+ +First, the SM_TRY clause is executed, then each SM_FINALLY clause is +executed in sequence. +If one or more of these clauses was terminated by an exception, +then the first such exception is remembered, and the other exceptions +are lost. + +If no exception was raised, then we are done. + +Otherwise, each of the SM_EXCEPT clauses is examined in sequence. +and the first SM_EXCEPT clause whose pattern argument matches the exception +(see sm_exc_match) is executed. +If none of the SM_EXCEPT clauses matched the exception, or if there are +no SM_EXCEPT clauses, then the remembered exception is re-raised. + +

+SM_TRY .. SM_END_TRY clauses may be nested arbitrarily. + +

+It is illegal to jump out of a SM_TRY or SM_FINALLY clause +using goto, break, continue, return or longjmp. +If you do this, you will corrupt the internal exception handling stack. +You can't use break or continue in an SM_EXCEPT clause; +these are reserved for use by the implementation. +It is legal to jump out of an SM_EXCEPT clause using goto or return; +however, in this case, you must take responsibility +for freeing the exception object. + +

+The SM_TRY and SM_FINALLY macros contain calls to setjmp, +and consequently, they suffer from the limitations imposed on setjmp +by the C standard. +Suppose you declare an auto variable i outside of a +SM_TRY ... SM_END_TRY statement, initializing it to 0. +Then you modify i inside of a SM_TRY or SM_FINALLY clause, +setting it to 1. +If you reference i in a different SM_FINALLY clause, or in +an SM_EXCEPT clause, then it is implementation dependent whether i +will be 0 or 1, unless you have declared i to be volatile. + +

+int volatile i = 0;
+
+SM_TRY
+	i = 1;
+	...
+SM_FINALLY
+	/* the following reference to i only works if i is declared volatile */
+	use(i);
+	...
+SM_EXCEPT(exc, "*")
+	/* the following reference to i only works if i is declared volatile */
+	use(i);
+	...
+SM_END_TRY
+
+ + + diff --git a/gnu/dist/sendmail/libsm/fclose.c b/gnu/dist/sendmail/libsm/fclose.c new file mode 100644 index 000000000000..13adfa786d5a --- /dev/null +++ b/gnu/dist/sendmail/libsm/fclose.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fclose.c,v 1.42 2002/02/01 02:28:00 ca Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +static jmp_buf CloseTimeOut; + +/* +** CLOSEALRM -- handler when timeout activated for sm_io_close() +** +** Returns flow of control to where setjmp(CloseTimeOut) was set. +** +** Parameters: +** sig -- unused +** +** Returns: +** does not return +** +** Side Effects: +** returns flow of control to setjmp(CloseTimeOut). +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED0 */ +static void +closealrm(sig) + int sig; +{ + longjmp(CloseTimeOut, 1); +} + +/* +** SM_IO_CLOSE -- close a file handle/pointer +** +** Parameters: +** fp -- file pointer to be closed +** timeout -- maximum time allowed to perform the close (millisecs) +** +** Returns: +** 0 on success +** -1 on failure and sets errno +** +** Side Effects: +** file pointer 'fp' will no longer be valid. +*/ + +int +sm_io_close(fp, timeout) + register SM_FILE_T *fp; + int SM_NONVOLATILE timeout; +{ + register int SM_NONVOLATILE r; + SM_EVENT *evt = NULL; + + if (fp == NULL) + { + errno = EBADF; + return SM_IO_EOF; + } + + SM_REQUIRE_ISA(fp, SmFileMagic); + + /* XXX this won't be reached if above macro is active */ + if (fp->sm_magic == NULL) + { + /* not open! */ + errno = EBADF; + return SM_IO_EOF; + } + if (fp->f_close == NULL) + { + /* no close function! */ + errno = ENODEV; + return SM_IO_EOF; + } + if (fp->f_dup_cnt > 0) + { + /* decrement file pointer open count */ + fp->f_dup_cnt--; + return 0; + } + + /* Okay, this is where we set the timeout. */ + if (timeout == SM_TIME_DEFAULT) + timeout = fp->f_timeout; + if (timeout == SM_TIME_IMMEDIATE) + { + errno = EAGAIN; + return -1; + } + + /* No more duplicates of file pointer. Flush buffer and close */ + r = fp->f_flags & SMWR ? sm_flush(fp, (int *) &timeout) : 0; + + /* sm_flush() has updated to.it_value for the time it's used */ + if (timeout != SM_TIME_FOREVER) + { + if (setjmp(CloseTimeOut) != 0) + { + errno = EAGAIN; + return SM_IO_EOF; + } + evt = sm_seteventm(timeout, closealrm, 0); + } + if ((*fp->f_close)(fp) < 0) + r = SM_IO_EOF; + + /* We're back. So undo our timeout and handler */ + if (evt != NULL) + sm_clrevent(evt); + if (fp->f_flags & SMMBF) + { + sm_free((char *)fp->f_bf.smb_base); + fp->f_bf.smb_base = NULL; + } + if (HASUB(fp)) + FREEUB(fp); + fp->f_flags = 0; /* clear flags */ + fp->sm_magic = NULL; /* Release this SM_FILE_T for reuse. */ + fp->f_r = fp->f_w = 0; /* Mess up if reaccessed. */ + return r; +} diff --git a/gnu/dist/sendmail/libsm/feof.c b/gnu/dist/sendmail/libsm/feof.c new file mode 100644 index 000000000000..5beec50607c9 --- /dev/null +++ b/gnu/dist/sendmail/libsm/feof.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: feof.c,v 1.13 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include "local.h" + +/* +** SM_IO_EOF -- subroutine version of the macro sm_io_eof. +** +** Tests if the file for 'fp' has reached the end. +** +** Parameters: +** fp -- file pointer. +** +** Returns: +** 0 (zero) when the file is not at end +** non-zero when EOF has been found +*/ +#undef sm_io_eof + +int +sm_io_eof(fp) + SM_FILE_T *fp; +{ + SM_REQUIRE_ISA(fp, SmFileMagic); + + return sm_eof(fp); +} diff --git a/gnu/dist/sendmail/libsm/ferror.c b/gnu/dist/sendmail/libsm/ferror.c new file mode 100644 index 000000000000..c0d0188ec094 --- /dev/null +++ b/gnu/dist/sendmail/libsm/ferror.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: ferror.c,v 1.13 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include "local.h" + +/* +** SM_IO_ERROR -- subroutine version of the macro sm_io_error. +** +** Parameters: +** fp -- file pointer +** +** Returns: +** 0 (zero) when 'fp' is not in an error state +** non-zero when 'fp' is in an error state +*/ + +#undef sm_io_error + +int +sm_io_error(fp) + SM_FILE_T *fp; +{ + SM_REQUIRE_ISA(fp, SmFileMagic); + + return sm_error(fp); +} diff --git a/gnu/dist/sendmail/libsm/fflush.c b/gnu/dist/sendmail/libsm/fflush.c new file mode 100644 index 000000000000..f542c43a8b2e --- /dev/null +++ b/gnu/dist/sendmail/libsm/fflush.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fflush.c,v 1.43 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" +#include + +/* +** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" +** +** Flush a single file. We don't allow this function to flush +** all open files when fp==NULL any longer. +** +** Parameters: +** fp -- the file pointer buffer to flush +** timeout -- time to complete the flush +** +** Results: +** Failure: SM_IO_EOF and sets errno +** Success: 0 (zero) +*/ + +int +sm_io_flush(fp, timeout) + register SM_FILE_T *fp; + int SM_NONVOLATILE timeout; +{ + int fd; + struct timeval to; + + SM_REQUIRE_ISA(fp, SmFileMagic); + + if ((fp->f_flags & (SMWR | SMRW)) == 0) + { + /* + ** The file is not opened for writing, so it cannot be flushed + ** (writable means SMWR [write] or SMRW [read/write]. + */ + + errno = EBADF; + return SM_IO_EOF; + } + + SM_CONVERT_TIME(fp, fd, timeout, &to); + + /* Now do the flush */ + return sm_flush(fp, (int *) &timeout); +} + +/* +** SM_FLUSH -- perform the actual flush +** +** Assumes that 'fp' has been validated before this function called. +** +** Parameters: +** fp -- file pointer to be flushed +** timeout -- max time allowed for flush (milliseconds) +** +** Results: +** Success: 0 (zero) +** Failure: SM_IO_EOF and errno set +** +** Side Effects: +** timeout will get updated with the time remaining (if any) +*/ + +int +sm_flush(fp, timeout) + register SM_FILE_T *fp; + int *timeout; +{ + register unsigned char *p; + register int n, t; + int fd; + + SM_REQUIRE_ISA(fp, SmFileMagic); + + t = fp->f_flags; + if ((t & SMWR) == 0) + return 0; + + if (t & SMSTR) + { + *fp->f_p = '\0'; + return 0; + } + + if ((p = fp->f_bf.smb_base) == NULL) + return 0; + + n = fp->f_p - p; /* write this much */ + + if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) + { + /* can't get an fd, likely internal 'fake' fp */ + errno = 0; + fd = -1; + } + + /* + ** Set these immediately to avoid problems with longjmp and to allow + ** exchange buffering (via setvbuf) in user write function. + */ + + fp->f_p = p; + fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */ + + for (; n > 0; n -= t, p += t) + { + errno = 0; /* needed to ensure EOF correctly found */ + + /* Call the file type's write function */ + t = (*fp->f_write)(fp, (char *)p, n); + if (t <= 0) + { + if (t == 0 && errno == 0) + break; /* EOF found */ + + if (IS_IO_ERROR(fd, t, *timeout)) + { + fp->f_flags |= SMERR; + + /* errno set by fp->f_write */ + return SM_IO_EOF; + } + SM_IO_WR_TIMEOUT(fp, fd, *timeout); + } + } + return 0; +} diff --git a/gnu/dist/sendmail/libsm/fget.c b/gnu/dist/sendmail/libsm/fget.c new file mode 100644 index 000000000000..1709eea32e9f --- /dev/null +++ b/gnu/dist/sendmail/libsm/fget.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fget.c,v 1.24 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include +#include "local.h" + +/* +** SM_IO_FGETS -- get a string from a file +** +** Read at most n-1 characters from the given file. +** Stop when a newline has been read, or the count ('n') runs out. +** +** Parameters: +** fp -- the file to read from +** timeout -- time to complete reading the string in milliseconds +** buf -- buffer to place read string in +** n -- size of 'buf' +** +** Returns: +** success: returns value of 'buf' +** failure: NULL (no characters were read) +** timeout: NULL and errno set to EAGAIN +** +** Side Effects: +** may move the file pointer +*/ + +char * +sm_io_fgets(fp, timeout, buf, n) + register SM_FILE_T *fp; + int timeout; + char *buf; + register int n; +{ + register int len; + register char *s; + register unsigned char *p, *t; + + SM_REQUIRE_ISA(fp, SmFileMagic); + if (n <= 0) /* sanity check */ + return NULL; + + s = buf; + n--; /* leave space for NUL */ + while (n > 0) + { + /* If the buffer is empty, refill it. */ + if ((len = fp->f_r) <= 0) + { + + /* + ** Timeout is only passed if we can't get the data + ** from the buffer (which is counted as immediately). + */ + + if (sm_refill(fp, timeout) != 0) + { + /* EOF/error: stop with partial or no line */ + if (s == buf) + return NULL; + break; + } + len = fp->f_r; + } + p = fp->f_p; + + /* + ** Scan through at most n bytes of the current buffer, + ** looking for '\n'. If found, copy up to and including + ** newline, and stop. Otherwise, copy entire chunk + ** and loop. + */ + + if (len > n) + len = n; + t = (unsigned char *) memchr((void *) p, '\n', len); + if (t != NULL) + { + len = ++t - p; + fp->f_r -= len; + fp->f_p = t; + (void) memcpy((void *) s, (void *) p, len); + s[len] = 0; + return buf; + } + fp->f_r -= len; + fp->f_p += len; + (void) memcpy((void *) s, (void *) p, len); + s += len; + n -= len; + } + *s = 0; + return buf; +} diff --git a/gnu/dist/sendmail/libsm/findfp.c b/gnu/dist/sendmail/libsm/findfp.c new file mode 100644 index 000000000000..42de8485f410 --- /dev/null +++ b/gnu/dist/sendmail/libsm/findfp.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: findfp.c,v 1.66 2002/02/20 02:40:24 ca Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" +#include "glue.h" + +bool Sm_IO_DidInit; /* IO system has been initialized? */ + +const char SmFileMagic[] = "sm_file"; + +/* An open type to map to fopen()-like behavior */ +SM_FILE_T SmFtStdio_def = + {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0, + sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, + sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, + SM_TIME_BLOCK, "stdio" }; + +/* An open type to map to fdopen()-like behavior */ +SM_FILE_T SmFtStdiofd_def = + {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0, + sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, + sm_stdfdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, + SM_TIME_BLOCK, "stdiofd" }; + +/* A string file type */ +SM_FILE_T SmFtString_def = + {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0, + sm_strclose, sm_strread, sm_strseek, sm_strwrite, + sm_stropen, sm_strsetinfo, sm_strgetinfo, SM_TIME_FOREVER, + SM_TIME_BLOCK, "string" }; + +#if 0 +/* A file type for syslog communications */ +SM_FILE_T SmFtSyslog_def = + {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0, + sm_syslogclose, sm_syslogread, sm_syslogseek, sm_syslogwrite, + sm_syslogopen, sm_syslogsetinfo, sm_sysloggetinfo, SM_TIME_FOREVER, + SM_TIME_BLOCK, "syslog" }; +#endif /* 0 */ + +#define NDYNAMIC 10 /* add ten more whenever necessary */ + +#define smio(flags, file, name) \ + {SmFileMagic, 0, 0, 0, flags, file, {0}, 0, SmIoF+file, 0, \ + sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, \ + sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, \ + SM_TIME_BLOCK, name} + +/* sm_magic p r w flags file bf lbfsize cookie ival */ +#define smstd(flags, file, name) \ + {SmFileMagic, 0, 0, 0, flags, -1, {0}, 0, 0, file, \ + sm_stdioclose, sm_stdioread, sm_stdioseek, sm_stdiowrite, \ + sm_stdioopen, sm_stdiosetinfo, sm_stdiogetinfo, SM_TIME_FOREVER,\ + SM_TIME_BLOCK, name} + +/* A file type for interfacing to stdio FILE* streams. */ +SM_FILE_T SmFtRealStdio_def = smstd(SMRW|SMNBF, -1, "realstdio"); + + /* the usual - (stdin + stdout + stderr) */ +static SM_FILE_T usual[SM_IO_OPEN_MAX - 3]; +static struct sm_glue smuglue = { 0, SM_IO_OPEN_MAX - 3, usual }; + +/* List of builtin automagically already open file pointers */ +SM_FILE_T SmIoF[6] = +{ + smio(SMRD|SMLBF, SMIOIN_FILENO, "smioin"), /* smioin */ + smio(SMWR|SMLBF, SMIOOUT_FILENO, "smioout"), /* smioout */ + smio(SMWR|SMNBF, SMIOERR_FILENO, "smioerr"), /* smioerr */ + smstd(SMRD|SMNBF, SMIOIN_FILENO, "smiostdin"), /* smiostdin */ + smstd(SMWR|SMNBF, SMIOOUT_FILENO, "smiostdout"),/* smiostdout */ + smstd(SMWR|SMNBF, SMIOERR_FILENO, "smiostderr") /* smiostderr */ +}; + +/* Structure containing list of currently open file pointers */ +struct sm_glue smglue = { &smuglue, 3, SmIoF }; + +/* +** SM_MOREGLUE -- adds more space for open file pointers +** +** Parameters: +** n -- number of new spaces for file pointers +** +** Returns: +** Raises an exception if no more memory. +** Otherwise, returns a pointer to new spaces. +*/ + +static struct sm_glue *sm_moreglue_x __P((int)); +static SM_FILE_T empty; + +static struct sm_glue * +sm_moreglue_x(n) + register int n; +{ + register struct sm_glue *g; + register SM_FILE_T *p; + + g = (struct sm_glue *) sm_pmalloc_x(sizeof(*g) + SM_ALIGN_BITS + + n * sizeof(SM_FILE_T)); + p = (SM_FILE_T *) SM_ALIGN(g + 1); + g->gl_next = NULL; + g->gl_niobs = n; + g->gl_iobs = p; + while (--n >= 0) + *p++ = empty; + return g; +} + +/* +** SM_FP -- allocate and initialize an SM_FILE structure +** +** Parameters: +** t -- file type requested to be opened. +** flags -- control flags for file type behavior +** oldfp -- file pointer to reuse if available (optional) +** +** Returns: +** Raises exception on memory exhaustion. +** Aborts if type is invalid. +** Otherwise, returns file pointer for requested file type. +*/ + +SM_FILE_T * +sm_fp(t, flags, oldfp) + const SM_FILE_T *t; + const int flags; + SM_FILE_T *oldfp; +{ + register SM_FILE_T *fp; + register int n; + register struct sm_glue *g; + + SM_REQUIRE(t->f_open && t->f_close && (t->f_read || t->f_write)); + + if (!Sm_IO_DidInit) + sm_init(); + + if (oldfp != NULL) + { + fp = oldfp; + goto found; /* for opening reusing an 'fp' */ + } + + for (g = &smglue;; g = g->gl_next) + { + for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++) + if (fp->sm_magic == NULL) + goto found; + if (g->gl_next == NULL) + g->gl_next = sm_moreglue_x(NDYNAMIC); + } +found: + fp->sm_magic = SmFileMagic; /* 'fp' now valid and in-use */ + fp->f_p = NULL; /* no current pointer */ + fp->f_w = 0; /* nothing to write */ + fp->f_r = 0; /* nothing to read */ + fp->f_flags = flags; + fp->f_file = -1; /* no file */ + fp->f_bf.smb_base = NULL; /* no buffer */ + fp->f_bf.smb_size = 0; /* no buffer size with no buffer */ + fp->f_lbfsize = 0; /* not line buffered */ + fp->f_flushfp = NULL; /* no associated flush file */ + + fp->f_cookie = fp; /* default: *open* overrides cookie setting */ + fp->f_close = t->f_close; /* assign close function */ + fp->f_read = t->f_read; /* assign read function */ + fp->f_seek = t->f_seek; /* assign seek function */ + fp->f_write = t->f_write; /* assign write function */ + fp->f_open = t->f_open; /* assign open function */ + fp->f_setinfo = t->f_setinfo; /* assign setinfo function */ + fp->f_getinfo = t->f_getinfo; /* assign getinfo function */ + fp->f_type = t->f_type; /* file type */ + + fp->f_ub.smb_base = NULL; /* no ungetc buffer */ + fp->f_ub.smb_size = 0; /* no size for no ungetc buffer */ + + if (fp->f_timeout == SM_TIME_DEFAULT) + fp->f_timeout = SM_TIME_FOREVER; + else + fp->f_timeout = t->f_timeout; /* traditional behavior */ + fp->f_timeoutstate = SM_TIME_BLOCK; /* by default */ + + return fp; +} + +/* +** SM_CLEANUP -- cleanup function when exit called. +** +** This function is registered via atexit(). +** +** Parameters: +** none +** +** Returns: +** nothing. +** +** Side Effects: +** flushes open files before they are forced closed +*/ + +void +sm_cleanup() +{ + int timeout = SM_TIME_DEFAULT; + + (void) sm_fwalk(sm_flush, &timeout); /* `cheating' */ +} + +/* +** SM_INIT -- called whenever sm_io's internal variables must be set up. +** +** Parameters: +** none +** +** Returns: +** none +** +** Side Effects: +** Registers sm_cleanup() using atexit(). +*/ + +void +sm_init() +{ + if (Sm_IO_DidInit) /* paranoia */ + return; + + /* more paranoia: initialize pointers in a static variable */ + empty.f_type = NULL; + empty.sm_magic = NULL; + + /* make sure we clean up on exit */ + atexit(sm_cleanup); /* conservative */ + Sm_IO_DidInit = true; +} + +/* +** SM_IO_SETINFO -- change info for an open file type (fp) +** +** The generic SM_IO_WHAT_VECTORS is auto supplied for all file types. +** If the request is to set info other than SM_IO_WHAT_VECTORS then +** the request is passed on to the file type's specific setinfo vector. +** WARNING: this is working on an active/open file type. +** +** Parameters: +** fp -- file to make the setting on +** what -- type of information to set +** valp -- structure to obtain info from +** +** Returns: +** 0 on success +** -1 on error and sets errno: +** - when what != SM_IO_WHAT_VECTORS and setinfo vector +** not set +** - when vectored setinfo returns -1 +*/ + +int +sm_io_setinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + SM_FILE_T *v = (SM_FILE_T *) valp; + + SM_REQUIRE_ISA(fp, SmFileMagic); + switch (what) + { + case SM_IO_WHAT_VECTORS: + + /* + ** This is the "generic" available for all. + ** This allows the function vectors to be replaced + ** while the file type is active. + */ + + fp->f_close = v->f_close; + fp->f_read = v->f_read; + fp->f_seek = v->f_seek; + fp->f_write = v->f_write; + fp->f_open = v->f_open; + fp->f_setinfo = v->f_setinfo; + fp->f_getinfo = v->f_getinfo; + sm_free(fp->f_type); + fp->f_type = sm_strdup_x(v->f_type); + return 0; + case SM_IO_WHAT_TIMEOUT: + fp->f_timeout = *((int *)valp); + return 0; + } + + /* Otherwise the vector will check it out */ + if (fp->f_setinfo == NULL) + { + errno = EINVAL; + return -1; + } + else + return (*fp->f_setinfo)(fp, what, valp); +} + +/* +** SM_IO_GETINFO -- get information for an active file type (fp) +** +** This function supplies for all file types the answers for the +** three requests SM_IO_WHAT_VECTORS, SM_IO_WHAT_TYPE and +** SM_IO_WHAT_ISTYPE. Other requests are handled by the getinfo +** vector if available for the open file type. +** SM_IO_WHAT_VECTORS returns information for the file pointer vectors. +** SM_IO_WHAT_TYPE returns the type identifier for the file pointer +** SM_IO_WHAT_ISTYPE returns >0 if the passed in type matches the +** file pointer's type. +** SM_IO_IS_READABLE returns 1 if there is data available for reading, +** 0 otherwise. +** +** Parameters: +** fp -- file pointer for active file type +** what -- type of information request +** valp -- structure to place obtained info into +** +** Returns: +** -1 on error and sets errno: +** - when valp==NULL and request expects otherwise +** - when request is not SM_IO_WHAT_VECTORS and not +** SM_IO_WHAT_TYPE and not SM_IO_WHAT_ISTYPE +** and getinfo vector is NULL +** - when getinfo type vector returns -1 +** >=0 on success +*/ + +int +sm_io_getinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + SM_FILE_T *v = (SM_FILE_T *) valp; + + SM_REQUIRE_ISA(fp, SmFileMagic); + + switch (what) + { + case SM_IO_WHAT_VECTORS: + + /* This is the "generic" available for all */ + v->f_close = fp->f_close; + v->f_read = fp->f_read; + v->f_seek = fp->f_seek; + v->f_write = fp->f_write; + v->f_open = fp->f_open; + v->f_setinfo = fp->f_setinfo; + v->f_getinfo = fp->f_getinfo; + v->f_type = fp->f_type; + return 0; + + case SM_IO_WHAT_TYPE: + if (valp == NULL) + { + errno = EINVAL; + return -1; + } + valp = sm_strdup_x(fp->f_type); + return 0; + + case SM_IO_WHAT_ISTYPE: + if (valp == NULL) + { + errno = EINVAL; + return -1; + } + return strcmp(fp->f_type, valp) == 0; + + case SM_IO_IS_READABLE: + + /* if there is data in the buffer, it must be readable */ + if (fp->f_r > 0) + return 1; + + /* otherwise query the underlying file */ + break; + + case SM_IO_WHAT_TIMEOUT: + *((int *) valp) = fp->f_timeout; + return 0; + + case SM_IO_WHAT_FD: + if (fp->f_file > -1) + return fp->f_file; + + /* try the file type specific getinfo to see if it knows */ + break; + } + + /* Otherwise the vector will check it out */ + if (fp->f_getinfo == NULL) + { + errno = EINVAL; + return -1; + } + return (*fp->f_getinfo)(fp, what, valp); +} diff --git a/gnu/dist/sendmail/libsm/flags.c b/gnu/dist/sendmail/libsm/flags.c new file mode 100644 index 000000000000..b4cef2115650 --- /dev/null +++ b/gnu/dist/sendmail/libsm/flags.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: flags.c,v 1.20 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include + +/* +** SM_FLAGS -- translate external (user) flags into internal flags +** +** Paramters: +** flags -- user select flags +** +** Returns: +** Internal flag value matching user selected flags +*/ + +int +sm_flags(flags) + register int flags; +{ + register int ret; + + switch(flags) + { + case SM_IO_RDONLY: /* open for reading */ + ret = SMRD; + break; + + case SM_IO_WRONLY: /* open for writing */ + ret = SMWR; + break; + + case SM_IO_APPEND: /* open for appending */ + ret = SMWR; + break; + + case SM_IO_RDWR: /* open for read and write */ + ret = SMRW; + break; + + default: + ret = 0; + break; + } + return ret; +} diff --git a/gnu/dist/sendmail/libsm/fopen.c b/gnu/dist/sendmail/libsm/fopen.c new file mode 100644 index 000000000000..d37f574dc370 --- /dev/null +++ b/gnu/dist/sendmail/libsm/fopen.c @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fopen.c,v 1.60 2002/01/07 21:41:35 ca Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +extern int sm_io_fclose __P((SM_FILE_T *)); + +static jmp_buf OpenTimeOut, ReopenTimeOut; + +/* +** OPENALRM -- handler when timeout activated for sm_io_open() +** +** Returns flow of control to where setjmp(OpenTimeOut) was set. +** +** Parameters: +** sig -- unused +** +** Returns: +** does not return +** +** Side Effects: +** returns flow of control to setjmp(OpenTimeOut). +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED0 */ +static void +openalrm(sig) + int sig; +{ + longjmp(OpenTimeOut, 1); +} +/* +** REOPENALRM -- handler when timeout activated for sm_io_reopen() +** +** Returns flow of control to where setjmp(ReopenTimeOut) was set. +** +** Parameters: +** sig -- unused +** +** Returns: +** does not return +** +** Side Effects: +** returns flow of control to setjmp(ReopenTimeOut). +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED0 */ +static void +reopenalrm(sig) + int sig; +{ + longjmp(ReopenTimeOut, 1); +} + +/* +** SM_IO_OPEN -- open a file of a specific type +** +** Parameters: +** type -- type of file to open +** timeout -- time to complete the open +** info -- info describing what is to be opened (type dependant) +** flags -- user selected flags +** rpool -- pointer to rpool to be used for this open +** +** Returns: +** Raises exception on heap exhaustion. +** Aborts if type is invalid. +** Returns NULL and sets errno +** - when the type specific open fails +** - when open vector errors +** - when flags not set or invalid +** Success returns a file pointer to the opened file type. +*/ + +SM_FILE_T * +sm_io_open(type, timeout, info, flags, rpool) + const SM_FILE_T *type; + int SM_NONVOLATILE timeout; /* this is not the file type timeout */ + const void *info; + int flags; + const void *rpool; +{ + register SM_FILE_T *fp; + int ioflags; + SM_EVENT *evt = NULL; + + ioflags = sm_flags(flags); + + if (ioflags == 0) + { + /* must give some indication/intent */ + errno = EINVAL; + return NULL; + } + + if (timeout == SM_TIME_DEFAULT) + timeout = SM_TIME_FOREVER; + if (timeout == SM_TIME_IMMEDIATE) + { + errno = EAGAIN; + return NULL; + } + + fp = sm_fp(type, ioflags, NULL); + + /* Okay, this is where we set the timeout. */ + if (timeout != SM_TIME_FOREVER) + { + if (setjmp(OpenTimeOut) != 0) + { + errno = EAGAIN; + return NULL; + } + evt = sm_seteventm(timeout, openalrm, 0); + } + + if ((*fp->f_open)(fp, info, flags, rpool) < 0) + { + fp->f_flags = 0; /* release */ + fp->sm_magic = NULL; /* release */ + return NULL; + } + + /* We're back. So undo our timeout and handler */ + if (evt != NULL) + sm_clrevent(evt); + +#if SM_RPOOL + if (rpool != NULL) + sm_rpool_attach_x(rpool, sm_io_fclose, fp); +#endif /* SM_RPOOL */ + + return fp; +} +/* +** SM_IO_DUP -- duplicate a file pointer +** +** Parameters: +** fp -- file pointer to duplicate +** +** Returns: +** Success - the duplicated file pointer +** Failure - NULL (was an invalid file pointer or too many open) +** +** Increments the duplicate counter (dup_cnt) for the open file pointer. +** The counter counts the number of duplicates. When the duplicate +** counter is 0 (zero) then the file pointer is the only one left +** (no duplicates, it is the only one). +*/ + +SM_FILE_T * +sm_io_dup(fp) + SM_FILE_T *fp; +{ + + SM_REQUIRE_ISA(fp, SmFileMagic); + if (fp->sm_magic != SmFileMagic) + { + errno = EBADF; + return NULL; + } + if (fp->f_dup_cnt >= INT_MAX - 1) + { + /* Can't let f_dup_cnt wrap! */ + errno = EMFILE; + return NULL; + } + fp->f_dup_cnt++; + return fp; +} +/* +** SM_IO_REOPEN -- open a new file using the old file pointer +** +** Parameters: +** type -- file type to be opened +** timeout -- time to complete the reopen +** info -- infomation about what is to be "re-opened" (type dep.) +** flags -- user flags to map to internal flags +** rpool -- rpool file to be associated with +** fp -- the file pointer to reuse +** +** Returns: +** Raises an exception on heap exhaustion. +** Aborts if type is invalid. +** Failure: returns NULL +** Success: returns "reopened" file pointer +*/ + +SM_FILE_T * +sm_io_reopen(type, timeout, info, flags, rpool, fp) + const SM_FILE_T *type; + int SM_NONVOLATILE timeout; + const void *info; + int flags; + const void *rpool; + SM_FILE_T *fp; +{ + int ioflags, ret; + SM_FILE_T *fp2; + SM_EVENT *evt = NULL; + + if ((ioflags = sm_flags(flags)) == 0) + { + (void) sm_io_close(fp, timeout); + return NULL; + } + + if (!Sm_IO_DidInit) + sm_init(); + + if (timeout == SM_TIME_DEFAULT) + timeout = SM_TIME_FOREVER; + if (timeout == SM_TIME_IMMEDIATE) + { + /* + ** Filling the buffer will take time and we are wanted to + ** return immediately. So... + */ + + errno = EAGAIN; + return NULL; + } + /* Okay, this is where we set the timeout. */ + if (timeout != SM_TIME_FOREVER) + { + if (setjmp(ReopenTimeOut) != 0) + { + errno = EAGAIN; + return NULL; + } + + evt = sm_seteventm(timeout, reopenalrm, 0); + } + + /* + ** There are actually programs that depend on being able to "reopen" + ** descriptors that weren't originally open. Keep this from breaking. + ** Remember whether the stream was open to begin with, and which file + ** descriptor (if any) was associated with it. If it was attached to + ** a descriptor, defer closing it; reopen("/dev/stdin", "r", stdin) + ** should work. This is unnecessary if it was not a Unix file. + */ + + if (fp != NULL) + { + if (fp->sm_magic != SmFileMagic) + fp->f_flags = SMFEOF; /* hold on to it */ + else + { + /* flush the stream; ANSI doesn't require this. */ + (void) sm_io_flush(fp, SM_TIME_FOREVER); + (void) sm_io_close(fp, SM_TIME_FOREVER); + } + } + + fp2 = sm_fp(type, ioflags, fp); + ret = (*fp2->f_open)(fp2, info, flags, rpool); + + /* We're back. So undo our timeout and handler */ + if (evt != NULL) + sm_clrevent(evt); + + if (ret < 0) + { + fp2->f_flags = 0; /* release */ + fp2->sm_magic = NULL; /* release */ + return NULL; + } + + /* + ** We're not preserving this logic (below) for sm_io because it is now + ** abstracted at least one "layer" away. By closing and reopening + ** the 1st fd used should be the just released one (when Unix + ** behavior followed). Old comment:: + ** If reopening something that was open before on a real file, try + ** to maintain the descriptor. Various C library routines (perror) + ** assume stderr is always fd STDERR_FILENO, even if being reopen'd. + */ + +#if SM_RPOOL + if (rpool != NULL) + sm_rpool_attach_x(rpool, sm_io_close, fp2); +#endif /* SM_RPOOL */ + + return fp2; +} +/* +** SM_IO_AUTOFLUSH -- link another file to this for auto-flushing +** +** When a read occurs on fp, fp2 will be flushed iff there is no +** data waiting on fp. +** +** Parameters: +** fp -- the file opened for reading. +** fp2 -- the file opened for writing. +** +** Returns: +** The old flush file pointer. +*/ + +SM_FILE_T * +sm_io_autoflush(fp, fp2) + SM_FILE_T *fp; + SM_FILE_T *fp2; +{ + SM_FILE_T *savefp; + + SM_REQUIRE_ISA(fp, SmFileMagic); + if (fp2 != NULL) + SM_REQUIRE_ISA(fp2, SmFileMagic); + + savefp = fp->f_flushfp; + fp->f_flushfp = fp2; + return savefp; +} +/* +** SM_IO_AUTOMODE -- link another file to this for auto-moding +** +** When the mode (blocking or non-blocking) changes for fp1 then +** update fp2's mode at the same time. This is to be used when +** a system dup() has generated a second file descriptor for +** another sm_io_open() by file descriptor. The modes have been +** linked in the system and this formalizes it for sm_io internally. +** +** Parameters: +** fp1 -- the first file +** fp2 -- the second file +** +** Returns: +** nothing +*/ + +void +sm_io_automode(fp1, fp2) + SM_FILE_T *fp1; + SM_FILE_T *fp2; +{ + SM_REQUIRE_ISA(fp1, SmFileMagic); + SM_REQUIRE_ISA(fp2, SmFileMagic); + + fp1->f_modefp = fp2; + fp2->f_modefp = fp1; +} diff --git a/gnu/dist/sendmail/libsm/fpos.c b/gnu/dist/sendmail/libsm/fpos.c new file mode 100644 index 000000000000..69cd1f0b3376 --- /dev/null +++ b/gnu/dist/sendmail/libsm/fpos.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fpos.c,v 1.37 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +static jmp_buf TellTimeOut; + +/* +** TELLALRM -- handler when timeout activated for sm_io_tell() +** +** Returns flow of control to where setjmp(TellTimeOut) was set. +** +** Parameters: +** sig -- unused +** +** Returns: +** does not return +** +** Side Effects: +** returns flow of control to setjmp(TellTimeOut). +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED0 */ +static void +tellalrm(sig) + int sig; +{ + longjmp(TellTimeOut, 1); +} + +/* +** SM_IO_TELL -- position the file pointer +** +** Paramters: +** fp -- the file pointer to get repositioned +** timeout -- time to complete the tell (milliseconds) +** +** Returns: +** Success -- the repositioned location. +** Failure -- -1 (minus 1) and sets errno +*/ + +long +sm_io_tell(fp, timeout) + register SM_FILE_T *fp; + int SM_NONVOLATILE timeout; +{ + register off_t pos; + SM_EVENT *evt = NULL; + + SM_REQUIRE_ISA(fp, SmFileMagic); + if (fp->f_seek == NULL) + { + errno = ESPIPE; /* historic practice */ + return -1L; + } + + if (timeout == SM_TIME_DEFAULT) + timeout = fp->f_timeout; + if (timeout == SM_TIME_IMMEDIATE) + { + /* + ** Filling the buffer will take time and we are wanted to + ** return immediately. So... + */ + + errno = EAGAIN; + return -1L; + } + + /* + ** Find offset of underlying I/O object, then adjust byte position + ** may adjust seek offset on append stream + */ + + (void) sm_flush(fp, (int *) &timeout); + + /* This is where we start the timeout */ + if (timeout != SM_TIME_FOREVER) + { + if (setjmp(TellTimeOut) != 0) + { + errno = EAGAIN; + return -1L; + } + + evt = sm_seteventm(timeout, tellalrm, 0); + } + + if (fp->f_flags & SMOFF) + pos = fp->f_lseekoff; + else + { + /* XXX only set the timeout here? */ + pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR); + if (pos == -1L) + goto clean; + } + if (fp->f_flags & SMRD) + { + /* + ** Reading. Any unread characters (including + ** those from ungetc) cause the position to be + ** smaller than that in the underlying object. + */ + + pos -= fp->f_r; + if (HASUB(fp)) + pos -= fp->f_ur; + } + else if (fp->f_flags & SMWR && fp->f_p != NULL) + { + /* + ** Writing. Any buffered characters cause the + ** position to be greater than that in the + ** underlying object. + */ + + pos += fp->f_p - fp->f_bf.smb_base; + } + +clean: + /* We're back. So undo our timeout and handler */ + if (evt != NULL) + sm_clrevent(evt); + return pos; +} diff --git a/gnu/dist/sendmail/libsm/fprintf.c b/gnu/dist/sendmail/libsm/fprintf.c new file mode 100644 index 000000000000..e9d07190253a --- /dev/null +++ b/gnu/dist/sendmail/libsm/fprintf.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fprintf.c,v 1.17 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include "local.h" + +/* +** SM_IO_FPRINTF -- format and print a string to a file pointer +** +** Parameters: +** fp -- file pointer to be printed to +** timeout -- time to complete print +** fmt -- markup format for the string to be printed +** ... -- additional information for 'fmt' +** +** Returns: +** Failure: returns SM_IO_EOF and sets errno +** Success: returns the number of characters o/p +*/ + +int +#if SM_VA_STD +sm_io_fprintf(SM_FILE_T *fp, int timeout, const char *fmt, ...) +#else /* SM_VA_STD */ +sm_io_fprintf(fp, timeout, fmt, va_alist) + SM_FILE_T *fp; + int timeout; + char *fmt; + va_dcl +#endif /* SM_VA_STD */ +{ + int ret; + SM_VA_LOCAL_DECL + + SM_REQUIRE_ISA(fp, SmFileMagic); + SM_VA_START(ap, fmt); + ret = sm_io_vfprintf(fp, timeout, fmt, ap); + SM_VA_END(ap); + return ret; +} diff --git a/gnu/dist/sendmail/libsm/fpurge.c b/gnu/dist/sendmail/libsm/fpurge.c new file mode 100644 index 000000000000..cfc9dd884a6e --- /dev/null +++ b/gnu/dist/sendmail/libsm/fpurge.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fpurge.c,v 1.20 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include +#include "local.h" + +/* +** SM_IO_PURGE -- purge/empty the buffer without committing buffer content +** +** Parameters: +** fp -- file pointer to purge +** +** Returns: +** Failure: returns SM_IO_EOF and sets errno +** Success: returns 0 (zero) +*/ + +int +sm_io_purge(fp) + register SM_FILE_T *fp; +{ + SM_REQUIRE_ISA(fp, SmFileMagic); + if (!fp->f_flags) + { + errno = EBADF; + return SM_IO_EOF; + } + + if (HASUB(fp)) + FREEUB(fp); + fp->f_p = fp->f_bf.smb_base; + fp->f_r = 0; + + /* implies SMFBF */ + fp->f_w = fp->f_flags & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; + return 0; +} diff --git a/gnu/dist/sendmail/libsm/fput.c b/gnu/dist/sendmail/libsm/fput.c new file mode 100644 index 000000000000..2328dd2a02dd --- /dev/null +++ b/gnu/dist/sendmail/libsm/fput.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fput.c,v 1.20 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include +#include "local.h" +#include "fvwrite.h" + +/* +** SM_IO_FPUTS -- add a string to the buffer for the file pointer +** +** Parameters: +** fp -- the file pointer for the buffer to be written to +** timeout -- time to complete the put-string +** s -- string to be placed in the buffer +** +** Returns: +** Failure: returns SM_IO_EOF +** Success: returns 0 (zero) +*/ + +int +sm_io_fputs(fp, timeout, s) + SM_FILE_T *fp; + int timeout; + const char *s; +{ + struct sm_uio uio; + struct sm_iov iov; + + SM_REQUIRE_ISA(fp, SmFileMagic); + iov.iov_base = (void *) s; + iov.iov_len = uio.uio_resid = strlen(s); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + return sm_fvwrite(fp, timeout, &uio); +} diff --git a/gnu/dist/sendmail/libsm/fread.c b/gnu/dist/sendmail/libsm/fread.c new file mode 100644 index 000000000000..6a6309faf21d --- /dev/null +++ b/gnu/dist/sendmail/libsm/fread.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fread.c,v 1.28 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include +#include "local.h" + +/* +** SM_IO_READ -- read data from the file pointer +** +** Parameters: +** fp -- file pointer to read from +** timeout -- time to complete the read +** buf -- location to place read data +** size -- size of each chunk of data +** +** Returns: +** Failure: returns 0 (zero) _and_ sets errno +** Success: returns the number of whole chunks read. +** +** A read returning 0 (zero) is only an indication of error when errno +** has been set. +*/ + +size_t +sm_io_read(fp, timeout, buf, size) + SM_FILE_T *fp; + int timeout; + void *buf; + size_t size; +{ + register size_t resid = size; + register char *p; + register int r; + + SM_REQUIRE_ISA(fp, SmFileMagic); + + if (fp->f_read == NULL) + { + errno = ENODEV; + return 0; + } + + /* + ** The ANSI standard requires a return value of 0 for a count + ** or a size of 0. Peculiarily, it imposes no such requirements + ** on fwrite; it only requires read to be broken. + */ + + if (resid == 0) + return 0; + if (fp->f_r < 0) + fp->f_r = 0; + p = buf; + while ((int) resid > (r = fp->f_r)) + { + (void) memcpy((void *) p, (void *) fp->f_p, (size_t) r); + fp->f_p += r; + /* fp->f_r = 0 ... done in sm_refill */ + p += r; + resid -= r; + if ((fp->f_flags & SMNOW) != 0 && r > 0) + { + /* + ** Take whatever we have available. Spend no more time + ** trying to get all that has been requested. + ** This is needed on some file types (such as + ** SASL) that would jam when given extra, untimely + ** reads. + */ + + fp->f_r -= r; + return size - resid; + } + if (sm_refill(fp, timeout) != 0) + { + /* no more input: return partial result */ + return size - resid; + } + } + (void) memcpy((void *) p, (void *) fp->f_p, resid); + fp->f_r -= resid; + fp->f_p += resid; + return size; +} diff --git a/gnu/dist/sendmail/libsm/fscanf.c b/gnu/dist/sendmail/libsm/fscanf.c new file mode 100644 index 000000000000..7bd8310bcb28 --- /dev/null +++ b/gnu/dist/sendmail/libsm/fscanf.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fscanf.c,v 1.17 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include "local.h" + +/* +** SM_IO_FSCANF -- convert input data to translated format +** +** Parameters: +** fp -- the file pointer to obtain the data from +** timeout -- time to complete scan +** fmt -- the format to translate the data to +** ... -- memory locations to place the formated data +** +** Returns: +** Failure: returns SM_IO_EOF +** Success: returns the number of data units translated +*/ + +int +#if SM_VA_STD +sm_io_fscanf(SM_FILE_T *fp, int timeout, char const *fmt, ...) +#else /* SM_VA_STD */ +sm_io_fscanf(fp, timeout, fmt, va_alist) + SM_FILE_T *fp; + int timeout; + char *fmt; + va_dcl +#endif /* SM_VA_STD */ +{ + int ret; + SM_VA_LOCAL_DECL + + SM_REQUIRE_ISA(fp, SmFileMagic); + SM_VA_START(ap, fmt); + ret = sm_vfscanf(fp, timeout, fmt, ap); + SM_VA_END(ap); + return ret; +} diff --git a/gnu/dist/sendmail/libsm/fseek.c b/gnu/dist/sendmail/libsm/fseek.c new file mode 100644 index 000000000000..e979a710320a --- /dev/null +++ b/gnu/dist/sendmail/libsm/fseek.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fseek.c,v 1.45 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +#define POS_ERR (-(off_t)1) + +static jmp_buf SeekTimeOut; + +/* +** SEEKALRM -- handler when timeout activated for sm_io_seek() +** +** Returns flow of control to where setjmp(SeekTimeOut) was set. +** +** Parameters: +** sig -- unused +** +** Returns: +** does not return +** +** Side Effects: +** returns flow of control to setjmp(SeekTimeOut). +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED0 */ +static void +seekalrm(sig) + int sig; +{ + longjmp(SeekTimeOut, 1); +} + +/* +** SM_IO_SEEK -- position the file pointer +** +** Parameters: +** fp -- the file pointer to be seek'd +** timeout -- time to complete seek (milliseconds) +** offset -- seek offset based on 'whence' +** whence -- indicates where seek is relative from. +** One of SM_IO_SEEK_{CUR,SET,END}. +** Returns: +** Failure: returns -1 (minus 1) and sets errno +** Success: returns 0 (zero) +*/ + +int +sm_io_seek(fp, timeout, offset, whence) + register SM_FILE_T *fp; + int SM_NONVOLATILE timeout; + long SM_NONVOLATILE offset; + int SM_NONVOLATILE whence; +{ + bool havepos; + off_t target, curoff; + size_t n; + struct stat st; + int ret; + SM_EVENT *evt = NULL; + register off_t (*seekfn) __P((SM_FILE_T *, off_t, int)); + + SM_REQUIRE_ISA(fp, SmFileMagic); + + /* make sure stdio is set up */ + if (!Sm_IO_DidInit) + sm_init(); + + /* Have to be able to seek. */ + if ((seekfn = fp->f_seek) == NULL) + { + errno = ESPIPE; /* historic practice */ + return -1; + } + + if (timeout == SM_TIME_DEFAULT) + timeout = fp->f_timeout; + if (timeout == SM_TIME_IMMEDIATE) + { + /* + ** Filling the buffer will take time and we are wanted to + ** return immediately. So... + */ + + errno = EAGAIN; + return -1; + } + +#define SM_SET_ALARM() \ + if (timeout != SM_TIME_FOREVER) \ + { \ + if (setjmp(SeekTimeOut) != 0) \ + { \ + errno = EAGAIN; \ + return -1; \ + } \ + evt = sm_seteventm(timeout, seekalrm, 0); \ + } + + /* + ** Change any SM_IO_SEEK_CUR to SM_IO_SEEK_SET, and check `whence' + ** argument. After this, whence is either SM_IO_SEEK_SET or + ** SM_IO_SEEK_END. + */ + + switch (whence) + { + case SM_IO_SEEK_CUR: + + /* + ** In order to seek relative to the current stream offset, + ** we have to first find the current stream offset a la + ** ftell (see ftell for details). + */ + + /* may adjust seek offset on append stream */ + sm_flush(fp, (int *) &timeout); + SM_SET_ALARM(); + if (fp->f_flags & SMOFF) + curoff = fp->f_lseekoff; + else + { + curoff = (*seekfn)(fp, (off_t) 0, SM_IO_SEEK_CUR); + if (curoff == -1L) + { + ret = -1; + goto clean; + } + } + if (fp->f_flags & SMRD) + { + curoff -= fp->f_r; + if (HASUB(fp)) + curoff -= fp->f_ur; + } + else if (fp->f_flags & SMWR && fp->f_p != NULL) + curoff += fp->f_p - fp->f_bf.smb_base; + + offset += curoff; + whence = SM_IO_SEEK_SET; + havepos = true; + break; + + case SM_IO_SEEK_SET: + case SM_IO_SEEK_END: + SM_SET_ALARM(); + curoff = 0; /* XXX just to keep gcc quiet */ + havepos = false; + break; + + default: + errno = EINVAL; + return -1; + } + + /* + ** Can only optimise if: + ** reading (and not reading-and-writing); + ** not unbuffered; and + ** this is a `regular' Unix file (and hence seekfn==sm_stdseek). + ** We must check SMNBF first, because it is possible to have SMNBF + ** and SMSOPT both set. + */ + + if (fp->f_bf.smb_base == NULL) + sm_makebuf(fp); + if (fp->f_flags & (SMWR | SMRW | SMNBF | SMNPT)) + goto dumb; + if ((fp->f_flags & SMOPT) == 0) + { + if (seekfn != sm_stdseek || + fp->f_file < 0 || fstat(fp->f_file, &st) || + (st.st_mode & S_IFMT) != S_IFREG) + { + fp->f_flags |= SMNPT; + goto dumb; + } + fp->f_blksize = st.st_blksize; + fp->f_flags |= SMOPT; + } + + /* + ** We are reading; we can try to optimise. + ** Figure out where we are going and where we are now. + */ + + if (whence == SM_IO_SEEK_SET) + target = offset; + else + { + if (fstat(fp->f_file, &st)) + goto dumb; + target = st.st_size + offset; + } + + if (!havepos) + { + if (fp->f_flags & SMOFF) + curoff = fp->f_lseekoff; + else + { + curoff = (*seekfn)(fp, (off_t) 0, SM_IO_SEEK_CUR); + if (curoff == POS_ERR) + goto dumb; + } + curoff -= fp->f_r; + if (HASUB(fp)) + curoff -= fp->f_ur; + } + + /* + ** Compute the number of bytes in the input buffer (pretending + ** that any ungetc() input has been discarded). Adjust current + ** offset backwards by this count so that it represents the + ** file offset for the first byte in the current input buffer. + */ + + if (HASUB(fp)) + { + curoff += fp->f_r; /* kill off ungetc */ + n = fp->f_up - fp->f_bf.smb_base; + curoff -= n; + n += fp->f_ur; + } + else + { + n = fp->f_p - fp->f_bf.smb_base; + curoff -= n; + n += fp->f_r; + } + + /* + ** If the target offset is within the current buffer, + ** simply adjust the pointers, clear SMFEOF, undo ungetc(), + ** and return. (If the buffer was modified, we have to + ** skip this; see getln in fget.c.) + */ + + if (target >= curoff && target < curoff + (off_t) n) + { + register int o = target - curoff; + + fp->f_p = fp->f_bf.smb_base + o; + fp->f_r = n - o; + if (HASUB(fp)) + FREEUB(fp); + fp->f_flags &= ~SMFEOF; + ret = 0; + goto clean; + } + + /* + ** The place we want to get to is not within the current buffer, + ** but we can still be kind to the kernel copyout mechanism. + ** By aligning the file offset to a block boundary, we can let + ** the kernel use the VM hardware to map pages instead of + ** copying bytes laboriously. Using a block boundary also + ** ensures that we only read one block, rather than two. + */ + + curoff = target & ~(fp->f_blksize - 1); + if ((*seekfn)(fp, curoff, SM_IO_SEEK_SET) == POS_ERR) + goto dumb; + fp->f_r = 0; + fp->f_p = fp->f_bf.smb_base; + if (HASUB(fp)) + FREEUB(fp); + fp->f_flags &= ~SMFEOF; + n = target - curoff; + if (n) + { + /* Note: SM_TIME_FOREVER since fn timeout already set */ + if (sm_refill(fp, SM_TIME_FOREVER) || fp->f_r < (int) n) + goto dumb; + fp->f_p += n; + fp->f_r -= n; + } + + ret = 0; +clean: + /* We're back. So undo our timeout and handler */ + if (evt != NULL) + sm_clrevent(evt); + return ret; +dumb: + /* + ** We get here if we cannot optimise the seek ... just + ** do it. Allow the seek function to change fp->f_bf.smb_base. + */ + + /* Note: SM_TIME_FOREVER since fn timeout already set */ + ret = SM_TIME_FOREVER; + if (sm_flush(fp, &ret) != 0 || + (*seekfn)(fp, (off_t) offset, whence) == POS_ERR) + { + ret = -1; + goto clean; + } + + /* success: clear SMFEOF indicator and discard ungetc() data */ + if (HASUB(fp)) + FREEUB(fp); + fp->f_p = fp->f_bf.smb_base; + fp->f_r = 0; + fp->f_flags &= ~SMFEOF; + ret = 0; + goto clean; +} diff --git a/gnu/dist/sendmail/libsm/fvwrite.c b/gnu/dist/sendmail/libsm/fvwrite.c new file mode 100644 index 000000000000..43c1ec91c7a3 --- /dev/null +++ b/gnu/dist/sendmail/libsm/fvwrite.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fvwrite.c,v 1.49 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" +#include "fvwrite.h" + +/* +** SM_FVWRITE -- write memory regions and buffer for file pointer +** +** Parameters: +** fp -- the file pointer to write to +** timeout -- time length for function to return by +** uio -- the memory regions to write +** +** Returns: +** Failure: returns SM_IO_EOF and sets errno +** Success: returns 0 (zero) +** +** This routine is large and unsightly, but most of the ugliness due +** to the different kinds of output buffering handled here. +*/ + +#define COPY(n) (void)memcpy((void *)fp->f_p, (void *)p, (size_t)(n)) +#define GETIOV(extra_work) \ + while (len == 0) \ + { \ + extra_work; \ + p = iov->iov_base; \ + len = iov->iov_len; \ + iov++; \ + } + +int +sm_fvwrite(fp, timeout, uio) + register SM_FILE_T *fp; + int timeout; + register struct sm_uio *uio; +{ + register size_t len; + register char *p; + register struct sm_iov *iov; + register int w, s; + char *nl; + int nlknown, nldist; + int fd; + struct timeval to; + + if (uio->uio_resid == 0) + return 0; + + /* make sure we can write */ + if (cantwrite(fp)) + { + errno = EBADF; + return SM_IO_EOF; + } + + SM_CONVERT_TIME(fp, fd, timeout, &to); + + iov = uio->uio_iov; + p = iov->iov_base; + len = iov->iov_len; + iov++; + if (fp->f_flags & SMNBF) + { + /* Unbuffered: write up to BUFSIZ bytes at a time. */ + do + { + GETIOV(;); + errno = 0; /* needed to ensure EOF correctly found */ + w = (*fp->f_write)(fp, p, SM_MIN(len, SM_IO_BUFSIZ)); + if (w <= 0) + { + if (w == 0 && errno == 0) + break; /* EOF found */ + if (IS_IO_ERROR(fd, w, timeout)) + goto err; /* errno set */ + + /* write would block */ + SM_IO_WR_TIMEOUT(fp, fd, timeout); + w = 0; + } + else + { + p += w; + len -= w; + } + } while ((uio->uio_resid -= w) != 0); + } + else if ((fp->f_flags & SMLBF) == 0) + { + /* + ** Not SMLBF (line-buffered). Either SMFBF or SMNOW + ** buffered: fill partially full buffer, if any, + ** and then flush. If there is no partial buffer, write + ** one bf._size byte chunk directly (without copying). + ** + ** String output is a special case: write as many bytes + ** as fit, but pretend we wrote everything. This makes + ** snprintf() return the number of bytes needed, rather + ** than the number used, and avoids its write function + ** (so that the write function can be invalid). + */ + + do + { + GETIOV(;); + if ((((fp->f_flags & (SMALC | SMSTR)) == (SMALC | SMSTR)) + || ((fp->f_flags & SMNOW) != 0)) + && (size_t) fp->f_w < len) + { + size_t blen = fp->f_p - fp->f_bf.smb_base; + unsigned char *tbase; + int tsize; + + /* Allocate space exponentially. */ + tsize = fp->f_bf.smb_size; + do + { + tsize = (tsize << 1) + 1; + } while ((size_t) tsize < blen + len); + tbase = (unsigned char *) sm_realloc(fp->f_bf.smb_base, + tsize + 1); + if (tbase == NULL) + { + errno = ENOMEM; + goto err; /* errno set */ + } + fp->f_w += tsize - fp->f_bf.smb_size; + fp->f_bf.smb_base = tbase; + fp->f_bf.smb_size = tsize; + fp->f_p = tbase + blen; + } + w = fp->f_w; + errno = 0; /* needed to ensure EOF correctly found */ + if (fp->f_flags & SMSTR) + { + if (len < (size_t) w) + w = len; + COPY(w); /* copy SM_MIN(fp->f_w,len), */ + fp->f_w -= w; + fp->f_p += w; + w = len; /* but pretend copied all */ + } + else if (fp->f_p > fp->f_bf.smb_base + && len > (size_t) w) + { + /* fill and flush */ + COPY(w); + fp->f_p += w; + if (sm_flush(fp, &timeout)) + goto err; /* errno set */ + } + else if (len >= (size_t) (w = fp->f_bf.smb_size)) + { + /* write directly */ + w = (*fp->f_write)(fp, p, w); + if (w <= 0) + { + if (w == 0 && errno == 0) + break; /* EOF found */ + if (IS_IO_ERROR(fd, w, timeout)) + goto err; /* errno set */ + + /* write would block */ + SM_IO_WR_TIMEOUT(fp, fd, timeout); + w = 0; + } + } + else + { + /* fill and done */ + w = len; + COPY(w); + fp->f_w -= w; + fp->f_p += w; + } + p += w; + len -= w; + } while ((uio->uio_resid -= w) != 0); + + if ((fp->f_flags & SMNOW) != 0 && sm_flush(fp, &timeout)) + goto err; /* errno set */ + } + else + { + /* + ** Line buffered: like fully buffered, but we + ** must check for newlines. Compute the distance + ** to the first newline (including the newline), + ** or `infinity' if there is none, then pretend + ** that the amount to write is SM_MIN(len,nldist). + */ + + nlknown = 0; + nldist = 0; /* XXX just to keep gcc happy */ + do + { + GETIOV(nlknown = 0); + if (!nlknown) + { + nl = memchr((void *)p, '\n', len); + nldist = nl != NULL ? nl + 1 - p : len + 1; + nlknown = 1; + } + s = SM_MIN(len, ((size_t) nldist)); + w = fp->f_w + fp->f_bf.smb_size; + errno = 0; /* needed to ensure EOF correctly found */ + if (fp->f_p > fp->f_bf.smb_base && s > w) + { + COPY(w); + /* fp->f_w -= w; */ + fp->f_p += w; + if (sm_flush(fp, &timeout)) + goto err; /* errno set */ + } + else if (s >= (w = fp->f_bf.smb_size)) + { + w = (*fp->f_write)(fp, p, w); + if (w <= 0) + { + if (w == 0 && errno == 0) + break; /* EOF found */ + if (IS_IO_ERROR(fd, w, timeout)) + goto err; /* errno set */ + + /* write would block */ + SM_IO_WR_TIMEOUT(fp, fd, timeout); + w = 0; + } + } + else + { + w = s; + COPY(w); + fp->f_w -= w; + fp->f_p += w; + } + if ((nldist -= w) == 0) + { + /* copied the newline: flush and forget */ + if (sm_flush(fp, &timeout)) + goto err; /* errno set */ + nlknown = 0; + } + p += w; + len -= w; + } while ((uio->uio_resid -= w) != 0); + } + + return 0; + +err: + /* errno set before goto places us here */ + fp->f_flags |= SMERR; + return SM_IO_EOF; +} diff --git a/gnu/dist/sendmail/libsm/fvwrite.h b/gnu/dist/sendmail/libsm/fvwrite.h new file mode 100644 index 000000000000..83c78f2cdb80 --- /dev/null +++ b/gnu/dist/sendmail/libsm/fvwrite.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + * + * Id: fvwrite.h,v 1.7 2001/03/02 00:18:19 ca Exp + */ + +/* I/O descriptors for sm_fvwrite() */ +struct sm_iov +{ + void *iov_base; + size_t iov_len; +}; +struct sm_uio +{ + struct sm_iov *uio_iov; + int uio_iovcnt; + int uio_resid; +}; + +extern int sm_fvwrite __P((SM_FILE_T *, int, struct sm_uio *)); diff --git a/gnu/dist/sendmail/libsm/fwalk.c b/gnu/dist/sendmail/libsm/fwalk.c new file mode 100644 index 000000000000..a84c0a0d6539 --- /dev/null +++ b/gnu/dist/sendmail/libsm/fwalk.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fwalk.c,v 1.21 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include "local.h" +#include "glue.h" + +/* +** SM_FWALK -- apply a function to all found-open file pointers +** +** Parameters: +** function -- a function vector to be applied +** timeout -- time to complete actions (milliseconds) +** +** Returns: +** The (binary) OR'd result of each function call +*/ + +int +sm_fwalk(function, timeout) + int (*function) __P((SM_FILE_T *, int *)); + int *timeout; +{ + register SM_FILE_T *fp; + register int n, ret; + register struct sm_glue *g; + int fptimeout; + + ret = 0; + for (g = &smglue; g != NULL; g = g->gl_next) + { + for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++) + { + if (fp->f_flags != 0) + { + if (*timeout == SM_TIME_DEFAULT) + fptimeout = fp->f_timeout; + else + fptimeout = *timeout; + if (fptimeout == SM_TIME_IMMEDIATE) + continue; /* skip it */ + ret |= (*function)(fp, &fptimeout); + } + } + } + return ret; +} diff --git a/gnu/dist/sendmail/libsm/fwrite.c b/gnu/dist/sendmail/libsm/fwrite.c new file mode 100644 index 000000000000..a1f3d4fa37c0 --- /dev/null +++ b/gnu/dist/sendmail/libsm/fwrite.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: fwrite.c,v 1.24 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include +#include "local.h" +#include "fvwrite.h" + +/* +** SM_IO_WRITE -- write to a file pointer +** +** Parameters: +** fp -- file pointer writing to +** timeout -- time to complete the write +** buf -- location of data to be written +** size -- number of bytes to be written +** +** Result: +** Failure: returns 0 _and_ sets errno +** Success: returns >=0 with errno unchanged, where the +** number returned is the number of bytes written. +*/ + +size_t +sm_io_write(fp, timeout, buf, size) + SM_FILE_T *fp; + int timeout; + const void *buf; + size_t size; +{ + struct sm_uio uio; + struct sm_iov iov; + + SM_REQUIRE_ISA(fp, SmFileMagic); + + if (fp->f_write == NULL) + { + errno = ENODEV; + return 0; + } + + iov.iov_base = (void *) buf; + uio.uio_resid = iov.iov_len = size; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + + /* The usual case is success (sm_fvwrite returns 0) */ + if (sm_fvwrite(fp, timeout, &uio) == 0) + return size; + + /* else return number of bytes actually written */ + return size - uio.uio_resid; +} diff --git a/gnu/dist/sendmail/libsm/gen.html b/gnu/dist/sendmail/libsm/gen.html new file mode 100644 index 000000000000..cd2d6917e0bd --- /dev/null +++ b/gnu/dist/sendmail/libsm/gen.html @@ -0,0 +1,43 @@ + + + libsm : General Definitions + + + +Back to libsm overview + +
+

libsm : General Definitions

+
Id: gen.html,v 1.5 2000/12/08 21:41:42 ca Exp +
+ +

Introduction

+ +The header file <sm/gen.h> +contains general definitions that are used by every other +header file in libsm. + +

Synopsis

+ +
+#include <sm/gen.h>
+
+#define NULL		((void*)0)
+
+typedef int bool;
+#define false	0
+#define true	1
+
+#define SM_MAX(a, b)	((a) > (b) ? (a) : (b))
+#define SM_MIN(a, b)	((a) < (b) ? (a) : (b))
+
+/*
+**  The following types can be accessed and updated atomically.
+**  This is relevant in the context of signal handlers and threads.
+*/
+typedef some signed integral type SM_ATOMIC_INT_T;
+typedef some unsigned integral type SM_ATOMIC_UINT_T;
+
+ + + diff --git a/gnu/dist/sendmail/libsm/get.c b/gnu/dist/sendmail/libsm/get.c new file mode 100644 index 000000000000..0e88838524f6 --- /dev/null +++ b/gnu/dist/sendmail/libsm/get.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: get.c,v 1.18 2001/09/11 04:04:48 gshapiro Exp") +#include +#include +#include "local.h" + +/* +** SM_IO_GETC -- get a character from a file +** +** Parameters: +** fp -- the file to get the character from +** timeout -- time to complete getc +** +** Returns: +** Success: the value of the character read. +** Failure: SM_IO_EOF +** +** This is a function version of the macro (in ). +** It is guarded with locks (which are currently not functional) +** for multi-threaded programs. +*/ + +#undef sm_io_getc + +int +sm_io_getc(fp, timeout) + register SM_FILE_T *fp; + int timeout; +{ + SM_REQUIRE_ISA(fp, SmFileMagic); + return sm_getc(fp, timeout); +} diff --git a/gnu/dist/sendmail/libsm/glue.h b/gnu/dist/sendmail/libsm/glue.h new file mode 100644 index 000000000000..91deb83b4a0f --- /dev/null +++ b/gnu/dist/sendmail/libsm/glue.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + * + * Id: glue.h,v 1.6 2001/01/22 23:09:49 ca Exp + */ + +/* +** The first few FILEs are statically allocated; others are dynamically +** allocated and linked in via this glue structure. +*/ + +extern struct sm_glue +{ + struct sm_glue *gl_next; + int gl_niobs; + SM_FILE_T *gl_iobs; +} smglue; diff --git a/gnu/dist/sendmail/libsm/heap.c b/gnu/dist/sendmail/libsm/heap.c new file mode 100644 index 000000000000..aa3d51b7070f --- /dev/null +++ b/gnu/dist/sendmail/libsm/heap.c @@ -0,0 +1,819 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: heap.c,v 1.50 2001/09/11 04:04:48 gshapiro Exp") + +/* +** debugging memory allocation package +** See heap.html for documentation. +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* undef all macro versions of the "functions" so they can be specified here */ +#undef sm_malloc +#undef sm_malloc_x +#undef sm_malloc_tagged +#undef sm_malloc_tagged_x +#undef sm_free +#undef sm_free_tagged +#undef sm_realloc +#if SM_HEAP_CHECK +# undef sm_heap_register +# undef sm_heap_checkptr +# undef sm_heap_report +#endif /* SM_HEAP_CHECK */ + +#if SM_HEAP_CHECK +SM_DEBUG_T SmHeapCheck = SM_DEBUG_INITIALIZER("sm_check_heap", + "@(#)$Debug: sm_check_heap - check sm_malloc, sm_realloc, sm_free calls $"); +# define HEAP_CHECK sm_debug_active(&SmHeapCheck, 1) +#endif /* SM_HEAP_CHECK */ + +const SM_EXC_TYPE_T SmHeapOutOfMemoryType = +{ + SmExcTypeMagic, + "F:sm.heap", + "", + sm_etype_printf, + "out of memory", +}; + +SM_EXC_T SmHeapOutOfMemory = SM_EXC_INITIALIZER(&SmHeapOutOfMemoryType, NULL); + + +/* +** The behaviour of malloc with size==0 is platform dependent (it +** says so in the C standard): it can return NULL or non-NULL. We +** don't want sm_malloc_x(0) to raise an exception on some platforms +** but not others, so this case requires special handling. We've got +** two choices: "size = 1" or "return NULL". We use the former in the +** following. +** If we had something like autoconf we could figure out the +** behaviour of the platform and either use this hack or just +** use size. +*/ + +#define MALLOC_SIZE(size) ((size) == 0 ? 1 : (size)) + +/* +** SM_MALLOC_X -- wrapper around malloc(), raises an exception on error. +** +** Parameters: +** size -- size of requested memory. +** +** Returns: +** Pointer to memory region. +** +** Note: +** sm_malloc_x only gets called from source files in which heap +** debugging is disabled at compile time. Otherwise, a call to +** sm_malloc_x is macro expanded to a call to sm_malloc_tagged_x. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +void * +sm_malloc_x(size) + size_t size; +{ + void *ptr; + + ENTER_CRITICAL(); + ptr = malloc(MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + if (ptr == NULL) + sm_exc_raise_x(&SmHeapOutOfMemory); + return ptr; +} + +#if !SM_HEAP_CHECK + +/* +** SM_MALLOC -- wrapper around malloc() +** +** Parameters: +** size -- size of requested memory. +** +** Returns: +** Pointer to memory region. +*/ + +void * +sm_malloc(size) + size_t size; +{ + void *ptr; + + ENTER_CRITICAL(); + ptr = malloc(MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + return ptr; +} + +/* +** SM_REALLOC -- wrapper for realloc() +** +** Parameters: +** ptr -- pointer to old memory area. +** size -- size of requested memory. +** +** Returns: +** Pointer to new memory area, NULL on failure. +*/ + +void * +sm_realloc(ptr, size) + void *ptr; + size_t size; +{ + void *newptr; + + ENTER_CRITICAL(); + newptr = realloc(ptr, MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + return newptr; +} + +/* +** SM_REALLOC_X -- wrapper for realloc() +** +** Parameters: +** ptr -- pointer to old memory area. +** size -- size of requested memory. +** +** Returns: +** Pointer to new memory area. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +void * +sm_realloc_x(ptr, size) + void *ptr; + size_t size; +{ + void *newptr; + + ENTER_CRITICAL(); + newptr = realloc(ptr, MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + if (newptr == NULL) + sm_exc_raise_x(&SmHeapOutOfMemory); + return newptr; +} +/* +** SM_FREE -- wrapper around free() +** +** Parameters: +** ptr -- pointer to memory region. +** +** Returns: +** none. +*/ + +void +sm_free(ptr) + void *ptr; +{ + if (ptr == NULL) + return; + ENTER_CRITICAL(); + free(ptr); + LEAVE_CRITICAL(); + return; +} + +#else /* !SM_HEAP_CHECK */ + +/* +** Each allocated block is assigned a "group number". +** By default, all blocks are assigned to group #1. +** By convention, group #0 is for memory that is never freed. +** You can use group numbers any way you want, in order to help make +** sense of sm_heap_report output. +*/ + +int SmHeapGroup = 1; +int SmHeapMaxGroup = 1; + +/* +** Total number of bytes allocated. +** This is only maintained if the sm_check_heap debug category is active. +*/ + +size_t SmHeapTotal = 0; + +/* +** High water mark: the most that SmHeapTotal has ever been. +*/ + +size_t SmHeapMaxTotal = 0; + +/* +** Maximum number of bytes that may be allocated at any one time. +** 0 means no limit. +** This is only honoured if sm_check_heap is active. +*/ + +SM_DEBUG_T SmHeapLimit = SM_DEBUG_INITIALIZER("sm_heap_limit", + "@(#)$Debug: sm_heap_limit - max # of bytes permitted in heap $"); + +/* +** This is the data structure that keeps track of all currently +** allocated blocks of memory known to the heap package. +*/ + +typedef struct sm_heap_item SM_HEAP_ITEM_T; +struct sm_heap_item +{ + void *hi_ptr; + size_t hi_size; + char *hi_tag; + int hi_num; + int hi_group; + SM_HEAP_ITEM_T *hi_next; +}; + +#define SM_HEAP_TABLE_SIZE 256 +static SM_HEAP_ITEM_T *SmHeapTable[SM_HEAP_TABLE_SIZE]; + +/* +** This is a randomly generated table +** which contains exactly one occurrence +** of each of the numbers between 0 and 255. +** It is used by ptrhash. +*/ + +static unsigned char hashtab[SM_HEAP_TABLE_SIZE] = +{ + 161, 71, 77,187, 15,229, 9,176,221,119,239, 21, 85,138,203, 86, + 102, 65, 80,199,235, 32,140, 96,224, 78,126,127,144, 0, 11,179, + 64, 30,120, 23,225,226, 33, 50,205,167,130,240,174, 99,206, 73, + 231,210,189,162, 48, 93,246, 54,213,141,135, 39, 41,192,236,193, + 157, 88, 95,104,188, 63,133,177,234,110,158,214,238,131,233, 91, + 125, 82, 94, 79, 66, 92,151, 45,252, 98, 26,183, 7,191,171,106, + 145,154,251,100,113, 5, 74, 62, 76,124, 14,217,200, 75,115,190, + 103, 28,198,196,169,219, 37,118,150, 18,152,175, 49,136, 6,142, + 89, 19,243,254, 47,137, 24,166,180, 10, 40,186,202, 46,184, 67, + 148,108,181, 81, 25,241, 13,139, 58, 38, 84,253,201, 12,116, 17, + 195, 22,112, 69,255, 43,147,222,111, 56,194,216,149,244, 42,173, + 232,220,249,105,207, 51,197,242, 72,211,208, 59,122,230,237,170, + 165, 44, 68,123,129,245,143,101, 8,209,215,247,185, 57,218, 53, + 114,121, 3,128, 4,204,212,146, 2,155, 83,250, 87, 29, 31,159, + 60, 27,107,156,227,182, 1, 61, 36,160,109, 97, 90, 20,168,132, + 223,248, 70,164, 55,172, 34, 52,163,117, 35,153,134, 16,178,228 +}; + +/* +** PTRHASH -- hash a pointer value +** +** Parameters: +** p -- pointer. +** +** Returns: +** hash value. +** +** ptrhash hashes a pointer value to a uniformly distributed random +** number between 0 and 255. +** +** This hash algorithm is based on Peter K. Pearson, +** "Fast Hashing of Variable-Length Text Strings", +** in Communications of the ACM, June 1990, vol 33 no 6. +*/ + +static int +ptrhash(p) + void *p; +{ + int h; + + if (sizeof(void*) == 4 && sizeof(unsigned long) == 4) + { + unsigned long n = (unsigned long)p; + + h = hashtab[n & 0xFF]; + h = hashtab[h ^ ((n >> 8) & 0xFF)]; + h = hashtab[h ^ ((n >> 16) & 0xFF)]; + h = hashtab[h ^ ((n >> 24) & 0xFF)]; + } +# if 0 + else if (sizeof(void*) == 8 && sizeof(unsigned long) == 8) + { + unsigned long n = (unsigned long)p; + + h = hashtab[n & 0xFF]; + h = hashtab[h ^ ((n >> 8) & 0xFF)]; + h = hashtab[h ^ ((n >> 16) & 0xFF)]; + h = hashtab[h ^ ((n >> 24) & 0xFF)]; + h = hashtab[h ^ ((n >> 32) & 0xFF)]; + h = hashtab[h ^ ((n >> 40) & 0xFF)]; + h = hashtab[h ^ ((n >> 48) & 0xFF)]; + h = hashtab[h ^ ((n >> 56) & 0xFF)]; + } +# endif /* 0 */ + else + { + unsigned char *cp = (unsigned char *)&p; + int i; + + h = 0; + for (i = 0; i < sizeof(void*); ++i) + h = hashtab[h ^ cp[i]]; + } + return h; +} + +/* +** SM_MALLOC_TAGGED -- wrapper around malloc(), debugging version. +** +** Parameters: +** size -- size of requested memory. +** tag -- tag for debugging. +** num -- additional value for debugging. +** group -- heap group for debugging. +** +** Returns: +** Pointer to memory region. +*/ + +void * +sm_malloc_tagged(size, tag, num, group) + size_t size; + char *tag; + int num; + int group; +{ + void *ptr; + + if (!HEAP_CHECK) + { + ENTER_CRITICAL(); + ptr = malloc(MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + return ptr; + } + + if (sm_xtrap_check()) + return NULL; + if (sm_debug_active(&SmHeapLimit, 1) + && sm_debug_level(&SmHeapLimit) < SmHeapTotal + size) + return NULL; + ENTER_CRITICAL(); + ptr = malloc(MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + if (ptr != NULL && !sm_heap_register(ptr, size, tag, num, group)) + { + ENTER_CRITICAL(); + free(ptr); + LEAVE_CRITICAL(); + ptr = NULL; + } + SmHeapTotal += size; + if (SmHeapTotal > SmHeapMaxTotal) + SmHeapMaxTotal = SmHeapTotal; + return ptr; +} + +/* +** SM_MALLOC_TAGGED_X -- wrapper around malloc(), debugging version. +** +** Parameters: +** size -- size of requested memory. +** tag -- tag for debugging. +** num -- additional value for debugging. +** group -- heap group for debugging. +** +** Returns: +** Pointer to memory region. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +void * +sm_malloc_tagged_x(size, tag, num, group) + size_t size; + char *tag; + int num; + int group; +{ + void *ptr; + + if (!HEAP_CHECK) + { + ENTER_CRITICAL(); + ptr = malloc(MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + if (ptr == NULL) + sm_exc_raise_x(&SmHeapOutOfMemory); + return ptr; + } + + sm_xtrap_raise_x(&SmHeapOutOfMemory); + if (sm_debug_active(&SmHeapLimit, 1) + && sm_debug_level(&SmHeapLimit) < SmHeapTotal + size) + { + sm_exc_raise_x(&SmHeapOutOfMemory); + } + ENTER_CRITICAL(); + ptr = malloc(MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + if (ptr != NULL && !sm_heap_register(ptr, size, tag, num, group)) + { + ENTER_CRITICAL(); + free(ptr); + LEAVE_CRITICAL(); + ptr = NULL; + } + if (ptr == NULL) + sm_exc_raise_x(&SmHeapOutOfMemory); + SmHeapTotal += size; + if (SmHeapTotal > SmHeapMaxTotal) + SmHeapMaxTotal = SmHeapTotal; + return ptr; +} + +/* +** SM_HEAP_REGISTER -- register a pointer into the heap for debugging. +** +** Parameters: +** ptr -- pointer to register. +** size -- size of requested memory. +** tag -- tag for debugging. +** num -- additional value for debugging. +** group -- heap group for debugging. +** +** Returns: +** true iff successfully registered (not yet in table). +*/ + +bool +sm_heap_register(ptr, size, tag, num, group) + void *ptr; + size_t size; + char *tag; + int num; + int group; +{ + int i; + SM_HEAP_ITEM_T *hi; + + if (!HEAP_CHECK) + return true; + SM_REQUIRE(ptr != NULL); + i = ptrhash(ptr); +# if SM_CHECK_REQUIRE + + /* + ** We require that ptr is not already in SmHeapTable. + */ + + for (hi = SmHeapTable[i]; hi != NULL; hi = hi->hi_next) + { + if (hi->hi_ptr == ptr) + sm_abort("sm_heap_register: ptr %p is already registered (%s:%d)", + ptr, hi->hi_tag, hi->hi_num); + } +# endif /* SM_CHECK_REQUIRE */ + ENTER_CRITICAL(); + hi = (SM_HEAP_ITEM_T *) malloc(sizeof(SM_HEAP_ITEM_T)); + LEAVE_CRITICAL(); + if (hi == NULL) + return false; + hi->hi_ptr = ptr; + hi->hi_size = size; + hi->hi_tag = tag; + hi->hi_num = num; + hi->hi_group = group; + hi->hi_next = SmHeapTable[i]; + SmHeapTable[i] = hi; + return true; +} +/* +** SM_REALLOC -- wrapper for realloc(), debugging version. +** +** Parameters: +** ptr -- pointer to old memory area. +** size -- size of requested memory. +** +** Returns: +** Pointer to new memory area, NULL on failure. +*/ + +void * +sm_realloc(ptr, size) + void *ptr; + size_t size; +{ + void *newptr; + SM_HEAP_ITEM_T *hi, **hp; + + if (!HEAP_CHECK) + { + ENTER_CRITICAL(); + newptr = realloc(ptr, MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + return newptr; + } + + if (ptr == NULL) + return sm_malloc_tagged(size, "realloc", 0, SmHeapGroup); + + for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next) + { + if ((**hp).hi_ptr == ptr) + { + if (sm_xtrap_check()) + return NULL; + hi = *hp; + if (sm_debug_active(&SmHeapLimit, 1) + && sm_debug_level(&SmHeapLimit) + < SmHeapTotal - hi->hi_size + size) + { + return NULL; + } + ENTER_CRITICAL(); + newptr = realloc(ptr, MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + if (newptr == NULL) + return NULL; + SmHeapTotal = SmHeapTotal - hi->hi_size + size; + if (SmHeapTotal > SmHeapMaxTotal) + SmHeapMaxTotal = SmHeapTotal; + *hp = hi->hi_next; + hi->hi_ptr = newptr; + hi->hi_size = size; + hp = &SmHeapTable[ptrhash(newptr)]; + hi->hi_next = *hp; + *hp = hi; + return newptr; + } + } + sm_abort("sm_realloc: bad argument (%p)", ptr); + /* NOTREACHED */ + return NULL; /* keep Irix compiler happy */ +} + +/* +** SM_REALLOC_X -- wrapper for realloc(), debugging version. +** +** Parameters: +** ptr -- pointer to old memory area. +** size -- size of requested memory. +** +** Returns: +** Pointer to new memory area. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +void * +sm_realloc_x(ptr, size) + void *ptr; + size_t size; +{ + void *newptr; + SM_HEAP_ITEM_T *hi, **hp; + + if (!HEAP_CHECK) + { + ENTER_CRITICAL(); + newptr = realloc(ptr, MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + if (newptr == NULL) + sm_exc_raise_x(&SmHeapOutOfMemory); + return newptr; + } + + if (ptr == NULL) + return sm_malloc_tagged_x(size, "realloc", 0, SmHeapGroup); + + for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next) + { + if ((**hp).hi_ptr == ptr) + { + sm_xtrap_raise_x(&SmHeapOutOfMemory); + hi = *hp; + if (sm_debug_active(&SmHeapLimit, 1) + && sm_debug_level(&SmHeapLimit) + < SmHeapTotal - hi->hi_size + size) + { + sm_exc_raise_x(&SmHeapOutOfMemory); + } + ENTER_CRITICAL(); + newptr = realloc(ptr, MALLOC_SIZE(size)); + LEAVE_CRITICAL(); + if (newptr == NULL) + sm_exc_raise_x(&SmHeapOutOfMemory); + SmHeapTotal = SmHeapTotal - hi->hi_size + size; + if (SmHeapTotal > SmHeapMaxTotal) + SmHeapMaxTotal = SmHeapTotal; + *hp = hi->hi_next; + hi->hi_ptr = newptr; + hi->hi_size = size; + hp = &SmHeapTable[ptrhash(newptr)]; + hi->hi_next = *hp; + *hp = hi; + return newptr; + } + } + sm_abort("sm_realloc_x: bad argument (%p)", ptr); + /* NOTREACHED */ + return NULL; /* keep Irix compiler happy */ +} + +/* +** SM_FREE_TAGGED -- wrapper around free(), debugging version. +** +** Parameters: +** ptr -- pointer to memory region. +** tag -- tag for debugging. +** num -- additional value for debugging. +** +** Returns: +** none. +*/ + +void +sm_free_tagged(ptr, tag, num) + void *ptr; + char *tag; + int num; +{ + SM_HEAP_ITEM_T **hp; + + if (ptr == NULL) + return; + if (!HEAP_CHECK) + { + ENTER_CRITICAL(); + free(ptr); + LEAVE_CRITICAL(); + return; + } + for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next) + { + if ((**hp).hi_ptr == ptr) + { + SM_HEAP_ITEM_T *hi = *hp; + + *hp = hi->hi_next; + + /* + ** Fill the block with zeros before freeing. + ** This is intended to catch problems with + ** dangling pointers. The block is filled with + ** zeros, not with some non-zero value, because + ** it is common practice in some C code to store + ** a zero in a structure member before freeing the + ** structure, as a defense against dangling pointers. + */ + + (void) memset(ptr, 0, hi->hi_size); + SmHeapTotal -= hi->hi_size; + ENTER_CRITICAL(); + free(ptr); + free(hi); + LEAVE_CRITICAL(); + return; + } + } + sm_abort("sm_free: bad argument (%p) (%s:%d)", ptr, tag, num); +} + +/* +** SM_HEAP_CHECKPTR_TAGGED -- check whether ptr is a valid argument to sm_free +** +** Parameters: +** ptr -- pointer to memory region. +** tag -- tag for debugging. +** num -- additional value for debugging. +** +** Returns: +** none. +** +** Side Effects: +** aborts if check fails. +*/ + +void +sm_heap_checkptr_tagged(ptr, tag, num) + void *ptr; + char *tag; + int num; +{ + SM_HEAP_ITEM_T *hp; + + if (!HEAP_CHECK) + return; + if (ptr == NULL) + return; + for (hp = SmHeapTable[ptrhash(ptr)]; hp != NULL; hp = hp->hi_next) + { + if (hp->hi_ptr == ptr) + return; + } + sm_abort("sm_heap_checkptr(%p): bad ptr (%s:%d)", ptr, tag, num); +} + +/* +** SM_HEAP_REPORT -- output "map" of used heap. +** +** Parameters: +** stream -- the file pointer to write to. +** verbosity -- how much info? +** +** Returns: +** none. +*/ + +void +sm_heap_report(stream, verbosity) + SM_FILE_T *stream; + int verbosity; +{ + int i; + unsigned long group0total, group1total, otherstotal, grandtotal; + + if (!HEAP_CHECK || verbosity <= 0) + return; + group0total = group1total = otherstotal = grandtotal = 0; + for (i = 0; i < sizeof(SmHeapTable) / sizeof(SmHeapTable[0]); ++i) + { + SM_HEAP_ITEM_T *hi = SmHeapTable[i]; + + while (hi != NULL) + { + if (verbosity > 2 + || (verbosity > 1 && hi->hi_group != 0)) + { + sm_io_fprintf(stream, SM_TIME_DEFAULT, + "%4d %*lx %7lu bytes", + hi->hi_group, + (int) sizeof(void *) * 2, + (long)hi->hi_ptr, + (unsigned long)hi->hi_size); + if (hi->hi_tag != NULL) + { + sm_io_fprintf(stream, SM_TIME_DEFAULT, + " %s", + hi->hi_tag); + if (hi->hi_num) + { + sm_io_fprintf(stream, + SM_TIME_DEFAULT, + ":%d", + hi->hi_num); + } + } + sm_io_fprintf(stream, SM_TIME_DEFAULT, "\n"); + } + switch (hi->hi_group) + { + case 0: + group0total += hi->hi_size; + break; + case 1: + group1total += hi->hi_size; + break; + default: + otherstotal += hi->hi_size; + break; + } + grandtotal += hi->hi_size; + hi = hi->hi_next; + } + } + sm_io_fprintf(stream, SM_TIME_DEFAULT, + "heap max=%lu, total=%lu, ", + (unsigned long) SmHeapMaxTotal, grandtotal); + sm_io_fprintf(stream, SM_TIME_DEFAULT, + "group 0=%lu, group 1=%lu, others=%lu\n", + group0total, group1total, otherstotal); + if (grandtotal != SmHeapTotal) + { + sm_io_fprintf(stream, SM_TIME_DEFAULT, + "BUG => SmHeapTotal: got %lu, expected %lu\n", + (unsigned long) SmHeapTotal, grandtotal); + } +} +#endif /* !SM_HEAP_CHECK */ diff --git a/gnu/dist/sendmail/libsm/heap.html b/gnu/dist/sendmail/libsm/heap.html new file mode 100644 index 000000000000..599ffd470666 --- /dev/null +++ b/gnu/dist/sendmail/libsm/heap.html @@ -0,0 +1,424 @@ + + + libsm : Memory Allocation + + + +Back to libsm overview + +
+

libsm : Memory Allocation

+
Id: heap.html,v 1.9 2000/12/08 21:41:42 ca Exp +
+ +

Introduction

+ +The heap package provides a layer of abstraction on top of +malloc, realloc and free +that provides optional error checking and memory leak detection, +and which optionally raises an exception when an allocation request +cannot be satisfied. + +

Synopsis

+ +
+#include <sm/heap.h>
+
+/*
+**  Wrappers for malloc, realloc, free
+*/
+void *sm_malloc(size_t size);
+void *sm_realloc(void *ptr, size_t size);
+void  sm_free(void *ptr);
+
+/*
+**  Wrappers for malloc, realloc that raise an exception instead of
+**  returning NULL on heap exhaustion.
+*/
+void *sm_malloc_x(size_t size);
+void *sm_realloc_x(void *ptr, size_t size);
+
+/*
+**  Print a list of currently allocated blocks,
+**  used to diagnose memory leaks.
+*/
+void  sm_heap_report(FILE *stream, int verbosity);
+
+/*
+**  Low level interfaces.
+*/
+int sm_heap_group();
+int sm_heap_setgroup(int g);
+int sm_heap_newgroup();
+void *sm_malloc_tagged(size_t size, char *file, int line, int group);
+void *sm_malloc_tagged_x(size_t size, char *file, int line, int group);
+bool  sm_heap_register(void *ptr, size_t size, char *file, int line);
+
+ +

How to allocate and free memory

+ + sm_malloc, sm_realloc and sm_free + are portable plug in replacements + for malloc, realloc and free that provide + error checking and memory leak detection. + sm_malloc_x and sm_realloc_x + are variants of + sm_malloc and sm_realloc + that raise an exception on error. + To use the package effectively, + all calls to malloc, realloc and free + should be replaced by calls + to the corresponding sm_* routines. + +
+
+ void *sm_malloc(size_t size) +
+ This function is a plug-in replacement for malloc. + It allocates size bytes of memory on the heap + and returns a pointer to it, + or it returns NULL on failure. +

+ + The C standard says that malloc(0) may return + either NULL or a non-NULL value. + To ensure consistent behaviour on all platforms, + sm_malloc(0) is equivalent to sm_malloc(1). +

+ + In addition, if heap checking is enabled, then sm_malloc + maintains a hash table describing all currently allocated + memory blocks. This table is used for argument validity + checking in sm_realloc and sm_free, + and it can be printed using sm_heap_report + as an aid to finding memory leaks. +

+ +

+ void *sm_malloc_x(size_t size) +
+ This function is just like sm_malloc + except that it raises the SmHeapOutOfMemory exception + instead of returning NULL on error. +

+ +

+ void *sm_realloc(void *ptr, size_t size) +
+ This function is a plug-in replacement for realloc. + If ptr is null then this call is equivalent + to sm_malloc(size). + Otherwise, the size of the object pointed to by ptr + is changed to size bytes, and a pointer to the + (possibly moved) object is returned. + If the space cannot be allocated, then the object pointed to + by ptr is unchanged and NULL is returned. +

+ + If size is 0 then we pretend that size is 1. + This may be a mistake. +

+ + If ptr is not NULL and heap checking is enabled, + then ptr is required to be a value that was + previously returned by sm_malloc or sm_realloc, and which + has not yet been freed by sm_free. If this condition is not + met, then the program is aborted using sm_abort. +

+ +

+ void *sm_realloc_x(void *ptr, size_t size) +
+ This function is just like sm_realloc + except that it raises the SmHeapOutOfMemory exception + instead of returning NULL on error. +

+ +

+ void sm_free(void *ptr) +
+ This function is a plug-in replacement for free. + If heap checking is disabled, then this function is equivalent + to a call to free. Otherwise, the following additional semantics + apply. +

+ + If ptr is NULL, this function has no effect. +

+ + Otherwise, ptr is required to be a value that was + previously returned by sm_malloc or sm_realloc, and which + has not yet been freed by sm_free. If this condition is not + met, then the program is aborted using sm_abort. +

+ + Otherwise, if there is no error, then the block pointed to by ptr + will be set to all zeros before free() is called. This is intended + to assist in detecting the use of dangling pointers. +

+ +

How to control tag information

+ +When heap checking is enabled, +the heap package maintains a hash table which associates the +following values with each currently allocated block: + +
+
+ size_t size +
+ The size of the block. +
+ char *tag +
+ By default, this is the name of the source file from which + the block was allocated, but you can specify an arbitrary + string pointer, or NULL. +
+ int num +
+ By default, this is the line number from which the block was + allocated. +
+ int group +
+ By convention, group==0 indicates that the block is permanently + allocated and will never be freed. The meanings of other group + numbers are defined by the application developer. + Unless you take special action, all blocks allocated by + sm_malloc and sm_malloc_x will be assigned + to group 1. +
+ +These tag values are printed by sm_heap_report, +and are used to help analyze memory allocation behaviour +and to find memory leaks. +The following functions give you precise control over the +tag values associated with each allocated block. + +
+
+ void *sm_malloc_tagged(size_t size, int tag, int num, int group) +
+ Just like sm_malloc, except you directly specify + all of the tag values. + If heap checking is disabled at compile time, then a call + to sm_malloc_tagged is macro expanded to + a call to malloc. +

+ + Note that the expression sm_malloc(size) is macro expanded to + +

+sm_malloc_tagged(size, __FILE__, __LINE__, sm_heap_group())
+
+ +
+ void *sm_malloc_tagged_x(size_t size, int tag, int num, int group) +
+ A variant of sm_malloc_tagged + that raises an exception on error. + A call to sm_malloc_x is macro expanded + to a call to sm_malloc_tagged_x. +

+ +

+ int sm_heap_group() +
+ The heap package maintains a thread-local variable containing + the current group number. + This is the group that sm_malloc and sm_malloc_x + will assign a newly allocated block to. + The initial value of this variable is 1. + The current value of this variable is returned by + sm_heap_group(). +

+ +

+ int sm_heap_setgroup(int g) +
+ Set the current group to the specified value. +
+ +Here are two examples of how you might use these interfaces. + +
    +
  1. +One way to detect memory leaks is to turn on heap checking +and call sm_heap_report(stdout,2) +when the program exits. +This prints a list of all allocated blocks that do not belong to group 0. +(Blocks in group 0 are assumed to be permanently allocated, +and so their existence at program exit does not indicate a leak.) +If you want to allocate a block and assign it to group 0, +you have two choices: + +
    +int g = sm_heap_group();
    +sm_heap_setgroup(0);
    +p = sm_malloc_x(size);
    +sm_heap_setgroup(g);
    +
    + +or + +
    +p = sm_malloc_tagged_x(size, __FILE__, __LINE__, 0);
    +
    + +
  2. +Suppose you have a utility function foo_alloc which allocates +and initializes a 'foo' object. When sm_heap_report is called, +all unfreed 'foo' objects will be reported to have the same +source code file name and line number. +That might make it difficult to determine where a memory leak is. +

    + +Here is how you can arrange for more precise reporting for +unfreed foo objects: + +

    +#include <sm/heap.h>
    +
    +#if SM_HEAP_CHECK
    +#  define foo_alloc_x() foo_alloc_tagged_x(__FILE__,__LINE)
    +   FOO *foo_alloc_tagged_x(char *, int);
    +#else
    +   FOO *foo_alloc_x(void);
    +#  define foo_alloc_tagged_x(file,line) foo_alloc_x()
    +#endif
    +
    +...
    +
    +#if SM_HEAP_CHECK
    +FOO *
    +foo_alloc_tagged_x(char *file, int line)
    +#else
    +FOO *
    +foo_alloc_x(void)
    +#endif
    +{
    +	FOO *p;
    +
    +	p = sm_malloc_tagged_x(sizeof(FOO), file, line, sm_heap_group());
    +	...
    +	return p;
    +}
    +
    +
+ +

How to dump the block list

+ +To perform memory leak detection, you need to arrange for your +program to call sm_heap_report at appropriate times. + +
+
+ void sm_heap_report(FILE *stream, int verbosity) +
+ If heap checking is disabled, this function does nothing. + If verbosity <= 0, this function does nothing. +

+ + If verbosity >= 1, then sm_heap_report prints a single line + to stream giving the total number of bytes currently allocated. + If you call sm_heap_report each time the program has reached a + "ground state", and the reported amount of heap storage is + monotonically increasing, that indicates a leak. +

+ + If verbosity >= 2, then sm_heap_report additionally prints one line + for each block of memory currently allocated, providing that + the group != 0. + (Such blocks are assumed to be permanently allocated storage, and + are not reported to cut down the level of noise.) +

+ + If verbosity >= 3, then sm_heap_report prints one line for each + allocated block, regardless of the group. +

+ +

How to enable heap checking

+ +The overhead of using the package can be made as small as you want. +You have three options: + +
    +
  1. + If you compile your software with -DSM_HEAP_CHECK=0 then + sm_malloc, sm_realloc and sm_free will be redefined + as macros that call malloc, realloc, and free. In this case, + there is zero overhead. +
  2. + If you do not define -DSM_HEAP_CHECK=0, and you do not explicitly + turn on heap checking at run time, then your program will run + without error checking and memory leak detection, and the additional + cost of calling sm_malloc, sm_realloc and sm_free is a + function call and test. That overhead is sufficiently low that + the checking code can be left compiled in a production environment. +
  3. + If you do not define -DSM_HEAP_CHECK=0, and you explicitly turn on + heap checking at run time, then the additional cost of calling + sm_malloc, sm_realloc and sm_free is a hash table lookup. +
+ + Here's how to modify your application to use the heap package. + First, change all calls to malloc, realloc and free to sm_malloc, + sm_realloc and sm_free. + Make sure that there is a -d command line option that + uses the libsm debug package to enable named debug options. + Add the following code to your program just before it calls exit, + or register an atexit handler function containing the following code: + +
+#if SM_HEAP_CHECK
+	/* dump the heap, if we are checking for memory leaks */
+	if (sm_debug_active(&SmHeapCheck, 2))
+		sm_heap_report(stdout, sm_debug_level(&SmHeapCheck) - 1);
+#endif
+
+ + To turn on heap checking, use the command line option "-dsm_check_heap.1". + This will cause a table of all currently allocated blocks to be + maintained. The table is used by sm_realloc and sm_free to perform + validity checking on the first argument. + +

+ The command line option "-dsm_check_heap.2" will cause your application + to invoke sm_heap_report with verbosity=1 just before exit. + That will print a single line reporting total storage allocation. + +

+ The command line option "-dsm_check_heap.3" will cause your application + to invoke sm_heap_report with verbosity=2 just before exit. + This will print a list of all leaked blocks. + +

+ The command line option "-dsm_check_heap.4" will cause your application + to invoke sm_heap_report with verbosity=3 just before exit. + This will print a list of all allocated blocks. + +

Using sm_heap_register

+ + Suppose you call a library routine foo that allocates a block of storage + for you using malloc, and expects you to free the block later using + free. Because the storage was not allocated using sm_malloc, you + will normally get an abort if you try to pass the pointer to + sm_free. The way to fix this problem is to 'register' the pointer + returned by foo with the heap package, by calling sm_heap_register: + +
+bool sm_heap_register(ptr, size, file, line, group)
+
+ + The 'ptr' argument is the pointer returned by foo. The 'size' argument + can be smaller than the actual size of the allocated block, but it must + not be larger. The file and line arguments indicate at which line of + source code the block was allocated, and is printed by sm_heap_report. + For group, you probably want to pass sm_heap_group(). +

+ This function returns true on success, + or false if it failed due to heap exhaustion. + + + diff --git a/gnu/dist/sendmail/libsm/index.html b/gnu/dist/sendmail/libsm/index.html new file mode 100644 index 000000000000..0f3a0e3c5620 --- /dev/null +++ b/gnu/dist/sendmail/libsm/index.html @@ -0,0 +1,174 @@ + + + libsm Overview + + + +

+

libsm Overview

+
Id: index.html,v 1.14 2001/02/13 21:21:25 gshapiro Exp +
+ +

Introduction

+ +Libsm is a library of generally useful C abstractions. +Libsm stands alone; it depends on no other sendmail libraries, +and the only sendmail header files it depends on are its own, +which reside in ../include/sm. + +

Contents

+ +Here is the current set of packages: +
+ gen: general definitions
+ debug: debugging and tracing
+ assert: assertion handling and aborts
+ heap: memory allocation
+ exc: exception handling
+ rpool: resource pools
+ cdefs: C language portability macros
+ io: buffered i/o
+
+ +

Naming Conventions

+ + Some of the symbols defined by libsm + come from widely used defacto or dejure standards. + Examples include size_t (from the C 89 standard), + bool (from the C 99 standard), + strerror (from Posix), + and __P (from BSD and Linux). + In these cases, we use the standard name rather than + inventing a new name. + We import the name from the appropriate header file when possible, + or define it ourselves when necessary. + When you are using one of these abstractions, you must include + the appropriate libsm header file. + For example, when you are using strerror, you must + include <sm/string.h> instead of <string.h>. + +

+ When we aren't implementing a standard interface, + we use a naming convention that attempts to maximize portability + across platforms, and minimize conflicts with other libraries. + Except for a few seemingly benign exceptions, + all names begin with SM_, Sm or sm_. + +

+ The ISO C, Posix and Unix standards forbid applications + from using names beginning with __ or _[A-Z], + and place restrictions on what sorts of names can begin + with _[a-z]. Such names are reserved for the compiler and + the standard libraries. + For this reason, we avoid defining any names that begin + with _. + For example, all libsm header file idempotency macros have the form + SM_FOO_H (no leading _). + +

+ Type names begin with SM_ and end with _T. + Note that the Posix standard reserves all identifiers ending + with _t. + +

+ All functions that are capable of raising an exception + have names ending in _x, and developers are + encouraged to use this convention when writing new code. + This naming convention may seem unnecessary at first, + but it becomes extremely useful during maintenance, + when you are attempting to reason about the correctness + of a block of code, + and when you are trying to track down exception-related bugs + in existing code. + +

Coding Conventions

+ +The official style for function prototypes in libsm header files is + +
+extern int
+foo __P((
+	int _firstarg,
+	int _secondarg));
+
+ +The extern is useless, but required for stylistic reasons. +The parameter names are optional; if present they are lowercase +and begin with _ to avoid namespace conflicts. +Each parameter is written on its own line to avoid very long lines. + +

+For each structure struct sm_foo defined by libsm, +there is a typedef: + +

+typedef struct sm_foo SM_FOO_T;
+
+ +and there is a global variable which is defined as follows: + +
+const char SmFooMagic[] = "sm_foo";
+
+ +The first member of each structure defined by libsm is + +
+const char *sm_magic;
+
+ +For all instances of struct sm_foo, +sm_magic contains SmFooMagic, +which points to a unique character string naming the type. +It is used for debugging and run time type checking. + +

+Each function with a parameter declared SM_FOO_T *foo +contains the following assertion: + +

+SM_REQUIRE_ISA(foo, SmFooMagic);
+
+ +which is equivalent to + +
+SM_REQUIRE(foo != NULL && foo->sm_magic == SmFooMagic);
+
+ +When an object of type SM_FOO_T is deallocated, +the member sm_magic is set to NULL. +That will cause the above assertion to fail if a dangling pointer is used. + +

Additional Design Goals

+ +Here are some of my design goals: +
    +

    +

  • The sm library is self contained; it does not depend on any other + sendmail libraries or header files. +

    +

  • The sm library must be compatible with shared libraries, + even on platforms with weird implementation restrictions. + I assume that a shared library can export global variables; + the debug package relies on this assumption. + I do not assume that if an application redefines a function defined + in a shared library, the shared library will use the version of the + function defined in the application in preference to the version + that it defines. + For this reason, I provide interfaces for registering handler functions + in cases where an application might need to override standard behaviour. +

    +

  • The sm library must be compatible with threads. + The debug package presents a small problem: I don't want + sm_debug_active to acquire and release a lock. + So I assume that + there exists an integral type SM_ATOMIC_INT_T + (see <sm/gen.h>) + that can be accessed and updated atomically. + I assume that locking must be used to guard updates and accesses to + any other type, and I have designed the interfaces accordingly. +
+ + + diff --git a/gnu/dist/sendmail/libsm/io.html b/gnu/dist/sendmail/libsm/io.html new file mode 100644 index 000000000000..3fbf0f476a3b --- /dev/null +++ b/gnu/dist/sendmail/libsm/io.html @@ -0,0 +1,745 @@ + + +libsm sm_io general overview + + +Back to libsm overview +
+

libsm sm_io general overview

+
Id: io.html,v 1.3 2001/03/17 03:22:50 gshapiro Exp +
+

Introduction

+

+The sm_io portion of the libsm library is similar to +the stdio library. It is derived from the Chris Torek version +of the stdio library (BSD). There are some key differences +described below between sm_io and stdio but many +similarities will be noticed. +

+

+A key difference between stdio and sm_io is that the +functional code that does the open, close, read, write, etc. on a file +can be different for different files. For example, with stdio +the functional code (read, write) is either the default supplied in the +library or a "programmer specified" set of functions set via +sm_io_open(). Whichever set of functions are specified all +open's, read's, write's, etc use the same set of functions. In contrast, with +sm_io a different set of functions can be specified with each +active file for read's, write's, etc. These different function sets +are identified as file types (see sm_io_open()). Each function +set can handle the actions directly, pass the action request to +another function set or do some work before passing it on to another function +set. The setting of a function set for a file type can be done for +a file type at any time (even after the type is open). +

+

+A second difference is the use of rpools. +An rpool is specified with the opening of a file +(sm_io_open()). +This allows of a file to be associated with an rpool so that when the +rpool is released the open file will be closed; the sm_io_open() +registers that sm_io_close() should be called when the rpool is +released. +

+

+A third difference is that the I/O functions take a timeout +argument. This allows the setting of a maximum amount of time allowable +for the I/O to be completed. This means the calling program does not need +to setup it's own timeout mechanism. NOTE: SIGALRM's should not be +active in the calling program when an I/O function with a timeout +is used. +

+

+When converting source code from stdio to sm_io be +very careful to NOTE: the arguments to functions have been rationalized. +That is, unlike stdio, all sm_io functions that +take a file pointer (SM_FILE_T *) argument have the file pointer +as the first argument. Also not all functions with stdio have +an identical matching sm_io API: the API list has been thinned +since a number of stdio API's overlapped in functionality. +Remember many functions also have a timeout argument added. +

+

+When a file is going to be opened, the file type is included with +sm_io_open(). +A file type is either one automatically included with the sm_io +library or one created by the program at runtime. +File types can be either buffered or unbuffered. When buffered the buffering +is either the builtin sm_io buffering or as done by the file type. +File types can be disk files, strings, TCP/IP connections or whatever +your imagination can come up with that can be read and/or written to. +

+

+Information about a particular file type or pointer can be obtained or set with +the sm_io "info" functions. +The sm_io_setinfo() and sm_io_getinfo() functions work on +an active file pointer. +

+

Include files

+

+There is one main include file for use with sm_io: io.h. Since the +use of rpools is specified with sm_io_open() an +rpool may +be created and thus rpool.h may need to be included as well +(before io.h). +

+
+#include <rpool.h>
+#include <io.h>
+
+ +

Functions/API's

+

+Below is a list of the functions for sm_io listed in +alphabetical order. Currently these functions return error codes +and set errno when appropriate. These (may?/will?) change to +raising exceptions later. +

+
+SM_FILE_T *sm_io_autoflush(SM_FILE_T *fp, SM_FILE_T *)
+
+void sm_io_automode(SM_FILE_T *fp, SM_FILE_T *)
+
+void sm_io_clearerr(SM_FILE_T *fp)
+
+int sm_io_close(SM_FILE_T *fp, int timeout)
+
+int sm_io_dup(SM_FILE_T *fp)
+
+int sm_io_eof(SM_FILE_T *fp)
+
+int sm_io_error(SM_FILE_T *fp)
+
+char * sm_io_fgets(SM_FILE_T *fp, int timeout, char *buf, int n)
+
+int sm_io_flush(SM_FILE_T *fp, int timeout)
+
+int sm_io_fopen(char *pathname, int flags [, MODE_T mode])
+
+int sm_io_fprintf(SM_FILE_T *fp, int timeout, const char *fmt, ...)
+
+int sm_io_fputs(s, int, SM_FILE_T *fp)
+
+int sm_io_fscanf(SM_FILE_T *fp, int timeout, char const *fmt, ...) 
+
+int sm_io_getc(SM_FILE_T *fp, int timeout)
+
+void sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)
+
+SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)
+
+int sm_io_purge(SM_FILE_T *fp)
+
+int sm_io_putc(SM_FILE_T *fp, int timeout, int c)
+
+size_t sm_io_read(SM_FILE_T *fp, int timeout, char *buf, size_t size)
+
+SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)
+
+void sm_io_rewind(SM_FILE_T *fp, int timeout)
+
+int sm_io_seek(SM_FILE_T *fp, off_t offset, int timeout, int whence)
+
+void sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)
+
+int sm_io_setvbuf(SM_FILE_T *fp, int timeout, char *buf, int mode, size_t size)
+
+int sm_io_sscanf(const char *str, char const *fmt, ...)
+
+long sm_io_tell(SM_FILE_T *fp, int timeout)
+
+int sm_io_ungetc(SM_FILE_T *fp, int timeout, int c)
+
+size_t sm_io_write(SM_FILE_T *fp, int timeout, char *buf, size_t size)
+
+int sm_snprintf(char *str, size_t n, char const *fmt, ...)
+
+
+ +

Timeouts

+

+For many of the functions a timeout argument is given. This limits +the amount of time allowed for the function to complete. There are three +pre-defined values: +

+
  • +SM_TIME_DEFAULT - timeout using the default setting for this file type +
  • +
  • +SM_TIME_FOREVER - timeout will take forever; blocks until task completed +
  • +
  • +SM_TIME_IMMEDIATE - timeout (virtually) now +
  • +
    +

    +

    +A function caller can also specify a positive integer value in milliseconds. +A function will return with errno set to EINVAL if a bad value +is given for timeout. +When a function times out the function returns in error with errno +set to EAGAIN. In the future this may change to an exception being +thrown. +

    +

    Function Descriptions

    +
    + +

    +
    +SM_FILE_T * +
    +sm_io_fopen(char *pathname, int flags) +
    +SM_FILE_T * +
    +sm_io_fopen(char *pathname, int flags, MODE_T mode) +
    +
    +Open the file named by pathname, and associate a stream with it. +The arguments are the same as for the open(2) system call. +
    +If memory could not be allocated, an exception is raised. +If successful, an SM_FILE_T pointer is returned. +Otherwise, NULL is returned and errno is set. + +

    +
    +SM_FILE_T * +
    +sm_io_open(const SM_FILE_T *type, int timeout, const void *info, int flags, void *rpool) +
    +
    +Opens a file by type directed by info. Type is a filled-in +SM_FILE_T structure from the following builtin list +(descriptions below) +or one specified by the program. + +
  • +SmFtString +
  • +
  • +SmFtStdio +
  • +
  • +SmFtStdiofd +
  • +
  • +smioin * +
  • +
  • +smioout * +
  • +
  • +smioerr * +
  • +
  • +smiostdin * +
  • +
  • +smiostdout * +
  • +
  • +smiostderr * +
  • +
  • +SmFtSyslog +
  • +
    +
    +The above list of file types are already appropriately filled in. Those marked +with a "*" are already open and may be used directly and immediately. +For program specified types, to set the type argument easily and with minimal error the macro +SM_IO_SET_TYPE should be used. The SM_FILE_T structure is fairly +large, but only a small portion of it need to be initialized for a new +type. +See also "Writing Functions for a File Type". + +
    +SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout)
    +
    +
    +
    +Timeout is set as described in the Timeouts +section. +
    +Info is information that describes for the file type what is +to be opened and any associated information. +For a disk file this would be a file path; with a TCP +connection this could be an a structure containing an IP address and port. +
    Flags is a +set of sm_io flags that describes how the file is to be interacted with: + +
  • +SM_IO_RDWR - read and write +
  • +
  • +SM_IO_RDONLY - read only +
  • +
  • +SM_IO_WRONLY - write only +
  • +
  • +SM_IO_APPEND - allow write to EOF only +
  • +
  • +SM_IO_APPENDRW - allow read-write from EOF only +
  • +
  • +SM_IO_RDWRTR - read and write with truncation of file first +
  • +
    +Rpool is the address of the rpool that this open is to be associated +with. When the rpool is released then the close function for this +file type will be automatically called to close the file for cleanup. +If NULL is specified for rpool then the close function is not +associated (attached) to an rpool. +
    +On cannot allocate memory, an exception is raised. +If the type is invalid, sm_io_open will abort the process. +On success an SM_FILE_T * pointer is returned. +On failure the NULL pointer is returned and errno is set. +
    + +

    +
    +int +
    +sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp) +
    +
    +For the open file sfp set the indicated information (what) +to the new value (valp). +This will make the change for this SM_FILE_T only. The file +type that sfp originally belonged to will still be +configured the same way (this is to prevent side-effect +to other open's of the same file type, particularly with threads). +The value of what will be file-type dependant since this function +is one of the per file type setable functions. +One value for what that is valid for all file types is +SM_WHAT_VECTORS. This sets the currently open file with a new function +vector set for open, close, etc. The new values are taken from valp +a SM_FILE_T filled in by the used via the macro SM_IO_SET_TYPE +(see and +"Writing Functions for a File Type" for more information). +
    +On success 0 (zero) is returned. On failure -1 is returned and errno is set. +
    + +

    +
    +int +
    +sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp) +
    +
    +For the open file sfp get the indicated information (what) +and place the result in (valp). +This will obtain information for SM_FILE_T only and may be different than +the information for the file type it was originally opened as. +The value of what will be file type dependant since this function +is one of the per file type setable functions. +One value for what that is valid for all file types is +SM_WHAT_VECTORS. This gets from the currently open file a copy of +the function vectors and stores them in valp a SM_FILE_T +(see +"Writing Functions for a File Type" for more information). +
    +On success 0 (zero) is returned. On failure -1 is returned and errno is set. +
    + +

    +
    +void +
    +sm_io_autoflush(SM_FILE_T *fp1, *SM_FILE_T fp2) +
    +
    +Associate a read of fp1 with a data flush for fp2. If a read +of fp1 discovers that there is no data available to be read, then +fp2 will have it's data buffer flushed for writable data. It is +assumed that fp1 is open for reading and fp2 is open +for writing. +
    +On return the old file pointer associated with fp1 for flushing +is returned. A return of NULL is no an error; this merely indicates no +previous association. +
    + +

    +
    +void +
    +sm_io_automode(SM_FILE_T *fp1, *SM_FILE_T fp2) +
    +
    +
    +Associate the two file pointers for blocking/non-blocking mode changes. +In the handling of timeouts sm_io may need to switch the mode of +a file between blocking and non-blocking. If the underlying file descriptor +has been duplicated with dup(2) and these descriptors are used +by sm_io (for example with an SmFtStdiofd file type), then this API +should be called to associate them. Otherwise odd behavior (i.e. errors) +may result that is not consistently reproducable nor easily identifiable. +
    + +

    +
    +int +
    +sm_io_close(SM_FILE_T *sfp, int timeout) +
    +
    +Release all resources (file handles, memory, etc.) associated with +the open SM_FILE_T sfp. If buffering is active then the +buffer is flushed before any resources are released. +Timeout is set as described in the Timeouts +section. +The first resources released after buffer flushing will be the +buffer itself. Then the close function specified in the +file type at open will be called. It is the responsibility +of the close function to release any file type +specific resources allocated and to call sm_io_close() +for the next file type layer(s) that the current file type uses (if any). +
    +On success 0 (zero) is returned. On failure SM_IO_EOF is returned and +errno is set. +
    +
    +

    +Description of Builtin File Types +

    +

    +There are several builtin file types as mentioned in sm_io_open(). +More file types may be added later. +

    +
    +

    +
    SmFtString
    +
    +Operates on a character string. SmFtString is a file type only. +The string starts at the location 0 (zero) +and ends at the last character. A read will obtain the requested +number of characters if available; else as many as possible. A read +will not terminate the read characters with a NULL ('\0'). A write +will place the number of requested characters at the current location. +To append to a string either the pointer must currently be at the end +of the string or a seek done to position the pointer. The file type +handles the space needed for the string. Thus space needed for the +string will be grown automagically without the user worrying about +space management. +
    +
    SmFtStdio
    +
    +A predefined SM_FILE_T structure with function vectors pointing to +functions that result in the file-type behaving as the system stdio +normally does. The info portion of the sm_io_open +is the path of the file to be opened. Note that this file type +does not interact with the system's stdio. Thus a program mixing system +stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input +and output. +
    +
    SmFtStdiofd
    +
    +A predefined SM_FILE_T structure with function vectors pointing to +functions that result in the file-type behaving as the system stdio +normally does. The info portion of the sm_io_open +is a file descriptor (the value returned by open(2)). Note that this file type +does not interact with the system's stdio. Thus a program mixing system +stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input +and output. +
    +
    smioin
    +
    smioout
    +
    smioerr
    +
    +The three types smioin, smioout and smioerr are grouped +together. These three types +perform in the same manner as stdio's stdin, stdout +and stderr. These types are both the names and the file pointers. +They are already open when a program starts (unless the parent explictly +closed file descriptors 0, 1 and 2). +Thus sm_io_open() should never be called for these types: +the named file pointers should be used directly. +Smioin and smioout are buffered +by default. Smioerr is not buffered by default. Calls to stdio +are safe to make when using these threesm_io file pointers. +There is no interaction between sm_io and stdio. Hence, +due to buffering, the sequence of input and output data from both sm_io +and stdio at the same time may appear unordered. For +coordination between sm_io and stdio use the three +file pointers below (smiostdin, smiostdout, smiostderr). +
    +
    smiostdin
    +
    smiostdout
    +
    smiostderr
    +
    +The three types smiostdin, smioostdut and smiostderr +are grouped together. These three types +perform in the same manner as stdio's stdin, stdout +and stderr. These types are both the names and file pointers. +They are already open when a program starts (unless the parent explictly +close file descriptors 0, 1 and 2). +Thus sm_io_open() should +never be called: the named file pointers should be used directly. +Calls to stdio are safe to make when using these threesm_io +file pointers though no code is shared between the two libaries. +However, the input and output between sm_io and stdio is +coordinated for these three file pointers: smiostdin, +smiostdout and smiostderr are layered on-top-of +the system's stdio. +Smiostdin, smiostdout +and Smiostderr are not buffered by default. +Hence, due to buffering in stdio only, the sequence of input and +output data from both sm_io and stdio at the same time will +appear ordered. If sm_io buffering is turned on then the +input and output can appear unordered or lost. +
    +
    SmFtSyslog
    +
    +This opens the channel to the system log. Reads are not allowed. Writes +cannot be undone once they have left the sm_io buffer. +The man pages for syslog(3) should be read for information +on syslog. +
    +
    +

    +
    +

    +

    + +Writing Functions for a File Type + +

    +

    +When writing functions to create a file type a function needs to +be created for each function vector in the SM_FILE_T structure +that will be passed to sm_io_open() or sm_io_setinfo(). +Otherwise the setting will be rejected and errno set to EINVAL. +Each function should accept and handle the number and types of arguments as +described in the portion of the SM_FILE_T structure shown below: +

    +
    +        int      (*open) __P((SM_FILE_T *fp, const void *, int flags,
    +                              const void *rpool));
    +        int      (*close) __P((SM_FILE_T *fp));
    +        int      (*read)  __P((SM_FILE_T *fp, char *buf, size_t size));
    +        int      (*write) __P((SM_FILE_T *fp, const char *buf, size_t size));
    +        off_t    (*seek)  __P((SM_FILE_T *fp, off_t offset, int whence));
    +        int      (*getinfo) __P((SM_FILE_T *fp, int what, void *valp));
    +        int      (*setinfo) __P((SM_FILE_T *fp, int what, void *valp));
    +
    +

    +The macro SM_IO_SET_TYPE should be used to initialized an SM_FILE_T as a file +type for an sm_io_open(): +

    +
    +SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout)
    +
    +
    +where: + +
  • +type - is the SM_FILE_T being filled-in +
  • +
  • +name - a human readable character string for human identification purposes +
  • +
  • +open - the vector to the open function +
  • +
  • +close - the vector to the close function +
  • +
  • +read - the vector to the read function +
  • +
  • +write - the vector to the write function +
  • +
  • +seek - the vector to the seek function +
  • +
  • +set - the vector to the set function +
  • +
  • +get - the vector to the get function +
  • +
  • +timeout - the default to be used for a timeout when SM_TIME_DEFAULT specified +
  • +
    +
    +You should avoid trying to change or use the other structure members of the +SM_FILE_T. The file pointer content (internal structure members) of an active +file should only be set and observed with the "info" functions. +The two exceptions to the above statement are the structure members +cookie and ival. Cookie is of type void * +while ival is of type int. These two structure members exist +specificly for your created file type to use. The sm_io functions +will not change or set these two structure members; only specific file type +will change or set these variables. +

    +

    +For maintaining information privately about status for a file type the +information should be encapsulated in a cookie. A cookie +is an opaque type that contains information that is only known to +the file type layer itself. The sm_io package will know +nothing about the contents of the cookie; sm_io only +maintains the location of the cookie so that it may be passed +to the functions of a file type. It is up to the file type to +determine what to do with the cookie. It is the responsibility +of the file type's open to create the cookie and point the SM_FILE_T's +cookie at the address of the cookie. +It is the responsibility of close to clean up +any resources that the cookie and instance of the file type have used. +

    +

    +For the cookie to be passed to all members of a function type +cleanly the location of the cookie must assigned during +the call to open. The file type functions should not attempt to +maintain the cookie internally since the file type may have +serveral instances (file pointers). +

    +

    +The SM_FILE_T's member ival may be used in a manner similar to +cookie. It is not to be used for maintaining the file's offset +or access status (other members do that). It is intended as a "light" +reference. +

    +

    +The file type vector functions are called by the sm_io_*() +functions after sm_io processing has occurred. The sm_io +processing validates SM_FILE_T's and may then handle the call entirely +itself or pass the request to the file type vector functions. +

    +

    +All of the "int" functions should return -1 (minus one) on failure +and 0 (zero) or greater on success. Errno should be set to +provide diagnostic information to the caller if it has not already +been set by another function the file type function used. +

    +

    +Examples are a wonderful manner of clarifying details. Below is an example +of an open function. +

    +

    +This shows the setup. +

    +
    +SM_FILE_T *fp;
    +SM_FILE_T SM_IO_SET_TYPE(vector, "my_type", myopen, myclose, myread, mywrite,
    +				myseek, myget, myset, SM_TIME_FOREVER);
    +
    +fp = sm_io_open(&vector, 1000, "data", SM_IO_RDONLY, NULL);
    +
    +if (fp == NULL)
    +	return(-1);
    +
    +The above code open's a file of type "my_type". The info is set +to a string "data". "data" may be the name of a file or have some special +meaning to the file type. For sake of the example, we will have it be +the name of a file in the home directory of the user running the program. +Now the only file type function that is dependent on this information +will be the open function. +
    +We have also specified read-only access (SM_IO_RDONLY) and that no rpool +will be used. The timeout has been set to 1000 milliseconds which +directs that the file and all associated setup should be done within +1000 milliseconds or return that the function erred (with errno==EAGAIN). +
    +int myopen(fp, info, flags, rpools)
    +	SM_FILE_T *fp;
    +        const void *info; 
    +        int flags;
    +        void *rpool;
    +{
    +	/*
    +	**  now we could do the open raw (i.e with read(2)), but we will
    +	**  use file layering instead. We will use the stdio file
    +	**  type (different than the system's stdio).
    +	*/
    +	struct passwd *pw;
    +	char path[PATH_MAX];
    +
    +	pw = getpwuid(getuid());
    +	sm_io_snprintf(path, PATH_MAX, "%s/%s", pw->pw_dir, info);
    +
    +	/*
    +	**  Okay. Now the path pass-in has been prefixed with the
    +	**  user's HOME directory. We'll call the regular stdio (SmFtStdio)
    +	**  now to handle the rest of the open.
    +	*/
    +	fp->cookie = sm_io_open(SmFtStdio, path, flags, rpools);
    +	if (fp->cookie == NULL)
    +		return(-1) /* errno set by sm_io_open call */
    +	else
    +		return(0);
    +}
    +
    +Later on when a write is performed the function mywrite will +be invoked. To match the above myopen, mywrite could +be written as: +
    +int mywrite(fp, buf, size)
    +	SM_FILE_T *fp;
    +        char *buf;
    +        size_t size;
    +{
    +	/*
    +	**  As an example, we can change, modify, refuse, filter, etc.
    +	**  the content being passed through before we ask the SmFtStdio
    +	**  to do the actual write.
    +	**  This example is very simple and contrived, but this keeps it
    +	**  clear.
    +	*/
    +	if (size == 0)
    +		return(0); /* why waste the cycles? */
    +	if (*buf == 'X')
    +		*buf = 'Y';
    +
    +	/*
    +	**  Note that the file pointer passed to the next level is the
    +	**  one that was stored in the cookie during the open.
    +	*/
    +	return(sm_io_write(fp->cookie, buf, size));
    +}
    +
    +As a thought-exercise for the fair reader: how would you modify the +above two functions to make a "tee". That is the program will call +sm_io_open or sm_io_write and two or more files will +be opened and written to. (Hint: create a cookie to hold two or more +file pointers). +
    +

    +

    +
    +
    +
    +

    +
    +

    + +libsm sm_io default API definition + +

    +
    +

    Introduction

    +

    +A number of sm_io API's perform similar to their stdio +counterparts (same name as when the "sm_io_" is removed). +One difference between sm_io and stdio functions is that +if a "file pointer" (FILE/SM_FILE_T) +is one of the arguments for the function, then it is now the first +argument. Sm_io is standardized so that when a file pointer is +one of the arguments to function then it will always be the first +arguement. Many of the sm_io function take a timeout +argument (see Timeouts). +

    +

    +The API you have selected is one of these. Please consult the +appropriate stdio man page for now. +

    + + + diff --git a/gnu/dist/sendmail/libsm/ldap.c b/gnu/dist/sendmail/libsm/ldap.c new file mode 100644 index 000000000000..0682d2c62226 --- /dev/null +++ b/gnu/dist/sendmail/libsm/ldap.c @@ -0,0 +1,1213 @@ +/* + * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: ldap.c,v 1.44.2.2 2002/08/09 22:23:12 gshapiro Exp") + +#if LDAPMAP +# include +# include +# include +# include +# include + +# include +# include +# include +# include +# include +# include +# include +# ifdef EX_OK +# undef EX_OK /* for SVr4.2 SMP */ +# endif /* EX_OK */ +# include + +SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", + "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); + +static void ldaptimeout __P((int)); + +/* +** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT +** +** Parameters: +** lmap -- pointer to SM_LDAP_STRUCT to clear +** +** Returns: +** None. +** +*/ + +void +sm_ldap_clear(lmap) + SM_LDAP_STRUCT *lmap; +{ + if (lmap == NULL) + return; + + lmap->ldap_target = NULL; + lmap->ldap_port = LDAP_PORT; +#if _FFR_LDAP_URI + lmap->ldap_uri = false; +#endif /* _FFR_LDAP_URI */ +# if _FFR_LDAP_SETVERSION + lmap->ldap_version = 0; +# endif /* _FFR_LDAP_SETVERSION */ + lmap->ldap_deref = LDAP_DEREF_NEVER; + lmap->ldap_timelimit = LDAP_NO_LIMIT; + lmap->ldap_sizelimit = LDAP_NO_LIMIT; +# ifdef LDAP_REFERRALS + lmap->ldap_options = LDAP_OPT_REFERRALS; +# else /* LDAP_REFERRALS */ + lmap->ldap_options = 0; +# endif /* LDAP_REFERRALS */ + lmap->ldap_attrsep = '\0'; + lmap->ldap_binddn = NULL; + lmap->ldap_secret = NULL; + lmap->ldap_method = LDAP_AUTH_SIMPLE; + lmap->ldap_base = NULL; + lmap->ldap_scope = LDAP_SCOPE_SUBTREE; + lmap->ldap_attrsonly = LDAPMAP_FALSE; + lmap->ldap_timeout.tv_sec = 0; + lmap->ldap_timeout.tv_usec = 0; + lmap->ldap_ld = NULL; + lmap->ldap_filter = NULL; + lmap->ldap_attr[0] = NULL; +#if _FFR_LDAP_RECURSION + lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; + lmap->ldap_attr_needobjclass[0] = NULL; +#endif /* _FFR_LDAP_RECURSION */ + lmap->ldap_res = NULL; + lmap->ldap_next = NULL; + lmap->ldap_pid = 0; +} + +/* +** SM_LDAP_START -- actually connect to an LDAP server +** +** Parameters: +** name -- name of map for debug output. +** lmap -- the LDAP map being opened. +** +** Returns: +** true if connection is successful, false otherwise. +** +** Side Effects: +** Populates lmap->ldap_ld. +*/ + +static jmp_buf LDAPTimeout; + +#define SM_LDAP_SETTIMEOUT(to) \ +do \ +{ \ + if (to != 0) \ + { \ + if (setjmp(LDAPTimeout) != 0) \ + { \ + errno = ETIMEDOUT; \ + return false; \ + } \ + ev = sm_setevent(to, ldaptimeout, 0); \ + } \ +} while (0) + +#define SM_LDAP_CLEARTIMEOUT() \ +do \ +{ \ + if (ev != NULL) \ + sm_clrevent(ev); \ +} while (0) + +bool +sm_ldap_start(name, lmap) + char *name; + SM_LDAP_STRUCT *lmap; +{ + int bind_result; + int save_errno; + SM_EVENT *ev = NULL; + LDAP *ld; + + if (sm_debug_active(&SmLDAPTrace, 2)) + sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); + + if (sm_debug_active(&SmLDAPTrace, 9)) + sm_dprintf("ldapmap_start(%s, %d)\n", + lmap->ldap_target == NULL ? "localhost" : lmap->ldap_target, + lmap->ldap_port); + +# if USE_LDAP_INIT +# if _FFR_LDAP_URI + if (lmap->ldap_uri) + errno = ldap_initialize(&ld, lmap->ldap_target); + else +# endif /* _FFR_LDAP_URI */ + ld = ldap_init(lmap->ldap_target, lmap->ldap_port); + save_errno = errno; +# else /* USE_LDAP_INIT */ + /* + ** If using ldap_open(), the actual connection to the server + ** happens now so we need the timeout here. For ldap_init(), + ** the connection happens at bind time. + */ + + SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); + ld = ldap_open(lmap->ldap_target, lmap->ldap_port); + save_errno = errno; + + /* clear the event if it has not sprung */ + SM_LDAP_CLEARTIMEOUT(); +# endif /* USE_LDAP_INIT */ + + errno = save_errno; + if (ld == NULL) + return false; + + sm_ldap_setopts(ld, lmap); + +# if USE_LDAP_INIT + /* + ** If using ldap_init(), the actual connection to the server + ** happens at ldap_bind_s() so we need the timeout here. + */ + + SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); +# endif /* USE_LDAP_INIT */ + +# ifdef LDAP_AUTH_KRBV4 + if (lmap->ldap_method == LDAP_AUTH_KRBV4 && + lmap->ldap_secret != NULL) + { + /* + ** Need to put ticket in environment here instead of + ** during parseargs as there may be different tickets + ** for different LDAP connections. + */ + + (void) putenv(lmap->ldap_secret); + } +# endif /* LDAP_AUTH_KRBV4 */ + + bind_result = ldap_bind_s(ld, lmap->ldap_binddn, + lmap->ldap_secret, lmap->ldap_method); + +# if USE_LDAP_INIT + /* clear the event if it has not sprung */ + SM_LDAP_CLEARTIMEOUT(); +# endif /* USE_LDAP_INIT */ + + if (bind_result != LDAP_SUCCESS) + { + errno = bind_result + E_LDAPBASE; + return false; + } + + /* Save PID to make sure only this PID closes the LDAP connection */ + lmap->ldap_pid = getpid(); + lmap->ldap_ld = ld; + return true; +} + +/* ARGSUSED */ +static void +ldaptimeout(unused) + int unused; +{ + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; + longjmp(LDAPTimeout, 1); +} + +/* +** SM_LDAP_SEARCH -- iniate LDAP search +** +** Initiate an LDAP search, return the msgid. +** The calling function must collect the results. +** +** Parameters: +** lmap -- LDAP map information +** key -- key to substitute in LDAP filter +** +** Returns: +** -1 on failure, msgid on success +** +*/ + +int +sm_ldap_search(lmap, key) + SM_LDAP_STRUCT *lmap; + char *key; +{ + int msgid; + char *fp, *p, *q; + char filter[LDAPMAP_MAX_FILTER + 1]; + + /* substitute key into filter, perhaps multiple times */ + memset(filter, '\0', sizeof filter); + fp = filter; + p = lmap->ldap_filter; + while ((q = strchr(p, '%')) != NULL) + { + if (q[1] == 's') + { + (void) sm_snprintf(fp, SPACELEFT(filter, fp), + "%.*s%s", (int) (q - p), p, key); + fp += strlen(fp); + p = q + 2; + } + else if (q[1] == '0') + { + char *k = key; + + (void) sm_snprintf(fp, SPACELEFT(filter, fp), + "%.*s", (int) (q - p), p); + fp += strlen(fp); + p = q + 2; + + /* Properly escape LDAP special characters */ + while (SPACELEFT(filter, fp) > 0 && + *k != '\0') + { + if (*k == '*' || *k == '(' || + *k == ')' || *k == '\\') + { + (void) sm_strlcat(fp, + (*k == '*' ? "\\2A" : + (*k == '(' ? "\\28" : + (*k == ')' ? "\\29" : + (*k == '\\' ? "\\5C" : + "\00")))), + SPACELEFT(filter, fp)); + fp += strlen(fp); + k++; + } + else + *fp++ = *k++; + } + } + else + { + (void) sm_snprintf(fp, SPACELEFT(filter, fp), + "%.*s", (int) (q - p + 1), p); + p = q + (q[1] == '%' ? 2 : 1); + fp += strlen(fp); + } + } + (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); + if (sm_debug_active(&SmLDAPTrace, 20)) + sm_dprintf("ldap search filter=%s\n", filter); + + lmap->ldap_res = NULL; + msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, + lmap->ldap_scope, filter, + (lmap->ldap_attr[0] == NULL ? NULL : + lmap->ldap_attr), + lmap->ldap_attrsonly); + return msgid; +} + +# if _FFR_LDAP_RECURSION +/* +** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a +** particular objectClass +** +** Parameters: +** lmap -- pointer to SM_LDAP_STRUCT in use +** entry -- current LDAP entry struct +** ocvalue -- particular objectclass in question. +** may be of form (fee|foo|fum) meaning +** any entry can be part of either fee, +** foo or fum objectclass +** +** Returns: +** true if item has that objectClass +*/ + +static bool +sm_ldap_has_objectclass(lmap, entry, ocvalue) + SM_LDAP_STRUCT *lmap; + LDAPMessage *entry; + char *ocvalue; +{ + char **vals = NULL; + int i; + + if (ocvalue == NULL) + return false; + + vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); + if (vals == NULL) + return false; + + for (i = 0; vals[i] != NULL; i++) + { + char *p; + char *q; + + p = q = ocvalue; + while (*p != '\0') + { + while (*p != '\0' && *p != '|') + p++; + + if ((p - q) == strlen(vals[i]) && + sm_strncasecmp(vals[i], q, p - q) == 0) + { + ldap_value_free(vals); + return true; + } + + while (*p == '|') + p++; + q = p; + } + } + + ldap_value_free(vals); + return false; +} + +/* +** SM_LDAP_RESULTS -- return results from an LDAP lookup in result +** +** Parameters: +** lmap -- pointer to SM_LDAP_STRUCT in use +** msgid -- msgid returned by sm_ldap_search() +** flags -- flags for the lookup +** delim -- delimiter for result concatenation +** rpool -- memory pool for storage +** result -- return string +** recurse -- recursion list +** +** Returns: +** status (sysexit) +*/ + +# define SM_LDAP_ERROR_CLEANUP() \ +{ \ + if (lmap->ldap_res != NULL) \ + { \ + ldap_msgfree(lmap->ldap_res); \ + lmap->ldap_res = NULL; \ + } \ + (void) ldap_abandon(lmap->ldap_ld, msgid); \ +} + +static SM_LDAP_RECURSE_ENTRY * +sm_ldap_add_recurse(top, item, type, rpool) + SM_LDAP_RECURSE_LIST **top; + char *item; + int type; + SM_RPOOL_T *rpool; +{ + int n; + int m; + int p; + int insertat; + int moveb; + int oldsizeb; + int rc; + SM_LDAP_RECURSE_ENTRY *newe; + SM_LDAP_RECURSE_ENTRY **olddata; + + /* + ** This code will maintain a list of + ** SM_LDAP_RECURSE_ENTRY structures + ** in ascending order. + */ + + if (*top == NULL) + { + /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ + *top = sm_rpool_malloc_x(rpool, sizeof **top); + (*top)->lr_cnt = 0; + (*top)->lr_size = 0; + (*top)->lr_data = NULL; + } + + if ((*top)->lr_cnt >= (*top)->lr_size) + { + /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ + olddata = (*top)->lr_data; + if ((*top)->lr_size == 0) + { + oldsizeb = 0; + (*top)->lr_size = 256; + } + else + { + oldsizeb = (*top)->lr_size * sizeof *((*top)->lr_data); + (*top)->lr_size *= 2; + } + (*top)->lr_data = sm_rpool_malloc_x(rpool, + (*top)->lr_size * sizeof *((*top)->lr_data)); + if (oldsizeb > 0) + memcpy((*top)->lr_data, olddata, oldsizeb); + } + + /* + ** Binary search/insert item:type into list. + ** Return current entry pointer if already exists. + */ + + n = 0; + m = (*top)->lr_cnt - 1; + if (m < 0) + insertat = 0; + else + insertat = -1; + + while (insertat == -1) + { + p = (m + n) / 2; + + rc = sm_strcasecmp(item, (*top)->lr_data[p]->lr_search); + if (rc == 0) + rc = type - (*top)->lr_data[p]->lr_type; + + if (rc < 0) + m = p - 1; + else if (rc > 0) + n = p + 1; + else + return (*top)->lr_data[p]; + + if (m == -1) + insertat = 0; + else if (n >= (*top)->lr_cnt) + insertat = (*top)->lr_cnt; + else if (m < n) + insertat = m + 1; + } + + /* + ** Not found in list, make room + ** at insert point and add it. + */ + + newe = sm_rpool_malloc_x(rpool, sizeof *newe); + if (newe != NULL) + { + moveb = ((*top)->lr_cnt - insertat) * sizeof *((*top)->lr_data); + if (moveb > 0) + memmove(&((*top)->lr_data[insertat + 1]), + &((*top)->lr_data[insertat]), + moveb); + + newe->lr_search = sm_rpool_strdup_x(rpool, item); + newe->lr_type = type; + newe->lr_done = false; + + ((*top)->lr_data)[insertat] = newe; + (*top)->lr_cnt++; + } + return newe; +} + +int +sm_ldap_results(lmap, msgid, flags, delim, rpool, result, + resultln, resultsz, recurse) + SM_LDAP_STRUCT *lmap; + int msgid; + int flags; + int delim; + SM_RPOOL_T *rpool; + char **result; + int *resultln; + int *resultsz; + SM_LDAP_RECURSE_LIST *recurse; +{ + bool toplevel; + int i; + int statp; + int vsize; + int ret; + int save_errno; + char *p; + SM_LDAP_RECURSE_ENTRY *rl; + + /* Are we the top top level of the search? */ + toplevel = (recurse == NULL); + + /* Get results */ + statp = EX_NOTFOUND; + while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, + (lmap->ldap_timeout.tv_sec == 0 ? NULL : + &(lmap->ldap_timeout)), + &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) + { + LDAPMessage *entry; + + /* If we don't want multiple values and we have one, break */ + if ((char) delim == '\0' && *result != NULL) + break; + + /* Cycle through all entries */ + for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); + entry != NULL; + entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) + { + BerElement *ber; + char *attr; + char **vals = NULL; + char *dn; + + /* + ** If matching only and found an entry, + ** no need to spin through attributes + */ + + if (statp == EX_OK && + bitset(SM_LDAP_MATCHONLY, flags)) + continue; + + /* record completed DN's to prevent loops */ + dn = ldap_get_dn(lmap->ldap_ld, entry); + if (dn == NULL) + { + save_errno = sm_ldap_geterrno(lmap->ldap_ld); + save_errno += E_LDAPBASE; + SM_LDAP_ERROR_CLEANUP(); + errno = save_errno; + return EX_OSERR; + } + + rl = sm_ldap_add_recurse(&recurse, dn, + SM_LDAP_ATTR_DN, + rpool); + + if (rl == NULL) + { + ldap_memfree(dn); + SM_LDAP_ERROR_CLEANUP(); + errno = ENOMEM; + return EX_OSERR; + } + else if (rl->lr_done) + { + /* already on list, skip it */ + ldap_memfree(dn); + continue; + } + ldap_memfree(dn); + +# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) + /* + ** Reset value to prevent lingering + ** LDAP_DECODING_ERROR due to + ** OpenLDAP 1.X's hack (see below) + */ + + lmap->ldap_ld->ld_errno = LDAP_SUCCESS; +# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ + + for (attr = ldap_first_attribute(lmap->ldap_ld, entry, + &ber); + attr != NULL; + attr = ldap_next_attribute(lmap->ldap_ld, entry, + ber)) + { + char *tmp, *vp_tmp; + int type; + char *needobjclass = NULL; + + type = SM_LDAP_ATTR_NONE; + for (i = 0; lmap->ldap_attr[i] != NULL; i++) + { + if (sm_strcasecmp(lmap->ldap_attr[i], + attr) == 0) + { + type = lmap->ldap_attr_type[i]; + needobjclass = lmap->ldap_attr_needobjclass[i]; + break; + } + } + + if (bitset(SM_LDAP_USE_ALLATTR, flags) && + type == SM_LDAP_ATTR_NONE) + { + /* URL lookups specify attrs to use */ + type = SM_LDAP_ATTR_NORMAL; + needobjclass = NULL; + } + + if (type == SM_LDAP_ATTR_NONE) + { + /* attribute not requested */ + ldap_memfree(attr); + SM_LDAP_ERROR_CLEANUP(); + errno = EFAULT; + return EX_SOFTWARE; + } + + /* + ** For recursion on a particular attribute, + ** we may need to see if this entry is + ** part of a particular objectclass. + ** Also, ignore objectClass attribute. + ** Otherwise we just ignore this attribute. + */ + + if (type == SM_LDAP_ATTR_OBJCLASS || + (needobjclass != NULL && + !sm_ldap_has_objectclass(lmap, entry, + needobjclass))) + { + ldap_memfree(attr); + continue; + } + + if (lmap->ldap_attrsonly == LDAPMAP_FALSE) + { + vals = ldap_get_values(lmap->ldap_ld, + entry, + attr); + if (vals == NULL) + { + save_errno = sm_ldap_geterrno(lmap->ldap_ld); + if (save_errno == LDAP_SUCCESS) + { + ldap_memfree(attr); + continue; + } + + /* Must be an error */ + save_errno += E_LDAPBASE; + ldap_memfree(attr); + SM_LDAP_ERROR_CLEANUP(); + errno = save_errno; + return EX_TEMPFAIL; + } + } + + statp = EX_OK; + +# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) + /* + ** Reset value to prevent lingering + ** LDAP_DECODING_ERROR due to + ** OpenLDAP 1.X's hack (see below) + */ + + lmap->ldap_ld->ld_errno = LDAP_SUCCESS; +# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ + + /* + ** If matching only, + ** no need to spin through entries + */ + + if (bitset(SM_LDAP_MATCHONLY, flags)) + { + if (lmap->ldap_attrsonly == LDAPMAP_FALSE) + ldap_value_free(vals); + ldap_memfree(attr); + continue; + } + + /* + ** If we don't want multiple values, + ** return first found. + */ + + if ((char) delim == '\0') + { + if (*result != NULL) + { + /* already have a value */ + break; + } + + if (bitset(SM_LDAP_SINGLEMATCH, + flags) && + *result != NULL) + { + /* only wanted one match */ + SM_LDAP_ERROR_CLEANUP(); + errno = ENOENT; + return EX_NOTFOUND; + } + + if (lmap->ldap_attrsonly == LDAPMAP_TRUE) + { + *result = sm_rpool_strdup_x(rpool, + attr); + ldap_memfree(attr); + break; + } + + if (vals[0] == NULL) + { + ldap_value_free(vals); + ldap_memfree(attr); + continue; + } + + vsize = strlen(vals[0]) + 1; + if (lmap->ldap_attrsep != '\0') + vsize += strlen(attr) + 1; + *result = sm_rpool_malloc_x(rpool, + vsize); + if (lmap->ldap_attrsep != '\0') + sm_snprintf(*result, vsize, + "%s%c%s", + attr, + lmap->ldap_attrsep, + vals[0]); + else + sm_strlcpy(*result, vals[0], + vsize); + ldap_value_free(vals); + ldap_memfree(attr); + break; + } + + /* attributes only */ + if (lmap->ldap_attrsonly == LDAPMAP_TRUE) + { + if (*result == NULL) + *result = sm_rpool_strdup_x(rpool, + attr); + else + { + if (bitset(SM_LDAP_SINGLEMATCH, + flags) && + *result != NULL) + { + /* only wanted one match */ + SM_LDAP_ERROR_CLEANUP(); + errno = ENOENT; + return EX_NOTFOUND; + } + + vsize = strlen(*result) + + strlen(attr) + 2; + tmp = sm_rpool_malloc_x(rpool, + vsize); + (void) sm_snprintf(tmp, + vsize, "%s%c%s", + *result, (char) delim, + attr); + *result = tmp; + } + ldap_memfree(attr); + continue; + } + + /* + ** If there is more than one, munge then + ** into a map_coldelim separated string. + ** If we are recursing we may have an entry + ** with no 'normal' values to put in the + ** string. + ** This is not an error. + */ + + if (type == SM_LDAP_ATTR_NORMAL && + bitset(SM_LDAP_SINGLEMATCH, flags) && + *result != NULL) + { + /* only wanted one match */ + SM_LDAP_ERROR_CLEANUP(); + errno = ENOENT; + return EX_NOTFOUND; + } + + vsize = 0; + for (i = 0; vals[i] != NULL; i++) + { + if (type == SM_LDAP_ATTR_DN || + type == SM_LDAP_ATTR_FILTER || + type == SM_LDAP_ATTR_URL) + { + /* add to recursion */ + if (sm_ldap_add_recurse(&recurse, + vals[i], + type, + rpool) == NULL) + { + SM_LDAP_ERROR_CLEANUP(); + errno = ENOMEM; + return EX_OSERR; + } + continue; + } + + vsize += strlen(vals[i]) + 1; + if (lmap->ldap_attrsep != '\0') + vsize += strlen(attr) + 1; + } + + /* + ** Create/Append to string any normal + ** attribute values. Otherwise, just free + ** memory and move on to the next + ** attribute in this entry. + */ + + if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) + { + char *pe; + + /* Grow result string if needed */ + if ((*resultln + vsize) >= *resultsz) + { + while ((*resultln + vsize) >= *resultsz) + { + if (*resultsz == 0) + *resultsz = 1024; + else + *resultsz *= 2; + } + + vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); + *vp_tmp = '\0'; + + if (*result != NULL) + sm_strlcpy(vp_tmp, + *result, + *resultsz); + *result = vp_tmp; + } + + p = *result + *resultln; + pe = *result + *resultsz; + + for (i = 0; vals[i] != NULL; i++) + { + if (*resultln > 0 && + p < pe) + *p++ = (char) delim; + + if (lmap->ldap_attrsep != '\0') + { + p += sm_strlcpy(p, attr, + pe - p); + if (p < pe) + *p++ = lmap->ldap_attrsep; + } + + p += sm_strlcpy(p, vals[i], + pe - p); + *resultln = p - (*result); + if (p >= pe) + { + /* Internal error: buffer too small for LDAP values */ + SM_LDAP_ERROR_CLEANUP(); + errno = ENOMEM; + return EX_OSERR; + } + } + } + + ldap_value_free(vals); + ldap_memfree(attr); + } + save_errno = sm_ldap_geterrno(lmap->ldap_ld); + + /* + ** We check save_errno != LDAP_DECODING_ERROR since + ** OpenLDAP 1.X has a very ugly *undocumented* + ** hack of returning this error code from + ** ldap_next_attribute() if the library freed the + ** ber attribute. See: + ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html + */ + + if (save_errno != LDAP_SUCCESS && + save_errno != LDAP_DECODING_ERROR) + { + /* Must be an error */ + save_errno += E_LDAPBASE; + SM_LDAP_ERROR_CLEANUP(); + errno = save_errno; + return EX_TEMPFAIL; + } + + /* mark this DN as done */ + rl->lr_done = true; + + /* We don't want multiple values and we have one */ + if ((char) delim == '\0' && *result != NULL) + break; + } + save_errno = sm_ldap_geterrno(lmap->ldap_ld); + if (save_errno != LDAP_SUCCESS && + save_errno != LDAP_DECODING_ERROR) + { + /* Must be an error */ + save_errno += E_LDAPBASE; + SM_LDAP_ERROR_CLEANUP(); + errno = save_errno; + return EX_TEMPFAIL; + } + ldap_msgfree(lmap->ldap_res); + lmap->ldap_res = NULL; + } + + if (ret == 0) + save_errno = ETIMEDOUT; + else + save_errno = sm_ldap_geterrno(lmap->ldap_ld); + if (save_errno != LDAP_SUCCESS) + { + statp = EX_TEMPFAIL; + if (ret != 0) + { + switch (save_errno) + { +#ifdef LDAP_SERVER_DOWN + case LDAP_SERVER_DOWN: +#endif /* LDAP_SERVER_DOWN */ + case LDAP_TIMEOUT: + case LDAP_UNAVAILABLE: + + /* + ** server disappeared, + ** try reopen on next search + */ + + statp = EX_RESTART; + break; + } + save_errno += E_LDAPBASE; + } + SM_LDAP_ERROR_CLEANUP(); + errno = save_errno; + return statp; + } + + if (lmap->ldap_res != NULL) + { + ldap_msgfree(lmap->ldap_res); + lmap->ldap_res = NULL; + } + + if (toplevel) + { + int rlidx; + + /* + ** Spin through the built-up recurse list at the top + ** of the recursion. Since new items are added at the + ** end of the shared list, we actually only ever get + ** one level of recursion before things pop back to the + ** top. Any items added to the list during that recursion + ** will be expanded by the top level. + */ + + for (rlidx = 0; recurse != NULL && rlidx < recurse->lr_cnt; rlidx++) + { + int newflags; + int sid; + int status; + + rl = recurse->lr_data[rlidx]; + + newflags = flags; + if (rl->lr_done) + { + /* already expanded */ + continue; + } + + if (rl->lr_type == SM_LDAP_ATTR_DN) + { + /* do DN search */ + sid = ldap_search(lmap->ldap_ld, + rl->lr_search, + lmap->ldap_scope, + "(objectClass=*)", + (lmap->ldap_attr[0] == NULL ? + NULL : lmap->ldap_attr), + lmap->ldap_attrsonly); + } + else if (rl->lr_type == SM_LDAP_ATTR_FILTER) + { + /* do new search */ + sid = ldap_search(lmap->ldap_ld, + lmap->ldap_base, + lmap->ldap_scope, + rl->lr_search, + (lmap->ldap_attr[0] == NULL ? + NULL : lmap->ldap_attr), + lmap->ldap_attrsonly); + } + else if (rl->lr_type == SM_LDAP_ATTR_URL) + { + /* do new URL search */ + sid = ldap_url_search(lmap->ldap_ld, + rl->lr_search, + lmap->ldap_attrsonly); + newflags |= SM_LDAP_USE_ALLATTR; + } + else + { + /* unknown or illegal attribute type */ + errno = EFAULT; + return EX_SOFTWARE; + } + + /* Collect results */ + if (sid == -1) + { + save_errno = sm_ldap_geterrno(lmap->ldap_ld); + statp = EX_TEMPFAIL; + switch (save_errno) + { +#ifdef LDAP_SERVER_DOWN + case LDAP_SERVER_DOWN: +#endif /* LDAP_SERVER_DOWN */ + case LDAP_TIMEOUT: + case LDAP_UNAVAILABLE: + + /* + ** server disappeared, + ** try reopen on next search + */ + + statp = EX_RESTART; + break; + } + errno = save_errno + E_LDAPBASE; + return statp; + } + + status = sm_ldap_results(lmap, sid, newflags, delim, + rpool, result, resultln, + resultsz, recurse); + save_errno = errno; + if (status != EX_OK && status != EX_NOTFOUND) + { + errno = save_errno; + return status; + } + + /* Mark as done */ + rl->lr_done = true; + + /* Reset rlidx as new items may have been added */ + rlidx = -1; + } + } + return statp; +} +#endif /* _FFR_LDAP_RECURSION */ + +/* +** SM_LDAP_CLOSE -- close LDAP connection +** +** Parameters: +** lmap -- LDAP map information +** +** Returns: +** None. +** +*/ + +void +sm_ldap_close(lmap) + SM_LDAP_STRUCT *lmap; +{ + if (lmap->ldap_ld == NULL) + return; + + if (lmap->ldap_pid == getpid()) + ldap_unbind(lmap->ldap_ld); + lmap->ldap_ld = NULL; + lmap->ldap_pid = 0; +} + +/* +** SM_LDAP_SETOPTS -- set LDAP options +** +** Parameters: +** ld -- LDAP session handle +** lmap -- LDAP map information +** +** Returns: +** None. +** +*/ + +void +sm_ldap_setopts(ld, lmap) + LDAP *ld; + SM_LDAP_STRUCT *lmap; +{ +# if USE_LDAP_SET_OPTION +# if _FFR_LDAP_SETVERSION + if (lmap->ldap_version != 0) + { + ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, + &lmap->ldap_version); + } +# endif /* _FFR_LDAP_SETVERSION */ + ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); + if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) + ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); + else + ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); + ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); + ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); +# ifdef LDAP_OPT_RESTART + ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); +# endif /* LDAP_OPT_RESTART */ +# else /* USE_LDAP_SET_OPTION */ + /* From here on in we can use ldap internal timelimits */ + ld->ld_deref = lmap->ldap_deref; + ld->ld_options = lmap->ldap_options; + ld->ld_sizelimit = lmap->ldap_sizelimit; + ld->ld_timelimit = lmap->ldap_timelimit; +# endif /* USE_LDAP_SET_OPTION */ +} + +/* +** SM_LDAP_GETERRNO -- get ldap errno value +** +** Parameters: +** ld -- LDAP session handle +** +** Returns: +** LDAP errno. +** +*/ + +int +sm_ldap_geterrno(ld) + LDAP *ld; +{ + int err = LDAP_SUCCESS; + +# if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 + (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); +# else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ +# ifdef LDAP_OPT_SIZELIMIT + err = ldap_get_lderrno(ld, NULL, NULL); +# else /* LDAP_OPT_SIZELIMIT */ + err = ld->ld_errno; + + /* + ** Reset value to prevent lingering LDAP_DECODING_ERROR due to + ** OpenLDAP 1.X's hack (see above) + */ + + ld->ld_errno = LDAP_SUCCESS; +# endif /* LDAP_OPT_SIZELIMIT */ +# endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ + return err; +} +# endif /* LDAPMAP */ diff --git a/gnu/dist/sendmail/libsm/local.h b/gnu/dist/sendmail/libsm/local.h new file mode 100644 index 000000000000..2211dbba6f6c --- /dev/null +++ b/gnu/dist/sendmail/libsm/local.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + * + * Id: local.h,v 1.51.2.1 2002/09/09 21:38:08 gshapiro Exp + */ + +/* +** Information local to this implementation of stdio, +** in particular, macros and private variables. +*/ + +#include +#if !SM_CONF_MEMCHR +# include +#endif /* !SM_CONF_MEMCHR */ +#include + +int sm_flush __P((SM_FILE_T *, int *)); +SM_FILE_T *smfp __P((void)); +int sm_refill __P((SM_FILE_T *, int)); +void sm_init __P((void)); +void sm_cleanup __P((void)); +void sm_makebuf __P((SM_FILE_T *)); +int sm_whatbuf __P((SM_FILE_T *, size_t *, int *)); +int sm_fwalk __P((int (*)(SM_FILE_T *, int *), int *)); +int sm_wsetup __P((SM_FILE_T *)); +int sm_flags __P((int)); +SM_FILE_T *sm_fp __P((const SM_FILE_T *, const int, SM_FILE_T *)); +int sm_vprintf __P((int, char const *, va_list)); +int sm_vfscanf __P((SM_FILE_T *, int, char const *, va_list)); + +/* std io functions */ +ssize_t sm_stdread __P((SM_FILE_T *, char *, size_t)); +ssize_t sm_stdwrite __P((SM_FILE_T *, char const *, size_t)); +off_t sm_stdseek __P((SM_FILE_T *, off_t, int)); +int sm_stdclose __P((SM_FILE_T *)); +int sm_stdopen __P((SM_FILE_T *, const void *, int, const void *)); +int sm_stdfdopen __P((SM_FILE_T *, const void *, int, const void *)); +int sm_stdsetinfo __P((SM_FILE_T *, int , void *)); +int sm_stdgetinfo __P((SM_FILE_T *, int , void *)); + +/* stdio io functions */ +ssize_t sm_stdioread __P((SM_FILE_T *, char *, size_t)); +ssize_t sm_stdiowrite __P((SM_FILE_T *, char const *, size_t)); +off_t sm_stdioseek __P((SM_FILE_T *, off_t, int)); +int sm_stdioclose __P((SM_FILE_T *)); +int sm_stdioopen __P((SM_FILE_T *, const void *, int, const void *)); +int sm_stdiosetinfo __P((SM_FILE_T *, int , void *)); +int sm_stdiogetinfo __P((SM_FILE_T *, int , void *)); + +/* string io functions */ +ssize_t sm_strread __P((SM_FILE_T *, char *, size_t)); +ssize_t sm_strwrite __P((SM_FILE_T *, char const *, size_t)); +off_t sm_strseek __P((SM_FILE_T *, off_t, int)); +int sm_strclose __P((SM_FILE_T *)); +int sm_stropen __P((SM_FILE_T *, const void *, int, const void *)); +int sm_strsetinfo __P((SM_FILE_T *, int , void *)); +int sm_strgetinfo __P((SM_FILE_T *, int , void *)); + +/* syslog io functions */ +ssize_t sm_syslogread __P((SM_FILE_T *, char *, size_t)); +ssize_t sm_syslogwrite __P((SM_FILE_T *, char const *, size_t)); +off_t sm_syslogseek __P((SM_FILE_T *, off_t, int)); +int sm_syslogclose __P((SM_FILE_T *)); +int sm_syslogopen __P((SM_FILE_T *, const void *, int, const void *)); +int sm_syslogsetinfo __P((SM_FILE_T *, int , void *)); +int sm_sysloggetinfo __P((SM_FILE_T *, int , void *)); + +/* should be defined in sys/time.h */ +#ifndef timersub +# define timersub(tvp, uvp, vvp) \ + do \ + { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) \ + { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* !timersub */ + +#ifndef timeradd +# define timeradd(tvp, uvp, vvp) \ + do \ + { \ + (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ + if ((vvp)->tv_usec >= 1000000) \ + { \ + (vvp)->tv_sec++; \ + (vvp)->tv_usec -= 1000000; \ + } \ + } while (0) +#endif /* !timeradd */ + +#ifndef timercmp +# define timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) +#endif /* !timercmp */ + +extern bool Sm_IO_DidInit; + +/* Return true iff the given SM_FILE_T cannot be written now. */ +#define cantwrite(fp) \ + ((((fp)->f_flags & SMWR) == 0 || (fp)->f_bf.smb_base == NULL) && \ + sm_wsetup(fp)) + +/* +** Test whether the given stdio file has an active ungetc buffer; +** release such a buffer, without restoring ordinary unread data. +*/ + +#define HASUB(fp) ((fp)->f_ub.smb_base != NULL) +#define FREEUB(fp) \ +{ \ + if ((fp)->f_ub.smb_base != (fp)->f_ubuf) \ + sm_free((char *)(fp)->f_ub.smb_base); \ + (fp)->f_ub.smb_base = NULL; \ +} + +extern const char SmFileMagic[]; + +#define SM_ALIGN(p) (((unsigned long)(p) + SM_ALIGN_BITS) & ~SM_ALIGN_BITS) + +#define sm_io_flockfile(fp) ((void) 0) +#define sm_io_funlockfile(fp) ((void) 0) + +#ifndef FDSET_CAST +# define FDSET_CAST /* empty cast for fd_set arg to select */ +#endif + +/* +** SM_CONVERT_TIME -- convert the API timeout flag for select() usage. +** +** This takes a 'fp' (a file type pointer) and obtains the "raw" +** file descriptor (fd) if possible. The 'fd' is needed to possibly +** switch the mode of the file (blocking/non-blocking) to match +** the type of timeout. If timeout is SM_TIME_FOREVER then the +** timeout using select won't be needed and the file is best placed +** in blocking mode. If there is to be a finite timeout then the file +** is best placed in non-blocking mode. Then, if not enough can be +** written, select() can be used to test when something can be written +** yet still timeout if the wait is too long. +** If the mode is already in the correct state we don't change it. +** Iff (yes "iff") the 'fd' is "-1" in value then the mode change +** will not happen. This situation arises when a late-binding-to-disk +** file type is in use. An example of this is the sendmail buffered +** file type (in sendmail/bf.c). +** +** Parameters +** fp -- the file pointer the timeout is for +** fd -- to become the file descriptor value from 'fp' +** val -- the timeout value to be converted +** time -- a struct timeval holding the converted value +** +** Returns +** nothing, this is flow-through code +** +** Side Effects: +** May or may not change the mode of a currently open file. +** The file mode may be changed to O_NONBLOCK or ~O_NONBLOCK +** (meaning block). This is done to best match the type of +** timeout and for (possible) use with select(). +*/ + +# define SM_CONVERT_TIME(fp, fd, val, time) { \ + if (((fd) = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) \ + { \ + /* can't get an fd, likely internal 'fake' fp */ \ + errno = 0; \ + } \ + if ((val) == SM_TIME_DEFAULT) \ + (val) = (fp)->f_timeout; \ + if ((val) == SM_TIME_IMMEDIATE || (val) == SM_TIME_FOREVER) \ + { \ + (time)->tv_sec = 0; \ + (time)->tv_usec = 0; \ + } \ + else \ + { \ + (time)->tv_sec = (val) / 1000; \ + (time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 10; \ + } \ + if ((val) == SM_TIME_FOREVER) \ + { \ + if ((fp)->f_timeoutstate == SM_TIME_NONBLOCK && (fd) != -1) \ + { \ + int ret; \ + ret = fcntl((fd), F_GETFL, 0); \ + if (ret == -1 || fcntl((fd), F_SETFL, \ + ret & ~O_NONBLOCK) == -1) \ + { \ + /* errno should be set */ \ + return SM_IO_EOF; \ + } \ + (fp)->f_timeoutstate = SM_TIME_BLOCK; \ + if ((fp)->f_modefp != NULL) \ + (fp)->f_modefp->f_timeoutstate = SM_TIME_BLOCK; \ + } \ + } \ + else { \ + if ((fp)->f_timeoutstate == SM_TIME_BLOCK && (fd) != -1) \ + { \ + int ret; \ + ret = fcntl((fd), F_GETFL, 0); \ + if (ret == -1 || fcntl((fd), F_SETFL, \ + ret | O_NONBLOCK) == -1) \ + { \ + /* errno should be set */ \ + return SM_IO_EOF; \ + } \ + (fp)->f_timeoutstate = SM_TIME_NONBLOCK; \ + if ((fp)->f_modefp != NULL) \ + (fp)->f_modefp->f_timeoutstate = SM_TIME_NONBLOCK; \ + } \ + } \ +} + +/* +** SM_IO_WR_TIMEOUT -- setup the timeout for the write +** +** This #define uses a select() to wait for the 'fd' to become writable. +** The select() can be active for up to 'to' time. The select may not +** use all of the the 'to' time. Hence, the amount of "wall-clock" time is +** measured to decide how much to subtract from 'to' to update it. On some +** BSD-based/like systems the timeout for a select is updated for the +** amount of time used. On many/most systems this does not happen. Therefore +** the updating of 'to' must be done ourselves; a copy of 'to' is passed +** since a BSD-like system will have updated it and we don't want to +** double the time used! +** Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the +** sendmail buffered file type in sendmail/bf.c; see fvwrite.c). +** +** Parameters +** fd -- a file descriptor for doing select() with +** timeout -- the original user set value. +** +** Returns +** nothing, this is flow through code +** +** Side Effects: +** adjusts 'timeout' for time used +*/ + +#define SM_IO_WR_TIMEOUT(fp, fd, to) { \ + struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \ + struct timeval sm_io_to; \ + int sm_io_to_sel; \ + fd_set sm_io_to_mask, sm_io_x_mask; \ + errno = 0; \ + if ((to) == SM_TIME_DEFAULT) \ + (to) = (fp)->f_timeout; \ + if ((to) == SM_TIME_IMMEDIATE) \ + { \ + errno = EAGAIN; \ + return SM_IO_EOF; \ + } \ + else if ((to) == SM_TIME_FOREVER) \ + { \ + errno = EINVAL; \ + return SM_IO_EOF; \ + } \ + else \ + { \ + sm_io_to.tv_sec = (to) / 1000; \ + sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 10; \ + } \ + if (FD_SETSIZE > 0 && (fd) >= FD_SETSIZE) \ + { \ + errno = EINVAL; \ + return SM_IO_EOF; \ + } \ + FD_ZERO(&sm_io_to_mask); \ + FD_SET((fd), &sm_io_to_mask); \ + FD_ZERO(&sm_io_x_mask); \ + FD_SET((fd), &sm_io_x_mask); \ + if (gettimeofday(&sm_io_to_before, NULL) < 0) \ + return SM_IO_EOF; \ + sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, &sm_io_x_mask, \ + &sm_io_to); \ + if (sm_io_to_sel < 0) \ + { \ + /* something went wrong, errno set */ \ + return SM_IO_EOF; \ + } \ + else if (sm_io_to_sel == 0) \ + { \ + /* timeout */ \ + errno = EAGAIN; \ + return SM_IO_EOF; \ + } \ + /* else loop again */ \ + if (gettimeofday(&sm_io_to_after, NULL) < 0) \ + return SM_IO_EOF; \ + timersub(&sm_io_to_before, &sm_io_to_after, &sm_io_to_diff); \ + timersub(&sm_io_to, &sm_io_to_diff, &sm_io_to); \ + (to) -= (sm_io_to.tv_sec * 1000); \ + (to) -= (sm_io_to.tv_usec / 10); \ + if ((to) < 0) \ + (to) = 0; \ +} + +/* +** If there is no 'fd' just error (we can't timeout). If the timeout +** is SM_TIME_FOREVER then there is no need to do a timeout with +** select since this will be a real error. If the error is not +** EAGAIN/EWOULDBLOCK (from a nonblocking) then it's a real error. +** Specify the condition here as macro so it can be used in several places. +*/ + +#define IS_IO_ERROR(fd, ret, to) \ + ((fd) < 0 || \ + ((ret) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || \ + (to) == SM_TIME_FOREVER) + diff --git a/gnu/dist/sendmail/libsm/makebuf.c b/gnu/dist/sendmail/libsm/makebuf.c new file mode 100644 index 000000000000..2648a425d3bf --- /dev/null +++ b/gnu/dist/sendmail/libsm/makebuf.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: makebuf.c,v 1.26 2001/10/31 16:04:08 ca Exp") +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +/* +** SM_MAKEBUF -- make a buffer for the file +** +** Parameters: +** fp -- the file to be buffered +** +** Returns: +** nothing +** +** Allocate a file buffer, or switch to unbuffered I/O. +** By default tty devices default to line buffered. +*/ + +void +sm_makebuf(fp) + register SM_FILE_T *fp; +{ + register void *p; + register int flags; + size_t size; + int couldbetty; + + if (fp->f_flags & SMNBF) + { + fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; + fp->f_bf.smb_size = 1; + return; + } + flags = sm_whatbuf(fp, &size, &couldbetty); + if ((p = sm_malloc(size)) == NULL) + { + fp->f_flags |= SMNBF; + fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; + fp->f_bf.smb_size = 1; + return; + } + if (!Sm_IO_DidInit) + sm_init(); + flags |= SMMBF; + fp->f_bf.smb_base = fp->f_p = p; + fp->f_bf.smb_size = size; + if (couldbetty && isatty(fp->f_file)) + flags |= SMLBF; + fp->f_flags |= flags; +} + +/* +** SM_WHATBUF -- determine proper buffer for a file (internal) +** +** Plus it fills in 'bufsize' for recommended buffer size and +** fills in flag to indicate if 'fp' could be a tty (nothing +** to do with "betty" :-) ). +** +** Parameters: +** fp -- file pointer to be buffered +** bufsize -- new buffer size (a return) +** couldbetty -- could be a tty (returns) +** +** Returns: +** Success: +** on error: +** SMNPT -- not seek opimized +** SMOPT -- seek opimized +*/ + +int +sm_whatbuf(fp, bufsize, couldbetty) + register SM_FILE_T *fp; + size_t *bufsize; + int *couldbetty; +{ + struct stat st; + + if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) + { + *couldbetty = 0; + *bufsize = SM_IO_BUFSIZ; + return SMNPT; + } + + /* could be a tty iff it is a character device */ + *couldbetty = S_ISCHR(st.st_mode); + if (st.st_blksize == 0) + { + *bufsize = SM_IO_BUFSIZ; + return SMNPT; + } + +#if SM_IO_MAX_BUF_FILE > 0 + if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE) + st.st_blksize = SM_IO_MAX_BUF_FILE; +#endif /* SM_IO_MAX_BUF_FILE > 0 */ + +#if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 + if (!S_ISREG(st.st_mode)) + { +# if SM_IO_MAX_BUF > 0 + if (st.st_blksize > SM_IO_MAX_BUF) + st.st_blksize = SM_IO_MAX_BUF; +# if SM_IO_MIN_BUF > 0 + else +# endif /* SM_IO_MIN_BUF > 0 */ +# endif /* SM_IO_MAX_BUF > 0 */ +# if SM_IO_MIN_BUF > 0 + if (st.st_blksize < SM_IO_MIN_BUF) + st.st_blksize = SM_IO_MIN_BUF; +# endif /* SM_IO_MIN_BUF > 0 */ + } +#endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */ + + /* + ** Optimise fseek() only if it is a regular file. (The test for + ** sm_std_seek is mainly paranoia.) It is safe to set _blksize + ** unconditionally; it will only be used if SMOPT is also set. + */ + + if ((fp->f_flags & SMSTR) == 0) + { + *bufsize = st.st_blksize; + fp->f_blksize = st.st_blksize; + } + else + *bufsize = SM_IO_BUFSIZ; + if ((st.st_mode & S_IFMT) == S_IFREG && + fp->f_seek == sm_stdseek) + return SMOPT; + else + return SMNPT; +} diff --git a/gnu/dist/sendmail/libsm/match.c b/gnu/dist/sendmail/libsm/match.c new file mode 100644 index 000000000000..914f96ae2dd5 --- /dev/null +++ b/gnu/dist/sendmail/libsm/match.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: match.c,v 1.10 2001/09/11 04:04:48 gshapiro Exp") + +#include + +/* +** SM_MATCH -- Match a character string against a glob pattern. +** +** Parameters: +** str -- string. +** par -- pattern to find in str. +** +** Returns: +** true on match, false on non-match. +** +** A pattern consists of normal characters, which match themselves, +** and meta-sequences. A * matches any sequence of characters. +** A ? matches any single character. A [ introduces a character class. +** A ] marks the end of a character class; if the ] is missing then +** the [ matches itself rather than introducing a character class. +** A character class matches any of the characters between the brackets. +** The range of characters from X to Y inclusive is written X-Y. +** If the first character after the [ is ! then the character class is +** complemented. +** +** To include a ] in a character class, make it the first character +** listed (after the !, if any). To include a -, make it the first +** character listed (after the !, if any) or the last character. +** It is impossible for a ] to be the final character in a range. +** For glob patterns that literally match "*", "?" or "[", +** use [*], [?] or [[]. +*/ + +bool +sm_match(str, pat) + const char *str; + const char *pat; +{ + bool ccnot, ccmatch, ccfirst; + const char *ccstart; + char c, c2; + + for (;;) + { + switch (*pat) + { + case '\0': + return *str == '\0'; + case '?': + if (*str == '\0') + return false; + ++pat; + ++str; + continue; + case '*': + ++pat; + if (*pat == '\0') + { + /* optimize case of trailing '*' */ + return true; + } + for (;;) + { + if (sm_match(pat, str)) + return true; + if (*str == '\0') + return false; + ++str; + } + /* NOTREACHED */ + case '[': + ccstart = pat++; + ccnot = false; + if (*pat == '!') + { + ccnot = true; + ++pat; + } + ccmatch = false; + ccfirst = true; + for (;;) + { + if (*pat == '\0') + { + pat = ccstart; + goto defl; + } + if (*pat == ']' && !ccfirst) + break; + c = *pat++; + ccfirst = false; + if (*pat == '-' && pat[1] != ']') + { + ++pat; + if (*pat == '\0') + { + pat = ccstart; + goto defl; + } + c2 = *pat++; + if (*str >= c && *str <= c2) + ccmatch = true; + } + else + { + if (*str == c) + ccmatch = true; + } + } + if (ccmatch ^ ccnot) + { + ++pat; + ++str; + } + else + return false; + continue; + default: + defl: + if (*pat != *str) + return false; + ++pat; + ++str; + continue; + } + } +} diff --git a/gnu/dist/sendmail/libsm/mbdb.c b/gnu/dist/sendmail/libsm/mbdb.c new file mode 100644 index 000000000000..6f5bf1520d26 --- /dev/null +++ b/gnu/dist/sendmail/libsm/mbdb.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: mbdb.c,v 1.38.2.1 2002/11/20 22:59:06 gshapiro Exp") + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +# ifdef EX_OK +# undef EX_OK /* for SVr4.2 SMP */ +# endif /* EX_OK */ +#include + +#if LDAPMAP +# if _LDAP_EXAMPLE_ +# include +# endif /* _LDAP_EXAMPLE_ */ +#endif /* LDAPMAP */ + +typedef struct +{ + char *mbdb_typename; + int (*mbdb_initialize) __P((char *)); + int (*mbdb_lookup) __P((char *name, SM_MBDB_T *user)); + void (*mbdb_terminate) __P((void)); +} SM_MBDB_TYPE_T; + +static int mbdb_pw_initialize __P((char *)); +static int mbdb_pw_lookup __P((char *name, SM_MBDB_T *user)); +static void mbdb_pw_terminate __P((void)); + +#if LDAPMAP +# if _LDAP_EXAMPLE_ +static struct sm_ldap_struct LDAPLMAP; +static int mbdb_ldap_initialize __P((char *)); +static int mbdb_ldap_lookup __P((char *name, SM_MBDB_T *user)); +static void mbdb_ldap_terminate __P((void)); +# endif /* _LDAP_EXAMPLE_ */ +#endif /* LDAPMAP */ + +static SM_MBDB_TYPE_T SmMbdbTypes[] = +{ + { "pw", mbdb_pw_initialize, mbdb_pw_lookup, mbdb_pw_terminate }, +#if LDAPMAP +# if _LDAP_EXAMPLE_ + { "ldap", mbdb_ldap_initialize, mbdb_ldap_lookup, mbdb_ldap_terminate }, +# endif /* _LDAP_EXAMPLE_ */ +#endif /* LDAPMAP */ + { NULL, NULL, NULL, NULL } +}; + +static SM_MBDB_TYPE_T *SmMbdbType = &SmMbdbTypes[0]; + +/* +** SM_MBDB_INITIALIZE -- specify which mailbox database to use +** +** If this function is not called, then the "pw" implementation +** is used by default; this implementation uses getpwnam(). +** +** Parameters: +** mbdb -- Which mailbox database to use. +** The argument has the form "name" or "name.arg". +** "pw" means use getpwnam(). +** +** Results: +** EX_OK on success, or an EX_* code on failure. +*/ + +int +sm_mbdb_initialize(mbdb) + char *mbdb; +{ + size_t namelen; + int err; + char *name; + char *arg; + SM_MBDB_TYPE_T *t; + + SM_REQUIRE(mbdb != NULL); + + name = mbdb; + arg = strchr(mbdb, '.'); + if (arg == NULL) + namelen = strlen(name); + else + { + namelen = arg - name; + ++arg; + } + + for (t = SmMbdbTypes; t->mbdb_typename != NULL; ++t) + { + if (strlen(t->mbdb_typename) == namelen && + strncmp(name, t->mbdb_typename, namelen) == 0) + { + err = EX_OK; + if (t->mbdb_initialize != NULL) + err = t->mbdb_initialize(arg); + if (err == EX_OK) + SmMbdbType = t; + return err; + } + } + return EX_UNAVAILABLE; +} + +/* +** SM_MBDB_TERMINATE -- terminate connection to the mailbox database +** +** Because this function closes any cached file descriptors that +** are being held open for the connection to the mailbox database, +** it should be called for security reasons prior to dropping privileges +** and execing another process. +** +** Parameters: +** none. +** +** Results: +** none. +*/ + +void +sm_mbdb_terminate() +{ + if (SmMbdbType->mbdb_terminate != NULL) + SmMbdbType->mbdb_terminate(); +} + +/* +** SM_MBDB_LOOKUP -- look up a local mail recipient, given name +** +** Parameters: +** name -- name of local mail recipient +** user -- pointer to structure to fill in on success +** +** Results: +** On success, fill in *user and return EX_OK. +** If the user does not exist, return EX_NOUSER. +** If a temporary failure (eg, a network failure) occurred, +** return EX_TEMPFAIL. Otherwise return EX_OSERR. +*/ + +int +sm_mbdb_lookup(name, user) + char *name; + SM_MBDB_T *user; +{ + int ret = EX_NOUSER; + + if (SmMbdbType->mbdb_lookup != NULL) + ret = SmMbdbType->mbdb_lookup(name, user); + return ret; +} + +/* +** SM_MBDB_FROMPW -- copy from struct pw to SM_MBDB_T +** +** Parameters: +** user -- destination user information structure +** pw -- source passwd structure +** +** Results: +** none. +*/ + +void +sm_mbdb_frompw(user, pw) + SM_MBDB_T *user; + struct passwd *pw; +{ + SM_REQUIRE(user != NULL); + (void) sm_strlcpy(user->mbdb_name, pw->pw_name, + sizeof(user->mbdb_name)); + user->mbdb_uid = pw->pw_uid; + user->mbdb_gid = pw->pw_gid; + sm_pwfullname(pw->pw_gecos, pw->pw_name, user->mbdb_fullname, + sizeof(user->mbdb_fullname)); + (void) sm_strlcpy(user->mbdb_homedir, pw->pw_dir, + sizeof(user->mbdb_homedir)); + (void) sm_strlcpy(user->mbdb_shell, pw->pw_shell, + sizeof(user->mbdb_shell)); +} + +/* +** SM_PWFULLNAME -- build full name of user from pw_gecos field. +** +** This routine interprets the strange entry that would appear +** in the GECOS field of the password file. +** +** Parameters: +** gecos -- name to build. +** user -- the login name of this user (for &). +** buf -- place to put the result. +** buflen -- length of buf. +** +** Returns: +** none. +*/ + +#if _FFR_HANDLE_ISO8859_GECOS +static char Latin1ToASCII[128] = +{ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, + 99, 80, 36, 89, 124, 36, 34, 99, 97, 60, 45, 45, 114, 45, 111, 42, + 50, 51, 39, 117, 80, 46, 44, 49, 111, 62, 42, 42, 42, 63, 65, 65, + 65, 65, 65, 65, 65, 67, 69, 69, 69, 69, 73, 73, 73, 73, 68, 78, 79, + 79, 79, 79, 79, 88, 79, 85, 85, 85, 85, 89, 80, 66, 97, 97, 97, 97, + 97, 97, 97, 99, 101, 101, 101, 101, 105, 105, 105, 105, 100, 110, + 111, 111, 111, 111, 111, 47, 111, 117, 117, 117, 117, 121, 112, 121 +}; +#endif /* _FFR_HANDLE_ISO8859_GECOS */ + +void +sm_pwfullname(gecos, user, buf, buflen) + register char *gecos; + char *user; + char *buf; + size_t buflen; +{ + register char *p; + register char *bp = buf; + + if (*gecos == '*') + gecos++; + + /* copy gecos, interpolating & to be full name */ + for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++) + { + if (bp >= &buf[buflen - 1]) + { + /* buffer overflow -- just use login name */ + (void) sm_strlcpy(buf, user, buflen); + return; + } + if (*p == '&') + { + /* interpolate full name */ + (void) sm_strlcpy(bp, user, buflen - (bp - buf)); + *bp = toupper(*bp); + bp += strlen(bp); + } + else + { +#if _FFR_HANDLE_ISO8859_GECOS + if ((unsigned char) *p >= 128) + *bp++ = Latin1ToASCII[(unsigned char) *p - 128]; + else +#endif /* _FFR_HANDLE_ISO8859_GECOS */ + *bp++ = *p; + } + } + *bp = '\0'; +} + +/* +** /etc/passwd implementation. +*/ + +/* +** MBDB_PW_INITIALIZE -- initialize getpwnam() version +** +** Parameters: +** arg -- unused. +** +** Results: +** EX_OK. +*/ + +/* ARGSUSED0 */ +static int +mbdb_pw_initialize(arg) + char *arg; +{ + return EX_OK; +} + +/* +** MBDB_PW_LOOKUP -- look up a local mail recipient, given name +** +** Parameters: +** name -- name of local mail recipient +** user -- pointer to structure to fill in on success +** +** Results: +** On success, fill in *user and return EX_OK. +** Failure: EX_NOUSER. +*/ + +static int +mbdb_pw_lookup(name, user) + char *name; + SM_MBDB_T *user; +{ + struct passwd *pw; + +#ifdef HESIOD + /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */ + { + char *p; + + for (p = name; *p != '\0'; p++) + if (!isascii(*p) || !isdigit(*p)) + break; + if (*p == '\0') + return EX_NOUSER; + } +#endif /* HESIOD */ + + errno = 0; + pw = getpwnam(name); + if (pw == NULL) + { +#if 0 + /* + ** getpwnam() isn't advertised as setting errno. + ** In fact, under FreeBSD, non-root getpwnam() on + ** non-existant users returns NULL with errno = EPERM. + ** This test won't work. + */ + switch (errno) + { + case 0: + return EX_NOUSER; + case EIO: + return EX_OSERR; + default: + return EX_TEMPFAIL; + } +#endif /* 0 */ + return EX_NOUSER; + } + + sm_mbdb_frompw(user, pw); + return EX_OK; +} + +/* +** MBDB_PW_TERMINATE -- terminate connection to the mailbox database +** +** Parameters: +** none. +** +** Results: +** none. +*/ + +static void +mbdb_pw_terminate() +{ + endpwent(); +} + +#if LDAPMAP +# if _LDAP_EXAMPLE_ +/* +** LDAP example implementation based on RFC 2307, "An Approach for Using +** LDAP as a Network Information Service": +** +** ( nisSchema.1.0 NAME 'uidNumber' +** DESC 'An integer uniquely identifying a user in an +** administrative domain' +** EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE ) +** +** ( nisSchema.1.1 NAME 'gidNumber' +** DESC 'An integer uniquely identifying a group in an +** administrative domain' +** EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE ) +** +** ( nisSchema.1.2 NAME 'gecos' +** DESC 'The GECOS field; the common name' +** EQUALITY caseIgnoreIA5Match +** SUBSTRINGS caseIgnoreIA5SubstringsMatch +** SYNTAX 'IA5String' SINGLE-VALUE ) +** +** ( nisSchema.1.3 NAME 'homeDirectory' +** DESC 'The absolute path to the home directory' +** EQUALITY caseExactIA5Match +** SYNTAX 'IA5String' SINGLE-VALUE ) +** +** ( nisSchema.1.4 NAME 'loginShell' +** DESC 'The path to the login shell' +** EQUALITY caseExactIA5Match +** SYNTAX 'IA5String' SINGLE-VALUE ) +** +** ( nisSchema.2.0 NAME 'posixAccount' SUP top AUXILIARY +** DESC 'Abstraction of an account with POSIX attributes' +** MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) +** MAY ( userPassword $ loginShell $ gecos $ description ) ) +** +*/ + +# define MBDB_LDAP_LABEL "MailboxDatabase" + +# ifndef MBDB_LDAP_FILTER +# define MBDB_LDAP_FILTER "(&(objectClass=posixAccount)(uid=%0))" +# endif /* MBDB_LDAP_FILTER */ + +# ifndef MBDB_DEFAULT_LDAP_BASEDN +# define MBDB_DEFAULT_LDAP_BASEDN NULL +# endif /* MBDB_DEFAULT_LDAP_BASEDN */ + +# ifndef MBDB_DEFAULT_LDAP_SERVER +# define MBDB_DEFAULT_LDAP_SERVER NULL +# endif /* MBDB_DEFAULT_LDAP_SERVER */ + +/* +** MBDB_LDAP_INITIALIZE -- initialize LDAP version +** +** Parameters: +** arg -- LDAP specification +** +** Results: +** EX_OK on success, or an EX_* code on failure. +*/ + +static int +mbdb_ldap_initialize(arg) + char *arg; +{ + sm_ldap_clear(&LDAPLMAP); + LDAPLMAP.ldap_base = MBDB_DEFAULT_LDAP_BASEDN; + LDAPLMAP.ldap_target = MBDB_DEFAULT_LDAP_SERVER; + LDAPLMAP.ldap_filter = MBDB_LDAP_FILTER; + + /* Only want one match */ + LDAPLMAP.ldap_sizelimit = 1; + + /* interpolate new ldap_base and ldap_target from arg if given */ + if (arg != NULL && *arg != '\0') + { + char *new; + char *sep; + size_t len; + + len = strlen(arg) + 1; + new = sm_malloc(len); + if (new == NULL) + return EX_TEMPFAIL; + (void) sm_strlcpy(new, arg, len); + sep = strrchr(new, '@'); + if (sep != NULL) + { + *sep++ = '\0'; + LDAPLMAP.ldap_target = sep; + } + LDAPLMAP.ldap_base = new; + } + return EX_OK; +} + + +/* +** MBDB_LDAP_LOOKUP -- look up a local mail recipient, given name +** +** Parameters: +** name -- name of local mail recipient +** user -- pointer to structure to fill in on success +** +** Results: +** On success, fill in *user and return EX_OK. +** Failure: EX_NOUSER. +*/ + +#define NEED_FULLNAME 0x01 +#define NEED_HOMEDIR 0x02 +#define NEED_SHELL 0x04 +#define NEED_UID 0x08 +#define NEED_GID 0x10 + +static int +mbdb_ldap_lookup(name, user) + char *name; + SM_MBDB_T *user; +{ + int msgid; + int need; + int ret; + int save_errno; + LDAPMessage *entry; + BerElement *ber; + char *attr = NULL; + + if (strlen(name) >= sizeof(user->mbdb_name)) + { + errno = EINVAL; + return EX_NOUSER; + } + + if (LDAPLMAP.ldap_filter == NULL) + { + /* map not initialized, but don't have arg here */ + errno = EFAULT; + return EX_TEMPFAIL; + } + + if (LDAPLMAP.ldap_pid != getpid()) + { + /* re-open map in this child process */ + LDAPLMAP.ldap_ld = NULL; + } + + if (LDAPLMAP.ldap_ld == NULL) + { + /* map not open, try to open now */ + if (!sm_ldap_start(MBDB_LDAP_LABEL, &LDAPLMAP)) + return EX_TEMPFAIL; + } + + sm_ldap_setopts(LDAPLMAP.ldap_ld, &LDAPLMAP); + msgid = sm_ldap_search(&LDAPLMAP, name); + if (msgid == -1) + { + save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld) + E_LDAPBASE; +# ifdef LDAP_SERVER_DOWN + if (errno == LDAP_SERVER_DOWN) + { + /* server disappeared, try reopen on next search */ + sm_ldap_close(&LDAPLMAP); + } +# endif /* LDAP_SERVER_DOWN */ + errno = save_errno; + return EX_TEMPFAIL; + } + + /* Get results */ + ret = ldap_result(LDAPLMAP.ldap_ld, msgid, 1, + (LDAPLMAP.ldap_timeout.tv_sec == 0 ? NULL : + &(LDAPLMAP.ldap_timeout)), + &(LDAPLMAP.ldap_res)); + + if (ret != LDAP_RES_SEARCH_RESULT && + ret != LDAP_RES_SEARCH_ENTRY) + { + if (ret == 0) + errno = ETIMEDOUT; + else + errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); + ret = EX_TEMPFAIL; + goto abort; + } + + entry = ldap_first_entry(LDAPLMAP.ldap_ld, LDAPLMAP.ldap_res); + if (entry == NULL) + { + save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); + if (save_errno == LDAP_SUCCESS) + { + errno = ENOENT; + ret = EX_NOUSER; + } + else + { + errno = save_errno; + ret = EX_TEMPFAIL; + } + goto abort; + } + +# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) + /* + ** Reset value to prevent lingering + ** LDAP_DECODING_ERROR due to + ** OpenLDAP 1.X's hack (see below) + */ + + LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS; +# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ + + ret = EX_OK; + need = NEED_FULLNAME|NEED_HOMEDIR|NEED_SHELL|NEED_UID|NEED_GID; + for (attr = ldap_first_attribute(LDAPLMAP.ldap_ld, entry, &ber); + attr != NULL; + attr = ldap_next_attribute(LDAPLMAP.ldap_ld, entry, ber)) + { + char **vals; + + vals = ldap_get_values(LDAPLMAP.ldap_ld, entry, attr); + if (vals == NULL) + { + errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); + if (errno == LDAP_SUCCESS) + { + ldap_memfree(attr); + continue; + } + + /* Must be an error */ + errno += E_LDAPBASE; + ret = EX_TEMPFAIL; + goto abort; + } + +# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) + /* + ** Reset value to prevent lingering + ** LDAP_DECODING_ERROR due to + ** OpenLDAP 1.X's hack (see below) + */ + + LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS; +# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ + + if (vals[0] == NULL || vals[0][0] == '\0') + goto skip; + + if (strcasecmp(attr, "gecos") == 0) + { + if (!bitset(NEED_FULLNAME, need) || + strlen(vals[0]) >= sizeof(user->mbdb_fullname)) + goto skip; + + sm_pwfullname(vals[0], name, user->mbdb_fullname, + sizeof(user->mbdb_fullname)); + need &= ~NEED_FULLNAME; + } + else if (strcasecmp(attr, "homeDirectory") == 0) + { + if (!bitset(NEED_HOMEDIR, need) || + strlen(vals[0]) >= sizeof(user->mbdb_homedir)) + goto skip; + + (void) sm_strlcpy(user->mbdb_homedir, vals[0], + sizeof(user->mbdb_homedir)); + need &= ~NEED_HOMEDIR; + } + else if (strcasecmp(attr, "loginShell") == 0) + { + if (!bitset(NEED_SHELL, need) || + strlen(vals[0]) >= sizeof(user->mbdb_shell)) + goto skip; + + (void) sm_strlcpy(user->mbdb_shell, vals[0], + sizeof(user->mbdb_shell)); + need &= ~NEED_SHELL; + } + else if (strcasecmp(attr, "uidNumber") == 0) + { + char *p; + + if (!bitset(NEED_UID, need)) + goto skip; + + for (p = vals[0]; *p != '\0'; p++) + { + /* allow negative numbers */ + if (p == vals[0] && *p == '-') + { + /* but not simply '-' */ + if (*(p + 1) == '\0') + goto skip; + } + else if (!isascii(*p) || !isdigit(*p)) + goto skip; + } + user->mbdb_uid = atoi(vals[0]); + need &= ~NEED_UID; + } + else if (strcasecmp(attr, "gidNumber") == 0) + { + char *p; + + if (!bitset(NEED_GID, need)) + goto skip; + + for (p = vals[0]; *p != '\0'; p++) + { + /* allow negative numbers */ + if (p == vals[0] && *p == '-') + { + /* but not simply '-' */ + if (*(p + 1) == '\0') + goto skip; + } + else if (!isascii(*p) || !isdigit(*p)) + goto skip; + } + user->mbdb_gid = atoi(vals[0]); + need &= ~NEED_GID; + } + +skip: + ldap_value_free(vals); + ldap_memfree(attr); + } + + errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); + + /* + ** We check errno != LDAP_DECODING_ERROR since + ** OpenLDAP 1.X has a very ugly *undocumented* + ** hack of returning this error code from + ** ldap_next_attribute() if the library freed the + ** ber attribute. See: + ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html + */ + + if (errno != LDAP_SUCCESS && + errno != LDAP_DECODING_ERROR) + { + /* Must be an error */ + errno += E_LDAPBASE; + ret = EX_TEMPFAIL; + goto abort; + } + + abort: + save_errno = errno; + if (attr != NULL) + { + ldap_memfree(attr); + attr = NULL; + } + if (LDAPLMAP.ldap_res != NULL) + { + ldap_msgfree(LDAPLMAP.ldap_res); + LDAPLMAP.ldap_res = NULL; + } + if (ret == EX_OK) + { + if (need == 0) + { + (void) sm_strlcpy(user->mbdb_name, name, + sizeof(user->mbdb_name)); + save_errno = 0; + } + else + { + ret = EX_NOUSER; + save_errno = EINVAL; + } + } + errno = save_errno; + return ret; +} + +/* +** MBDB_LDAP_TERMINATE -- terminate connection to the mailbox database +** +** Parameters: +** none. +** +** Results: +** none. +*/ + +static void +mbdb_ldap_terminate() +{ + sm_ldap_close(&LDAPLMAP); +} +# endif /* _LDAP_EXAMPLE_ */ +#endif /* LDAPMAP */ diff --git a/gnu/dist/sendmail/libsm/mpeix.c b/gnu/dist/sendmail/libsm/mpeix.c new file mode 100644 index 000000000000..c9d7f36f6433 --- /dev/null +++ b/gnu/dist/sendmail/libsm/mpeix.c @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: mpeix.c,v 1.6 2002/05/24 20:50:14 gshapiro Exp") + +#ifdef MPE +/* +** MPE lacks many common functions required across all sendmail programs +** so we define implementations for these functions here. +*/ + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +/* +** CHROOT -- dummy chroot() function +** +** The MPE documentation for sendmail says that chroot-based +** functionality is not implemented because MPE lacks chroot. But +** rather than mucking around with all the sendmail calls to chroot, +** we define this dummy function to return an ENOSYS failure just in +** case a sendmail user attempts to enable chroot-based functionality. +** +** Parameters: +** path -- pathname of new root (ignored). +** +** Returns: +** -1 and errno == ENOSYS (function not implemented) +*/ + +int +chroot(path) + char *path; +{ + errno = ENOSYS; + return -1; +} + +/* +** ENDPWENT -- dummy endpwent() function +** +** Parameters: +** none +** +** Returns: +** none +*/ + +void +endpwent() +{ + return; +} + +/* +** In addition to missing functions, certain existing MPE functions have +** slightly different semantics (or bugs) compared to normal Unix OSes. +** +** Here we define wrappers for these functions to make them behave in the +** manner expected by sendmail. +*/ + +/* +** SENDMAIL_MPE_BIND -- shadow function for the standard socket bind() +** +** MPE requires GETPRIVMODE() for AF_INET sockets less than port 1024. +** +** Parameters: +** sd -- socket descriptor. +** addr -- socket address. +** addrlen -- length of socket address. +** +** Results: +** 0 -- success +** != 0 -- failure +*/ + +#undef bind +int +sendmail_mpe_bind(sd, addr, addrlen) + int sd; + void *addr; + int addrlen; +{ + bool priv = false; + int result; + extern void GETPRIVMODE __P((void)); + extern void GETUSERMODE __P((void)); + + if (addrlen == sizeof(struct sockaddr_in) && + ((struct sockaddr_in *)addr)->sin_family == AF_INET) + { + /* AF_INET */ + if (((struct sockaddr_in *)addr)->sin_port > 0 && + ((struct sockaddr_in *)addr)->sin_port < 1024) + { + priv = true; + GETPRIVMODE(); + } + ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; + result = bind(sd, addr, addrlen); + if (priv) + GETUSERMODE(); + return result; + } + + /* AF_UNIX */ + return bind(sd, addr, addrlen); +} + +/* +** SENDMAIL_MPE__EXIT -- wait for children to terminate, then _exit() +** +** Child processes cannot survive the death of their parent on MPE, so +** we must call wait() before _exit() in order to prevent this +** infanticide. +** +** Parameters: +** status -- _exit status value. +** +** Returns: +** none. +*/ + +#undef _exit +void +sendmail_mpe__exit(status) + int status; +{ + int result; + + /* Wait for all children to terminate. */ + do + { + result = wait(NULL); + } while (result > 0 || errno == EINTR); + _exit(status); +} + +/* +** SENDMAIL_MPE_EXIT -- wait for children to terminate, then exit() +** +** Child processes cannot survive the death of their parent on MPE, so +** we must call wait() before exit() in order to prevent this +** infanticide. +** +** Parameters: +** status -- exit status value. +** +** Returns: +** none. +*/ + +#undef exit +void +sendmail_mpe_exit(status) + int status; +{ + int result; + + /* Wait for all children to terminate. */ + do + { + result = wait(NULL); + } while (result > 0 || errno == EINTR); + exit(status); +} + +/* +** SENDMAIL_MPE_FCNTL -- shadow function for fcntl() +** +** MPE requires sfcntl() for sockets, and fcntl() for everything +** else. This shadow routine determines the descriptor type and +** makes the appropriate call. +** +** Parameters: +** same as fcntl(). +** +** Returns: +** same as fcntl(). +*/ + +#undef fcntl +int +sendmail_mpe_fcntl(int fildes, int cmd, ...) +{ + int len, result; + struct sockaddr sa; + + void *arg; + va_list ap; + + va_start(ap, cmd); + arg = va_arg(ap, void *); + va_end(ap); + + len = sizeof sa; + if (getsockname(fildes, &sa, &len) == -1) + { + if (errno == EAFNOSUPPORT) + { + /* AF_UNIX socket */ + return sfcntl(fildes, cmd, arg); + } + else if (errno == ENOTSOCK) + { + /* file or pipe */ + return fcntl(fildes, cmd, arg); + } + + /* unknown getsockname() failure */ + return (-1); + } + else + { + /* AF_INET socket */ + if ((result = sfcntl(fildes, cmd, arg)) != -1 && + cmd == F_GETFL) + result |= O_RDWR; /* fill in some missing flags */ + return result; + } +} + +/* +** SENDMAIL_MPE_GETPWNAM - shadow function for getpwnam() +** +** Several issues apply here: +** +** - MPE user names MUST have one '.' separator character +** - MPE user names MUST be in upper case +** - MPE does not initialize all fields in the passwd struct +** +** Parameters: +** name -- username string. +** +** Returns: +** pointer to struct passwd if found else NULL +*/ + +static char *sendmail_mpe_nullstr = ""; + +#undef getpwnam +extern struct passwd *getpwnam(const char *); + +struct passwd * +sendmail_mpe_getpwnam(name) + const char *name; +{ + int dots = 0; + int err; + int i = strlen(name); + char *upper; + struct passwd *result = NULL; + + if (i <= 0) + { + errno = EINVAL; + return result; + } + + if ((upper = (char *)malloc(i + 1)) != NULL) + { + /* upshift the username parameter and count the dots */ + while (i >= 0) + { + if (name[i] == '.') + { + dots++; + upper[i] = '.'; + } + else + upper[i] = toupper(name[i]); + i--; + } + + if (dots != 1) + { + /* prevent bug when dots == 0 */ + err = EINVAL; + } + else if ((result = getpwnam(upper)) != NULL) + { + /* init the uninitialized fields */ + result->pw_gecos = sendmail_mpe_nullstr; + result->pw_passwd = sendmail_mpe_nullstr; + result->pw_age = sendmail_mpe_nullstr; + result->pw_comment = sendmail_mpe_nullstr; + result->pw_audid = 0; + result->pw_audflg = 0; + } + err = errno; + free(upper); + } + errno = err; + return result; +} + +/* +** SENDMAIL_MPE_GETPWUID -- shadow function for getpwuid() +** +** Initializes the uninitalized fields in the passwd struct. +** +** Parameters: +** uid -- uid to obtain passwd data for +** +** Returns: +** pointer to struct passwd or NULL if not found +*/ + +#undef getpwuid +extern struct passwd *getpwuid __P((uid_t)); + +struct passwd * +sendmail_mpe_getpwuid(uid) + uid_t uid; +{ + struct passwd *result; + + if ((result = getpwuid(uid)) != NULL) + { + /* initialize the uninitialized fields */ + result->pw_gecos = sendmail_mpe_nullstr; + result->pw_passwd = sendmail_mpe_nullstr; + result->pw_age = sendmail_mpe_nullstr; + result->pw_comment = sendmail_mpe_nullstr; + result->pw_audid = 0; + result->pw_audflg = 0; + } + return result; +} + +/* +** OK boys and girls, time for some serious voodoo! +** +** MPE does not have a complete implementation of POSIX users and groups: +** +** - there is no uid 0 superuser +** - setuid/setgid file permission bits exist but have no-op functionality +** - setgid() exists, but only supports new gid == current gid (boring!) +** - setuid() forces a gid change to the new uid's primary (and only) gid +** +** ...all of which thoroughly annoys sendmail. +** +** So what to do? We can't go on an #ifdef MPE rampage throughout +** sendmail, because there are only about a zillion references to uid 0 +** and so success (and security) would probably be rather dubious by the +** time we finished. +** +** Instead we take the approach of defining wrapper functions for the +** gid/uid management functions getegid(), geteuid(), setgid(), and +** setuid() in order to implement the following model: +** +** - the sendmail program thinks it is a setuid-root (uid 0) program +** - uid 0 is recognized as being valid, but does not grant extra powers +** - MPE priv mode allows sendmail to call setuid(), not uid 0 +** - file access is still controlled by the real non-zero uid +** - the other programs (vacation, etc) have standard MPE POSIX behavior +** +** This emulation model is activated by use of the program file setgid and +** setuid mode bits which exist but are unused by MPE. If the setgid mode +** bit is on, then gid emulation will be enabled. If the setuid mode bit is +** on, then uid emulation will be enabled. So for the mail daemon, we need +** to do chmod u+s,g+s /SENDMAIL/CURRENT/SENDMAIL. +** +** The following flags determine the current emulation state: +** +** true == emulation enabled +** false == emulation disabled, use unmodified MPE semantics +*/ + +static bool sendmail_mpe_flaginit = false; +static bool sendmail_mpe_gidflag = false; +static bool sendmail_mpe_uidflag = false; + +/* +** SENDMAIL_MPE_GETMODE -- return the mode bits for the current process +** +** Parameters: +** none. +** +** Returns: +** file mode bits for the current process program file. +*/ + +mode_t +sendmail_mpe_getmode() +{ + int status = 666; + int myprogram_length; + int myprogram_syntax = 2; + char formaldesig[28]; + char myprogram[PATH_MAX + 2]; + char path[PATH_MAX + 1]; + struct stat st; + extern HPMYPROGRAM __P((int parms, char *formaldesig, int *status, + int *length, char *myprogram, + int *myprogram_length, int *myprogram_syntax)); + + myprogram_length = sizeof(myprogram); + HPMYPROGRAM(6, formaldesig, &status, NULL, myprogram, + &myprogram_length, &myprogram_syntax); + + /* should not occur, do not attempt emulation */ + if (status != 0) + return 0; + + memcpy(&path, &myprogram[1], myprogram_length - 2); + path[myprogram_length - 2] = '\0'; + + /* should not occur, do not attempt emulation */ + if (stat(path, &st) < 0) + return 0; + + return st.st_mode; +} + +/* +** SENDMAIL_MPE_EMULGID -- should we perform gid emulation? +** +** If !sendmail_mpe_flaginit then obtain the mode bits to determine +** if the setgid bit is on, we want gid emulation and so set +** sendmail_mpe_gidflag to true. Otherwise we do not want gid emulation +** and so set sendmail_mpe_gidflag to false. +** +** Parameters: +** none. +** +** Returns: +** true -- perform gid emulation +** false -- do not perform gid emulation +*/ + +bool +sendmail_mpe_emulgid() +{ + if (!sendmail_mpe_flaginit) + { + mode_t mode; + + mode = sendmail_mpe_getmode(); + sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID); + sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID); + sendmail_mpe_flaginit = true; + } + return sendmail_mpe_gidflag; +} + +/* +** SENDMAIL_MPE_EMULUID -- should we perform uid emulation? +** +** If sendmail_mpe_uidflag == -1 then obtain the mode bits to determine +** if the setuid bit is on, we want uid emulation and so set +** sendmail_mpe_uidflag to true. Otherwise we do not want uid emulation +** and so set sendmail_mpe_uidflag to false. +** +** Parameters: +** none. +** +** Returns: +** true -- perform uid emulation +** false -- do not perform uid emulation +*/ + +bool +sendmail_mpe_emuluid() +{ + if (!sendmail_mpe_flaginit) + { + mode_t mode; + + mode = sendmail_mpe_getmode(); + sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID); + sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID); + sendmail_mpe_flaginit = true; + } + return sendmail_mpe_uidflag; +} + +/* +** SENDMAIL_MPE_GETEGID -- shadow function for getegid() +** +** If emulation mode is in effect and the saved egid has been +** initialized, return the saved egid; otherwise return the value of the +** real getegid() function. +** +** Parameters: +** none. +** +** Returns: +** emulated egid if present, else true egid. +*/ + +static uid_t sendmail_mpe_egid = -1; + +#undef getegid +gid_t +sendmail_mpe_getegid() +{ + if (sendmail_mpe_emulgid() && sendmail_mpe_egid != -1) + return sendmail_mpe_egid; + return getegid(); +} + +/* +** SENDMAIL_MPE_GETEUID -- shadow function for geteuid() +** +** If emulation mode is in effect, return the saved euid; otherwise +** return the value of the real geteuid() function. +** +** Note that the initial value of the saved euid is zero, to simulate +** a setuid-root program. +** +** Parameters: +** none +** +** Returns: +** emulated euid if in emulation mode, else true euid. +*/ + +static uid_t sendmail_mpe_euid = 0; + +#undef geteuid +uid_t +sendmail_mpe_geteuid() +{ + if (sendmail_mpe_emuluid()) + return sendmail_mpe_euid; + return geteuid(); +} + +/* +** SENDMAIL_MPE_SETGID -- shadow function for setgid() +** +** Simulate a call to setgid() without actually calling the real +** function. Implement the expected uid 0 semantics. +** +** Note that sendmail will also be calling setuid() which will force an +** implicit real setgid() to the proper primary gid. So it doesn't matter +** that we don't actually alter the real gid in this shadow function. +** +** Parameters: +** gid -- desired gid. +** +** Returns: +** 0 -- emulated success +** -1 -- emulated failure +*/ + +#undef setgid +int +sendmail_mpe_setgid(gid) + gid_t gid; +{ + if (sendmail_mpe_emulgid()) + { + if (gid == getgid() || sendmail_mpe_euid == 0) + { + sendmail_mpe_egid = gid; + return 0; + } + errno = EINVAL; + return -1; + } + return setgid(gid); +} + +/* +** SENDMAIL_MPE_SETUID -- shadow function for setuid() +** +** setuid() is broken as of MPE 7.0 in that it changes the current +** working directory to be the home directory of the new uid. Thus +** we must obtain the cwd and restore it after the setuid(). +** +** Note that expected uid 0 semantics have been added, as well as +** remembering the new uid for later use by the other shadow functions. +** +** Parameters: +** uid -- desired uid. +** +** Returns: +** 0 -- success +** -1 -- failure +** +** Globals: +** sendmail_mpe_euid +*/ + +#undef setuid +int +sendmail_mpe_setuid(uid) + uid_t uid; +{ + char *cwd; + char cwd_buf[PATH_MAX + 1]; + int result; + extern void GETPRIVMODE __P((void)); + extern void GETUSERMODE __P((void)); + + if (sendmail_mpe_emuluid()) + { + if (uid == 0) + { + if (sendmail_mpe_euid != 0) + { + errno = EINVAL; + return -1; + } + sendmail_mpe_euid = 0; + return 0; + } + + /* Preserve the current working directory */ + if ((cwd = getcwd(cwd_buf, PATH_MAX + 1)) == NULL) + return -1; + + GETPRIVMODE(); + result = setuid(uid); + GETUSERMODE(); + + /* Restore the current working directory */ + chdir(cwd_buf); + + if (result == 0) + sendmail_mpe_euid = uid; + + return result; + } + return setuid(uid); +} +#endif /* MPE */ diff --git a/gnu/dist/sendmail/libsm/niprop.c b/gnu/dist/sendmail/libsm/niprop.c new file mode 100644 index 000000000000..b73482e4cd10 --- /dev/null +++ b/gnu/dist/sendmail/libsm/niprop.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: niprop.c,v 1.8 2001/09/11 04:04:48 gshapiro Exp") + +#if NETINFO +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** NI_PROPVAL -- NetInfo property value lookup routine +** +** Parameters: +** keydir -- the NetInfo directory name in which to search +** for the key. +** keyprop -- the name of the property in which to find the +** property we are interested. Defaults to "name". +** keyval -- the value for which we are really searching. +** valprop -- the property name for the value in which we +** are interested. +** sepchar -- if non-nil, this can be multiple-valued, and +** we should return a string separated by this +** character. +** +** Returns: +** NULL -- if: +** 1. the directory is not found +** 2. the property name is not found +** 3. the property contains multiple values +** 4. some error occurred +** else -- the value of the lookup. +** +** Example: +** To search for an alias value, use: +** ni_propval("/aliases", "name", aliasname, "members", ',') +** +** Notes: +** Caller should free the return value of ni_proval +*/ + +# include + +# define LOCAL_NETINFO_DOMAIN "." +# define PARENT_NETINFO_DOMAIN ".." +# define MAX_NI_LEVELS 256 + +char * +ni_propval(keydir, keyprop, keyval, valprop, sepchar) + char *keydir; + char *keyprop; + char *keyval; + char *valprop; + int sepchar; +{ + char *propval = NULL; + int i; + int j, alen, l; + void *ni = NULL; + void *lastni = NULL; + ni_status nis; + ni_id nid; + ni_namelist ninl; + register char *p; + char keybuf[1024]; + + /* + ** Create the full key from the two parts. + ** + ** Note that directory can end with, e.g., "name=" to specify + ** an alternate search property. + */ + + i = strlen(keydir) + strlen(keyval) + 2; + if (keyprop != NULL) + i += strlen(keyprop) + 1; + if (i >= sizeof keybuf) + return NULL; + (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, keydir, "/"); + if (keyprop != NULL) + { + (void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf); + } + (void) sm_strlcat(keybuf, keyval, sizeof keybuf); + +#if 0 + if (tTd(38, 21)) + sm_dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", + keydir, keyprop, keyval, valprop, sepchar, keybuf); +#endif /* 0 */ + + /* + ** If the passed directory and property name are found + ** in one of netinfo domains we need to search (starting + ** from the local domain moving all the way back to the + ** root domain) set propval to the property's value + ** and return it. + */ + + for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) + { + if (i == 0) + { + nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); +#if 0 + if (tTd(38, 20)) + sm_dprintf("ni_open(LOCAL) = %d\n", nis); +#endif /* 0 */ + } + else + { + if (lastni != NULL) + ni_free(lastni); + lastni = ni; + nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); +#if 0 + if (tTd(38, 20)) + sm_dprintf("ni_open(PARENT) = %d\n", nis); +#endif /* 0 */ + } + + /* + ** Don't bother if we didn't get a handle on a + ** proper domain. This is not necessarily an error. + ** We would get a positive ni_status if, for instance + ** we never found the directory or property and tried + ** to open the parent of the root domain! + */ + + if (nis != 0) + break; + + /* + ** Find the path to the server information. + */ + + if (ni_pathsearch(ni, &nid, keybuf) != 0) + continue; + + /* + ** Find associated value information. + */ + + if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) + continue; + +#if 0 + if (tTd(38, 20)) + sm_dprintf("ni_lookupprop: len=%d\n", + ninl.ni_namelist_len); +#endif /* 0 */ + + /* + ** See if we have an acceptable number of values. + */ + + if (ninl.ni_namelist_len <= 0) + continue; + + if (sepchar == '\0' && ninl.ni_namelist_len > 1) + { + ni_namelist_free(&ninl); + continue; + } + + /* + ** Calculate number of bytes needed and build result + */ + + alen = 1; + for (j = 0; j < ninl.ni_namelist_len; j++) + alen += strlen(ninl.ni_namelist_val[j]) + 1; + propval = p = sm_malloc(alen); + if (propval == NULL) + goto cleanup; + for (j = 0; j < ninl.ni_namelist_len; j++) + { + (void) sm_strlcpy(p, ninl.ni_namelist_val[j], alen); + l = strlen(p); + p += l; + *p++ = sepchar; + alen -= l + 1; + } + *--p = '\0'; + + ni_namelist_free(&ninl); + } + + cleanup: + if (ni != NULL) + ni_free(ni); + if (lastni != NULL && ni != lastni) + ni_free(lastni); +#if 0 + if (tTd(38, 20)) + sm_dprintf("ni_propval returns: '%s'\n", propval); +#endif /* 0 */ + + return propval; +} +#endif /* NETINFO */ diff --git a/gnu/dist/sendmail/libsm/path.c b/gnu/dist/sendmail/libsm/path.c new file mode 100644 index 000000000000..b66c7e247e9c --- /dev/null +++ b/gnu/dist/sendmail/libsm/path.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: path.c,v 1.9 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include + diff --git a/gnu/dist/sendmail/libsm/put.c b/gnu/dist/sendmail/libsm/put.c new file mode 100644 index 000000000000..d3382bebcfd0 --- /dev/null +++ b/gnu/dist/sendmail/libsm/put.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: put.c,v 1.27 2001/12/19 05:19:35 ca Exp") +#include +#include +#include +#include +#include +#include +#include "local.h" +#include "fvwrite.h" + +/* +** SM_IO_PUTC -- output a character to the file +** +** Function version of the macro sm_io_putc (in ). +** +** Parameters: +** fp -- file to output to +** timeout -- time to complete putc +** c -- int value of character to output +** +** Returns: +** Failure: returns SM_IO_EOF _and_ sets errno +** Success: returns sm_putc() value. +** +*/ + +#undef sm_io_putc + +int +sm_io_putc(fp, timeout, c) + SM_FILE_T *fp; + int timeout; + int c; +{ + SM_REQUIRE_ISA(fp, SmFileMagic); + if (cantwrite(fp)) + { + errno = EBADF; + return SM_IO_EOF; + } + return sm_putc(fp, timeout, c); +} + + +/* +** SM_PERROR -- print system error messages to smioerr +** +** Parameters: +** s -- message to print +** +** Returns: +** none +*/ + +void +sm_perror(s) + const char *s; +{ + int save_errno = errno; + + if (s != NULL && *s != '\0') + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s: ", s); + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n", + sm_errstring(save_errno)); +} diff --git a/gnu/dist/sendmail/libsm/refill.c b/gnu/dist/sendmail/libsm/refill.c new file mode 100644 index 000000000000..9b179e529075 --- /dev/null +++ b/gnu/dist/sendmail/libsm/refill.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: refill.c,v 1.49.2.1 2002/09/09 21:38:08 gshapiro Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +static int sm_lflush __P((SM_FILE_T *, int *)); + +/* +** SM_IO_RD_TIMEOUT -- measured timeout for reads +** +** This #define uses a select() to wait for the 'fd' to become readable. +** The select() can be active for up to 'To' time. The select() may not +** use all of the the 'To' time. Hence, the amount of "wall-clock" time is +** measured to decide how much to subtract from 'To' to update it. On some +** BSD-based/like systems the timeout for a select() is updated for the +** amount of time used. On many/most systems this does not happen. Therefore +** the updating of 'To' must be done ourselves; a copy of 'To' is passed +** since a BSD-like system will have updated it and we don't want to +** double the time used! +** Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the +** sendmail buffered file type in sendmail/bf.c; see use below). +** +** Parameters +** fp -- the file pointer for the active file +** fd -- raw file descriptor (from 'fp') to use for select() +** to -- struct timeval of the timeout +** timeout -- the original timeout value +** sel_ret -- the return value from the select() +** +** Returns: +** nothing, flow through code +*/ + +#define SM_IO_RD_TIMEOUT(fp, fd, to, timeout, sel_ret) \ +{ \ + struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \ + fd_set sm_io_to_mask, sm_io_x_mask; \ + errno = 0; \ + if (timeout == SM_TIME_IMMEDIATE) \ + { \ + errno = EAGAIN; \ + return SM_IO_EOF; \ + } \ + if (FD_SETSIZE > 0 && (fd) >= FD_SETSIZE) \ + { \ + errno = EINVAL; \ + return SM_IO_EOF; \ + } \ + FD_ZERO(&sm_io_to_mask); \ + FD_SET((fd), &sm_io_to_mask); \ + FD_ZERO(&sm_io_x_mask); \ + FD_SET((fd), &sm_io_x_mask); \ + if (gettimeofday(&sm_io_to_before, NULL) < 0) \ + return SM_IO_EOF; \ + (sel_ret) = select((fd) + 1, &sm_io_to_mask, NULL, \ + &sm_io_x_mask, (to)); \ + if ((sel_ret) < 0) \ + { \ + /* something went wrong, errno set */ \ + fp->f_r = 0; \ + fp->f_flags |= SMERR; \ + return SM_IO_EOF; \ + } \ + else if ((sel_ret) == 0) \ + { \ + /* timeout */ \ + errno = EAGAIN; \ + return SM_IO_EOF; \ + } \ + /* calulate wall-clock time used */ \ + if (gettimeofday(&sm_io_to_after, NULL) < 0) \ + return SM_IO_EOF; \ + timersub(&sm_io_to_before, &sm_io_to_after, &sm_io_to_diff); \ + timersub((to), &sm_io_to_diff, (to)); \ +} + +/* +** SM_LFLUSH -- flush a file if it is line buffered and writable +** +** Parameters: +** fp -- file pointer to flush +** timeout -- original timeout value (in milliseconds) +** +** Returns: +** Failure: returns SM_IO_EOF and sets errno +** Success: returns 0 +*/ + +static int +sm_lflush(fp, timeout) + SM_FILE_T *fp; + int *timeout; +{ + + if ((fp->f_flags & (SMLBF|SMWR)) == (SMLBF|SMWR)) + return sm_flush(fp, timeout); + return 0; +} + +/* +** SM_REFILL -- refill a buffer +** +** Parameters: +** fp -- file pointer for buffer refill +** timeout -- time to complete filling the buffer in milliseconds +** +** Returns: +** Success: returns 0 +** Failure: returns SM_IO_EOF +*/ + +int +sm_refill(fp, timeout) + register SM_FILE_T *fp; + int timeout; +{ + int ret, r; + struct timeval to; + int fd; + + if (timeout == SM_TIME_DEFAULT) + timeout = fp->f_timeout; + if (timeout == SM_TIME_IMMEDIATE) + { + /* + ** Filling the buffer will take time and we are wanted to + ** return immediately. And we're not EOF or ERR really. + ** So... the failure is we couldn't do it in time. + */ + + errno = EAGAIN; + fp->f_r = 0; /* just to be sure */ + return 0; + } + + /* make sure stdio is set up */ + if (!Sm_IO_DidInit) + sm_init(); + + fp->f_r = 0; /* largely a convenience for callers */ + + if (fp->f_flags & SMFEOF) + return SM_IO_EOF; + + SM_CONVERT_TIME(fp, fd, timeout, &to); + + /* if not already reading, have to be reading and writing */ + if ((fp->f_flags & SMRD) == 0) + { + if ((fp->f_flags & SMRW) == 0) + { + errno = EBADF; + fp->f_flags |= SMERR; + return SM_IO_EOF; + } + + /* switch to reading */ + if (fp->f_flags & SMWR) + { + if (sm_flush(fp, &timeout)) + return SM_IO_EOF; + fp->f_flags &= ~SMWR; + fp->f_w = 0; + fp->f_lbfsize = 0; + } + fp->f_flags |= SMRD; + } + else + { + /* + ** We were reading. If there is an ungetc buffer, + ** we must have been reading from that. Drop it, + ** restoring the previous buffer (if any). If there + ** is anything in that buffer, return. + */ + + if (HASUB(fp)) + { + FREEUB(fp); + if ((fp->f_r = fp->f_ur) != 0) + { + fp->f_p = fp->f_up; + + /* revert blocking state */ + return 0; + } + } + } + + if (fp->f_bf.smb_base == NULL) + sm_makebuf(fp); + + /* + ** Before reading from a line buffered or unbuffered file, + ** flush all line buffered output files, per the ANSI C standard. + */ + + if (fp->f_flags & (SMLBF|SMNBF)) + (void) sm_fwalk(sm_lflush, &timeout); + + /* + ** If this file is linked to another, and we are going to hang + ** on the read, flush the linked file before continuing. + */ + + if (fp->f_flushfp != NULL && + (*fp->f_getinfo)(fp, SM_IO_IS_READABLE, NULL) <= 0) + sm_flush(fp->f_flushfp, &timeout); + + fp->f_p = fp->f_bf.smb_base; + + /* + ** The do-while loop stops trying to read when something is read + ** or it appears that the timeout has expired before finding + ** something available to be read (via select()). + */ + + ret = 0; + do + { + errno = 0; /* needed to ensure EOF correctly found */ + r = (*fp->f_read)(fp, (char *)fp->f_p, fp->f_bf.smb_size); + if (r <= 0) + { + if (r == 0 && errno == 0) + break; /* EOF found */ + if (IS_IO_ERROR(fd, r, timeout)) + goto err; /* errno set */ + + /* read would block */ + SM_IO_RD_TIMEOUT(fp, fd, &to, timeout, ret); + } + } while (r <= 0 && ret > 0); + +err: + if (r <= 0) + { + if (r == 0) + fp->f_flags |= SMFEOF; + else + fp->f_flags |= SMERR; + fp->f_r = 0; + return SM_IO_EOF; + } + fp->f_r = r; + return 0; +} + +/* +** SM_RGET -- refills buffer and returns first character +** +** Handle sm_getc() when the buffer ran out: +** Refill, then return the first character in the newly-filled buffer. +** +** Parameters: +** fp -- file pointer to work on +** timeout -- time to complete refill +** +** Returns: +** Success: first character in refilled buffer as an int +** Failure: SM_IO_EOF +*/ + +int +sm_rget(fp, timeout) + register SM_FILE_T *fp; + int timeout; +{ + if (sm_refill(fp, timeout) == 0) + { + fp->f_r--; + return *fp->f_p++; + } + return SM_IO_EOF; +} diff --git a/gnu/dist/sendmail/libsm/rewind.c b/gnu/dist/sendmail/libsm/rewind.c new file mode 100644 index 000000000000..9e18162618ba --- /dev/null +++ b/gnu/dist/sendmail/libsm/rewind.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: rewind.c,v 1.18 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include +#include "local.h" + +/* +** SM_IO_REWIND -- rewind the file +** +** Seeks the file to the begining and clears any outstanding errors. +** +** Parameters: +** fp -- the flie pointer for rewind +** timeout -- time to complete the rewind +** +** Returns: +** none. +*/ + +void +sm_io_rewind(fp, timeout) + register SM_FILE_T *fp; + int timeout; +{ + SM_REQUIRE_ISA(fp, SmFileMagic); + (void) sm_io_seek(fp, timeout, 0L, SM_IO_SEEK_SET); + (void) sm_io_clearerr(fp); + errno = 0; /* not required, but seems reasonable */ +} diff --git a/gnu/dist/sendmail/libsm/rpool.c b/gnu/dist/sendmail/libsm/rpool.c new file mode 100644 index 000000000000..f3dbc45b01d5 --- /dev/null +++ b/gnu/dist/sendmail/libsm/rpool.c @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: rpool.c,v 1.24 2002/01/11 21:54:43 ca Exp") + +/* +** resource pools +** For documentation, see rpool.html +*/ + +#include +#include +#include +#include +#include +#if _FFR_PERF_RPOOL +# include +#endif /* _FFR_PERF_RPOOL */ + +const char SmRpoolMagic[] = "sm_rpool"; + +typedef union +{ + SM_POOLLINK_T link; + char align[SM_ALIGN_SIZE]; +} SM_POOLHDR_T; + +/* +** Tune this later +*/ + +#define POOLSIZE 4096 +#define BIG_OBJECT_RATIO 10 + +/* +** SM_RPOOL_ALLOCBLOCK_X -- allocate a new block for an rpool. +** +** Parameters: +** rpool -- rpool to which the block should be added. +** size -- size of block. +** +** Returns: +** Pointer to block. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +static char * +sm_rpool_allocblock_x(rpool, size) + SM_RPOOL_T *rpool; + size_t size; +{ + SM_POOLLINK_T *p; + + p = sm_malloc_x(sizeof(SM_POOLHDR_T) + size); + p->sm_pnext = rpool->sm_pools; + rpool->sm_pools = p; + return (char*) p + sizeof(SM_POOLHDR_T); +} + +/* +** SM_RPOOL_ALLOCBLOCK -- allocate a new block for an rpool. +** +** Parameters: +** rpool -- rpool to which the block should be added. +** size -- size of block. +** +** Returns: +** Pointer to block, NULL on failure. +*/ + +static char * +sm_rpool_allocblock(rpool, size) + SM_RPOOL_T *rpool; + size_t size; +{ + SM_POOLLINK_T *p; + + p = sm_malloc(sizeof(SM_POOLHDR_T) + size); + if (p == NULL) + return NULL; + p->sm_pnext = rpool->sm_pools; + rpool->sm_pools = p; + return (char*) p + sizeof(SM_POOLHDR_T); +} + +/* +** SM_RPOOL_MALLOC_TAGGED_X -- allocate memory from rpool +** +** Parameters: +** rpool -- rpool from which memory should be allocated; +** can be NULL, use sm_malloc() then. +** size -- size of block. +** file -- filename. +** line -- line number in file. +** group -- heap group for debugging. +** +** Returns: +** Pointer to block. +** +** Exceptions: +** F:sm_heap -- out of memory +** +** Notice: XXX +** if size == 0 and the rpool is new (no memory +** allocated yet) NULL is returned! +** We could solve this by +** - wasting 1 byte (size < avail) +** - checking for rpool->sm_poolptr != NULL +** - not asking for 0 sized buffer +*/ + +void * +#if SM_HEAP_CHECK +sm_rpool_malloc_tagged_x(rpool, size, file, line, group) + SM_RPOOL_T *rpool; + size_t size; + char *file; + int line; + int group; +#else /* SM_HEAP_CHECK */ +sm_rpool_malloc_x(rpool, size) + SM_RPOOL_T *rpool; + size_t size; +#endif /* SM_HEAP_CHECK */ +{ + char *ptr; + + if (rpool == NULL) + return sm_malloc_tagged_x(size, file, line, group); + + /* Ensure that size is properly aligned. */ + if (size & SM_ALIGN_BITS) + size = (size & ~SM_ALIGN_BITS) + SM_ALIGN_SIZE; + + /* The common case. This is optimized for speed. */ + if (size <= rpool->sm_poolavail) + { + ptr = rpool->sm_poolptr; + rpool->sm_poolptr += size; + rpool->sm_poolavail -= size; + return ptr; + } + + /* + ** The slow case: we need to call malloc. + ** The SM_REQUIRE assertion is deferred until now, for speed. + ** That's okay: we set rpool->sm_poolavail to 0 when we free an rpool, + ** so the common case code won't be triggered on a dangling pointer. + */ + + SM_REQUIRE(rpool->sm_magic == SmRpoolMagic); + + /* + ** If size > sm_poolsize, then malloc a new block especially for + ** this request. Future requests will be allocated from the + ** current pool. + ** + ** What if the current pool is mostly unallocated, and the current + ** request is larger than the available space, but < sm_poolsize? + ** If we discard the current pool, and start allocating from a new + ** pool, then we will be wasting a lot of space. For this reason, + ** we malloc a block just for the current request if size > + ** sm_bigobjectsize, where sm_bigobjectsize <= sm_poolsize. + ** Thus, the most space that we will waste at the end of a pool + ** is sm_bigobjectsize - 1. + */ + + if (size > rpool->sm_bigobjectsize) + { +#if _FFR_PERF_RPOOL + ++rpool->sm_nbigblocks; +#endif /* _FFR_PERF_RPOOL */ + return sm_rpool_allocblock_x(rpool, size); + } + SM_ASSERT(rpool->sm_bigobjectsize <= rpool->sm_poolsize); + ptr = sm_rpool_allocblock_x(rpool, rpool->sm_poolsize); + rpool->sm_poolptr = ptr + size; + rpool->sm_poolavail = rpool->sm_poolsize - size; +#if _FFR_PERF_RPOOL + ++rpool->sm_npools; +#endif /* _FFR_PERF_RPOOL */ + return ptr; +} + +/* +** SM_RPOOL_MALLOC_TAGGED -- allocate memory from rpool +** +** Parameters: +** rpool -- rpool from which memory should be allocated; +** can be NULL, use sm_malloc() then. +** size -- size of block. +** file -- filename. +** line -- line number in file. +** group -- heap group for debugging. +** +** Returns: +** Pointer to block, NULL on failure. +** +** Notice: XXX +** if size == 0 and the rpool is new (no memory +** allocated yet) NULL is returned! +** We could solve this by +** - wasting 1 byte (size < avail) +** - checking for rpool->sm_poolptr != NULL +** - not asking for 0 sized buffer +*/ + +void * +#if SM_HEAP_CHECK +sm_rpool_malloc_tagged(rpool, size, file, line, group) + SM_RPOOL_T *rpool; + size_t size; + char *file; + int line; + int group; +#else /* SM_HEAP_CHECK */ +sm_rpool_malloc(rpool, size) + SM_RPOOL_T *rpool; + size_t size; +#endif /* SM_HEAP_CHECK */ +{ + char *ptr; + + if (rpool == NULL) + return sm_malloc_tagged(size, file, line, group); + + /* Ensure that size is properly aligned. */ + if (size & SM_ALIGN_BITS) + size = (size & ~SM_ALIGN_BITS) + SM_ALIGN_SIZE; + + /* The common case. This is optimized for speed. */ + if (size <= rpool->sm_poolavail) + { + ptr = rpool->sm_poolptr; + rpool->sm_poolptr += size; + rpool->sm_poolavail -= size; + return ptr; + } + + /* + ** The slow case: we need to call malloc. + ** The SM_REQUIRE assertion is deferred until now, for speed. + ** That's okay: we set rpool->sm_poolavail to 0 when we free an rpool, + ** so the common case code won't be triggered on a dangling pointer. + */ + + SM_REQUIRE(rpool->sm_magic == SmRpoolMagic); + + /* + ** If size > sm_poolsize, then malloc a new block especially for + ** this request. Future requests will be allocated from the + ** current pool. + ** + ** What if the current pool is mostly unallocated, and the current + ** request is larger than the available space, but < sm_poolsize? + ** If we discard the current pool, and start allocating from a new + ** pool, then we will be wasting a lot of space. For this reason, + ** we malloc a block just for the current request if size > + ** sm_bigobjectsize, where sm_bigobjectsize <= sm_poolsize. + ** Thus, the most space that we will waste at the end of a pool + ** is sm_bigobjectsize - 1. + */ + + if (size > rpool->sm_bigobjectsize) + { +#if _FFR_PERF_RPOOL + ++rpool->sm_nbigblocks; +#endif /* _FFR_PERF_RPOOL */ + return sm_rpool_allocblock(rpool, size); + } + SM_ASSERT(rpool->sm_bigobjectsize <= rpool->sm_poolsize); + ptr = sm_rpool_allocblock(rpool, rpool->sm_poolsize); + if (ptr == NULL) + return NULL; + rpool->sm_poolptr = ptr + size; + rpool->sm_poolavail = rpool->sm_poolsize - size; +#if _FFR_PERF_RPOOL + ++rpool->sm_npools; +#endif /* _FFR_PERF_RPOOL */ + return ptr; +} + +/* +** SM_RPOOL_NEW_X -- create a new rpool. +** +** Parameters: +** parent -- pointer to parent rpool, can be NULL. +** +** Returns: +** Pointer to new rpool. +*/ + +SM_RPOOL_T * +sm_rpool_new_x(parent) + SM_RPOOL_T *parent; +{ + SM_RPOOL_T *rpool; + + rpool = sm_malloc_x(sizeof(SM_RPOOL_T)); + if (parent == NULL) + rpool->sm_parentlink = NULL; + else + { + SM_TRY + rpool->sm_parentlink = sm_rpool_attach_x(parent, + (SM_RPOOL_RFREE_T) sm_rpool_free, + (void *) rpool); + SM_EXCEPT(exc, "*") + sm_free(rpool); + sm_exc_raise_x(exc); + SM_END_TRY + } + rpool->sm_magic = SmRpoolMagic; + + rpool->sm_poolsize = POOLSIZE - sizeof(SM_POOLHDR_T); + rpool->sm_bigobjectsize = rpool->sm_poolsize / BIG_OBJECT_RATIO; + rpool->sm_poolptr = NULL; + rpool->sm_poolavail = 0; + rpool->sm_pools = NULL; + + rpool->sm_rptr = NULL; + rpool->sm_ravail = 0; + rpool->sm_rlists = NULL; +#if _FFR_PERF_RPOOL + rpool->sm_nbigblocks = 0; + rpool->sm_npools = 0; +#endif /* _FFR_PERF_RPOOL */ + + return rpool; +} + +/* +** SM_RPOOL_SETSIZES -- set sizes for rpool. +** +** Parameters: +** poolsize -- size of a single rpool block. +** bigobjectsize -- if this size is exceeded, an individual +** block is allocated (must be less or equal poolsize). +** +** Returns: +** none. +*/ + +void +sm_rpool_setsizes(rpool, poolsize, bigobjectsize) + SM_RPOOL_T *rpool; + size_t poolsize; + size_t bigobjectsize; +{ + SM_REQUIRE(poolsize >= bigobjectsize); + if (poolsize == 0) + poolsize = POOLSIZE - sizeof(SM_POOLHDR_T); + if (bigobjectsize == 0) + bigobjectsize = poolsize / BIG_OBJECT_RATIO; + rpool->sm_poolsize = poolsize; + rpool->sm_bigobjectsize = bigobjectsize; +} + +/* +** SM_RPOOL_FREE -- free an rpool and release all of its resources. +** +** Parameters: +** rpool -- rpool to free. +** +** Returns: +** none. +*/ + +void +sm_rpool_free(rpool) + SM_RPOOL_T *rpool; +{ + SM_RLIST_T *rl, *rnext; + SM_RESOURCE_T *r, *rmax; + SM_POOLLINK_T *pp, *pnext; + + if (rpool == NULL) + return; + + /* + ** It's important to free the resources before the memory pools, + ** because the resource free functions might modify the contents + ** of the memory pools. + */ + + rl = rpool->sm_rlists; + if (rl != NULL) + { + rmax = rpool->sm_rptr; + for (;;) + { + for (r = rl->sm_rvec; r < rmax; ++r) + { + if (r->sm_rfree != NULL) + r->sm_rfree(r->sm_rcontext); + } + rnext = rl->sm_rnext; + sm_free(rl); + if (rnext == NULL) + break; + rl = rnext; + rmax = &rl->sm_rvec[SM_RLIST_MAX]; + } + } + + /* + ** Now free the memory pools. + */ + + for (pp = rpool->sm_pools; pp != NULL; pp = pnext) + { + pnext = pp->sm_pnext; + sm_free(pp); + } + + /* + ** Disconnect rpool from its parent. + */ + + if (rpool->sm_parentlink != NULL) + *rpool->sm_parentlink = NULL; + + /* + ** Setting these fields to zero means that any future to attempt + ** to use the rpool after it is freed will cause an assertion failure. + */ + + rpool->sm_magic = NULL; + rpool->sm_poolavail = 0; + rpool->sm_ravail = 0; + +#if _FFR_PERF_RPOOL + if (rpool->sm_nbigblocks > 0 || rpool->sm_npools > 1) + syslog(LOG_NOTICE, + "perf: rpool=%lx, sm_nbigblocks=%d, sm_npools=%d", + (long) rpool, rpool->sm_nbigblocks, rpool->sm_npools); + rpool->sm_nbigblocks = 0; + rpool->sm_npools = 0; +#endif /* _FFR_PERF_RPOOL */ + sm_free(rpool); +} + +/* +** SM_RPOOL_ATTACH_X -- attach a resource to an rpool. +** +** Parameters: +** rpool -- rpool to which resource should be attached. +** rfree -- function to call when rpool is freed. +** rcontext -- argument for function to call when rpool is freed. +** +** Returns: +** Pointer to allocated function. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +SM_RPOOL_ATTACH_T +sm_rpool_attach_x(rpool, rfree, rcontext) + SM_RPOOL_T *rpool; + SM_RPOOL_RFREE_T rfree; + void *rcontext; +{ + SM_RLIST_T *rl; + SM_RPOOL_ATTACH_T a; + + SM_REQUIRE_ISA(rpool, SmRpoolMagic); + + if (rpool->sm_ravail == 0) + { + rl = sm_malloc_x(sizeof(SM_RLIST_T)); + rl->sm_rnext = rpool->sm_rlists; + rpool->sm_rlists = rl; + rpool->sm_rptr = rl->sm_rvec; + rpool->sm_ravail = SM_RLIST_MAX; + } + + a = &rpool->sm_rptr->sm_rfree; + rpool->sm_rptr->sm_rfree = rfree; + rpool->sm_rptr->sm_rcontext = rcontext; + ++rpool->sm_rptr; + --rpool->sm_ravail; + return a; +} diff --git a/gnu/dist/sendmail/libsm/rpool.html b/gnu/dist/sendmail/libsm/rpool.html new file mode 100644 index 000000000000..3b9082fedd6b --- /dev/null +++ b/gnu/dist/sendmail/libsm/rpool.html @@ -0,0 +1,187 @@ + + + libsm : Resource Pools + + + +Back to libsm overview + +
    +

    libsm : Resource Pools

    +
    Id: rpool.html,v 1.4 2000/12/07 17:33:09 dmoen Exp +
    + +

    Introduction

    + +A resource pool is an object that owns a collection of objects +that can be freed all at once. + +

    +Resource pools simplify storage management. + +

    +Resource pools also speed up memory management. +For example, here are some memory allocation statistics from a +run of `sendmail -q` that delivered 3 messages: +

    +     18	1	     82	12	     87	24	      7	42	      2	84
    +   3046	2	     18	13	      6	25	     89	44	      2	88
    +    728	3	     15	14	      2	26	     14	48	      1	91
    +     31	4	      9	15	      3	27	    104	52	      3	92
    +    103	5	    394	16	     80	28	      8	56	      2	96
    +    125	6	     16	17	      1	31	      2	60	      1	100
    +     45	7	     14	18	     59	32	     10	64	      9	108
    +    130	8	      6	19	      1	33	      6	68	      3	135
    +     40	9	    111	20	      7	34	      1	72	     10	140
    +     37	10	      7	21	     54	36	     10	76
    +     34	11	      4	22	     38	40	      5	80
    +
    +The second number in each pair is the size of a memory block; the first +number is the number of blocks of that size. We can see that sendmail +allocates large numbers of 2 byte blocks. These memory blocks can be +allocated and freed more quickly using resource pools, because: +
      +
    • + When you allocate a small block from a resource pool, the rpool + implementation carves off a chunk of a large preallocated block, + and hands you a pointer to it. +
    • + When you free a resource pool, only a small number of large + blocks need to be freed. +
    + +

    Synopsis

    + +
    +#include <sm/rpool.h>
    +
    +typedef void (*SM_RPOOL_RFREE_T)(void *rcontext);
    +typedef struct sm_rpool SM_RPOOL_T;
    +typedef ... SM_RPOOL_ATTACH_T;
    +
    +SM_RPOOL_T *
    +sm_rpool_new_x(
    +	SM_RPOOL_T *parent);
    +
    +void
    +sm_rpool_free(
    +	SM_RPOOL_T *rpool);
    +
    +void *
    +sm_rpool_malloc_x(
    +	SM_RPOOL_T *rpool,
    +	size_t size);
    +
    +SM_RPOOL_ATTACH_T
    +sm_rpool_attach_x(
    +	SM_RPOOL_T *rpool,
    +	SM_RPOOL_RFREE_T rfree,
    +	void *rcontext);
    +
    +void
    +sm_rpool_detach(
    +	SM_RPOOL_ATTACH_T);
    +
    +void
    +sm_rpool_setsizes(
    +	SM_RPOOL_T *rpool,
    +	size_t poolsize,
    +	size_t bigobjectsize);
    +
    + +

    Description

    + +
    +
    + SM_RPOOL_T *sm_rpool_new_x(SM_RPOOL_T *parent) +
    + Create a new resource pool object. + Raise an exception if there is insufficient heap space. + Initially, no memory is allocated for memory pools or resource lists. +

    + If parent != NULL then the new rpool will be added as a resource + to the specified parent rpool, so that when the parent is freed, + the child is also freed. However, even if a parent is specified, + you can free the rpool at any time, and it will be automatically + disconnected from the parent. +

    +

    + void *sm_rpool_malloc_x(SM_RPOOL_T *rpool, size_t size) +
    + Allocate a block of memory from a memory pool owned by the rpool. + Raise an exception if there is insufficient heap space. + A series of small allocation requests can be satisfied allocating + them from the same memory pool, which reduces the number of calls + to malloc. + All of the memory allocated by sm_rpool_malloc_x is freed when + the rpool is freed, and not before then. +

    +

    + void sm_rpool_setsizes(SM_RPOOL_T *rpool, size_t poolsize, size_t bigobjectsize) +
    + Set memory pool parameters. + You can safely call this function at any time, but an especially + good time to call it is immediately after creating the rpool, + before any pooled objects have been allocated using sm_rpool_malloc_x. +

    + poolsize is the number of bytes of pool memory + that will be available in the next pool object to be allocated. + If you happen to know the total number of bytes of memory that + you will allocate from an rpool using sm_rpool_malloc_x + (including alignment padding), then you can pass that value + as the poolsize, and only a single pool will be allocated + during the lifetime of the rpool. + poolsize is an optimization, not a hard limit: + if you allocate more than this number of bytes from the rpool, + then more than one memory pool may be allocated by the rpool + to satisfy your requests. +

    + bigobjectsize is a value <= poolsize. + It is used when an sm_rpool_malloc_x request exceeds + the number of bytes available in the current pool. + If the request is > bigobjectsize then the request + will be satisfied by allocating a new block just for this specific + request, and the current pool is not affected. + If the request is <= bigobjectsize then the current + pool is closed and a new memory pool is allocated, from which the + request is satisfied. + Consequently, no more than bigobjectsize-1 bytes will + ever be wasted at the end of a given pool. +

    + If poolsize or bigobjectsize are 0, then suitable default values + are chosen. +

    +

    + SM_RPOOL_ATTACH_T sm_rpool_attach_x(SM_RPOOL_T *rpool, SM_RPOOL_RFREE_T rfree, void *rcontext) +
    + Attach an object to a resource pool, along with its free function. + When the rpool is freed, the specified object will also be freed. + Raise an exception if there is insufficient heap space. +

    + The return value is a magic cookie which, if passed to + sm_rpool_detach, disconnects the object from the resource pool, + which prevents the object's free function from being called when + the rpool is freed. +

    +

    + void sm_rpool_detach(SM_RPOOL_ATTACH_T a) +
    + The argument is a magic cookie returned by sm_rpool_attach_t, + and refers to the object that was attached to an rpool by a specific + call to sm_rpool_attach_t. + Disconnect the object from the resource pool, + which prevents the object's free function from being called when + the rpool is freed. +

    +

    + void sm_rpool_free(SM_RPOOL_T *rpool) +
    + Free an rpool object. + All memory allocated using sm_rpool_malloc_x + and all objects attached using sm_rpool_attach_x + are freed at this time. + If the rpool has a parent rpool, it is detached from its parent. +
    + + + diff --git a/gnu/dist/sendmail/libsm/setvbuf.c b/gnu/dist/sendmail/libsm/setvbuf.c new file mode 100644 index 000000000000..c497eb092832 --- /dev/null +++ b/gnu/dist/sendmail/libsm/setvbuf.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: setvbuf.c,v 1.32 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +/* +** SM_IO_SETVBUF -- set the buffering type for a file +** +** Set one of the different kinds of buffering, optionally including +** a buffer. +** If 'size' is == 0 then an "optimal" size will be selected. +** If 'buf' is == NULL then space will be allocated at 'size'. +** +** Parameters: +** fp -- the file that buffering is to be changed for +** timeout -- time allowed for completing the function +** buf -- buffer to use +** mode -- buffering method to use +** size -- size of 'buf' +** +** Returns: +** Failure: SM_IO_EOF +** Success: 0 (zero) +*/ + +int +sm_io_setvbuf(fp, timeout, buf, mode, size) + SM_FILE_T *fp; + int timeout; + char *buf; + int mode; + size_t size; +{ + int ret, flags; + size_t iosize; + int ttyflag; + int fd; + struct timeval to; + + SM_REQUIRE_ISA(fp, SmFileMagic); + + /* + ** Verify arguments. The `int' limit on `size' is due to this + ** particular implementation. Note, buf and size are ignored + ** when setting SM_IO_NBF. + */ + + if (mode != SM_IO_NBF) + if ((mode != SM_IO_FBF && mode != SM_IO_LBF && + mode != SM_IO_NOW) || (int) size < 0) + return SM_IO_EOF; + + /* + ** Write current buffer, if any. Discard unread input (including + ** ungetc data), cancel line buffering, and free old buffer if + ** malloc()ed. We also clear any eof condition, as if this were + ** a seek. + */ + + ret = 0; + SM_CONVERT_TIME(fp, fd, timeout, &to); + (void) sm_flush(fp, &timeout); + if (HASUB(fp)) + FREEUB(fp); + fp->f_r = fp->f_lbfsize = 0; + flags = fp->f_flags; + if (flags & SMMBF) + { + sm_free((void *) fp->f_bf.smb_base); + fp->f_bf.smb_base = NULL; + } + flags &= ~(SMLBF | SMNBF | SMMBF | SMOPT | SMNPT | SMFEOF | SMNOW | + SMFBF); + + /* If setting unbuffered mode, skip all the hard work. */ + if (mode == SM_IO_NBF) + goto nbf; + + /* + ** Find optimal I/O size for seek optimization. This also returns + ** a `tty flag' to suggest that we check isatty(fd), but we do not + ** care since our caller told us how to buffer. + */ + + flags |= sm_whatbuf(fp, &iosize, &ttyflag); + if (size == 0) + { + buf = NULL; /* force local allocation */ + size = iosize; + } + + /* Allocate buffer if needed. */ + if (buf == NULL) + { + if ((buf = sm_malloc(size)) == NULL) + { + /* + ** Unable to honor user's request. We will return + ** failure, but try again with file system size. + */ + + ret = SM_IO_EOF; + if (size != iosize) + { + size = iosize; + buf = sm_malloc(size); + } + } + if (buf == NULL) + { + /* No luck; switch to unbuffered I/O. */ +nbf: + fp->f_flags = flags | SMNBF; + fp->f_w = 0; + fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; + fp->f_bf.smb_size = 1; + return ret; + } + flags |= SMMBF; + } + + /* + ** Kill any seek optimization if the buffer is not the + ** right size. + ** + ** SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)? + */ + + if (size != iosize) + flags |= SMNPT; + + /* + ** Fix up the SM_FILE_T fields, and set sm_cleanup for output flush on + ** exit (since we are buffered in some way). + */ + + if (mode == SM_IO_LBF) + flags |= SMLBF; + else if (mode == SM_IO_NOW) + flags |= SMNOW; + else if (mode == SM_IO_FBF) + flags |= SMFBF; + fp->f_flags = flags; + fp->f_bf.smb_base = fp->f_p = (unsigned char *)buf; + fp->f_bf.smb_size = size; + /* fp->f_lbfsize is still 0 */ + if (flags & SMWR) + { + /* + ** Begin or continue writing: see sm_wsetup(). Note + ** that SMNBF is impossible (it was handled earlier). + */ + + if (flags & SMLBF) + { + fp->f_w = 0; + fp->f_lbfsize = -fp->f_bf.smb_size; + } + else + fp->f_w = size; + } + else + { + /* begin/continue reading, or stay in intermediate state */ + fp->f_w = 0; + } + + atexit(sm_cleanup); + return ret; +} diff --git a/gnu/dist/sendmail/libsm/shm.c b/gnu/dist/sendmail/libsm/shm.c new file mode 100644 index 000000000000..96c6249d68a5 --- /dev/null +++ b/gnu/dist/sendmail/libsm/shm.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: shm.c,v 1.10 2001/12/14 00:22:58 ca Exp") + +#if SM_CONF_SHM +# include +# include +# include +# include + +/* +** SM_SHMSTART -- initialize shared memory segment. +** +** Parameters: +** key -- key for shared memory. +** size -- size of segment. +** shmflag -- initial flags. +** shmid -- pointer to return id. +** owner -- create segment. +** +** Returns: +** pointer to shared memory segment, +** NULL on failure. +** +** Side Effects: +** attaches shared memory segment. +*/ + +void * +sm_shmstart(key, size, shmflg, shmid, owner) + key_t key; + int size; + int shmflg; + int *shmid; + bool owner; +{ + int save_errno; + void *shm = SM_SHM_NULL; + + /* default: user/group accessible */ + if (shmflg == 0) + shmflg = SHM_R|SHM_W|(SHM_R>>3)|(SHM_W>>3); + if (owner) + shmflg |= IPC_CREAT|IPC_EXCL; + *shmid = shmget(key, size, shmflg); + if (*shmid < 0) + goto error; + + shm = shmat(*shmid, (void *) 0, 0); + if (shm == SM_SHM_NULL) + goto error; + + return shm; + + error: + save_errno = errno; + if (shm != SM_SHM_NULL || *shmid >= 0) + sm_shmstop(shm, *shmid, owner); + *shmid = SM_SHM_NO_ID; + errno = save_errno; + return (void *) 0; +} + +/* +** SM_SHMSTOP -- stop using shared memory segment. +** +** Parameters: +** shm -- pointer to shared memory. +** shmid -- id. +** owner -- delete segment. +** +** Returns: +** 0 on success. +** < 0 on failure. +** +** Side Effects: +** detaches (and maybe removes) shared memory segment. +*/ + +int +sm_shmstop(shm, shmid, owner) + void *shm; + int shmid; + bool owner; +{ + int r; + + if (shm != SM_SHM_NULL && (r = shmdt(shm)) < 0) + return r; + if (owner && shmid >= 0 && (r = shmctl(shmid, IPC_RMID, NULL)) < 0) + return r; + return 0; +} +#endif /* SM_CONF_SHM */ diff --git a/gnu/dist/sendmail/libsm/signal.c b/gnu/dist/sendmail/libsm/signal.c new file mode 100644 index 000000000000..00ec42482f28 --- /dev/null +++ b/gnu/dist/sendmail/libsm/signal.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: signal.c,v 1.16 2001/09/11 04:04:49 gshapiro Exp") + +#if SM_CONF_SETITIMER +# include +#endif /* SM_CONF_SETITIMER */ +#include +#include +#include +#include +#include +#include +#include +#include + +unsigned int volatile InCriticalSection; /* >0 if inside critical section */ +int volatile PendingSignal; /* pending signal to resend */ + +/* +** SM_SIGNAL -- set a signal handler +** +** This is essentially old BSD "signal(3)". +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +sigfunc_t +sm_signal(sig, handler) + int sig; + sigfunc_t handler; +{ +# if defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) + struct sigaction n, o; +# endif /* defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) */ + + /* + ** First, try for modern signal calls + ** and restartable syscalls + */ + +# ifdef SA_RESTART + (void) 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 /* USE_SA_SIGACTION */ + n.sa_handler = handler; + n.sa_flags = SA_RESTART; +# endif /* USE_SA_SIGACTION */ + if (sigaction(sig, &n, &o) < 0) + return SIG_ERR; + return o.sa_handler; +# 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 + */ + + (void) 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 */ +} +/* +** SM_BLOCKSIGNAL -- hold a signal to prevent delivery +** +** Parameters: +** sig -- the signal to block. +** +** Returns: +** 1 signal was previously blocked +** 0 signal was not previously blocked +** -1 on failure. +*/ + +int +sm_blocksignal(sig) + int sig; +{ +# ifdef BSD4_3 +# ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +# endif /* ! sigmask */ + return (sigblock(sigmask(sig)) & sigmask(sig)) != 0; +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V + sigfunc_t handler; + + handler = sigset(sig, SIG_HOLD); + if (handler == SIG_ERR) + return -1; + else + return handler == SIG_HOLD; +# else /* ALTOS_SYSTEM_V */ + sigset_t sset, oset; + + (void) sigemptyset(&sset); + (void) sigaddset(&sset, sig); + if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0) + return -1; + else + return sigismember(&oset, sig); +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ +} +/* +** SM_RELEASESIGNAL -- release a held signal +** +** Parameters: +** sig -- the signal to release. +** +** Returns: +** 1 signal was previously blocked +** 0 signal was not previously blocked +** -1 on failure. +*/ + +int +sm_releasesignal(sig) + int sig; +{ +# ifdef BSD4_3 + return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0; +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V + sigfunc_t handler; + + handler = sigset(sig, SIG_HOLD); + if (sigrelse(sig) < 0) + return -1; + else + return handler == SIG_HOLD; +# else /* ALTOS_SYSTEM_V */ + sigset_t sset, oset; + + (void) sigemptyset(&sset); + (void) sigaddset(&sset, sig); + if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0) + return -1; + else + return sigismember(&oset, sig); +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ +} +/* +** PEND_SIGNAL -- Add a signal to the pending signal list +** +** Parameters: +** sig -- signal to add +** +** Returns: +** none. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +void +pend_signal(sig) + int sig; +{ + int sigbit; + int save_errno = errno; +#if SM_CONF_SETITIMER + struct itimerval clr; +#endif /* SM_CONF_SETITIMER */ + + /* + ** Don't want to interrupt something critical, hence delay + ** the alarm for one second. Hopefully, by then we + ** will be out of the critical section. If not, then + ** we will just delay again. The events to be run will + ** still all be run, maybe just a little bit late. + */ + + switch (sig) + { + case SIGHUP: + sigbit = PEND_SIGHUP; + break; + + case SIGINT: + sigbit = PEND_SIGINT; + break; + + case SIGTERM: + sigbit = PEND_SIGTERM; + break; + + case SIGUSR1: + sigbit = PEND_SIGUSR1; + break; + + case SIGALRM: + /* don't have to pend these */ + sigbit = 0; + break; + + default: + /* If we get here, we are in trouble */ + abort(); + + /* NOTREACHED */ + /* shut up stupid compiler warning on HP-UX 11 */ + sigbit = 0; + break; + } + + if (sigbit != 0) + PendingSignal |= sigbit; + (void) sm_signal(SIGALRM, sm_tick); +#if SM_CONF_SETITIMER + clr.it_interval.tv_sec = 0; + clr.it_interval.tv_usec = 0; + clr.it_value.tv_sec = 1; + clr.it_value.tv_usec = 0; + (void) setitimer(ITIMER_REAL, &clr, NULL); +#else /* SM_CONF_SETITIMER */ + (void) alarm(1); +#endif /* SM_CONF_SETITIMER */ + errno = save_errno; +} +/* +** SM_ALLSIGNALS -- act on all signals +** +** Parameters: +** block -- whether to block or release all signals. +** +** Returns: +** none. +*/ + +void +sm_allsignals(block) + bool block; +{ +# ifdef BSD4_3 +# ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +# endif /* ! sigmask */ + if (block) + { + int mask = 0; + + mask |= sigmask(SIGALRM); + mask |= sigmask(SIGCHLD); + mask |= sigmask(SIGHUP); + mask |= sigmask(SIGINT); + mask |= sigmask(SIGTERM); + mask |= sigmask(SIGUSR1); + + (void) sigblock(mask); + } + else + sigsetmask(0); +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V + if (block) + { + (void) sigset(SIGALRM, SIG_HOLD); + (void) sigset(SIGCHLD, SIG_HOLD); + (void) sigset(SIGHUP, SIG_HOLD); + (void) sigset(SIGINT, SIG_HOLD); + (void) sigset(SIGTERM, SIG_HOLD); + (void) sigset(SIGUSR1, SIG_HOLD); + } + else + { + (void) sigset(SIGALRM, SIG_DFL); + (void) sigset(SIGCHLD, SIG_DFL); + (void) sigset(SIGHUP, SIG_DFL); + (void) sigset(SIGINT, SIG_DFL); + (void) sigset(SIGTERM, SIG_DFL); + (void) sigset(SIGUSR1, SIG_DFL); + } +# else /* ALTOS_SYSTEM_V */ + sigset_t sset; + + (void) sigemptyset(&sset); + (void) sigaddset(&sset, SIGALRM); + (void) sigaddset(&sset, SIGCHLD); + (void) sigaddset(&sset, SIGHUP); + (void) sigaddset(&sset, SIGINT); + (void) sigaddset(&sset, SIGTERM); + (void) sigaddset(&sset, SIGUSR1); + (void) sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL); +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ +} +/* +** SM_SIGNAL_NOOP -- A signal no-op function +** +** Parameters: +** sig -- signal received +** +** Returns: +** SIGFUNC_RETURN +*/ + +/* ARGSUSED */ +SIGFUNC_DECL +sm_signal_noop(sig) + int sig; +{ + int save_errno = errno; + + FIX_SYSV_SIGNAL(sig, sm_signal_noop); + errno = save_errno; + return SIGFUNC_RETURN; +} + diff --git a/gnu/dist/sendmail/libsm/smstdio.c b/gnu/dist/sendmail/libsm/smstdio.c new file mode 100644 index 000000000000..a096de45f7af --- /dev/null +++ b/gnu/dist/sendmail/libsm/smstdio.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: smstdio.c,v 1.32 2002/02/23 20:18:36 gshapiro Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +/* +** Overall: +** This is a file type which implements a layer on top of the system +** stdio. fp->f_cookie is the FILE* of stdio. The cookie may be +** "bound late" because of the manner which Linux implements stdio. +** When binding late (when fp->f_cookie==NULL) then the value of +** fp->f_ival is used (0, 1 or 2) to map to stdio's stdin, stdout or +** stderr. +*/ + +/* +** SM_STDIOOPEN -- open a file to system stdio implementation +** +** Parameters: +** fp -- file pointer assign for this open +** info -- info about file to open +** flags -- indicating method of opening +** rpool -- ignored +** +** Returns: +** Failure: -1 +** Success: 0 (zero) +*/ + +/* ARGSUSED3 */ +int +sm_stdioopen(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + register FILE *s; + char *stdiomode; + + switch (flags) + { + case SM_IO_RDONLY: + stdiomode = "r"; + break; + case SM_IO_WRONLY: + stdiomode = "w"; + break; + case SM_IO_APPEND: + stdiomode = "a"; + break; + case SM_IO_APPENDRW: + stdiomode = "a+"; + break; + case SM_IO_RDWR: + default: + stdiomode = "r+"; + break; + } + + if ((s = fopen((char *)info, stdiomode)) == NULL) + return -1; + fp->f_cookie = s; + return 0; +} + +/* +** SETUP -- assign file type cookie when not already assigned +** +** Parameters: +** fp - the file pointer to get the cookie assigned +** +** Return: +** none. +*/ + +static void +setup(fp) + SM_FILE_T *fp; +{ + if (fp->f_cookie == NULL) + { + switch (fp->f_ival) + { + case 0: + fp->f_cookie = stdin; + break; + case 1: + fp->f_cookie = stdout; + break; + case 2: + fp->f_cookie = stderr; + break; + default: + sm_abort("fp->f_ival=%d: out of range (0...2)", fp->f_ival); + break; + } + } +} + +/* +** SM_STDIOREAD -- read from the file +** +** Parameters: +** fp -- the file pointer +** buf -- location to place the read data +** n - number of bytes to read +** +** Returns: +** result from fread(). +*/ + +ssize_t +sm_stdioread(fp, buf, n) + SM_FILE_T *fp; + char *buf; + size_t n; +{ + register FILE *s; + + if (fp->f_cookie == NULL) + setup(fp); + s = fp->f_cookie; + return fread(buf, 1, n, s); +} + +/* +** SM_STDIOWRITE -- write to the file +** +** Parameters: +** fp -- the file pointer +** buf -- location of data to write +** n - number of bytes to write +** +** Returns: +** result from fwrite(). +*/ + +ssize_t +sm_stdiowrite(fp, buf, n) + SM_FILE_T *fp; + char const *buf; + size_t n; +{ + register FILE *s; + + if (fp->f_cookie == NULL) + setup(fp); + s = fp->f_cookie; + return fwrite(buf, 1, n, s); +} + +/* +** SM_STDIOSEEK -- set position within file +** +** Parameters: +** fp -- the file pointer +** offset -- new location based on 'whence' +** whence -- indicates "base" for 'offset' +** +** Returns: +** result from fseek(). +*/ + +off_t +sm_stdioseek(fp, offset, whence) + SM_FILE_T *fp; + off_t offset; + int whence; +{ + register FILE *s; + + if (fp->f_cookie == NULL) + setup(fp); + s = fp->f_cookie; + return fseek(s, offset, whence); +} + +/* +** SM_STDIOCLOSE -- close the file +** +** Parameters: +** fp -- close file pointer +** +** Return: +** status from fclose() +*/ + +int +sm_stdioclose(fp) + SM_FILE_T *fp; +{ + register FILE *s; + + if (fp->f_cookie == NULL) + setup(fp); + s = fp->f_cookie; + return fclose(s); +} + +/* +** SM_STDIOSETINFO -- set info for this open file +** +** Parameters: +** fp -- the file pointer +** what -- type of information setting +** valp -- memory location of info to set +** +** Return: +** Failure: -1 and sets errno +** Success: none (currently). +*/ + +/* ARGSUSED2 */ +int +sm_stdiosetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch (what) + { + case SM_IO_WHAT_MODE: + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_STDIOGETINFO -- get info for this open file +** +** Parameters: +** fp -- the file pointer +** what -- type of information request +** valp -- memory location to place info +** +** Return: +** Failure: -1 and sets errno +** Success: none (currently). +*/ + +/* ARGSUSED2 */ +int +sm_stdiogetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch (what) + { + case SM_IO_WHAT_SIZE: + { + int fd; + struct stat st; + + if (fp->f_cookie == NULL) + setup(fp); + fd = fileno((FILE *) fp->f_cookie); + if (fd < 0) + return -1; + if (fstat(fd, &st) == 0) + return st.st_size; + else + return -1; + } + + case SM_IO_WHAT_MODE: + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_IO_STDIOOPEN -- create an SM_FILE which interfaces to a stdio FILE +** +** Parameters: +** stream -- an open stdio stream, as returned by fopen() +** mode -- the mode argument to fopen() which describes stream +** +** Return: +** On success, return a pointer to an SM_FILE object which +** can be used for reading and writing 'stream'. +** Abort if mode is gibberish or stream is bad. +** Raise an exception if we can't allocate memory. +*/ + +SM_FILE_T * +sm_io_stdioopen(stream, mode) + FILE *stream; + char *mode; +{ + int fd; + bool r, w; + int ioflags; + SM_FILE_T *fp; + + fd = fileno(stream); + SM_REQUIRE(fd >= 0); + + r = w = false; + switch (mode[0]) + { + case 'r': + r = true; + break; + case 'w': + case 'a': + w = true; + break; + default: + sm_abort("sm_io_stdioopen: mode '%s' is bad", mode); + } + if (strchr(&mode[1], '+') != NULL) + r = w = true; + if (r && w) + ioflags = SMRW; + else if (r) + ioflags = SMRD; + else + ioflags = SMWR; + + fp = sm_fp(SmFtRealStdio, ioflags, NULL); + fp->f_file = fd; + fp->f_cookie = stream; + return fp; +} diff --git a/gnu/dist/sendmail/libsm/snprintf.c b/gnu/dist/sendmail/libsm/snprintf.c new file mode 100644 index 000000000000..8aa8bcea26ec --- /dev/null +++ b/gnu/dist/sendmail/libsm/snprintf.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: snprintf.c,v 1.23 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include +#include "local.h" + +/* +** SM_SNPRINTF -- format a string to a memory location of restricted size +** +** Parameters: +** str -- memory location to place formatted string +** n -- size of buffer pointed to by str, capped to +** a maximum of INT_MAX +** fmt -- the formatting directives +** ... -- the data to satisfy the formatting +** +** Returns: +** Failure: -1 +** Success: number of bytes that would have been written +** to str, not including the trailing '\0', +** up to a maximum of INT_MAX, as if there was +** no buffer size limitation. If the result >= n +** then the output was truncated. +** +** Side Effects: +** If n > 0, then between 0 and n-1 bytes of formatted output +** are written into 'str', followed by a '\0'. +*/ + +int +#if SM_VA_STD +sm_snprintf(char *str, size_t n, char const *fmt, ...) +#else /* SM_VA_STD */ +sm_snprintf(str, n, fmt, va_alist) + char *str; + size_t n; + char *fmt; + va_dcl +#endif /* SM_VA_STD */ +{ + int ret; + SM_VA_LOCAL_DECL + SM_FILE_T fake; + + /* While snprintf(3) specifies size_t stdio uses an int internally */ + if (n > INT_MAX) + n = INT_MAX; + SM_VA_START(ap, fmt); + + /* XXX put this into a static? */ + fake.sm_magic = SmFileMagic; + fake.f_file = -1; + fake.f_flags = SMWR | SMSTR; + fake.f_cookie = &fake; + fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; + fake.f_bf.smb_size = fake.f_w = n ? n - 1 : 0; + fake.f_timeout = SM_TIME_FOREVER; + fake.f_timeoutstate = SM_TIME_BLOCK; + fake.f_close = NULL; + fake.f_open = NULL; + fake.f_read = NULL; + fake.f_write = NULL; + fake.f_seek = NULL; + fake.f_setinfo = fake.f_getinfo = NULL; + fake.f_type = "sm_snprintf:fake"; + ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); + if (n > 0) + *fake.f_p = '\0'; + SM_VA_END(ap); + return ret; +} diff --git a/gnu/dist/sendmail/libsm/sscanf.c b/gnu/dist/sendmail/libsm/sscanf.c new file mode 100644 index 000000000000..23bf1bf93662 --- /dev/null +++ b/gnu/dist/sendmail/libsm/sscanf.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: sscanf.c,v 1.25 2002/02/01 02:28:00 ca Exp") +#include +#include +#include +#include "local.h" + +/* +** SM_EOFREAD -- dummy read function for faked file below +** +** Parameters: +** fp -- file pointer +** buf -- location to place read data +** len -- number of bytes to read +** +** Returns: +** 0 (zero) always +*/ + +static ssize_t +sm_eofread __P(( + SM_FILE_T *fp, + char *buf, + size_t len)); + +/* ARGSUSED0 */ +static ssize_t +sm_eofread(fp, buf, len) + SM_FILE_T *fp; + char *buf; + size_t len; +{ + return 0; +} + +/* +** SM_IO_SSCANF -- scan a string to find data units +** +** Parameters: +** str -- strings containing data +** fmt -- format directive for finding data units +** ... -- memory locations to place format found data units +** +** Returns: +** Failure: SM_IO_EOF +** Success: number of data units found +** +** Side Effects: +** Attempts to strlen() 'str'; if not a '\0' terminated string +** then the call may SEGV/fail. +** Faking the string 'str' as a file. +*/ + +int +#if SM_VA_STD +sm_io_sscanf(const char *str, char const *fmt, ...) +#else /* SM_VA_STD */ +sm_io_sscanf(str, fmt, va_alist) + const char *str; + char *fmt; + va_dcl +#endif /* SM_VA_STD */ +{ + int ret; + SM_FILE_T fake; + SM_VA_LOCAL_DECL + + fake.sm_magic = SmFileMagic; + fake.f_flags = SMRD; + fake.f_bf.smb_base = fake.f_p = (unsigned char *) str; + fake.f_bf.smb_size = fake.f_r = strlen(str); + fake.f_file = -1; + fake.f_read = sm_eofread; + fake.f_write = NULL; + fake.f_close = NULL; + fake.f_open = NULL; + fake.f_seek = NULL; + fake.f_setinfo = fake.f_getinfo = NULL; + fake.f_type = "sm_io_sscanf:fake"; + fake.f_flushfp = NULL; + fake.f_ub.smb_base = NULL; + fake.f_timeout = SM_TIME_FOREVER; + fake.f_timeoutstate = SM_TIME_BLOCK; + SM_VA_START(ap, fmt); + ret = sm_vfscanf(&fake, SM_TIME_FOREVER, fmt, ap); + SM_VA_END(ap); + return ret; +} diff --git a/gnu/dist/sendmail/libsm/stdio.c b/gnu/dist/sendmail/libsm/stdio.c new file mode 100644 index 000000000000..e9f67b5e5997 --- /dev/null +++ b/gnu/dist/sendmail/libsm/stdio.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: stdio.c,v 1.56.2.10 2003/01/10 23:07:17 ca Exp") +#include +#include +#include +#include /* FreeBSD: FD_ZERO needs */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +/* +** Overall: +** Small standard I/O/seek/close functions. +** These maintain the `known seek offset' for seek optimization. +*/ + +/* +** SM_STDOPEN -- open a file with stdio behavior +** +** Not associated with the system's stdio in libc. +** +** Parameters: +** fp -- file pointer to be associated with the open +** info -- pathname of the file to be opened +** flags -- indicates type of access methods +** rpool -- ignored +** +** Returns: +** Failure: -1 and set errno +** Success: 0 or greater (fd of file from open(2)). +** +*/ + +/* ARGSUSED3 */ +int +sm_stdopen(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + char *path = (char *) info; + int oflags; + + switch (flags) + { + case SM_IO_RDWR: + oflags = O_RDWR; + break; + case SM_IO_RDWRTR: + oflags = O_RDWR | O_CREAT | O_TRUNC; + break; + case SM_IO_RDONLY: + oflags = O_RDONLY; + break; + case SM_IO_WRONLY: + oflags = O_WRONLY | O_CREAT | O_TRUNC; + break; + case SM_IO_APPEND: + oflags = O_APPEND | O_WRONLY | O_CREAT; + break; + case SM_IO_APPENDRW: + oflags = O_APPEND | O_RDWR | O_CREAT; + break; + default: + errno = EINVAL; + return -1; + } + fp->f_file = open(path, oflags, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (fp->f_file < 0) + return -1; /* errno set by open() */ + + if (oflags & O_APPEND) + (void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END); + + return fp->f_file; +} + +/* +** SM_STDREAD -- read from the file +** +** Parameters: +** fp -- file pointer to read from +** buf -- location to place read data +** n -- number of bytes to read +** +** Returns: +** Failure: -1 and sets errno +** Success: number of bytes read +** +** Side Effects: +** Updates internal offset into file. +*/ + +ssize_t +sm_stdread(fp, buf, n) + SM_FILE_T *fp; + char *buf; + size_t n; +{ + register int ret; + + ret = read(fp->f_file, buf, n); + + /* if the read succeeded, update the current offset */ + if (ret > 0) + fp->f_lseekoff += ret; + return ret; +} + +/* +** SM_STDWRITE -- write to the file +** +** Parameters: +** fp -- file pointer ro write to +** buf -- location of data to be written +** n - number of bytes to write +** +** Returns: +** Failure: -1 and sets errno +** Success: number of bytes written +*/ + +ssize_t +sm_stdwrite(fp, buf, n) + SM_FILE_T *fp; + char const *buf; + size_t n; +{ + return write(fp->f_file, buf, n); +} + +/* +** SM_STDSEEK -- set the file offset position +** +** Parmeters: +** fp -- file pointer to position +** offset -- how far to position from "base" (set by 'whence') +** whence -- indicates where the "base" of the 'offset' to start +** +** Results: +** Failure: -1 and sets errno +** Success: the current offset +** +** Side Effects: +** Updates the internal value of the offset. +*/ + +off_t +sm_stdseek(fp, offset, whence) + SM_FILE_T *fp; + off_t offset; + int whence; +{ + register off_t ret; + + ret = lseek(fp->f_file, (off_t) offset, whence); + if (ret != (off_t) -1) + fp->f_lseekoff = ret; + return ret; +} + +/* +** SM_STDCLOSE -- close the file +** +** Parameters: +** fp -- the file pointer to close +** +** Returns: +** Success: 0 (zero) +** Failure: -1 and sets errno +*/ + +int +sm_stdclose(fp) + SM_FILE_T *fp; +{ + return close(fp->f_file); +} + +/* +** SM_STDSETMODE -- set the access mode for the file +** +** Called by sm_stdsetinfo(). +** +** Parameters: +** fp -- file pointer +** mode -- new mode to set the file access to +** +** Results: +** Success: 0 (zero); +** Failure: -1 and sets errno +*/ + +int +sm_stdsetmode(fp, mode) + SM_FILE_T *fp; + const int *mode; +{ + int flags = 0; + + switch (*mode) + { + case SM_IO_RDWR: + flags |= SMRW; + break; + case SM_IO_RDONLY: + flags |= SMRD; + break; + case SM_IO_WRONLY: + flags |= SMWR; + break; + case SM_IO_APPEND: + default: + errno = EINVAL; + return -1; + } + fp->f_flags = fp->f_flags & ~SMMODEMASK; + fp->f_flags |= flags; + return 0; +} + +/* +** SM_STDGETMODE -- for getinfo determine open mode +** +** Called by sm_stdgetinfo(). +** +** Parameters: +** fp -- the file mode being determined +** mode -- internal mode to map to external value +** +** Results: +** Failure: -1 and sets errno +** Success: external mode value +*/ + +int +sm_stdgetmode(fp, mode) + SM_FILE_T *fp; + int *mode; +{ + switch (fp->f_flags & SMMODEMASK) + { + case SMRW: + *mode = SM_IO_RDWR; + break; + case SMRD: + *mode = SM_IO_RDONLY; + break; + case SMWR: + *mode = SM_IO_WRONLY; + break; + default: + errno = EINVAL; + return -1; + } + return 0; +} + +/* +** SM_STDSETINFO -- set/modify information for a file +** +** Parameters: +** fp -- file to set info for +** what -- type of info to set +** valp -- location of data used for setting +** +** Returns: +** Failure: -1 and sets errno +** Success: >=0 +*/ + +int +sm_stdsetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch (what) + { + case SM_IO_WHAT_MODE: + return sm_stdsetmode(fp, (const int *)valp); + + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_GETINFO -- get information about the open file +** +** Parameters: +** fp -- file to get info for +** what -- type of info to get +** valp -- location to place found info +** +** Returns: +** Success: may or may not place info in 'valp' depending +** on 'what' value, and returns values >=0. Return +** value may be the obtained info +** Failure: -1 and sets errno +*/ + +int +sm_stdgetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch (what) + { + case SM_IO_WHAT_MODE: + return sm_stdgetmode(fp, (int *)valp); + + case SM_IO_WHAT_FD: + return fp->f_file; + + case SM_IO_WHAT_SIZE: + { + struct stat st; + + if (fstat(fp->f_file, &st) == 0) + return st.st_size; + else + return -1; + } + + case SM_IO_IS_READABLE: + { + fd_set readfds; + struct timeval timeout; + + if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE) + { + errno = EINVAL; + return -1; + } + FD_ZERO(&readfds); + SM_FD_SET(fp->f_file, &readfds); + timeout.tv_sec = 0; + timeout.tv_usec = 0; + if (select(fp->f_file + 1, FDSET_CAST &readfds, + NULL, NULL, &timeout) > 0 && + SM_FD_ISSET(fp->f_file, &readfds)) + return 1; + return 0; + } + + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname +** +** I/O function to handle fdopen() stdio equivalence. The rest of +** the functions are the same as the sm_stdopen() above. +** +** Parameters: +** fp -- the file pointer to be associated with the open +** name -- the primitive file descriptor for association +** flags -- indicates type of access methods +** rpool -- ignored +** +** Results: +** Success: primitive file descriptor value +** Failure: -1 and sets errno +*/ + +/* ARGSUSED3 */ +int +sm_stdfdopen(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + int oflags, tmp, fdflags, fd = *((int *) info); + + switch (flags) + { + case SM_IO_RDWR: + oflags = O_RDWR | O_CREAT; + break; + case SM_IO_RDONLY: + oflags = O_RDONLY; + break; + case SM_IO_WRONLY: + oflags = O_WRONLY | O_CREAT | O_TRUNC; + break; + case SM_IO_APPEND: + oflags = O_APPEND | O_WRONLY | O_CREAT; + break; + case SM_IO_APPENDRW: + oflags = O_APPEND | O_RDWR | O_CREAT; + break; + default: + errno = EINVAL; + return -1; + } + + /* Make sure the mode the user wants is a subset of the actual mode. */ + if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0) + return -1; + tmp = fdflags & O_ACCMODE; + if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) + { + errno = EINVAL; + return -1; + } + fp->f_file = fd; + if (oflags & O_APPEND) + (void) (*fp->f_seek)(fp, (off_t)0, SEEK_END); + return fp->f_file; +} + +/* +** SM_IO_FOPEN -- open a file +** +** Same interface and semantics as the open() system call, +** except that it returns SM_FILE_T* instead of a file descriptor. +** +** Parameters: +** pathname -- path of file to open +** flags -- flags controlling the open +** ... -- option "mode" for opening the file +** +** Returns: +** Raises an exception on heap exhaustion. +** Returns NULL and sets errno if open() fails. +** Returns an SM_FILE_T pointer on success. +*/ + +SM_FILE_T * +#if SM_VA_STD +sm_io_fopen(char *pathname, int flags, ...) +#else /* SM_VA_STD */ +sm_io_fopen(pathname, flags, va_alist) + char *pathname; + int flags; + va_dcl +#endif /* SM_VA_STD */ +{ + MODE_T mode; + SM_FILE_T *fp; + int ioflags; + + if (flags & O_CREAT) + { + SM_VA_LOCAL_DECL + + SM_VA_START(ap, flags); + mode = (MODE_T) SM_VA_ARG(ap, int); + SM_VA_END(ap); + } + else + mode = 0; + + switch (flags & O_ACCMODE) + { + case O_RDONLY: + ioflags = SMRD; + break; + case O_WRONLY: + ioflags = SMWR; + break; + case O_RDWR: + ioflags = SMRW; + break; + default: + sm_abort("sm_io_fopen: bad flags 0%o", flags); + } + + fp = sm_fp(SmFtStdio, ioflags, NULL); + fp->f_file = open(pathname, flags, mode); + if (fp->f_file == -1) + { + fp->f_flags = 0; + fp->sm_magic = NULL; + return NULL; + } + return fp; +} diff --git a/gnu/dist/sendmail/libsm/strcasecmp.c b/gnu/dist/sendmail/libsm/strcasecmp.c new file mode 100644 index 000000000000..9ebd6995258b --- /dev/null +++ b/gnu/dist/sendmail/libsm/strcasecmp.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1987, 1988, 1993 + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: strcasecmp.c,v 1.15 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include + +/* +** SM_STRCASECMP -- 8-bit clean version of strcasecmp +** +** Thank you, vendors, for making this all necessary. +*/ + +/* +** This array is designed for mapping upper and lower case letter +** together for a case independent comparison. The mappings are +** based upon ascii character sequences. +*/ + +const unsigned char charmap[] = +{ + 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, + 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, + 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, + 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, + 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, + 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, + 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, + 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, + 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, +}; + +int +sm_strcasecmp(s1, s2) + const char *s1, *s2; +{ + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + + while (charmap[*us1] == charmap[*us2]) + { + if (*us1 == '\0') + return 0; + ++us1; + ++us2; + } + return charmap[*us1] - charmap[*us2]; +} + +int +sm_strncasecmp(s1, s2, n) + const char *s1, *s2; + register size_t n; +{ + if (n != 0) + { + register const unsigned char *cm = charmap; + register const unsigned char *us1 = (const unsigned char *)s1; + register const unsigned char *us2 = (const unsigned char *)s2; + + do + { + if (cm[*us1] != cm[*us2++]) + return (cm[*us1] - cm[*--us2]); + if (*us1++ == '\0') + break; + } while (--n != 0); + } + return 0; +} diff --git a/gnu/dist/sendmail/libsm/strdup.c b/gnu/dist/sendmail/libsm/strdup.c new file mode 100644 index 000000000000..88b4aa831518 --- /dev/null +++ b/gnu/dist/sendmail/libsm/strdup.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: strdup.c,v 1.13 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include + +/* +** SM_STRNDUP_X -- Duplicate a string of a given length +** +** Allocates memory and copies source string (of given length) into it. +** +** Parameters: +** s -- string to copy. +** n -- length to copy. +** +** Returns: +** copy of string, raises exception if out of memory. +** +** Side Effects: +** allocate memory for new string. +*/ + +char * +sm_strndup_x(s, n) + const char *s; + size_t n; +{ + char *d = sm_malloc_x(n + 1); + + (void) memcpy(d, s, n); + d[n] = '\0'; + return d; +} + +/* +** SM_STRDUP -- Duplicate a string +** +** Allocates memory and copies source string into it. +** +** Parameters: +** s -- string to copy. +** +** Returns: +** copy of string, NULL if out of memory. +** +** Side Effects: +** allocate memory for new string. +*/ + +char * +sm_strdup(s) + char *s; +{ + size_t l; + char *d; + + l = strlen(s) + 1; + d = sm_malloc_tagged(l, "sm_strdup", 0, sm_heap_group()); + if (d != NULL) + (void) sm_strlcpy(d, s, l); + return d; +} diff --git a/gnu/dist/sendmail/libsm/strerror.c b/gnu/dist/sendmail/libsm/strerror.c new file mode 100644 index 000000000000..116cee50d32c --- /dev/null +++ b/gnu/dist/sendmail/libsm/strerror.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2000-2001 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. + * + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: strerror.c,v 1.23 2001/09/11 04:04:49 gshapiro Exp") + +/* +** define strerror for platforms that lack it. +*/ + +#include +#include /* sys_errlist, on some platforms */ + +#include /* sm_snprintf */ +#include +#include +#include + +#if !defined(ERRLIST_PREDEFINED) +extern char *sys_errlist[]; +extern int sys_nerr; +#endif /* !defined(ERRLIST_PREDEFINED) */ + +#if !HASSTRERROR + +/* +** STRERROR -- return error message string corresponding to an error number. +** +** Parameters: +** err -- error number. +** +** Returns: +** Error string (might be pointer to static buffer). +*/ + +char * +strerror(err) + int err; +{ + static char buf[64]; + + if (err >= 0 && err < sys_nerr) + return (char *) sys_errlist[err]; + else + { + (void) sm_snprintf(buf, sizeof(buf), "Error %d", err); + return buf; + } +} +#endif /* !HASSTRERROR */ diff --git a/gnu/dist/sendmail/libsm/strexit.c b/gnu/dist/sendmail/libsm/strexit.c new file mode 100644 index 000000000000..01de8c44c6ee --- /dev/null +++ b/gnu/dist/sendmail/libsm/strexit.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: strexit.c,v 1.5 2001/09/11 04:04:49 gshapiro Exp") +#include +#include + +/* +** SM_STREXIT -- convert EX_* value from to a character string +** +** This function is analogous to strerror(), except that it +** operates on EX_* values from . +** +** Parameters: +** ex -- EX_* value +** +** Results: +** pointer to a static message string +*/ + +char * +sm_strexit(ex) + int ex; +{ + char *msg; + static char buf[64]; + + msg = sm_sysexitmsg(ex); + if (msg == NULL) + { + (void) sm_snprintf(buf, sizeof buf, "Unknown exit status %d", + ex); + msg = buf; + } + return msg; +} + +/* +** SM_SYSEXITMSG -- convert an EX_* value to a character string, or NULL +** +** Parameters: +** ex -- EX_* value +** +** Results: +** If ex is a known exit value, then a pointer to a static +** message string is returned. Otherwise NULL is returned. +*/ + +char * +sm_sysexitmsg(ex) + int ex; +{ + char *msg; + + msg = sm_sysexmsg(ex); + if (msg != NULL) + return &msg[11]; + else + return msg; +} + +/* +** SM_SYSEXMSG -- convert an EX_* value to a character string, or NULL +** +** Parameters: +** ex -- EX_* value +** +** Results: +** If ex is a known exit value, then a pointer to a static +** string is returned. Otherwise NULL is returned. +** The string contains the following fixed width fields: +** [0] ':' if there is an errno value associated with this +** exit value, otherwise ' '. +** [1,3] 3 digit SMTP error code +** [4] ' ' +** [5,9] 3 digit SMTP extended error code +** [10] ' ' +** [11,] message string +*/ + +char * +sm_sysexmsg(ex) + int ex; +{ + switch (ex) + { + case EX_USAGE: + return " 500 5.0.0 Command line usage error"; + case EX_DATAERR: + return " 501 5.6.0 Data format error"; + case EX_NOINPUT: + return ":550 5.3.0 Cannot open input"; + case EX_NOUSER: + return " 550 5.1.1 User unknown"; + case EX_NOHOST: + return " 550 5.1.2 Host unknown"; + case EX_UNAVAILABLE: + return " 554 5.0.0 Service unavailable"; + case EX_SOFTWARE: + return ":554 5.3.0 Internal error"; + case EX_OSERR: + return ":451 4.0.0 Operating system error"; + case EX_OSFILE: + return ":554 5.3.5 System file missing"; + case EX_CANTCREAT: + return ":550 5.0.0 Can't create output"; + case EX_IOERR: + return ":451 4.0.0 I/O error"; + case EX_TEMPFAIL: + return " 450 4.0.0 Deferred"; + case EX_PROTOCOL: + return " 554 5.5.0 Remote protocol error"; + case EX_NOPERM: + return ":550 5.0.0 Insufficient permission"; + case EX_CONFIG: + return " 554 5.3.5 Local configuration error"; + default: + return NULL; + } +} diff --git a/gnu/dist/sendmail/libsm/string.c b/gnu/dist/sendmail/libsm/string.c new file mode 100644 index 000000000000..9149c4df65dd --- /dev/null +++ b/gnu/dist/sendmail/libsm/string.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: string.c,v 1.3 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include + +#include + +/* +** STRIPQUOTES -- Strip quotes & quote bits from a string. +** +** Runs through a string and strips off unquoted quote +** characters and quote bits. This is done in place. +** +** Parameters: +** s -- the string to strip. +** +** Returns: +** none. +** +** Side Effects: +** none. +*/ + +void +stripquotes(s) + char *s; +{ + register char *p; + register char *q; + register char c; + + if (s == NULL) + return; + + p = q = s; + do + { + c = *p++; + if (c == '\\') + c = *p++; + else if (c == '"') + continue; + *q++ = c; + } while (c != '\0'); +} diff --git a/gnu/dist/sendmail/libsm/stringf.c b/gnu/dist/sendmail/libsm/stringf.c new file mode 100644 index 000000000000..21a24a1267ba --- /dev/null +++ b/gnu/dist/sendmail/libsm/stringf.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: stringf.c,v 1.15 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include +#include +#include +#include + +/* +** SM_STRINGF_X -- printf() to dynamically allocated string. +** +** Takes the same arguments as printf. +** It returns a pointer to a dynamically allocated string +** containing the text that printf would print to standard output. +** It raises an exception on error. +** The name comes from a PWB Unix function called stringf. +** +** Parameters: +** fmt -- format string. +** ... -- arguments for format. +** +** Returns: +** Pointer to a dynamically allocated string. +** +** Exceptions: +** F:sm_heap -- out of memory (via sm_vstringf_x()). +*/ + +char * +#if SM_VA_STD +sm_stringf_x(const char *fmt, ...) +#else /* SM_VA_STD */ +sm_stringf_x(fmt, va_alist) + const char *fmt; + va_dcl +#endif /* SM_VA_STD */ +{ + SM_VA_LOCAL_DECL + char *s; + + SM_VA_START(ap, fmt); + s = sm_vstringf_x(fmt, ap); + SM_VA_END(ap); + return s; +} + +/* +** SM_VSTRINGF_X -- printf() to dynamically allocated string. +** +** Parameters: +** fmt -- format string. +** ap -- arguments for format. +** +** Returns: +** Pointer to a dynamically allocated string. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +char * +sm_vstringf_x(fmt, ap) + const char *fmt; + SM_VA_LOCAL_DECL +{ + char *s; + + sm_vasprintf(&s, fmt, ap); + if (s == NULL) + { + if (errno == ENOMEM) + sm_exc_raise_x(&SmHeapOutOfMemory); + sm_exc_raisenew_x(&SmEtypeOs, errno, "sm_vasprintf", NULL); + } + return s; +} diff --git a/gnu/dist/sendmail/libsm/strio.c b/gnu/dist/sendmail/libsm/strio.c new file mode 100644 index 000000000000..66e171d4f46e --- /dev/null +++ b/gnu/dist/sendmail/libsm/strio.c @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: strio.c,v 1.42 2002/02/11 23:05:50 gshapiro Exp") +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +/* +** Cookie structure for the "strio" file type +*/ + +struct sm_str_obj +{ + char *strio_base; + char *strio_end; + size_t strio_size; + size_t strio_offset; + int strio_flags; + const void *strio_rpool; +}; + +typedef struct sm_str_obj SM_STR_OBJ_T; + +/* +** SM_STRGROW -- increase storage space for string +** +** Parameters: +** s -- current cookie +** size -- new storage size request +** +** Returns: +** true iff successful. +*/ + +static bool sm_strgrow __P((SM_STR_OBJ_T *, size_t)); + +static bool +sm_strgrow(s, size) + SM_STR_OBJ_T *s; + size_t size; +{ + register void *p; + + if (s->strio_size >= size) + return true; + p = sm_realloc(s->strio_base, size); + if (p == NULL) + return false; + s->strio_base = p; + s->strio_end = s->strio_base + size; + s->strio_size = size; + return true; +} + +/* +** SM_STRREAD -- read a portion of the string +** +** Parameters: +** fp -- the file pointer +** buf -- location to place read data +** n -- number of bytes to read +** +** Returns: +** Failure: -1 and sets errno +** Success: >=0, number of bytes read +*/ + +ssize_t +sm_strread(fp, buf, n) + SM_FILE_T *fp; + char *buf; + size_t n; +{ + register SM_STR_OBJ_T *s = fp->f_cookie; + int len; + + if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW)) + { + errno = EBADF; + return -1; + } + len = SM_MIN(s->strio_size - s->strio_offset, n); + (void) memmove(buf, s->strio_base + s->strio_offset, len); + s->strio_offset += len; + return len; +} + +/* +** SM_STRWRITE -- write a portion of the string +** +** Parameters: +** fp -- the file pointer +** buf -- location of data for writing +** n -- number of bytes to write +** +** Returns: +** Failure: -1 and sets errno +** Success: >=0, number of bytes written +*/ + +ssize_t +sm_strwrite(fp, buf, n) + SM_FILE_T *fp; + char const *buf; + size_t n; +{ + register SM_STR_OBJ_T *s = fp->f_cookie; + + if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW)) + { + errno = EBADF; + return -1; + } + if (n + s->strio_offset > s->strio_size) + { + if (!sm_strgrow(s, n + s->strio_offset)) + return 0; + } + (void) memmove(s->strio_base + s->strio_offset, buf, n); + s->strio_offset += n; + return n; +} + +/* +** SM_STRSEEK -- position the offset pointer for the string +** +** Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid +** values for whence. +** +** Parameters: +** fp -- the file pointer +** offset -- number of bytes offset from "base" +** whence -- determines "base" for 'offset' +** +** Returns: +** Failure: -1 and sets errno +** Success: >=0, number of bytes read +*/ + +off_t +sm_strseek(fp, offset, whence) + SM_FILE_T *fp; + off_t offset; + int whence; +{ + register off_t ret; + register SM_STR_OBJ_T *s = fp->f_cookie; + +reseek: + switch (whence) + { + case SM_IO_SEEK_SET: + ret = offset; + break; + case SM_IO_SEEK_CUR: + ret = s->strio_offset + offset; + break; + case SM_IO_SEEK_END: + ret = s->strio_size; + break; + default: + errno = EINVAL; + return -1; + } + if (ret < 0 || ret > (off_t)(size_t)(-1)) /* XXX ugly */ + return -1; + if ((size_t) ret > s->strio_size) + { + if (sm_strgrow(s, (size_t)ret)) + goto reseek; + + /* errno set by sm_strgrow */ + return -1; + } + s->strio_offset = (size_t) ret; + return ret; +} + +/* +** SM_STROPEN -- open a string file type +** +** Parameters: +** fp -- file pointer open to be associated with +** info -- initial contents (NULL for none) +** flags -- flags for methods of access (was mode) +** rpool -- resource pool to use memory from (if applicable) +** +** Results: +** Success: 0 (zero) +** Failure: -1 and sets errno +*/ + +int +sm_stropen(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + register SM_STR_OBJ_T *s; + +#if SM_RPOOL + s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T)); +#else /* SM_RPOOL */ + s = sm_malloc(sizeof(SM_STR_OBJ_T)); + if (s == NULL) + return -1; +#endif /* SM_RPOOL */ + + fp->f_cookie = s; + s->strio_rpool = rpool; + s->strio_offset = 0; + s->strio_size = 0; + s->strio_base = NULL; + s->strio_end = 0; + + switch (flags) + { + case SM_IO_RDWR: + s->strio_flags = SMRW; + break; + case SM_IO_RDONLY: + s->strio_flags = SMRD; + break; + case SM_IO_WRONLY: + s->strio_flags = SMWR; + break; + case SM_IO_APPEND: + if (s->strio_rpool == NULL) + sm_free(s); + errno = EINVAL; + return -1; + default: + if (s->strio_rpool == NULL) + sm_free(s); + errno = EINVAL; + return -1; + } + + if (info != NULL) + { + s->strio_base = sm_strdup_x(info); + if (s->strio_base == NULL) + { + int save_errno = errno; + + if (s->strio_rpool == NULL) + sm_free(s); + errno = save_errno; + return -1; + } + s->strio_size = strlen(info); + s->strio_end = s->strio_base + s->strio_size; + } + return 0; +} + +/* +** SM_STRCLOSE -- close the string file type and free resources +** +** Parameters: +** fp -- file pointer +** +** Results: +** Success: 0 (zero) +*/ + +int +sm_strclose(fp) + SM_FILE_T *fp; +{ + SM_STR_OBJ_T *s = fp->f_cookie; + +#if !SM_RPOOL + sm_free(s->strio_base); + s->strio_base = NULL; +#endif /* !SM_RPOOL */ + return 0; +} + +/* +** SM_STRSETMODE -- set mode info for the file +** +** Note: changing the mode can be a safe way to have the "parent" +** set up a string that the "child" is not to modify +** +** Parameters: +** fp -- the file pointer +** mode -- location of new mode to set +** +** Results: +** Success: 0 (zero) +** Failure: -1 and sets errno +*/ + +int +sm_strsetmode(fp, mode) + SM_FILE_T *fp; + const int *mode; +{ + register SM_STR_OBJ_T *s = fp->f_cookie; + int flags; + + switch (*mode) + { + case SM_IO_RDWR: + flags = SMRW; + break; + case SM_IO_RDONLY: + flags = SMRD; + break; + case SM_IO_WRONLY: + flags = SMWR; + break; + case SM_IO_APPEND: + errno = EINVAL; + return -1; + default: + errno = EINVAL; + return -1; + } + s->strio_flags &= ~SMMODEMASK; + s->strio_flags |= flags; + return 0; +} + +/* +** SM_STRGETMODE -- get mode info for the file +** +** Parameters: +** fp -- the file pointer +** mode -- location to store current mode +** +** Results: +** Success: 0 (zero) +** Failure: -1 and sets errno +*/ + +int +sm_strgetmode(fp, mode) + SM_FILE_T *fp; + int *mode; +{ + register SM_STR_OBJ_T *s = fp->f_cookie; + + switch (s->strio_flags & SMMODEMASK) + { + case SMRW: + *mode = SM_IO_RDWR; + break; + case SMRD: + *mode = SM_IO_RDONLY; + break; + case SMWR: + *mode = SM_IO_WRONLY; + break; + default: + errno = EINVAL; + return -1; + } + return 0; +} + +/* +** SM_STRSETINFO -- set info for the file +** +** Currently only SM_IO_WHAT_MODE is supported for 'what'. +** +** Parameters: +** fp -- the file pointer +** what -- type of information to set +** valp -- location to data for doing set +** +** Results: +** Failure: -1 and sets errno +** Success: sm_strsetmode() return [0 (zero)] +*/ + +int +sm_strsetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch(what) + { + case SM_IO_WHAT_MODE: + return sm_strsetmode(fp, (int *) valp); + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_STRGETINFO -- get info for the file +** +** Currently only SM_IO_WHAT_MODE is supported for 'what'. +** +** Parameters: +** fp -- the file pointer +** what -- type of information requested +** valp -- location to return information in +** +** Results: +** Failure: -1 and sets errno +** Success: sm_strgetmode() return [0 (zero)] +*/ + +int +sm_strgetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch(what) + { + case SM_IO_WHAT_MODE: + return sm_strgetmode(fp, (int *) valp); + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_STRIO_INIT -- initializes a write-only string type +** +** Original comments below. This function does not appear to be used anywhere. +** The same functionality can be done by changing the mode of the file. +** ------------ +** sm_strio_init initializes an SM_FILE_T structure as a write-only file +** that writes into the specified buffer: +** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer. +** Attempts to write more than size-1 characters into the buffer will fail +** silently (no error is reported). +** - Use sm_io_fflush to nul terminate the string in the buffer +** (the write pointer is not advanced). +** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc. +** +** Parameters: +** fp -- file pointer +** buf -- memory location for stored data +** size -- size of 'buf' +** +** Results: +** none. +*/ + +void +sm_strio_init(fp, buf, size) + SM_FILE_T *fp; + char *buf; + size_t size; +{ + fp->sm_magic = SmFileMagic; + fp->f_flags = SMWR | SMSTR; + fp->f_file = -1; + fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf; + fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0); + fp->f_lbfsize = 0; + fp->f_r = 0; + fp->f_read = NULL; + fp->f_seek = NULL; + fp->f_getinfo = NULL; + fp->f_setinfo = NULL; +} diff --git a/gnu/dist/sendmail/libsm/strl.c b/gnu/dist/sendmail/libsm/strl.c new file mode 100644 index 000000000000..3f21e9c4ec2e --- /dev/null +++ b/gnu/dist/sendmail/libsm/strl.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: strl.c,v 1.31 2002/01/20 01:41:25 gshapiro Exp") +#include +#include + +/* +** Notice: this file is used by libmilter. Please try to avoid +** using libsm specific functions. +*/ + +/* +** XXX the type of the length parameter has been changed +** from size_t to ssize_t to avoid theoretical problems with negative +** numbers passed into these functions. +** The real solution to this problem is to make sure that this doesn't +** happen, but for now we'll use this workaround. +*/ + +/* +** SM_STRLCPY -- size bounded string copy +** +** This is a bounds-checking variant of strcpy. +** If size > 0, copy up to size-1 characters from the nul terminated +** string src to dst, nul terminating the result. If size == 0, +** the dst buffer is not modified. +** Additional note: this function has been "tuned" to run fast and tested +** as such (versus versions in some OS's libc). +** +** The result is strlen(src). You can detect truncation (not all +** of the characters in the source string were copied) using the +** following idiom: +** +** char *s, buf[BUFSIZ]; +** ... +** if (sm_strlcpy(buf, s, sizeof(buf)) >= sizeof(buf)) +** goto overflow; +** +** Parameters: +** dst -- destination buffer +** src -- source string +** size -- size of destination buffer +** +** Returns: +** strlen(src) +*/ + +size_t +sm_strlcpy(dst, src, size) + register char *dst; + register const char *src; + ssize_t size; +{ + register ssize_t i; + + if (size-- <= 0) + return strlen(src); + for (i = 0; i < size && (dst[i] = src[i]) != 0; i++) + continue; + dst[i] = '\0'; + if (src[i] == '\0') + return i; + else + return i + strlen(src + i); +} + +/* +** SM_STRLCAT -- size bounded string concatenation +** +** This is a bounds-checking variant of strcat. +** If strlen(dst) < size, then append at most size - strlen(dst) - 1 +** characters from the source string to the destination string, +** nul terminating the result. Otherwise, dst is not modified. +** +** The result is the initial length of dst + the length of src. +** You can detect overflow (not all of the characters in the +** source string were copied) using the following idiom: +** +** char *s, buf[BUFSIZ]; +** ... +** if (sm_strlcat(buf, s, sizeof(buf)) >= sizeof(buf)) +** goto overflow; +** +** Parameters: +** dst -- nul-terminated destination string buffer +** src -- nul-terminated source string +** size -- size of destination buffer +** +** Returns: +** total length of the string tried to create +** (= initial length of dst + length of src) +*/ + +size_t +sm_strlcat(dst, src, size) + register char *dst; + register const char *src; + ssize_t size; +{ + register ssize_t i, j, o; + + o = strlen(dst); + if (size < o + 1) + return o + strlen(src); + size -= o + 1; + for (i = 0, j = o; i < size && (dst[j] = src[i]) != 0; i++, j++) + continue; + dst[j] = '\0'; + if (src[i] == '\0') + return j; + else + return j + strlen(src + i); +} +/* +** SM_STRLCAT2 -- append two strings to dst obeying length and +** '\0' terminate it +** +** strlcat2 will append at most len - strlen(dst) - 1 chars. +** terminates with '\0' if len > 0 +** dst = dst "+" src1 "+" src2 +** use this instead of sm_strlcat(dst,src1); sm_strlcat(dst,src2); +** for better speed. +** +** Parameters: +** dst -- "destination" string. +** src1 -- "from" string 1. +** src2 -- "from" string 2. +** len -- max. length of "destination" string. +** +** Returns: +** total length of the string tried to create +** (= initial length of dst + length of src) +** if this is greater than len then an overflow would have +** occurred. +** +*/ + +size_t +sm_strlcat2(dst, src1, src2, len) + register char *dst; + register const char *src1; + register const char *src2; + ssize_t len; +{ + register ssize_t i, j, o; + + /* current size of dst */ + o = strlen(dst); + + /* max. size is less than current? */ + if (len < o + 1) + return o + strlen(src1) + strlen(src2); + + len -= o + 1; /* space left in dst */ + + /* copy the first string; i: index in src1; j: index in dst */ + for (i = 0, j = o; i < len && (dst[j] = src1[i]) != 0; i++, j++) + continue; + + /* src1: end reached? */ + if (src1[i] != '\0') + { + /* no: terminate dst; there is space since i < len */ + dst[j] = '\0'; + return j + strlen(src1 + i) + strlen(src2); + } + + len -= i; /* space left in dst */ + + /* copy the second string; i: index in src2; j: index in dst */ + for (i = 0; i < len && (dst[j] = src2[i]) != 0; i++, j++) + continue; + dst[j] = '\0'; /* terminate dst; there is space since i < len */ + if (src2[i] == '\0') + return j; + else + return j + strlen(src2 + i); +} + +/* +** SM_STRLCPYN -- concatenate n strings and assign the result to dst +** while obeying length and '\0' terminate it +** +** dst = src1 "+" src2 "+" ... +** use this instead of sm_snprintf() for string values +** and repeated sm_strlc*() calls for better speed. +** +** Parameters: +** dst -- "destination" string. +** len -- max. length of "destination" string. +** n -- number of strings +** strings... +** +** Returns: +** total length of the string tried to create +** (= initial length of dst + length of src) +** if this is greater than len then an overflow would have +** occurred. +*/ + +size_t +#ifdef __STDC__ +sm_strlcpyn(char *dst, ssize_t len, int n, ...) +#else /* __STDC__ */ +sm_strlcpyn(dst, len, n, va_alist) + register char *dst; + ssize_t len; + int n; + va_dcl +#endif /* __STDC__ */ +{ + register ssize_t i, j; + char *str; + SM_VA_LOCAL_DECL + + SM_VA_START(ap, n); + + if (len-- <= 0) /* This allows space for the terminating '\0' */ + { + i = 0; + while (n-- > 0) + i += strlen(SM_VA_ARG(ap, char *)); + SM_VA_END(ap); + return i; + } + + j = 0; /* index in dst */ + + /* loop through all source strings */ + while (n-- > 0) + { + str = SM_VA_ARG(ap, char *); + + /* copy string; i: index in str; j: index in dst */ + for (i = 0; j < len && (dst[j] = str[i]) != 0; i++, j++) + continue; + + /* str: end reached? */ + if (str[i] != '\0') + { + /* no: terminate dst; there is space since j < len */ + dst[j] = '\0'; + j += strlen(str + i); + while (n-- > 0) + j += strlen(SM_VA_ARG(ap, char *)); + SM_VA_END(ap); + return j; + } + } + SM_VA_END(ap); + + dst[j] = '\0'; /* terminate dst; there is space since j < len */ + return j; +} + +#if 0 +/* +** SM_STRLAPP -- append string if it fits into buffer. +** +** If size > 0, copy up to size-1 characters from the nul terminated +** string src to dst, nul terminating the result. If size == 0, +** the dst buffer is not modified. +** +** This routine is useful for appending strings in a loop, e.g, instead of +** s = buf; +** for (ptr, ptr != NULL, ptr = next->ptr) +** { +** (void) sm_strlcpy(s, ptr->string, sizeof buf - (s - buf)); +** s += strlen(s); +** } +** replace the loop body with: +** if (!sm_strlapp(*s, ptr->string, sizeof buf - (s - buf))) +** break; +** it's faster... +** +** XXX interface isn't completely clear (yet), hence this code is +** not available. +** +** +** Parameters: +** dst -- (pointer to) destination buffer +** src -- source string +** size -- size of destination buffer +** +** Returns: +** true if strlen(src) < size +** +** Side Effects: +** modifies dst if append succeeds (enough space). +*/ + +bool +sm_strlapp(dst, src, size) + register char **dst; + register const char *src; + ssize_t size; +{ + register size_t i; + + if (size-- <= 0) + return false; + for (i = 0; i < size && ((*dst)[i] = src[i]) != '\0'; i++) + continue; + (*dst)[i] = '\0'; + if (src[i] == '\0') + { + *dst += i; + return true; + } + + /* undo */ + (*dst)[0] = '\0'; + return false; +} +#endif /* 0 */ diff --git a/gnu/dist/sendmail/libsm/strrevcmp.c b/gnu/dist/sendmail/libsm/strrevcmp.c new file mode 100644 index 000000000000..3853f828d973 --- /dev/null +++ b/gnu/dist/sendmail/libsm/strrevcmp.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: strrevcmp.c,v 1.5 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include + +/* strcasecmp.c */ +extern const unsigned char charmap[]; + +/* +** SM_STRREVCASECMP -- compare two strings starting at the end (ignore case) +** +** Parameters: +** s1 -- first string. +** s2 -- second string. +** +** Returns: +** strcasecmp(reverse(s1), reverse(s2)) +*/ + +int +sm_strrevcasecmp(s1, s2) + const char *s1, *s2; +{ + register int i1, i2; + + i1 = strlen(s1) - 1; + i2 = strlen(s2) - 1; + while (i1 >= 0 && i2 >= 0 && + charmap[(unsigned char) s1[i1]] == + charmap[(unsigned char) s2[i2]]) + { + --i1; + --i2; + } + if (i1 < 0) + { + if (i2 < 0) + return 0; + else + return -1; + } + else + { + if (i2 < 0) + return 1; + else + return (charmap[(unsigned char) s1[i1]] - + charmap[(unsigned char) s2[i2]]); + } +} +/* +** SM_STRREVCMP -- compare two strings starting at the end +** +** Parameters: +** s1 -- first string. +** s2 -- second string. +** +** Returns: +** strcmp(reverse(s1), reverse(s2)) +*/ + +int +sm_strrevcmp(s1, s2) + const char *s1, *s2; +{ + register int i1, i2; + + i1 = strlen(s1) - 1; + i2 = strlen(s2) - 1; + while (i1 >= 0 && i2 >= 0 && s1[i1] == s2[i2]) + { + --i1; + --i2; + } + if (i1 < 0) + { + if (i2 < 0) + return 0; + else + return -1; + } + else + { + if (i2 < 0) + return 1; + else + return s1[i1] - s2[i2]; + } +} diff --git a/gnu/dist/sendmail/libsm/strto.c b/gnu/dist/sendmail/libsm/strto.c new file mode 100644 index 000000000000..b10cac7ae91a --- /dev/null +++ b/gnu/dist/sendmail/libsm/strto.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1992 + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: strto.c,v 1.18 2001/12/30 04:59:37 gshapiro Exp") + +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** SM_STRTOLL -- Convert a string to a (signed) long long integer. +** +** Ignores `locale' stuff. Assumes that the upper and lower case +** alphabets and digits are each contiguous. +** +** Parameters: +** nptr -- string containing number +** endptr -- location of first invalid character +** base -- numeric base that 'nptr' number is based in +** +** Returns: +** Failure: on underflow LLONG_MIN is returned; on overflow +** LLONG_MAX is returned and errno is set. +** When 'endptr' == '\0' then the entire string 'nptr' +** was valid. +** Success: returns the converted number +*/ + +LONGLONG_T +sm_strtoll(nptr, endptr, base) + const char *nptr; + char **endptr; + register int base; +{ + register bool neg; + register const char *s; + register LONGLONG_T acc, cutoff; + register int c; + register int any, cutlim; + + /* + ** Skip white space and pick up leading +/- sign if any. + ** If base is 0, allow 0x for hex and 0 for octal, else + ** assume decimal; if base is already 16, allow 0x. + */ + + s = nptr; + do + { + c = (unsigned char) *s++; + } while (isascii(c) && isspace(c)); + if (c == '-') + { + neg = true; + c = *s++; + } + else + { + neg = false; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + ** Compute the cutoff value between legal numbers and illegal + ** numbers. That is the largest legal value, divided by the + ** base. An input number that is greater than this value, if + ** followed by a legal input character, is too big. One that + ** is equal to this value may be valid or not; the limit + ** between valid and invalid numbers is then based on the last + ** digit. For instance, if the range for long-long's is + ** [-9223372036854775808..9223372036854775807] and the input base + ** is 10, cutoff will be set to 922337203685477580 and cutlim to + ** either 7 (!neg) or 8 (neg), meaning that if we have + ** accumulated a value > 922337203685477580, or equal but the + ** next digit is > 7 (or 8), the number is too big, and we will + ** return a range error. + ** + ** Set any if any `digits' consumed; make it negative to indicate + ** overflow. + */ + + cutoff = neg ? LLONG_MIN : LLONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + if (neg) + { + if (cutlim > 0) + { + cutlim -= base; + cutoff += 1; + } + cutlim = -cutlim; + } + for (acc = 0, any = 0;; c = (unsigned char) *s++) + { + if (isascii(c) && isdigit(c)) + c -= '0'; + else if (isascii(c) && isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0) + continue; + if (neg) + { + if (acc < cutoff || (acc == cutoff && c > cutlim)) + { + any = -1; + acc = LLONG_MIN; + errno = ERANGE; + } + else + { + any = 1; + acc *= base; + acc -= c; + } + } + else + { + if (acc > cutoff || (acc == cutoff && c > cutlim)) + { + any = -1; + acc = LLONG_MAX; + errno = ERANGE; + } + else + { + any = 1; + acc *= base; + acc += c; + } + } + } + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return acc; +} + +/* +** SM_STRTOULL -- Convert a string to an unsigned long long integer. +** +** Ignores `locale' stuff. Assumes that the upper and lower case +** alphabets and digits are each contiguous. +** +** Parameters: +** nptr -- string containing (unsigned) number +** endptr -- location of first invalid character +** base -- numeric base that 'nptr' number is based in +** +** Returns: +** Failure: on overflow ULLONG_MAX is returned and errno is set. +** When 'endptr' == '\0' then the entire string 'nptr' +** was valid. +** Success: returns the converted number +*/ + +ULONGLONG_T +sm_strtoull(nptr, endptr, base) + const char *nptr; + char **endptr; + register int base; +{ + register const char *s; + register ULONGLONG_T acc, cutoff; + register int c; + register bool neg; + register int any, cutlim; + + /* See sm_strtoll for comments as to the logic used. */ + s = nptr; + do + { + c = (unsigned char) *s++; + } while (isascii(c) && isspace(c)); + neg = (c == '-'); + if (neg) + { + c = *s++; + } + else + { + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + cutoff = ULLONG_MAX / (ULONGLONG_T)base; + cutlim = ULLONG_MAX % (ULONGLONG_T)base; + for (acc = 0, any = 0;; c = (unsigned char) *s++) + { + if (isascii(c) && isdigit(c)) + c -= '0'; + else if (isascii(c) && isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0) + continue; + if (acc > cutoff || (acc == cutoff && c > cutlim)) + { + any = -1; + acc = ULLONG_MAX; + errno = ERANGE; + } + else + { + any = 1; + acc *= (ULONGLONG_T)base; + acc += c; + } + } + if (neg && any > 0) + acc = -((LONGLONG_T) acc); + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return acc; +} diff --git a/gnu/dist/sendmail/libsm/syslogio.c b/gnu/dist/sendmail/libsm/syslogio.c new file mode 100644 index 000000000000..c6404ccb9990 --- /dev/null +++ b/gnu/dist/sendmail/libsm/syslogio.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: syslogio.c,v 1.29 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include +#include +#include +#ifdef SM_RPOOL +# include +#endif /* SM_RPOOL */ +#include +#include "local.h" + +/* +** Overall: +** This is a output file type that copies its output to the syslog daemon. +** Each line of output is written as a separate syslog message. +** The client is responsible for calling openlog() before writing to +** any syslog file, and calling closelog() after all syslog output is complete. +** The only state associated with a syslog file is 'int priority', +** which we store in fp->f_ival. +*/ + +/* +** SM_SYSLOGOPEN -- open a file pointer to syslog +** +** Parameters: +** fp -- file pointer assigned for the open +** info -- priority level of the syslog messages +** flags -- not used +** rpool -- ignored +** +** Returns: +** 0 (zero) success always (see Overall) +*/ + +int +sm_syslogopen(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + int *priority = (int *)info; + + fp->f_ival = *priority; + return 0; +} + +/* +** SM_SYSLOGREAD -- read function for syslog +** +** This is a "stub" function (placeholder) that always returns an error. +** It is an error to read syslog. +** +** Parameters: +** fp -- the file pointer +** buf -- buffer to place the data read +** n -- number of bytes to read +** +** Returns: +** -1 (error) always and sets errno +*/ + +ssize_t +sm_syslogread(fp, buf, n) + SM_FILE_T *fp; + char *buf; + size_t n; +{ + /* an error to read */ + errno = ENODEV; + return -1; +} + +/* +** SM_SYSLOGWRITE -- write function for syslog +** +** Send output to syslog. +** +** Parameters: +** fp -- the file pointer +** buf -- buffer that the write data comes from +** n -- number of bytes to write +** +** Returns: +** 0 (zero) for success always +*/ + +/* +** XXX TODO: more work needs to be done to ensure that each line of output +** XXX written to a syslog file is mapped to exactly one syslog message. +*/ +ssize_t +sm_syslogwrite(fp, buf, n) + SM_FILE_T *fp; + char const *buf; + size_t n; +{ + syslog(fp->f_ival, "%s", buf); + return 0; +} + +/* +** SM_SYSLOGSEEK -- position the syslog file offset +** +** This is a "stub" function (placeholder) that always returns an error. +** It is an error to seek syslog. +** +** Parameters: +** fp -- the file pointer +** offset -- the new offset position relative to 'whence' +** whence -- flag indicating start of 'offset' +** +** Returns: +** -1 (error) always. +*/ + +off_t +sm_syslogseek(fp, offset, whence) + SM_FILE_T *fp; + off_t offset; + int whence; +{ + errno = ENODEV; + return -1; +} + +/* +** SM_SYSLOGCLOSE -- close the syslog file pointer +** +** Parameters: +** fp -- the file pointer +** +** Returns: +** 0 (zero) success always (see Overall) +** +*/ + +int +sm_syslogclose(fp) + SM_FILE_T *fp; +{ + return 0; +} + +/* +** SM_SYSLOGSETINFO -- set information for the file pointer +** +** Parameters: +** fp -- the file pointer being set +** what -- what information is being set +** valp -- information content being set to +** +** Returns: +** -1 on failure +** 0 (zero) on success +** +** Side Effects: +** Sets internal file pointer data +*/ + +int +sm_syslogsetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch (what) + { + case SM_IO_SL_PRIO: + fp->f_ival = *((int *)(valp)); + return 0; + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_SYSLOGGETINFO -- get information relating to the file pointer +** +** Parameters: +** fp -- the file pointer being queried +** what -- the information type being queried +** valp -- location to placed queried information +** +** Returns: +** 0 (zero) on success +** -1 on failure +** +** Side Effects: +** Fills in 'valp' with data. +*/ + +int +sm_sysloggetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch (what) + { + case SM_IO_SL_PRIO: + *((int *)(valp)) = fp->f_ival; + return 0; + default: + errno = EINVAL; + return -1; + } +} diff --git a/gnu/dist/sendmail/libsm/t-cf.c b/gnu/dist/sendmail/libsm/t-cf.c new file mode 100644 index 000000000000..4e0982e5e0d8 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-cf.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_IDSTR(id, "@(#)Id: t-cf.c,v 1.7 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + SM_CF_OPT_T opt; + int err; + + if (argc != 3) + { + fprintf(stderr, "Usage: %s .cf-file option\n", argv[0]); + exit(1); + } + opt.opt_name = argv[2]; + opt.opt_val = NULL; + err = sm_cf_getopt(argv[1], 1, &opt); + if (err) + { + fprintf(stderr, "%s: %s\n", argv[1], strerror(err)); + exit(1); + } + if (opt.opt_val == NULL) + printf("Error: option \"%s\" not found\n", opt.opt_name); + else + printf("%s=%s\n", opt.opt_name, opt.opt_val); + return 0; +} diff --git a/gnu/dist/sendmail/libsm/t-event.c b/gnu/dist/sendmail/libsm/t-event.c new file mode 100644 index 000000000000..7bcce744728f --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-event.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: t-event.c,v 1.11 2002/04/25 01:50:25 ca Exp") + +#include + +#include +#include +# include +#if SM_CONF_SETITIMER +# include +#endif /* SM_CONF_SETITIMER */ + +#include +#include + +int check; + +void +evcheck(arg) + int arg; +{ + SM_TEST(arg == 3); + SM_TEST(check == 0); + check++; +} + +void +ev1(arg) + int arg; +{ + SM_TEST(arg == 1); +} + +/* define as x if you want debug output */ +#define DBG_OUT(x) + +int +main(argc, argv) + int argc; + char *argv[]; +{ + SM_EVENT *ev; + + sm_test_begin(argc, argv, "test event handling"); + fprintf(stdout, "This test may hang. If there is no output within twelve seconds, abort it\nand recompile with -DSM_CONF_SETITIMER=%d\n", + SM_CONF_SETITIMER == 0 ? 1 : 0); + sleep(1); + SM_TEST(1 == 1); + DBG_OUT(fprintf(stdout, "We're back, test 1 seems to work.\n")); + ev = sm_seteventm(1000, ev1, 1); + sleep(1); + SM_TEST(2 == 2); + DBG_OUT(fprintf(stdout, "We're back, test 2 seems to work.\n")); + + /* schedule an event in 9s */ + ev = sm_seteventm(9000, ev1, 2); + sleep(1); + + /* clear the event before it can fire */ + sm_clrevent(ev); + SM_TEST(3 == 3); + DBG_OUT(fprintf(stdout, "We're back, test 3 seems to work.\n")); + + /* schedule an event in 1s */ + check = 0; + ev = sm_seteventm(1000, evcheck, 3); + sleep(2); + + /* clear the event */ + sm_clrevent(ev); + SM_TEST(4 == 4); + SM_TEST(check == 1); + DBG_OUT(fprintf(stdout, "We're back, test 4 seems to work.\n")); + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-exc.c b/gnu/dist/sendmail/libsm/t-exc.c new file mode 100644 index 000000000000..0c059cb309d5 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-exc.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-exc.c,v 1.20 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include + +const SM_EXC_TYPE_T EtypeTest1 = +{ + SmExcTypeMagic, + "E:test1", + "i", + sm_etype_printf, + "test1 exception argv[0]=%0", +}; + +const SM_EXC_TYPE_T EtypeTest2 = +{ + SmExcTypeMagic, + "E:test2", + "i", + sm_etype_printf, + "test2 exception argv[0]=%0", +}; + +int +main(argc, argv) + int argc; + char **argv; +{ + void *p; + int volatile x; + char *unknown, *cant; + + sm_test_begin(argc, argv, "test exception handling"); + + /* + ** SM_TRY + */ + + cant = "can't happen"; + x = 0; + SM_TRY + x = 1; + SM_END_TRY + SM_TEST(x == 1); + + /* + ** SM_FINALLY-0 + */ + + x = 0; + SM_TRY + x = 1; + SM_FINALLY + x = 2; + SM_END_TRY + SM_TEST(x == 2); + + /* + ** SM_FINALLY-1 + */ + + x = 0; + SM_TRY + SM_TRY + x = 1; + sm_exc_raisenew_x(&EtypeTest1, 17); + SM_FINALLY + x = 2; + sm_exc_raisenew_x(&EtypeTest2, 42); + SM_END_TRY + SM_EXCEPT(exc, "E:test2") + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "got exception test2: can't happen\n"); + SM_EXCEPT(exc, "E:test1") + SM_TEST(x == 2 && exc->exc_argv[0].v_int == 17); + if (!(x == 2 && exc->exc_argv[0].v_int == 17)) + { + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "can't happen: x=%d argv[0]=%d\n", + x, exc->exc_argv[0].v_int); + } + SM_EXCEPT(exc, "*") + { + unknown = "unknown exception: "; + SM_TEST(strcmp(unknown, cant) == 0); + } + SM_END_TRY + + x = 3; + SM_TRY + x = 4; + sm_exc_raisenew_x(&EtypeTest1, 94); + SM_FINALLY + x = 5; + sm_exc_raisenew_x(&EtypeTest2, 95); + SM_EXCEPT(exc, "E:test2") + { + unknown = "got exception test2: "; + SM_TEST(strcmp(unknown, cant) == 0); + } + SM_EXCEPT(exc, "E:test1") + SM_TEST(x == 5 && exc->exc_argv[0].v_int == 94); + if (!(x == 5 && exc->exc_argv[0].v_int == 94)) + { + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "can't happen: x=%d argv[0]=%d\n", + x, exc->exc_argv[0].v_int); + } + SM_EXCEPT(exc, "*") + { + unknown = "unknown exception: "; + SM_TEST(strcmp(unknown, cant) == 0); + } + SM_END_TRY + + SM_TRY + sm_exc_raisenew_x(&SmEtypeErr, "test %d", 0); + SM_EXCEPT(exc, "*") +#if DEBUG + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "test 0 got an exception, as expected:\n"); + sm_exc_print(exc, smioout); +#endif /* DEBUG */ + return sm_test_end(); + SM_END_TRY + + p = sm_malloc_x((size_t)(-1)); + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "sm_malloc_x unexpectedly succeeded, returning %p\n", p); + unknown = "sm_malloc_x unexpectedly succeeded"; + SM_TEST(strcmp(unknown, cant) == 0); + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-float.c b/gnu/dist/sendmail/libsm/t-float.c new file mode 100644 index 000000000000..df60e90bdfbf --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-float.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-float.c,v 1.18 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + double d, d2; + double ld; + char buf[128]; + char *r; + + /* + ** Sendmail uses printf and scanf with doubles, + ** so make sure that this works. + */ + + sm_test_begin(argc, argv, "test floating point stuff"); + + d = 1.125; + sm_snprintf(buf, sizeof(buf), "%d %.3f %d", 0, d, 1); + r = "0 1.125 1"; + if (!SM_TEST(strcmp(buf, r) == 0)) + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "got %s instead\n", buf); + + d = 1.125; + sm_snprintf(buf, sizeof(buf), "%.3f", d); + r = "1.125"; + if (!SM_TEST(strcmp(buf, r) == 0)) + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "got %s instead\n", buf); + d2 = 0.0; + sm_io_sscanf(buf, "%lf", &d2); +#if SM_CONF_BROKEN_STRTOD + if (d != d2) + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "wanted %f, got %f\n", d, d2); + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "error ignored since SM_CONF_BROKEN_STRTOD is set for this OS\n"); + } +#else /* SM_CONF_BROKEN_STRTOD */ + if (!SM_TEST(d == d2)) + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "wanted %f, got %f\n", d, d2); +#endif /* SM_CONF_BROKEN_STRTOD */ + + ld = 2.5; + sm_snprintf(buf, sizeof(buf), "%.3f %.1f", d, ld); + r = "1.125 2.5"; + if (!SM_TEST(strcmp(buf, r) == 0)) + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "got %s instead\n", buf); + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-fopen.c b/gnu/dist/sendmail/libsm/t-fopen.c new file mode 100644 index 000000000000..da854a54949c --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-fopen.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-fopen.c,v 1.9 2002/02/06 23:57:45 ca Exp") + +#include +#include +#include + +/* ARGSUSED0 */ +int +main(argc, argv) + int argc; + char *argv[]; +{ + int m, r; + SM_FILE_T *out; + + sm_test_begin(argc, argv, "test sm_io_fopen"); + out = sm_io_fopen("foo", O_WRONLY|O_APPEND|O_CREAT, 0666); + SM_TEST(out != NULL); + if (out != NULL) + { + (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "foo\n"); + r = sm_io_getinfo(out, SM_IO_WHAT_MODE, &m); + SM_TEST(r == 0); + SM_TEST(m == SM_IO_WRONLY); + sm_io_close(out, SM_TIME_DEFAULT); + } + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-heap.c b/gnu/dist/sendmail/libsm/t-heap.c new file mode 100644 index 000000000000..b07148cf8ec7 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-heap.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-heap.c,v 1.10 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include +#include + +#if SM_HEAP_CHECK +extern SM_DEBUG_T SmHeapCheck; +# define HEAP_CHECK sm_debug_active(&SmHeapCheck, 1) +#else /* SM_HEAP_CHECK */ +# define HEAP_CHECK 0 +#endif /* SM_HEAP_CHECK */ + +int +main(argc, argv) + int argc; + char **argv; +{ + void *p; + + sm_test_begin(argc, argv, "test heap handling"); + if (argc > 1) + sm_debug_addsettings_x(argv[1]); + + p = sm_malloc(10); + SM_TEST(p != NULL); + p = sm_realloc_x(p, 20); + SM_TEST(p != NULL); + p = sm_realloc(p, 30); + SM_TEST(p != NULL); + if (HEAP_CHECK) + { + sm_dprintf("heap with 1 30-byte block allocated:\n"); + sm_heap_report(smioout, 3); + } + + if (HEAP_CHECK) + { + sm_free(p); + sm_dprintf("heap with 0 blocks allocated:\n"); + sm_heap_report(smioout, 3); + sm_dprintf("xtrap count = %d\n", SmXtrapCount); + } + +#if DEBUG + /* this will cause a core dump */ + sm_dprintf("about to free %p for the second time\n", p); + sm_free(p); +#endif /* DEBUG */ + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-match.c b/gnu/dist/sendmail/libsm/t-match.c new file mode 100644 index 000000000000..287ee1a8fd0b --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-match.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2000 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-match.c,v 1.9 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include + +#define try(str, pat, want) \ + got = sm_match(str, pat); \ + if (!SM_TEST(got == want)) \ + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, \ + "sm_match(\"%s\", \"%s\") returns %s\n", \ + str, pat, got ? "true" : "false"); + +int +main(argc, argv) + int argc; + char **argv; +{ + bool got; + + sm_test_begin(argc, argv, "test sm_match"); + + try("foo", "foo", true); + try("foo", "bar", false); + try("foo[bar", "foo[bar", true); + try("foo[bar]", "foo[bar]", false); + try("foob", "foo[bar]", true); + try("a-b", "a[]-]b", true); + try("abcde", "a*e", true); + try("[", "[[]", true); + try("c", "[a-z]", true); + try("C", "[a-z]", false); + try("F:sm.heap", "[!F]*", false); + try("E:sm.err", "[!F]*", true); + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-path.c b/gnu/dist/sendmail/libsm/t-path.c new file mode 100644 index 000000000000..af650b920f9b --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-path.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-path.c,v 1.8 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + char *r; + + sm_test_begin(argc, argv, "test path handling"); + + SM_TEST(sm_path_isdevnull(SM_PATH_DEVNULL)); + r = "/dev/null"; + SM_TEST(sm_path_isdevnull(r)); + r = "/nev/dull"; + SM_TEST(!sm_path_isdevnull(r)); + r = "nul"; + SM_TEST(!sm_path_isdevnull(r)); + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-rpool.c b/gnu/dist/sendmail/libsm/t-rpool.c new file mode 100644 index 000000000000..cc98c1f14744 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-rpool.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-rpool.c,v 1.18 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include +#include + +static void +rfree __P(( + void *cx)); + +static void +rfree(cx) + void *cx; +{ + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "rfree freeing `%s'\n", + (char *) cx); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + SM_RPOOL_T *rpool; + char *a[26]; + int i, j; + SM_RPOOL_ATTACH_T att; + + sm_test_begin(argc, argv, "test rpool"); + sm_debug_addsetting_x("sm_check_heap", 1); + rpool = sm_rpool_new_x(NULL); + SM_TEST(rpool != NULL); + att = sm_rpool_attach_x(rpool, rfree, "attachment #1"); + SM_TEST(att != NULL); + for (i = 0; i < 26; ++i) + { + size_t sz = i * i * i; + + a[i] = sm_rpool_malloc_x(rpool, sz); + for (j = 0; j < sz; ++j) + a[i][j] = 'a' + i; + } + att = sm_rpool_attach_x(rpool, rfree, "attachment #2"); + (void) sm_rpool_attach_x(rpool, rfree, "attachment #3"); + sm_rpool_detach(att); + + /* XXX more tests? */ +#if DEBUG + sm_dprintf("heap after filling up rpool:\n"); + sm_heap_report(smioout, 3); + sm_dprintf("freeing rpool:\n"); + sm_rpool_free(rpool); + sm_dprintf("heap after freeing rpool:\n"); + sm_heap_report(smioout, 3); +#endif /* DEBUG */ + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-scanf.c b/gnu/dist/sendmail/libsm/t-scanf.c new file mode 100644 index 000000000000..d5019b15756f --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-scanf.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-scanf.c,v 1.5 2001/11/13 00:51:28 ca Exp") + +#include +#include +#include +#include +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + int i, d, h; + char buf[128]; + char *r; + + sm_test_begin(argc, argv, "test scanf point stuff"); +#if !SM_CONF_BROKEN_SIZE_T + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, +"If tests for \"h == 2\" fail, check whether size_t is signed on your OS.\n\ +If that is the case, add -DSM_CONF_BROKEN_SIZE_T to confENVDEF\n\ +and start over. Otherwise contact sendmail.org.\n"); +#endif /* !SM_CONF_BROKEN_SIZE_T */ + + d = 2; + sm_snprintf(buf, sizeof(buf), "%d", d); + r = "2"; + if (!SM_TEST(strcmp(buf, r) == 0)) + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "got %s instead\n", buf); + + i = sm_io_sscanf(buf, "%d", &h); + SM_TEST(i == 1); + SM_TEST(h == 2); + + d = 2; + sm_snprintf(buf, sizeof(buf), "%d\n", d); + r = "2\n"; + if (!SM_TEST(strcmp(buf, r) == 0)) + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "got %s instead\n", buf); + + i = sm_io_sscanf(buf, "%d", &h); + SM_TEST(i == 1); + SM_TEST(h == 2); + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-shm.c b/gnu/dist/sendmail/libsm/t-shm.c new file mode 100644 index 000000000000..7f0e31e448d7 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-shm.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: t-shm.c,v 1.18 2002/01/31 04:11:41 ca Exp") + +#include + +#if SM_CONF_SHM +# include +# include +# include + +# include +# include +# include +# include + +# define SHMSIZE 1024 +# define SHM_MAX 6400000 +# define T_SHMKEY 21 + + +/* +** SHMINTER -- interactive testing of shared memory +** +** Parameters: +** owner -- create segment. +** +** Returns: +** 0 on success +** < 0 on failure. +*/ + +int shminter __P((bool)); + +int +shminter(owner) + bool owner; +{ + int *shm, shmid; + int i, j, t; + + shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner); + if (shm == (int *) 0) + { + perror("shminit failed"); + return -1; + } + + while ((t = getchar()) != EOF) + { + switch (t) + { + case 'c': + *shm = 0; + break; + case 'i': + ++*shm; + break; + case 'd': + --*shm; + break; + case 's': + sleep(1); + break; + case 'l': + t = *shm; + for (i = 0; i < SHM_MAX; i++) + { + j += i; + ++*shm; + } + if (*shm != SHM_MAX + t) + fprintf(stderr, "error: %d != %d\n", + *shm, SHM_MAX + t); + break; + case 'v': + printf("shmval: %d\n", *shm); + break; + } + } + return sm_shmstop((void *) shm, shmid, owner); +} + + +/* +** SHMBIG -- testing of shared memory +** +** Parameters: +** owner -- create segment. +** size -- size of segment. +** +** Returns: +** 0 on success +** < 0 on failure. +*/ + +int shmbig __P((bool, int)); + +int +shmbig(owner, size) + bool owner; + int size; +{ + int *shm, shmid; + int i; + + shm = (int *) sm_shmstart(T_SHMKEY, size, 0, &shmid, owner); + if (shm == (int *) 0) + { + perror("shminit failed"); + return -1; + } + + for (i = 0; i < size / sizeof(int); i++) + shm[i] = i; + for (i = 0; i < size / sizeof(int); i++) + { + if (shm[i] != i) + { + fprintf(stderr, "failed at %d: %d", i, shm[i]); + } + } + + return sm_shmstop((void *) shm, shmid, owner); +} + + +/* +** SHMTEST -- test of shared memory +** +** Parameters: +** owner -- create segment. +** +** Returns: +** 0 on success +** < 0 on failure. +*/ + +# define MAX_CNT 10 + +int +shmtest(owner) + int owner; +{ + int *shm, shmid; + int cnt = 0; + + shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner); + if (shm == (int *) 0) + { + perror("shminit failed"); + return -1; + } + + if (owner) + { + int r; + + *shm = 1; + while (*shm == 1 && cnt++ < MAX_CNT) + sleep(1); + SM_TEST(cnt <= MAX_CNT); + + /* release and re-acquire the segment */ + r = sm_shmstop((void *) shm, shmid, owner); + SM_TEST(r == 0); + shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner); + SM_TEST(shm != (int *) 0); + } + else + { + while (*shm != 1 && cnt++ < MAX_CNT) + sleep(1); + SM_TEST(cnt <= MAX_CNT); + *shm = 2; + + /* wait a momemt so the segment is still in use */ + sleep(2); + } + return sm_shmstop((void *) shm, shmid, owner); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + bool interactive = false; + bool owner = false; + int big = -1; + int ch; + int r = 0; + int status; + extern char *optarg; + +# define OPTIONS "b:io" + while ((ch = getopt(argc, argv, OPTIONS)) != -1) + { + switch ((char) ch) + { + case 'b': + big = atoi(optarg); + break; + + case 'i': + interactive = true; + break; + + case 'o': + owner = true; + break; + + default: + break; + } + } + + if (interactive) + r = shminter(owner); + else if (big > 0) + r = shmbig(true, big); + else + { + pid_t pid; + extern int SmTestNumErrors; + + if ((pid = fork()) < 0) + { + perror("fork failed\n"); + return -1; + } + + sm_test_begin(argc, argv, "test shared memory"); + if (pid == 0) + { + /* give the parent the chance to setup data */ + sleep(1); + r = shmtest(false); + } + else + { + r = shmtest(true); + (void) wait(&status); + } + SM_TEST(r == 0); + if (SmTestNumErrors > 0) + printf("add -DSM_CONF_SHM=0 to confENVDEF in devtools/Site/site.config.m4\nand start over.\n"); + return sm_test_end(); + } + return r; +} +#else /* SM_CONF_SHM */ +int +main(argc, argv) + int argc; + char *argv[]; +{ + printf("No support for shared memory configured on this machine\n"); + return 0; +} +#endif /* SM_CONF_SHM */ diff --git a/gnu/dist/sendmail/libsm/t-smstdio.c b/gnu/dist/sendmail/libsm/t-smstdio.c new file mode 100644 index 000000000000..8774dc9175f2 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-smstdio.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-smstdio.c,v 1.11 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + FILE *stream; + SM_FILE_T *fp; + char buf[128]; + size_t n; + static char testmsg[] = "hello, world\n"; + + sm_test_begin(argc, argv, + "test sm_io_stdioopen, smiostdin, smiostdout"); + + stream = fopen("t-smstdio.1", "w"); + SM_TEST(stream != NULL); + + fp = sm_io_stdioopen(stream, "w"); + SM_TEST(fp != NULL); + + (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", testmsg); + sm_io_close(fp, SM_TIME_DEFAULT); + +#if 0 + /* + ** stream should now be closed. This is a tricky way to test + ** if it is still open. Alas, it core dumps on Linux. + */ + + fprintf(stream, "oops! stream is still open!\n"); + fclose(stream); +#endif + + stream = fopen("t-smstdio.1", "r"); + SM_TEST(stream != NULL); + + fp = sm_io_stdioopen(stream, "r"); + SM_TEST(fp != NULL); + + n = sm_io_read(fp, SM_TIME_DEFAULT, buf, sizeof(buf)); + if (SM_TEST(n == strlen(testmsg))) + { + buf[n] = '\0'; + SM_TEST(strcmp(buf, testmsg) == 0); + } + +#if 0 + + /* + ** Copy smiostdin to smiostdout + ** gotta think some more about how to test smiostdin and smiostdout + */ + + while ((c = sm_io_getc(smiostdin)) != SM_IO_EOF) + sm_io_putc(smiostdout, c); +#endif + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-string.c b/gnu/dist/sendmail/libsm/t-string.c new file mode 100644 index 000000000000..33f9e79e2264 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-string.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-string.c,v 1.11 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + char *s; + char buf[4096]; + char foo[4]; + char *r; + int n; + + sm_test_begin(argc, argv, "test string utilities"); + + s = sm_stringf_x("%.3s%03d", "foobar", 42); + r = "foo042"; + SM_TEST(strcmp(s, r) == 0); + + s = sm_stringf_x("+%*x+", 2000, 0xCAFE); + sm_snprintf(buf, 4096, "+%*x+", 2000, 0xCAFE); + SM_TEST(strcmp(s, buf) == 0); + + foo[3] = 1; + n = sm_snprintf(foo, sizeof(foo), "foobar%dbaz", 42); + SM_TEST(n == 11); + r = "foo"; + SM_TEST(strcmp(foo, r) == 0); + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-strio.c b/gnu/dist/sendmail/libsm/t-strio.c new file mode 100644 index 000000000000..4c2f0e11c801 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-strio.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-strio.c,v 1.11 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char buf[20]; + char *r; + SM_FILE_T f; + + sm_test_begin(argc, argv, "test strio"); + (void) memset(buf, '.', 20); + sm_strio_init(&f, buf, 10); + (void) sm_io_fprintf(&f, SM_TIME_DEFAULT, "foobarbazoom"); + sm_io_flush(&f, SM_TIME_DEFAULT); + r = "foobarbaz"; + SM_TEST(strcmp(buf, r) == 0); + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-strl.c b/gnu/dist/sendmail/libsm/t-strl.c new file mode 100644 index 000000000000..84d03cda04d0 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-strl.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_IDSTR(id, "@(#)Id: t-strl.c,v 1.15 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include +#include + +#define MAXL 16 +#define N 5 +#define SIZE 128 + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char *s1, *s2, *s3; + int one, two, k; + char src1[N][SIZE], dst1[SIZE], dst2[SIZE]; + char *r; + + sm_test_begin(argc, argv, "test strl* string functions"); + s1 = "abc"; + s2 = "123"; + s3 = sm_malloc_x(MAXL); + + SM_TEST(sm_strlcpy(s3, s1, 4) == 3); + SM_TEST(strcmp(s1, s3) == 0); + + SM_TEST(sm_strlcat(s3, s2, 8) == 6); + r ="abc123"; + SM_TEST(strcmp(s3, r) == 0); + + SM_TEST(sm_strlcpy(s3, s1, 2) == 3); + r = "a"; + SM_TEST(strcmp(s3, r) == 0); + + SM_TEST(sm_strlcat(s3, s2, 3) == 4); + r = "a1"; + SM_TEST(strcmp(s3, r) == 0); + + SM_TEST(sm_strlcpy(s3, s1, 4) == 3); + r = ":"; + SM_TEST(sm_strlcat2(s3, r, s2, MAXL) == 7); + r = "abc:123"; + SM_TEST(strcmp(s3, r) == 0); + + SM_TEST(sm_strlcpy(s3, s1, 4) == 3); + r = ":"; + SM_TEST(sm_strlcat2(s3, r, s2, 6) == 7); + r = "abc:1"; + SM_TEST(strcmp(s3, r) == 0); + + SM_TEST(sm_strlcpy(s3, s1, 4) == 3); + r = ":"; + SM_TEST(sm_strlcat2(s3, r, s2, 2) == 7); + r = "abc"; + SM_TEST(strcmp(s3, r) == 0); + + SM_TEST(sm_strlcpy(s3, s1, 4) == 3); + r = ":"; + SM_TEST(sm_strlcat2(s3, r, s2, 4) == 7); + r = "abc"; + SM_TEST(strcmp(s3, r) == 0); + + SM_TEST(sm_strlcpy(s3, s1, 4) == 3); + r = ":"; + SM_TEST(sm_strlcat2(s3, r, s2, 5) == 7); + r = "abc:"; + SM_TEST(strcmp(s3, r) == 0); + + SM_TEST(sm_strlcpy(s3, s1, 4) == 3); + r = ":"; + SM_TEST(sm_strlcat2(s3, r, s2, 6) == 7); + r = "abc:1"; + SM_TEST(strcmp(s3, r) == 0); + + for (k = 0; k < N; k++) + { + (void) sm_strlcpy(src1[k], "abcdef", sizeof src1); + } + + one = sm_strlcpyn(dst1, sizeof dst1, 3, src1[0], "/", src1[1]); + two = sm_snprintf(dst2, sizeof dst2, "%s/%s", src1[0], src1[1]); + SM_TEST(one == two); + SM_TEST(strcmp(dst1, dst2) == 0); + one = sm_strlcpyn(dst1, 10, 3, src1[0], "/", src1[1]); + two = sm_snprintf(dst2, 10, "%s/%s", src1[0], src1[1]); + SM_TEST(one == two); + SM_TEST(strcmp(dst1, dst2) == 0); + one = sm_strlcpyn(dst1, 5, 3, src1[0], "/", src1[1]); + two = sm_snprintf(dst2, 5, "%s/%s", src1[0], src1[1]); + SM_TEST(one == two); + SM_TEST(strcmp(dst1, dst2) == 0); + one = sm_strlcpyn(dst1, 0, 3, src1[0], "/", src1[1]); + two = sm_snprintf(dst2, 0, "%s/%s", src1[0], src1[1]); + SM_TEST(one == two); + SM_TEST(strcmp(dst1, dst2) == 0); + one = sm_strlcpyn(dst1, sizeof dst1, 5, src1[0], "/", src1[1], "/", src1[2]); + two = sm_snprintf(dst2, sizeof dst2, "%s/%s/%s", src1[0], src1[1], src1[2]); + SM_TEST(one == two); + SM_TEST(strcmp(dst1, dst2) == 0); + one = sm_strlcpyn(dst1, 15, 5, src1[0], "/", src1[1], "/", src1[2]); + two = sm_snprintf(dst2, 15, "%s/%s/%s", src1[0], src1[1], src1[2]); + SM_TEST(one == two); + SM_TEST(strcmp(dst1, dst2) == 0); + one = sm_strlcpyn(dst1, 20, 5, src1[0], "/", src1[1], "/", src1[2]); + two = sm_snprintf(dst2, 20, "%s/%s/%s", src1[0], src1[1], src1[2]); + SM_TEST(one == two); + SM_TEST(strcmp(dst1, dst2) == 0); + + one = sm_strlcpyn(dst1, sizeof dst1, 0); + SM_TEST(one == 0); + r = ""; + SM_TEST(strcmp(dst1, r) == 0); + one = sm_strlcpyn(dst1, 20, 1, src1[0]); + two = sm_snprintf(dst2, 20, "%s", src1[0]); + SM_TEST(one == two); + one = sm_strlcpyn(dst1, 2, 1, src1[0]); + two = sm_snprintf(dst2, 2, "%s", src1[0]); + SM_TEST(one == two); + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-strrevcmp.c b/gnu/dist/sendmail/libsm/t-strrevcmp.c new file mode 100644 index 000000000000..fde499e13038 --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-strrevcmp.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-strrevcmp.c,v 1.3 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + char *s1; + char *s2; + + sm_test_begin(argc, argv, "test string compare"); + + s1 = "equal"; + s2 = "equal"; + SM_TEST(sm_strrevcmp(s1, s2) == 0); + + s1 = "equal"; + s2 = "qual"; + SM_TEST(sm_strrevcmp(s1, s2) > 0); + + s1 = "qual"; + s2 = "equal"; + SM_TEST(sm_strrevcmp(s1, s2) < 0); + + s1 = "Equal"; + s2 = "equal"; + SM_TEST(sm_strrevcmp(s1, s2) < 0); + + s1 = "Equal"; + s2 = "equal"; + SM_TEST(sm_strrevcasecmp(s1, s2) == 0); + + s1 = "Equal"; + s2 = "eQuaL"; + SM_TEST(sm_strrevcasecmp(s1, s2) == 0); + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/t-types.c b/gnu/dist/sendmail/libsm/t-types.c new file mode 100644 index 000000000000..bc36faeaa55b --- /dev/null +++ b/gnu/dist/sendmail/libsm/t-types.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: t-types.c,v 1.18 2002/03/13 17:29:53 gshapiro Exp") + +#include +#include +#include +#include +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + LONGLONG_T ll; + LONGLONG_T volatile lt; + ULONGLONG_T ull; + char buf[128]; + char *r; + + sm_test_begin(argc, argv, "test standard integral types"); + + SM_TEST(sizeof(LONGLONG_T) == sizeof(ULONGLONG_T)); + + /* + ** sendmail assumes that ino_t, off_t and void* can be cast + ** to ULONGLONG_T without losing information. + */ + + if (!SM_TEST(sizeof(ino_t) <= sizeof(ULONGLONG_T)) || + !SM_TEST(sizeof(off_t) <= sizeof(ULONGLONG_T)) || + !SM_TEST(sizeof(void*) <= sizeof(ULONGLONG_T))) + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "\ +Your C compiler appears to support a 64 bit integral type,\n\ +but libsm is not configured to use it. You will need to set\n\ +either SM_CONF_LONGLONG or SM_CONF_QUAD_T to 1. See libsm/README\n\ +for more details.\n"); + } + + /* + ** Most compilers notice that LLONG_MIN - 1 generate an underflow. + ** Some compiler generate code that will use the 'X' status bit + ** in a CPU and hence (LLONG_MIN - 1 > LLONG_MIN) will be false. + ** So we have to decide whether we want compiler warnings or + ** a wrong test... + ** Question: where do we really need what this test tests? + */ + +#if SM_CONF_TEST_LLONG + ll = LLONG_MIN; + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "\ +Your C compiler maybe issued a warning during compilation,\n\ +please IGNORE the compiler warning!.\n"); + lt = LLONG_MIN - 1; + SM_TEST(lt > ll); + sm_snprintf(buf, sizeof(buf), "%llx", ll); + r = "0"; + if (!SM_TEST(buf[0] == '8') + || !SM_TEST(strspn(&buf[1], r) == sizeof(ll) * 2 - 1)) + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "oops: LLONG_MIN=%s\n", buf); + } + + ll = LLONG_MAX; + lt = ll + 1; + SM_TEST(lt < ll); + sm_snprintf(buf, sizeof(buf), "%llx", ll); + r = "f"; + if (!SM_TEST(buf[0] == '7') + || !SM_TEST(strspn(&buf[1], r) == sizeof(ll) * 2 - 1)) + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "oops: LLONG_MAX=%s\n", buf); + } +#endif /* SM_CONF_TEST_LLONG */ + + ull = ULLONG_MAX; + SM_TEST(ull + 1 == 0); + sm_snprintf(buf, sizeof(buf), "%llx", ull); + r = "f"; + SM_TEST(strspn(buf, r) == sizeof(ll) * 2); + + /* + ** If QUAD_MAX is defined by then quad_t is defined. + ** Make sure LONGLONG_T is at least as big as quad_t. + */ +#ifdef QUAD_MAX + SM_TEST(QUAD_MAX <= LLONG_MAX); +#endif + + return sm_test_end(); +} diff --git a/gnu/dist/sendmail/libsm/test.c b/gnu/dist/sendmail/libsm/test.c new file mode 100644 index 000000000000..22ab9f5e4b54 --- /dev/null +++ b/gnu/dist/sendmail/libsm/test.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_IDSTR(Id, "@(#)Id: test.c,v 1.16 2002/01/08 17:54:40 ca Exp") + +/* +** Abstractions for writing libsm test programs. +*/ + +#include +#include +#include +#include +#include + +extern char *optarg; +extern int optind; +extern int optopt; +extern int opterr; + +int SmTestIndex; +int SmTestNumErrors; +bool SmTestVerbose; + +static char Help[] = "\ +%s [-h] [-d debugging] [-v]\n\ +\n\ +%s\n\ +\n\ +-h Display this help information.\n\ +-d debugging Set debug activation levels.\n\ +-v Verbose output.\n\ +"; + +static char Usage[] = "\ +Usage: %s [-h] [-v]\n\ +Use %s -h for help.\n\ +"; + +/* +** SM_TEST_BEGIN -- initialize test system. +** +** Parameters: +** argc -- argument counter. +** argv -- argument vector. +** testname -- description of tests. +** +** Results: +** none. +*/ + +void +sm_test_begin(argc, argv, testname) + int argc; + char **argv; + char *testname; +{ + int c; + + SmTestIndex = 0; + SmTestNumErrors = 0; + SmTestVerbose = false; + opterr = 0; + + while ((c = getopt(argc, argv, "vhd:")) != -1) + { + switch (c) + { + case 'v': + SmTestVerbose = true; + break; + case 'd': + sm_debug_addsettings_x(optarg); + break; + case 'h': + (void) fprintf(stdout, Help, argv[0], testname); + exit(0); + default: + (void) fprintf(stderr, + "Unknown command line option -%c\n", + optopt); + (void) fprintf(stderr, Usage, argv[0], argv[0]); + exit(1); + } + } +} + +/* +** SM_TEST -- single test. +** +** Parameters: +** success -- did test succeeed? +** expr -- expression that has been evaluated. +** filename -- guess... +** lineno -- line number. +** +** Results: +** value of success. +*/ + +bool +sm_test(success, expr, filename, lineno) + bool success; + char *expr; + char *filename; + int lineno; +{ + ++SmTestIndex; + if (SmTestVerbose) + (void) fprintf(stderr, "%d..", SmTestIndex); + if (!success) + { + ++SmTestNumErrors; + if (!SmTestVerbose) + (void) fprintf(stderr, "%d..", SmTestIndex); + (void) fprintf(stderr, "bad! %s:%d %s\n", filename, lineno, + expr); + } + else + { + if (SmTestVerbose) + (void) fprintf(stderr, "ok\n"); + } + return success; +} + +/* +** SM_TEST_END -- end of test system. +** +** Parameters: +** none. +** +** Results: +** number of errors. +*/ + +int +sm_test_end() +{ + (void) fprintf(stderr, "%d of %d tests completed successfully\n", + SmTestIndex - SmTestNumErrors, SmTestIndex); + if (SmTestNumErrors != 0) + (void) fprintf(stderr, "*** %d error%s in test! ***\n", + SmTestNumErrors, + SmTestNumErrors > 1 ? "s" : ""); + + return SmTestNumErrors; +} diff --git a/gnu/dist/sendmail/libsm/ungetc.c b/gnu/dist/sendmail/libsm/ungetc.c new file mode 100644 index 000000000000..ab2c565e292c --- /dev/null +++ b/gnu/dist/sendmail/libsm/ungetc.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: ungetc.c,v 1.28 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +/* +** SM_SUBMORE_X -- expand ungetc buffer +** +** Expand the ungetc buffer `in place'. That is, adjust fp->f_p when +** the buffer moves, so that it points the same distance from the end, +** and move the bytes in the buffer around as necessary so that they +** are all at the end (stack-style). +** +** Parameters: +** fp -- the file pointer +** +** Results: +** none. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +static void +sm_submore_x(fp) + register SM_FILE_T *fp; +{ + register int i; + register unsigned char *p; + + if (fp->f_ub.smb_base == fp->f_ubuf) + { + /* Get a buffer; f_ubuf is fixed size. */ + p = sm_malloc_x((size_t) SM_IO_BUFSIZ); + fp->f_ub.smb_base = p; + fp->f_ub.smb_size = SM_IO_BUFSIZ; + p += SM_IO_BUFSIZ - sizeof(fp->f_ubuf); + for (i = sizeof(fp->f_ubuf); --i >= 0;) + p[i] = fp->f_ubuf[i]; + fp->f_p = p; + return; + } + i = fp->f_ub.smb_size; + p = sm_realloc_x(fp->f_ub.smb_base, i << 1); + + /* no overlap (hence can use memcpy) because we doubled the size */ + (void) memcpy((void *) (p + i), (void *) p, (size_t) i); + fp->f_p = p + i; + fp->f_ub.smb_base = p; + fp->f_ub.smb_size = i << 1; +} + +/* +** SM_IO_UNGETC -- place a character back into the buffer just read +** +** Parameters: +** fp -- the file pointer affected +** timeout -- time to complete ungetc +** c -- the character to place back +** +** Results: +** On success, returns value of character placed back, 0-255. +** Returns SM_IO_EOF if c == SM_IO_EOF or if last operation +** was a write and flush failed. +** +** Exceptions: +** F:sm_heap -- out of memory +*/ + +int +sm_io_ungetc(fp, timeout, c) + register SM_FILE_T *fp; + int timeout; + int c; +{ + SM_REQUIRE_ISA(fp, SmFileMagic); + if (c == SM_IO_EOF) + return SM_IO_EOF; + if (timeout == SM_TIME_IMMEDIATE) + { + /* + ** Ungetting the buffer will take time and we are wanted to + ** return immediately. So... + */ + + errno = EAGAIN; + return SM_IO_EOF; + } + + if (!Sm_IO_DidInit) + sm_init(); + if ((fp->f_flags & SMRD) == 0) + { + /* + ** Not already reading: no good unless reading-and-writing. + ** Otherwise, flush any current write stuff. + */ + + if ((fp->f_flags & SMRW) == 0) + return SM_IO_EOF; + if (fp->f_flags & SMWR) + { + if (sm_flush(fp, &timeout)) + return SM_IO_EOF; + fp->f_flags &= ~SMWR; + fp->f_w = 0; + fp->f_lbfsize = 0; + } + fp->f_flags |= SMRD; + } + c = (unsigned char) c; + + /* + ** If we are in the middle of ungetc'ing, just continue. + ** This may require expanding the current ungetc buffer. + */ + + if (HASUB(fp)) + { + if (fp->f_r >= fp->f_ub.smb_size) + sm_submore_x(fp); + *--fp->f_p = c; + fp->f_r++; + return c; + } + fp->f_flags &= ~SMFEOF; + + /* + ** If we can handle this by simply backing up, do so, + ** but never replace the original character. + ** (This makes sscanf() work when scanning `const' data.) + */ + + if (fp->f_bf.smb_base != NULL && fp->f_p > fp->f_bf.smb_base && + fp->f_p[-1] == c) + { + fp->f_p--; + fp->f_r++; + return c; + } + + /* + ** Create an ungetc buffer. + ** Initially, we will use the `reserve' buffer. + */ + + fp->f_ur = fp->f_r; + fp->f_up = fp->f_p; + fp->f_ub.smb_base = fp->f_ubuf; + fp->f_ub.smb_size = sizeof(fp->f_ubuf); + fp->f_ubuf[sizeof(fp->f_ubuf) - 1] = c; + fp->f_p = &fp->f_ubuf[sizeof(fp->f_ubuf) - 1]; + fp->f_r = 1; + + return c; +} diff --git a/gnu/dist/sendmail/libsm/vasprintf.c b/gnu/dist/sendmail/libsm/vasprintf.c new file mode 100644 index 000000000000..7bf9bea18c46 --- /dev/null +++ b/gnu/dist/sendmail/libsm/vasprintf.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + */ + +/* + * Copyright (c) 1997 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +SM_RCSID("@(#)Id: vasprintf.c,v 1.26 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include +#include +#include "local.h" + +/* +** SM_VASPRINTF -- printf to a dynamically allocated string +** +** Write 'printf' output to a dynamically allocated string +** buffer which is returned to the caller. +** +** Parameters: +** str -- *str receives a pointer to the allocated string +** fmt -- format directives for printing +** ap -- variable argument list +** +** Results: +** On failure, set *str to NULL, set errno, and return -1. +** +** On success, set *str to a pointer to a nul-terminated +** string buffer containing printf output, and return the +** length of the string (not counting the nul). +*/ + +#define SM_VA_BUFSIZE 128 + +int +sm_vasprintf(str, fmt, ap) + char **str; + const char *fmt; + SM_VA_LOCAL_DECL +{ + int ret; + SM_FILE_T fake; + unsigned char *base; + + fake.sm_magic = SmFileMagic; + fake.f_timeout = SM_TIME_FOREVER; + fake.f_timeoutstate = SM_TIME_BLOCK; + fake.f_file = -1; + fake.f_flags = SMWR | SMSTR | SMALC; + fake.f_bf.smb_base = fake.f_p = (unsigned char *)sm_malloc(SM_VA_BUFSIZE); + if (fake.f_bf.smb_base == NULL) + goto err2; + fake.f_close = NULL; + fake.f_open = NULL; + fake.f_read = NULL; + fake.f_write = NULL; + fake.f_seek = NULL; + fake.f_setinfo = fake.f_getinfo = NULL; + fake.f_type = "sm_vasprintf:fake"; + fake.f_bf.smb_size = fake.f_w = SM_VA_BUFSIZE - 1; + fake.f_timeout = SM_TIME_FOREVER; + ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); + if (ret == -1) + goto err; + *fake.f_p = '\0'; + + /* use no more space than necessary */ + base = (unsigned char *) sm_realloc(fake.f_bf.smb_base, ret + 1); + if (base == NULL) + goto err; + *str = (char *)base; + return ret; + +err: + if (fake.f_bf.smb_base != NULL) + { + sm_free(fake.f_bf.smb_base); + fake.f_bf.smb_base = NULL; + } +err2: + *str = NULL; + errno = ENOMEM; + return -1; +} diff --git a/gnu/dist/sendmail/libsm/vfprintf.c b/gnu/dist/sendmail/libsm/vfprintf.c new file mode 100644 index 000000000000..7f2fa6d11434 --- /dev/null +++ b/gnu/dist/sendmail/libsm/vfprintf.c @@ -0,0 +1,1107 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: vfprintf.c,v 1.52 2001/09/11 04:04:49 gshapiro Exp") + +/* +** Overall: +** Actual printing innards. +** This code is large and complicated... +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" +#include "fvwrite.h" + +static void sm_find_arguments __P((const char *, va_list , va_list **)); +static void sm_grow_type_table_x __P((unsigned char **, int *)); +static int sm_print __P((SM_FILE_T *, int, struct sm_uio *)); + +/* +** SM_PRINT -- print/flush to the file +** +** Flush out all the vectors defined by the given uio, +** then reset it so that it can be reused. +** +** Parameters: +** fp -- file pointer +** timeout -- time to complete operation (milliseconds) +** uio -- vector list of memory locations of data for printing +** +** Results: +** Success: 0 (zero) +** Failure: +*/ + +static int +sm_print(fp, timeout, uio) + SM_FILE_T *fp; + int timeout; + register struct sm_uio *uio; +{ + register int err; + + if (uio->uio_resid == 0) + { + uio->uio_iovcnt = 0; + return 0; + } + err = sm_fvwrite(fp, timeout, uio); + uio->uio_resid = 0; + uio->uio_iovcnt = 0; + return err; +} + +/* +** SM_BPRINTF -- allow formating to an unbuffered file. +** +** Helper function for `fprintf to unbuffered unix file': creates a +** temporary buffer (via a "fake" file pointer). +** We only work on write-only files; this avoids +** worries about ungetc buffers and so forth. +** +** Parameters: +** fp -- the file to send the o/p to +** fmt -- format instructions for the o/p +** ap -- vectors of data units used for formating +** +** Results: +** Failure: SM_IO_EOF and errno set +** Success: number of data units used in the formating +** +** Side effects: +** formatted o/p can be SM_IO_BUFSIZ length maximum +*/ + +static int +sm_bprintf(fp, fmt, ap) + register SM_FILE_T *fp; + const char *fmt; + SM_VA_LOCAL_DECL +{ + int ret; + SM_FILE_T fake; + unsigned char buf[SM_IO_BUFSIZ]; + extern const char SmFileMagic[]; + + /* copy the important variables */ + fake.sm_magic = SmFileMagic; + fake.f_timeout = SM_TIME_FOREVER; + fake.f_timeoutstate = SM_TIME_BLOCK; + fake.f_flags = fp->f_flags & ~SMNBF; + fake.f_file = fp->f_file; + fake.f_cookie = fp->f_cookie; + fake.f_write = fp->f_write; + fake.f_close = NULL; + fake.f_open = NULL; + fake.f_read = NULL; + fake.f_seek = NULL; + fake.f_setinfo = fake.f_getinfo = NULL; + fake.f_type = "sm_bprintf:fake"; + + /* set up the buffer */ + fake.f_bf.smb_base = fake.f_p = buf; + fake.f_bf.smb_size = fake.f_w = sizeof(buf); + fake.f_lbfsize = 0; /* not actually used, but Just In Case */ + + /* do the work, then copy any error status */ + ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); + if (ret >= 0 && sm_io_flush(&fake, SM_TIME_FOREVER)) + ret = SM_IO_EOF; /* errno set by sm_io_flush */ + if (fake.f_flags & SMERR) + fp->f_flags |= SMERR; + return ret; +} + + +#define BUF 40 + +#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ + + +/* Macros for converting digits to letters and vice versa */ +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned) to_digit(c) <= 9) +#define to_char(n) ((char) (n) + '0') + +/* Flags used during conversion. */ +#define ALT 0x001 /* alternate form */ +#define HEXPREFIX 0x002 /* add 0x or 0X prefix */ +#define LADJUST 0x004 /* left adjustment */ +#define LONGINT 0x010 /* long integer */ +#define QUADINT 0x020 /* quad integer */ +#define SHORTINT 0x040 /* short integer */ +#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ +#define FPT 0x100 /* Floating point number */ + +/* +** SM_IO_VPRINTF -- performs actual formating for o/p +** +** Parameters: +** fp -- file pointer for o/p +** timeout -- time to complete the print +** fmt0 -- formating directives +** ap -- vectors with data units for formating +** +** Results: +** Success: number of data units used for formatting +** Failure: SM_IO_EOF and sets errno +*/ + +int +sm_io_vfprintf(fp, timeout, fmt0, ap) + SM_FILE_T *fp; + int timeout; + const char *fmt0; + SM_VA_LOCAL_DECL +{ + register char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int n, m, n2; /* handy integers (short term usage) */ + register char *cp; /* handy char pointer (short term usage) */ + register struct sm_iov *iovp;/* for PRINT macro */ + register int flags; /* flags as above */ + int ret; /* return value accumulator */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + char sign; /* sign prefix (' ', '+', '-', or \0) */ + wchar_t wc; + ULONGLONG_T _uquad; /* integer arguments %[diouxX] */ + enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int realsz; /* field size expanded by dprec */ + int size; /* size of converted field or string */ + char *xdigs="0123456789abcdef"; /* digits for [xX] conversion */ +#define NIOV 8 + struct sm_uio uio; /* output information: summary */ + struct sm_iov iov[NIOV];/* ... and individual io vectors */ + char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + char ox[2]; /* space for 0x hex-prefix */ + va_list *argtable; /* args, built due to positional arg */ + va_list statargtable[STATIC_ARG_TBL_SIZE]; + int nextarg; /* 1-based argument index */ + va_list orgap; /* original argument pointer */ + + /* + ** Choose PADSIZE to trade efficiency vs. size. If larger printf + ** fields occur frequently, increase PADSIZE and make the initialisers + ** below longer. + */ +#define PADSIZE 16 /* pad chunk size */ + static char blanks[PADSIZE] = + {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; + static char zeroes[PADSIZE] = + {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; + + /* + ** BEWARE, these `goto error' on error, and PAD uses `n'. + */ +#define PRINT(ptr, len) do { \ + iovp->iov_base = (ptr); \ + iovp->iov_len = (len); \ + uio.uio_resid += (len); \ + iovp++; \ + if (++uio.uio_iovcnt >= NIOV) \ + { \ + if (sm_print(fp, timeout, &uio)) \ + goto error; \ + iovp = iov; \ + } \ +} while (0) +#define PAD(howmany, with) do \ +{ \ + if ((n = (howmany)) > 0) \ + { \ + while (n > PADSIZE) { \ + PRINT(with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT(with, n); \ + } \ +} while (0) +#define FLUSH() do \ +{ \ + if (uio.uio_resid && sm_print(fp, timeout, &uio)) \ + goto error; \ + uio.uio_iovcnt = 0; \ + iovp = iov; \ +} while (0) + + /* + ** To extend shorts properly, we need both signed and unsigned + ** argument extraction methods. + */ +#define SARG() \ + (flags&QUADINT ? SM_VA_ARG(ap, LONGLONG_T) : \ + flags&LONGINT ? GETARG(long) : \ + flags&SHORTINT ? (long) (short) GETARG(int) : \ + (long) GETARG(int)) +#define UARG() \ + (flags&QUADINT ? SM_VA_ARG(ap, ULONGLONG_T) : \ + flags&LONGINT ? GETARG(unsigned long) : \ + flags&SHORTINT ? (unsigned long) (unsigned short) GETARG(int) : \ + (unsigned long) GETARG(unsigned int)) + + /* + ** Get * arguments, including the form *nn$. Preserve the nextarg + ** that the argument can be gotten once the type is determined. + */ +#define GETASTER(val) \ + n2 = 0; \ + cp = fmt; \ + while (is_digit(*cp)) \ + { \ + n2 = 10 * n2 + to_digit(*cp); \ + cp++; \ + } \ + if (*cp == '$') \ + { \ + int hold = nextarg; \ + if (argtable == NULL) \ + { \ + argtable = statargtable; \ + sm_find_arguments(fmt0, orgap, &argtable); \ + } \ + nextarg = n2; \ + val = GETARG(int); \ + nextarg = hold; \ + fmt = ++cp; \ + } \ + else \ + { \ + val = GETARG(int); \ + } + +/* +** Get the argument indexed by nextarg. If the argument table is +** built, use it to get the argument. If its not, get the next +** argument (and arguments must be gotten sequentially). +*/ + +#if SM_VA_STD +# define GETARG(type) \ + (((argtable != NULL) ? (void) (ap = argtable[nextarg]) : (void) 0), \ + nextarg++, SM_VA_ARG(ap, type)) +#else /* SM_VA_STD */ +# define GETARG(type) \ + ((argtable != NULL) ? (*((type*)(argtable[nextarg++]))) : \ + (nextarg++, SM_VA_ARG(ap, type))) +#endif /* SM_VA_STD */ + + /* sorry, fprintf(read_only_file, "") returns SM_IO_EOF, not 0 */ + if (cantwrite(fp)) + { + errno = EBADF; + return SM_IO_EOF; + } + + /* optimise fprintf(stderr) (and other unbuffered Unix files) */ + if ((fp->f_flags & (SMNBF|SMWR|SMRW)) == (SMNBF|SMWR) && + fp->f_file >= 0) + return sm_bprintf(fp, fmt0, ap); + + fmt = (char *) fmt0; + argtable = NULL; + nextarg = 1; + SM_VA_COPY(orgap, ap); + uio.uio_iov = iovp = iov; + uio.uio_resid = 0; + uio.uio_iovcnt = 0; + ret = 0; + + /* Scan the format for conversions (`%' character). */ + for (;;) + { + cp = fmt; + n = 0; + while ((wc = *fmt) != '\0') + { + if (wc == '%') + { + n = 1; + break; + } + fmt++; + } + if ((m = fmt - cp) != 0) + { + PRINT(cp, m); + ret += m; + } + if (n <= 0) + goto done; + fmt++; /* skip over '%' */ + + flags = 0; + dprec = 0; + width = 0; + prec = -1; + sign = '\0'; + +rflag: ch = *fmt++; +reswitch: switch (ch) + { + case ' ': + + /* + ** ``If the space and + flags both appear, the space + ** flag will be ignored.'' + ** -- ANSI X3J11 + */ + + if (!sign) + sign = ' '; + goto rflag; + case '#': + flags |= ALT; + goto rflag; + case '*': + + /* + ** ``A negative field width argument is taken as a + ** - flag followed by a positive field width.'' + ** -- ANSI X3J11 + ** They don't exclude field widths read from args. + */ + + GETASTER(width); + if (width >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case '-': + flags |= LADJUST; + goto rflag; + case '+': + sign = '+'; + goto rflag; + case '.': + if ((ch = *fmt++) == '*') + { + GETASTER(n); + prec = n < 0 ? -1 : n; + goto rflag; + } + n = 0; + while (is_digit(ch)) + { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } + if (ch == '$') + { + nextarg = n; + if (argtable == NULL) + { + argtable = statargtable; + sm_find_arguments(fmt0, orgap, + &argtable); + } + goto rflag; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + + /* + ** ``Note that 0 is taken as a flag, not as the + ** beginning of a field width.'' + ** -- ANSI X3J11 + */ + + flags |= ZEROPAD; + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do + { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + if (ch == '$') + { + nextarg = n; + if (argtable == NULL) + { + argtable = statargtable; + sm_find_arguments(fmt0, orgap, + &argtable); + } + goto rflag; + } + width = n; + goto reswitch; + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + if (*fmt == 'l') + { + fmt++; + flags |= QUADINT; + } + else + { + flags |= LONGINT; + } + goto rflag; + case 'q': + flags |= QUADINT; + goto rflag; + case 'c': + *(cp = buf) = GETARG(int); + size = 1; + sign = '\0'; + break; + case 'D': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'd': + case 'i': + _uquad = SARG(); + if ((LONGLONG_T) _uquad < 0) + { + _uquad = -(LONGLONG_T) _uquad; + sign = '-'; + } + base = DEC; + goto number; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + { + double val; + char *p; + char fmt[16]; + char out[150]; + size_t len; + + /* + ** This code implements floating point output + ** in the most portable manner possible, + ** relying only on 'sprintf' as defined by + ** the 1989 ANSI C standard. + ** We silently cap width and precision + ** at 120, to avoid buffer overflow. + */ + + val = GETARG(double); + + p = fmt; + *p++ = '%'; + if (sign) + *p++ = sign; + if (flags & ALT) + *p++ = '#'; + if (flags & LADJUST) + *p++ = '-'; + if (flags & ZEROPAD) + *p++ = '0'; + *p++ = '*'; + if (prec >= 0) + { + *p++ = '.'; + *p++ = '*'; + } + *p++ = ch; + *p = '\0'; + + if (width > 120) + width = 120; + if (prec > 120) + prec = 120; + if (prec >= 0) + sprintf(out, fmt, width, prec, val); + else + sprintf(out, fmt, width, val); + len = strlen(out); + PRINT(out, len); + FLUSH(); + continue; + } + case 'n': + if (flags & QUADINT) + *GETARG(LONGLONG_T *) = ret; + else if (flags & LONGINT) + *GETARG(long *) = ret; + else if (flags & SHORTINT) + *GETARG(short *) = ret; + else + *GETARG(int *) = ret; + continue; /* no output */ + case 'O': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'o': + _uquad = UARG(); + base = OCT; + goto nosign; + case 'p': + + /* + ** ``The argument shall be a pointer to void. The + ** value of the pointer is converted to a sequence + ** of printable characters, in an implementation- + ** defined manner.'' + ** -- ANSI X3J11 + */ + + /* NOSTRICT */ + { + union + { + void *p; + ULONGLONG_T ll; + unsigned long l; + unsigned i; + } u; + u.p = GETARG(void *); + if (sizeof(void *) == sizeof(ULONGLONG_T)) + _uquad = u.ll; + else if (sizeof(void *) == sizeof(long)) + _uquad = u.l; + else + _uquad = u.i; + } + base = HEX; + xdigs = "0123456789abcdef"; + flags |= HEXPREFIX; + ch = 'x'; + goto nosign; + case 's': + if ((cp = GETARG(char *)) == NULL) + cp = "(null)"; + if (prec >= 0) + { + /* + ** can't use strlen; can only look for the + ** NUL in the first `prec' characters, and + ** strlen() will go further. + */ + + char *p = memchr(cp, 0, prec); + + if (p != NULL) + { + size = p - cp; + if (size > prec) + size = prec; + } + else + size = prec; + } + else + size = strlen(cp); + sign = '\0'; + break; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + _uquad = UARG(); + base = DEC; + goto nosign; + case 'X': + xdigs = "0123456789ABCDEF"; + goto hex; + case 'x': + xdigs = "0123456789abcdef"; +hex: _uquad = UARG(); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _uquad != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ +nosign: sign = '\0'; + + /* + ** ``... diouXx conversions ... if a precision is + ** specified, the 0 flag will be ignored.'' + ** -- ANSI X3J11 + */ + +number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + ** ``The result of converting a zero value with an + ** explicit precision of zero is no characters.'' + ** -- ANSI X3J11 + */ + + cp = buf + BUF; + if (_uquad != 0 || prec != 0) + { + /* + ** Unsigned mod is hard, and unsigned mod + ** by a constant is easier than that by + ** a variable; hence this switch. + */ + + switch (base) + { + case OCT: + do + { + *--cp = to_char(_uquad & 7); + _uquad >>= 3; + } while (_uquad); + /* handle octal leading 0 */ + if (flags & ALT && *cp != '0') + *--cp = '0'; + break; + + case DEC: + /* many numbers are 1 digit */ + while (_uquad >= 10) + { + *--cp = to_char(_uquad % 10); + _uquad /= 10; + } + *--cp = to_char(_uquad); + break; + + case HEX: + do + { + *--cp = xdigs[_uquad & 15]; + _uquad >>= 4; + } while (_uquad); + break; + + default: + cp = "bug in sm_io_vfprintf: bad base"; + size = strlen(cp); + goto skipsize; + } + } + size = buf + BUF - cp; + skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + /* pretend it was %c with argument ch */ + cp = buf; + *cp = ch; + size = 1; + sign = '\0'; + break; + } + + /* + ** All reasonable formats wind up here. At this point, `cp' + ** points to a string which (if not flags&LADJUST) should be + ** padded out to `width' places. If flags&ZEROPAD, it should + ** first be prefixed by any sign or other prefix; otherwise, + ** it should be blank padded before the prefix is emitted. + ** After any left-hand padding and prefixing, emit zeroes + ** required by a decimal [diouxX] precision, then print the + ** string proper, then emit zeroes required by any leftover + ** floating precision; finally, if LADJUST, pad with blanks. + ** + ** Compute actual size, so we know how much to pad. + ** size excludes decimal prec; realsz includes it. + */ + + realsz = dprec > size ? dprec : size; + if (sign) + realsz++; + else if (flags & HEXPREFIX) + realsz+= 2; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST|ZEROPAD)) == 0) + PAD(width - realsz, blanks); + + /* prefix */ + if (sign) + { + PRINT(&sign, 1); + } + else if (flags & HEXPREFIX) + { + ox[0] = '0'; + ox[1] = ch; + PRINT(ox, 2); + } + + /* right-adjusting zero padding */ + if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) + PAD(width - realsz, zeroes); + + /* leading zeroes from decimal precision */ + PAD(dprec - size, zeroes); + + /* the string or number proper */ + PRINT(cp, size); + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) + PAD(width - realsz, blanks); + + /* finally, adjust ret */ + ret += width > realsz ? width : realsz; + + FLUSH(); /* copy out the I/O vectors */ + } +done: + FLUSH(); +error: + if ((argtable != NULL) && (argtable != statargtable)) + sm_free(argtable); + return sm_error(fp) ? SM_IO_EOF : ret; + /* NOTREACHED */ +} + +/* Type ids for argument type table. */ +#define T_UNUSED 0 +#define T_SHORT 1 +#define T_U_SHORT 2 +#define TP_SHORT 3 +#define T_INT 4 +#define T_U_INT 5 +#define TP_INT 6 +#define T_LONG 7 +#define T_U_LONG 8 +#define TP_LONG 9 +#define T_QUAD 10 +#define T_U_QUAD 11 +#define TP_QUAD 12 +#define T_DOUBLE 13 +#define TP_CHAR 15 +#define TP_VOID 16 + +/* +** SM_FIND_ARGUMENTS -- find all args when a positional parameter is found. +** +** Find all arguments when a positional parameter is encountered. Returns a +** table, indexed by argument number, of pointers to each arguments. The +** initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. +** It will be replaced with a malloc-ed one if it overflows. +** +** Parameters: +** fmt0 -- formating directives +** ap -- vector list of data unit for formating consumption +** argtable -- an indexable table (returned) of 'ap' +** +** Results: +** none. +*/ + +static void +sm_find_arguments(fmt0, ap, argtable) + const char *fmt0; + SM_VA_LOCAL_DECL + va_list **argtable; +{ + register char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int n, n2; /* handy integer (short term usage) */ + register char *cp; /* handy char pointer (short term usage) */ + register int flags; /* flags as above */ + unsigned char *typetable; /* table of types */ + unsigned char stattypetable[STATIC_ARG_TBL_SIZE]; + int tablesize; /* current size of type table */ + int tablemax; /* largest used index in table */ + int nextarg; /* 1-based argument index */ + + /* Add an argument type to the table, expanding if necessary. */ +#define ADDTYPE(type) \ + ((nextarg >= tablesize) ? \ + (sm_grow_type_table_x(&typetable, &tablesize), 0) : 0, \ + typetable[nextarg++] = type, \ + (nextarg > tablemax) ? tablemax = nextarg : 0) + +#define ADDSARG() \ + ((flags & LONGINT) ? ADDTYPE(T_LONG) : \ + ((flags & SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT))) + +#define ADDUARG() \ + ((flags & LONGINT) ? ADDTYPE(T_U_LONG) : \ + ((flags & SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT))) + + /* Add * arguments to the type array. */ +#define ADDASTER() \ + n2 = 0; \ + cp = fmt; \ + while (is_digit(*cp)) \ + { \ + n2 = 10 * n2 + to_digit(*cp); \ + cp++; \ + } \ + if (*cp == '$') \ + { \ + int hold = nextarg; \ + nextarg = n2; \ + ADDTYPE (T_INT); \ + nextarg = hold; \ + fmt = ++cp; \ + } \ + else \ + { \ + ADDTYPE (T_INT); \ + } + fmt = (char *) fmt0; + typetable = stattypetable; + tablesize = STATIC_ARG_TBL_SIZE; + tablemax = 0; + nextarg = 1; + (void) memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE); + + /* Scan the format for conversions (`%' character). */ + for (;;) + { + for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) + /* void */; + if (ch == '\0') + goto done; + fmt++; /* skip over '%' */ + + flags = 0; + +rflag: ch = *fmt++; +reswitch: switch (ch) + { + case ' ': + case '#': + goto rflag; + case '*': + ADDASTER(); + goto rflag; + case '-': + case '+': + goto rflag; + case '.': + if ((ch = *fmt++) == '*') + { + ADDASTER(); + goto rflag; + } + while (is_digit(ch)) + { + ch = *fmt++; + } + goto reswitch; + case '0': + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do + { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + if (ch == '$') + { + nextarg = n; + goto rflag; + } + goto reswitch; + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + flags |= LONGINT; + goto rflag; + case 'q': + flags |= QUADINT; + goto rflag; + case 'c': + ADDTYPE(T_INT); + break; + case 'D': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'd': + case 'i': + if (flags & QUADINT) + { + ADDTYPE(T_QUAD); + } + else + { + ADDSARG(); + } + break; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + ADDTYPE(T_DOUBLE); + break; + case 'n': + if (flags & QUADINT) + ADDTYPE(TP_QUAD); + else if (flags & LONGINT) + ADDTYPE(TP_LONG); + else if (flags & SHORTINT) + ADDTYPE(TP_SHORT); + else + ADDTYPE(TP_INT); + continue; /* no output */ + case 'O': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'o': + if (flags & QUADINT) + ADDTYPE(T_U_QUAD); + else + ADDUARG(); + break; + case 'p': + ADDTYPE(TP_VOID); + break; + case 's': + ADDTYPE(TP_CHAR); + break; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + if (flags & QUADINT) + ADDTYPE(T_U_QUAD); + else + ADDUARG(); + break; + case 'X': + case 'x': + if (flags & QUADINT) + ADDTYPE(T_U_QUAD); + else + ADDUARG(); + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + break; + } + } +done: + /* Build the argument table. */ + if (tablemax >= STATIC_ARG_TBL_SIZE) + { + *argtable = (va_list *) + sm_malloc(sizeof(va_list) * (tablemax + 1)); + } + + for (n = 1; n <= tablemax; n++) + { + SM_VA_COPY((*argtable)[n], ap); + switch (typetable [n]) + { + case T_UNUSED: + (void) SM_VA_ARG(ap, int); + break; + case T_SHORT: + (void) SM_VA_ARG(ap, int); + break; + case T_U_SHORT: + (void) SM_VA_ARG(ap, int); + break; + case TP_SHORT: + (void) SM_VA_ARG(ap, short *); + break; + case T_INT: + (void) SM_VA_ARG(ap, int); + break; + case T_U_INT: + (void) SM_VA_ARG(ap, unsigned int); + break; + case TP_INT: + (void) SM_VA_ARG(ap, int *); + break; + case T_LONG: + (void) SM_VA_ARG(ap, long); + break; + case T_U_LONG: + (void) SM_VA_ARG(ap, unsigned long); + break; + case TP_LONG: + (void) SM_VA_ARG(ap, long *); + break; + case T_QUAD: + (void) SM_VA_ARG(ap, LONGLONG_T); + break; + case T_U_QUAD: + (void) SM_VA_ARG(ap, ULONGLONG_T); + break; + case TP_QUAD: + (void) SM_VA_ARG(ap, LONGLONG_T *); + break; + case T_DOUBLE: + (void) SM_VA_ARG(ap, double); + break; + case TP_CHAR: + (void) SM_VA_ARG(ap, char *); + break; + case TP_VOID: + (void) SM_VA_ARG(ap, void *); + break; + } + } + + if ((typetable != NULL) && (typetable != stattypetable)) + sm_free(typetable); +} + +/* +** SM_GROW_TYPE_TABLE -- Increase the size of the type table. +** +** Parameters: +** tabletype -- type of table to grow +** tablesize -- requested new table size +** +** Results: +** Raises an exception if can't allocate memory. +*/ + +static void +sm_grow_type_table_x(typetable, tablesize) + unsigned char **typetable; + int *tablesize; +{ + unsigned char *oldtable = *typetable; + int newsize = *tablesize * 2; + + if (*tablesize == STATIC_ARG_TBL_SIZE) + { + *typetable = (unsigned char *) sm_malloc_x(sizeof(unsigned char) + * newsize); + (void) memmove(*typetable, oldtable, *tablesize); + } + else + { + *typetable = (unsigned char *) sm_realloc_x(typetable, + sizeof(unsigned char) * newsize); + } + (void) memset(&typetable [*tablesize], T_UNUSED, + (newsize - *tablesize)); + + *tablesize = newsize; +} diff --git a/gnu/dist/sendmail/libsm/vfscanf.c b/gnu/dist/sendmail/libsm/vfscanf.c new file mode 100644 index 000000000000..6ba8d5cf42a2 --- /dev/null +++ b/gnu/dist/sendmail/libsm/vfscanf.c @@ -0,0 +1,874 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_IDSTR(id, "@(#)Id: vfscanf.c,v 1.51 2001/09/11 04:04:49 gshapiro Exp") + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "local.h" + +#define BUF 513 /* Maximum length of numeric string. */ + +/* Flags used during conversion. */ +#define LONG 0x01 /* l: long or double */ +#define SHORT 0x04 /* h: short */ +#define QUAD 0x08 /* q: quad (same as ll) */ +#define SUPPRESS 0x10 /* suppress assignment */ +#define POINTER 0x20 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x40 /* do not skip blanks */ + +/* +** The following are used in numeric conversions only: +** SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; +** SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. +*/ + +#define SIGNOK 0x080 /* +/- is (still) legal */ +#define NDIGITS 0x100 /* no digits detected */ + +#define DPTOK 0x200 /* (float) decimal point is still legal */ +#define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */ + +#define PFXOK 0x200 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x400 /* no zero digits detected */ + +/* Conversion types. */ +#define CT_CHAR 0 /* %c conversion */ +#define CT_CCL 1 /* %[...] conversion */ +#define CT_STRING 2 /* %s conversion */ +#define CT_INT 3 /* integer, i.e., strtoll or strtoull */ +#define CT_FLOAT 4 /* floating, i.e., strtod */ + +static unsigned char *sm_sccl __P((char *, unsigned char *)); +static jmp_buf ScanTimeOut; + +/* +** SCANALRM -- handler when timeout activated for sm_io_vfscanf() +** +** Returns flow of control to where setjmp(ScanTimeOut) was set. +** +** Parameters: +** sig -- unused +** +** Returns: +** does not return +** +** Side Effects: +** returns flow of control to setjmp(ScanTimeOut). +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED0 */ +static void +scanalrm(sig) + int sig; +{ + longjmp(ScanTimeOut, 1); +} + +/* +** SM_VFSCANF -- convert input into data units +** +** Parameters: +** fp -- file pointer for input data +** timeout -- time intvl allowed to complete (milliseconds) +** fmt0 -- format for finding data units +** ap -- vectors for memory location for storing data units +** +** Results: +** Success: number of data units assigned +** Failure: SM_IO_EOF +*/ + +int +sm_vfscanf(fp, timeout, fmt0, ap) + register SM_FILE_T *fp; + int SM_NONVOLATILE timeout; + char const *fmt0; + va_list SM_NONVOLATILE ap; +{ + register unsigned char *SM_NONVOLATILE fmt = (unsigned char *) fmt0; + register int c; /* character from format, or conversion */ + register size_t width; /* field width, or 0 */ + register char *p; /* points into all kinds of strings */ + register int n; /* handy integer */ + register int flags; /* flags as defined above */ + register char *p0; /* saves original value of p when necessary */ + int nassigned; /* number of fields assigned */ + int nread; /* number of characters consumed from fp */ + int base; /* base argument to strtoll/strtoull */ + ULONGLONG_T (*ccfn)(); /* conversion function (strtoll/strtoull) */ + char ccltab[256]; /* character class table for %[...] */ + char buf[BUF]; /* buffer for numeric conversions */ + SM_EVENT *evt = NULL; + + /* `basefix' is used to avoid `if' tests in the integer scanner */ + static short basefix[17] = + { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + + if (timeout == SM_TIME_DEFAULT) + timeout = fp->f_timeout; + if (timeout == SM_TIME_IMMEDIATE) + { + /* + ** Filling the buffer will take time and we are wanted to + ** return immediately. So... + */ + + errno = EAGAIN; + return SM_IO_EOF; + } + + if (timeout != SM_TIME_FOREVER) + { + if (setjmp(ScanTimeOut) != 0) + { + errno = EAGAIN; + return SM_IO_EOF; + } + + evt = sm_seteventm(timeout, scanalrm, 0); + } + + nassigned = 0; + nread = 0; + base = 0; /* XXX just to keep gcc happy */ + ccfn = NULL; /* XXX just to keep gcc happy */ + for (;;) + { + c = *fmt++; + if (c == 0) + { + if (evt != NULL) + sm_clrevent(evt); /* undo our timeout */ + return nassigned; + } + if (isspace(c)) + { + while ((fp->f_r > 0 || sm_refill(fp, SM_TIME_FOREVER) + == 0) && + isspace(*fp->f_p)) + nread++, fp->f_r--, fp->f_p++; + continue; + } + if (c != '%') + goto literal; + width = 0; + flags = 0; + + /* + ** switch on the format. continue if done; + ** break once format type is derived. + */ + +again: c = *fmt++; + switch (c) + { + case '%': +literal: + if (fp->f_r <= 0 && sm_refill(fp, SM_TIME_FOREVER)) + goto input_failure; + if (*fp->f_p != c) + goto match_failure; + fp->f_r--, fp->f_p++; + nread++; + continue; + + case '*': + flags |= SUPPRESS; + goto again; + case 'h': + flags |= SHORT; + goto again; + case 'l': + if (*fmt == 'l') + { + fmt++; + flags |= QUAD; + } + else + { + flags |= LONG; + } + goto again; + case 'q': + flags |= QUAD; + goto again; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + width = width * 10 + c - '0'; + goto again; + + /* + ** Conversions. + ** Those marked `compat' are for 4.[123]BSD compatibility. + ** + ** (According to ANSI, E and X formats are supposed + ** to the same as e and x. Sorry about that.) + */ + + case 'D': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'd': + c = CT_INT; + ccfn = (ULONGLONG_T (*)())sm_strtoll; + base = 10; + break; + + case 'i': + c = CT_INT; + ccfn = (ULONGLONG_T (*)())sm_strtoll; + base = 0; + break; + + case 'O': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'o': + c = CT_INT; + ccfn = sm_strtoull; + base = 8; + break; + + case 'u': + c = CT_INT; + ccfn = sm_strtoull; + base = 10; + break; + + case 'X': + case 'x': + flags |= PFXOK; /* enable 0x prefixing */ + c = CT_INT; + ccfn = sm_strtoull; + base = 16; + break; + + case 'E': + case 'G': + case 'e': + case 'f': + case 'g': + c = CT_FLOAT; + break; + + case 's': + c = CT_STRING; + break; + + case '[': + fmt = sm_sccl(ccltab, fmt); + flags |= NOSKIP; + c = CT_CCL; + break; + + case 'c': + flags |= NOSKIP; + c = CT_CHAR; + break; + + case 'p': /* pointer format is like hex */ + flags |= POINTER | PFXOK; + c = CT_INT; + ccfn = sm_strtoull; + base = 16; + break; + + case 'n': + if (flags & SUPPRESS) /* ??? */ + continue; + if (flags & SHORT) + *SM_VA_ARG(ap, short *) = nread; + else if (flags & LONG) + *SM_VA_ARG(ap, long *) = nread; + else + *SM_VA_ARG(ap, int *) = nread; + continue; + + /* Disgusting backwards compatibility hacks. XXX */ + case '\0': /* compat */ + if (evt != NULL) + sm_clrevent(evt); /* undo our timeout */ + return SM_IO_EOF; + + default: /* compat */ + if (isupper(c)) + flags |= LONG; + c = CT_INT; + ccfn = (ULONGLONG_T (*)()) sm_strtoll; + base = 10; + break; + } + + /* We have a conversion that requires input. */ + if (fp->f_r <= 0 && sm_refill(fp, SM_TIME_FOREVER)) + goto input_failure; + + /* + ** Consume leading white space, except for formats + ** that suppress this. + */ + + if ((flags & NOSKIP) == 0) + { + while (isspace(*fp->f_p)) + { + nread++; + if (--fp->f_r > 0) + fp->f_p++; + else if (sm_refill(fp, SM_TIME_FOREVER)) + goto input_failure; + } + /* + ** Note that there is at least one character in + ** the buffer, so conversions that do not set NOSKIP + ** can no longer result in an input failure. + */ + } + + /* Do the conversion. */ + switch (c) + { + case CT_CHAR: + /* scan arbitrary characters (sets NOSKIP) */ + if (width == 0) + width = 1; + if (flags & SUPPRESS) + { + size_t sum = 0; + for (;;) + { + if ((size_t) (n = fp->f_r) < width) + { + sum += n; + width -= n; + fp->f_p += n; + if (sm_refill(fp, + SM_TIME_FOREVER)) + { + if (sum == 0) + goto input_failure; + break; + } + } + else + { + sum += width; + fp->f_r -= width; + fp->f_p += width; + break; + } + } + nread += sum; + } + else + { + size_t r; + + r = sm_io_read(fp, SM_TIME_FOREVER, + (void *) SM_VA_ARG(ap, char *), + width); + if (r == 0) + goto input_failure; + nread += r; + nassigned++; + } + break; + + case CT_CCL: + /* scan a (nonempty) character class (sets NOSKIP) */ + if (width == 0) + width = (size_t)~0; /* `infinity' */ + + /* take only those things in the class */ + if (flags & SUPPRESS) + { + n = 0; + while (ccltab[*fp->f_p] != '\0') + { + n++, fp->f_r--, fp->f_p++; + if (--width == 0) + break; + if (fp->f_r <= 0 && + sm_refill(fp, SM_TIME_FOREVER)) + { + if (n == 0) /* XXX how? */ + goto input_failure; + break; + } + } + if (n == 0) + goto match_failure; + } + else + { + p0 = p = SM_VA_ARG(ap, char *); + while (ccltab[*fp->f_p] != '\0') + { + fp->f_r--; + *p++ = *fp->f_p++; + if (--width == 0) + break; + if (fp->f_r <= 0 && + sm_refill(fp, SM_TIME_FOREVER)) + { + if (p == p0) + goto input_failure; + break; + } + } + n = p - p0; + if (n == 0) + goto match_failure; + *p = 0; + nassigned++; + } + nread += n; + break; + + case CT_STRING: + /* like CCL, but zero-length string OK, & no NOSKIP */ + if (width == 0) + width = (size_t)~0; + if (flags & SUPPRESS) + { + n = 0; + while (!isspace(*fp->f_p)) + { + n++, fp->f_r--, fp->f_p++; + if (--width == 0) + break; + if (fp->f_r <= 0 && + sm_refill(fp, SM_TIME_FOREVER)) + break; + } + nread += n; + } + else + { + p0 = p = SM_VA_ARG(ap, char *); + while (!isspace(*fp->f_p)) + { + fp->f_r--; + *p++ = *fp->f_p++; + if (--width == 0) + break; + if (fp->f_r <= 0 && + sm_refill(fp, SM_TIME_FOREVER)) + break; + } + *p = 0; + nread += p - p0; + nassigned++; + } + continue; + + case CT_INT: + /* scan an integer as if by strtoll/strtoull */ +#if SM_CONF_BROKEN_SIZE_T + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; +#else /* SM_CONF_BROKEN_SIZE_T */ + /* size_t is unsigned, hence this optimisation */ + if (--width > sizeof(buf) - 2) + width = sizeof(buf) - 2; + width++; +#endif /* SM_CONF_BROKEN_SIZE_T */ + flags |= SIGNOK | NDIGITS | NZDIGITS; + for (p = buf; width > 0; width--) + { + c = *fp->f_p; + + /* + ** Switch on the character; `goto ok' + ** if we accept it as a part of number. + */ + + switch (c) + { + + /* + ** The digit 0 is always legal, but is + ** special. For %i conversions, if no + ** digits (zero or nonzero) have been + ** scanned (only signs), we will have + ** base==0. In that case, we should set + ** it to 8 and enable 0x prefixing. + ** Also, if we have not scanned zero digits + ** before this, do not turn off prefixing + ** (someone else will turn it off if we + ** have scanned any nonzero digits). + */ + + case '0': + if (base == 0) + { + base = 8; + flags |= PFXOK; + } + if (flags & NZDIGITS) + flags &= ~(SIGNOK|NZDIGITS|NDIGITS); + else + flags &= ~(SIGNOK|PFXOK|NDIGITS); + goto ok; + + /* 1 through 7 always legal */ + case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + base = basefix[base]; + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* digits 8 and 9 ok iff decimal or hex */ + case '8': case '9': + base = basefix[base]; + if (base <= 8) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* letters ok iff hex */ + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + + /* no need to fix base here */ + if (base <= 10) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* sign ok only as first character */ + case '+': case '-': + if (flags & SIGNOK) + { + flags &= ~SIGNOK; + goto ok; + } + break; + + /* x ok iff flag still set & 2nd char */ + case 'x': case 'X': + if (flags & PFXOK && p == buf + 1) + { + base = 16; /* if %i */ + flags &= ~PFXOK; + goto ok; + } + break; + } + + /* + ** If we got here, c is not a legal character + ** for a number. Stop accumulating digits. + */ + + break; + ok: + /* c is legal: store it and look at the next. */ + *p++ = c; + if (--fp->f_r > 0) + fp->f_p++; + else if (sm_refill(fp, SM_TIME_FOREVER)) + break; /* SM_IO_EOF */ + } + + /* + ** If we had only a sign, it is no good; push + ** back the sign. If the number ends in `x', + ** it was [sign] '0' 'x', so push back the x + ** and treat it as [sign] '0'. + */ + + if (flags & NDIGITS) + { + if (p > buf) + (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, + *(unsigned char *)--p); + goto match_failure; + } + c = ((unsigned char *)p)[-1]; + if (c == 'x' || c == 'X') + { + --p; + (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c); + } + if ((flags & SUPPRESS) == 0) + { + ULONGLONG_T res; + + *p = 0; + res = (*ccfn)(buf, (char **)NULL, base); + if (flags & POINTER) + *SM_VA_ARG(ap, void **) = + (void *)(long) res; + else if (flags & QUAD) + *SM_VA_ARG(ap, LONGLONG_T *) = res; + else if (flags & LONG) + *SM_VA_ARG(ap, long *) = res; + else if (flags & SHORT) + *SM_VA_ARG(ap, short *) = res; + else + *SM_VA_ARG(ap, int *) = res; + nassigned++; + } + nread += p - buf; + break; + + case CT_FLOAT: + /* scan a floating point number as if by strtod */ + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; + flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; + for (p = buf; width; width--) + { + c = *fp->f_p; + + /* + ** This code mimicks the integer conversion + ** code, but is much simpler. + */ + + switch (c) + { + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + flags &= ~(SIGNOK | NDIGITS); + goto fok; + + case '+': case '-': + if (flags & SIGNOK) + { + flags &= ~SIGNOK; + goto fok; + } + break; + case '.': + if (flags & DPTOK) + { + flags &= ~(SIGNOK | DPTOK); + goto fok; + } + break; + case 'e': case 'E': + + /* no exponent without some digits */ + if ((flags&(NDIGITS|EXPOK)) == EXPOK) + { + flags = + (flags & ~(EXPOK|DPTOK)) | + SIGNOK | NDIGITS; + goto fok; + } + break; + } + break; + fok: + *p++ = c; + if (--fp->f_r > 0) + fp->f_p++; + else if (sm_refill(fp, SM_TIME_FOREVER)) + break; /* SM_IO_EOF */ + } + + /* + ** If no digits, might be missing exponent digits + ** (just give back the exponent) or might be missing + ** regular digits, but had sign and/or decimal point. + */ + + if (flags & NDIGITS) + { + if (flags & EXPOK) + { + /* no digits at all */ + while (p > buf) + (void) sm_io_ungetc(fp, + SM_TIME_DEFAULT, + *(unsigned char *)--p); + goto match_failure; + } + + /* just a bad exponent (e and maybe sign) */ + c = *(unsigned char *) --p; + if (c != 'e' && c != 'E') + { + (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, + c); /* sign */ + c = *(unsigned char *)--p; + } + (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c); + } + if ((flags & SUPPRESS) == 0) + { + double res; + + *p = 0; + res = strtod(buf, (char **) NULL); + if (flags & LONG) + *SM_VA_ARG(ap, double *) = res; + else + *SM_VA_ARG(ap, float *) = res; + nassigned++; + } + nread += p - buf; + break; + } + } +input_failure: + if (evt != NULL) + sm_clrevent(evt); /* undo our timeout */ + return nassigned ? nassigned : -1; +match_failure: + if (evt != NULL) + sm_clrevent(evt); /* undo our timeout */ + return nassigned; +} + +/* +** SM_SCCL -- sequenced character comparison list +** +** Fill in the given table from the scanset at the given format +** (just after `['). Return a pointer to the character past the +** closing `]'. The table has a 1 wherever characters should be +** considered part of the scanset. +** +** Parameters: +** tab -- array flagging "active" char's to match (returned) +** fmt -- character list (within "[]") +** +** Results: +*/ + +static unsigned char * +sm_sccl(tab, fmt) + register char *tab; + register unsigned char *fmt; +{ + register int c, n, v; + + /* first `clear' the whole table */ + c = *fmt++; /* first char hat => negated scanset */ + if (c == '^') + { + v = 1; /* default => accept */ + c = *fmt++; /* get new first char */ + } + else + v = 0; /* default => reject */ + + /* should probably use memset here */ + for (n = 0; n < 256; n++) + tab[n] = v; + if (c == 0) + return fmt - 1; /* format ended before closing ] */ + + /* + ** Now set the entries corresponding to the actual scanset + ** to the opposite of the above. + ** + ** The first character may be ']' (or '-') without being special; + ** the last character may be '-'. + */ + + v = 1 - v; + for (;;) + { + tab[c] = v; /* take character c */ +doswitch: + n = *fmt++; /* and examine the next */ + switch (n) + { + + case 0: /* format ended too soon */ + return fmt - 1; + + case '-': + /* + ** A scanset of the form + ** [01+-] + ** is defined as `the digit 0, the digit 1, + ** the character +, the character -', but + ** the effect of a scanset such as + ** [a-zA-Z0-9] + ** is implementation defined. The V7 Unix + ** scanf treats `a-z' as `the letters a through + ** z', but treats `a-a' as `the letter a, the + ** character -, and the letter a'. + ** + ** For compatibility, the `-' is not considerd + ** to define a range if the character following + ** it is either a close bracket (required by ANSI) + ** or is not numerically greater than the character + ** we just stored in the table (c). + */ + + n = *fmt; + if (n == ']' || n < c) + { + c = '-'; + break; /* resume the for(;;) */ + } + fmt++; + do + { + /* fill in the range */ + tab[++c] = v; + } while (c < n); +#if 1 /* XXX another disgusting compatibility hack */ + + /* + ** Alas, the V7 Unix scanf also treats formats + ** such as [a-c-e] as `the letters a through e'. + ** This too is permitted by the standard.... + */ + + goto doswitch; +#else + c = *fmt++; + if (c == 0) + return fmt - 1; + if (c == ']') + return fmt; + break; +#endif + + case ']': /* end of scanset */ + return fmt; + + default: /* just another character */ + c = n; + break; + } + } + /* NOTREACHED */ +} diff --git a/gnu/dist/sendmail/libsm/vprintf.c b/gnu/dist/sendmail/libsm/vprintf.c new file mode 100644 index 000000000000..0ee3cedc6405 --- /dev/null +++ b/gnu/dist/sendmail/libsm/vprintf.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: vprintf.c,v 1.14 2001/09/11 04:04:49 gshapiro Exp") +#include +#include "local.h" + +/* +** SM_VPRINTF -- print to standard out with variable length args +** +** Parameters: +** timeout -- length of time allow to do the print +** fmt -- the format of the output +** ap -- the variable number of args to be used for output +** +** Returns: +** as sm_io_vfprintf() does. +*/ + +int +sm_vprintf(timeout, fmt, ap) + int timeout; + char const *fmt; + SM_VA_LOCAL_DECL +{ + return sm_io_vfprintf(smiostdout, timeout, fmt, ap); +} diff --git a/gnu/dist/sendmail/libsm/vsnprintf.c b/gnu/dist/sendmail/libsm/vsnprintf.c new file mode 100644 index 000000000000..dbda9410ca46 --- /dev/null +++ b/gnu/dist/sendmail/libsm/vsnprintf.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: vsnprintf.c,v 1.23 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include "local.h" + +/* +** SM_VSNPRINTF -- format data for "output" into a string +** +** Assigned 'str' to a "fake" file pointer. This allows common +** o/p formatting function sm_vprintf() to be used. +** +** Parameters: +** str -- location for output +** n -- maximum size for o/p +** fmt -- format directives +** ap -- data unit vectors for use by 'fmt' +** +** Results: +** result from sm_io_vfprintf() +** +** Side Effects: +** Limits the size ('n') to INT_MAX. +*/ + +int +sm_vsnprintf(str, n, fmt, ap) + char *str; + size_t n; + const char *fmt; + SM_VA_LOCAL_DECL +{ + int ret; + char dummy; + SM_FILE_T fake; + + /* While snprintf(3) specifies size_t stdio uses an int internally */ + if (n > INT_MAX) + n = INT_MAX; + + /* Stdio internals do not deal correctly with zero length buffer */ + if (n == 0) + { + str = &dummy; + n = 1; + } + fake.sm_magic = SmFileMagic; + fake.f_timeout = SM_TIME_FOREVER; + fake.f_timeoutstate = SM_TIME_BLOCK; + fake.f_file = -1; + fake.f_flags = SMWR | SMSTR; + fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; + fake.f_bf.smb_size = fake.f_w = n - 1; + fake.f_close = NULL; + fake.f_open = NULL; + fake.f_read = NULL; + fake.f_write = NULL; + fake.f_seek = NULL; + fake.f_setinfo = fake.f_getinfo = NULL; + fake.f_type = "sm_vsnprintf:fake"; + ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); + *fake.f_p = 0; + return ret; +} diff --git a/gnu/dist/sendmail/libsm/vsprintf.c b/gnu/dist/sendmail/libsm/vsprintf.c new file mode 100644 index 000000000000..9969f1cc976d --- /dev/null +++ b/gnu/dist/sendmail/libsm/vsprintf.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: vsprintf.c,v 1.21 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include "local.h" + +/* +** SM_VSPRINTF -- format data for "output" into a string +** +** Assigned 'str' to a "fake" file pointer. This allows common +** o/p formatting function sm_vprintf() to be used. +** +** Parameters: +** str -- location for output +** fmt -- format directives +** ap -- data unit vectors for use by 'fmt' +** +** Results: +** result from sm_io_vfprintf() +** +** Side Effects: +** Quietly limits the size to INT_MAX though this may +** not prevent SEGV's. +*/ + +int +sm_vsprintf(str, fmt, ap) + char *str; + const char *fmt; + SM_VA_LOCAL_DECL +{ + int ret; + SM_FILE_T fake; + + fake.sm_magic = SmFileMagic; + fake.f_file = -1; + fake.f_flags = SMWR | SMSTR; + fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; + fake.f_bf.smb_size = fake.f_w = INT_MAX; + fake.f_timeout = SM_TIME_FOREVER; + fake.f_timeoutstate = SM_TIME_BLOCK; + fake.f_close = NULL; + fake.f_open = NULL; + fake.f_read = NULL; + fake.f_write = NULL; + fake.f_seek = NULL; + fake.f_setinfo = fake.f_getinfo = NULL; + fake.f_type = "sm_vsprintf:fake"; + ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); + *fake.f_p = '\0'; + return ret; +} diff --git a/gnu/dist/sendmail/libsm/vsscanf.c b/gnu/dist/sendmail/libsm/vsscanf.c new file mode 100644 index 000000000000..c3a75d7d54e5 --- /dev/null +++ b/gnu/dist/sendmail/libsm/vsscanf.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Donn Seeley at UUNET Technologies, Inc. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: vsscanf.c,v 1.23 2002/02/01 02:28:00 ca Exp") +#include +#include + +/* +** SM_EOFREAD -- dummy read function for faked file below +** +** Parameters: +** fp -- file pointer +** buf -- location to place read data +** len -- number of bytes to read +** +** Returns: +** 0 (zero) always +*/ + +/* type declaration for later use */ +static ssize_t sm_eofread __P((SM_FILE_T *, char *, size_t)); + +/* ARGSUSED0 */ +static ssize_t +sm_eofread(fp, buf, len) + SM_FILE_T *fp; + char *buf; + size_t len; +{ + return 0; +} + +/* +** SM_VSSCANF -- scan a string to find data units +** +** Parameters: +** str -- strings containing data +** fmt -- format directive for finding data units +** ap -- memory locations to place format found data units +** +** Returns: +** Failure: SM_IO_EOF +** Success: number of data units found +** +** Side Effects: +** Attempts to strlen() 'str'; if not a '\0' terminated string +** then the call may SEGV/fail. +** Faking the string 'str' as a file. +*/ + +int +sm_vsscanf(str, fmt, ap) + const char *str; + const char *fmt; + SM_VA_LOCAL_DECL +{ + SM_FILE_T fake; + + fake.sm_magic = SmFileMagic; + fake.f_timeout = SM_TIME_FOREVER; + fake.f_timeoutstate = SM_TIME_BLOCK; + fake.f_file = -1; + fake.f_flags = SMRD; + fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; + fake.f_bf.smb_size = fake.f_r = strlen(str); + fake.f_read = sm_eofread; + fake.f_ub.smb_base = NULL; + fake.f_close = NULL; + fake.f_open = NULL; + fake.f_write = NULL; + fake.f_seek = NULL; + fake.f_setinfo = fake.f_getinfo = NULL; + fake.f_type = "sm_vsscanf:fake"; + return sm_vfscanf(&fake, SM_TIME_FOREVER, fmt, ap); +} diff --git a/gnu/dist/sendmail/libsm/wbuf.c b/gnu/dist/sendmail/libsm/wbuf.c new file mode 100644 index 000000000000..331bcd52538f --- /dev/null +++ b/gnu/dist/sendmail/libsm/wbuf.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: wbuf.c,v 1.21 2001/09/11 04:04:49 gshapiro Exp") +#include +#include +#include "local.h" + +/* Note: This function is called from a macro located in */ + +/* +** SM_WBUF -- write character to and flush (likely now full) buffer +** +** Write the given character into the (probably full) buffer for +** the given file. Flush the buffer out if it is or becomes full, +** or if c=='\n' and the file is line buffered. +** +** Parameters: +** fp -- the file pointer +** timeout -- time to complete operation (milliseconds) +** c -- int representation of the character to add +** +** Results: +** Failure: -1 and sets errno +** Success: int value of 'c' +*/ + +int +sm_wbuf(fp, timeout, c) + register SM_FILE_T *fp; + int timeout; + register int c; +{ + register int n; + + /* + ** In case we cannot write, or longjmp takes us out early, + ** make sure w is 0 (if fully- or un-buffered) or -bf.smb_size + ** (if line buffered) so that we will get called again. + ** If we did not do this, a sufficient number of sm_io_putc() + ** calls might wrap w from negative to positive. + */ + + fp->f_w = fp->f_lbfsize; + if (cantwrite(fp)) + { + errno = EBADF; + return SM_IO_EOF; + } + c = (unsigned char)c; + + /* + ** If it is completely full, flush it out. Then, in any case, + ** stuff c into the buffer. If this causes the buffer to fill + ** completely, or if c is '\n' and the file is line buffered, + ** flush it (perhaps a second time). The second flush will always + ** happen on unbuffered streams, where bf.smb_size==1; sm_io_flush() + ** guarantees that sm_io_putc() will always call sm_wbuf() by setting + ** w to 0, so we need not do anything else. + ** Note for the timeout, only one of the sm_io_flush's will get called. + */ + + n = fp->f_p - fp->f_bf.smb_base; + if (n >= fp->f_bf.smb_size) + { + if (sm_io_flush(fp, timeout)) + return SM_IO_EOF; /* sm_io_flush() sets errno */ + n = 0; + } + fp->f_w--; + *fp->f_p++ = c; + if (++n == fp->f_bf.smb_size || (fp->f_flags & SMLBF && c == '\n')) + if (sm_io_flush(fp, timeout)) + return SM_IO_EOF; /* sm_io_flush() sets errno */ + return c; +} diff --git a/gnu/dist/sendmail/libsm/wsetup.c b/gnu/dist/sendmail/libsm/wsetup.c new file mode 100644 index 000000000000..676c3bd32f50 --- /dev/null +++ b/gnu/dist/sendmail/libsm/wsetup.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. + */ + +#include +SM_RCSID("@(#)Id: wsetup.c,v 1.20 2002/02/07 18:02:45 ca Exp") +#include +#include +#include +#include "local.h" + +/* +** SM_WSETUP -- check writing is safe +** +** Various output routines call wsetup to be sure it is safe to write, +** because either flags does not include SMMWR, or buf is NULL. +** Used in the macro "cantwrite" found in "local.h". +** +** Parameters: +** fp -- the file pointer +** +** Results: +** Failure: SM_IO_EOF and sets errno +** Success: 0 (zero) +*/ + +int +sm_wsetup(fp) + register SM_FILE_T *fp; +{ + /* make sure stdio is set up */ + if (!Sm_IO_DidInit) + sm_init(); + + /* If we are not writing, we had better be reading and writing. */ + if ((fp->f_flags & SMWR) == 0) + { + if ((fp->f_flags & SMRW) == 0) + { + errno = EBADF; + return SM_IO_EOF; + } + if (fp->f_flags & SMRD) + { + /* clobber any ungetc data */ + if (HASUB(fp)) + FREEUB(fp); + + /* discard read buffer */ + fp->f_flags &= ~(SMRD|SMFEOF); + fp->f_r = 0; + fp->f_p = fp->f_bf.smb_base; + } + fp->f_flags |= SMWR; + } + + /* Make a buffer if necessary, then set w. */ + if (fp->f_bf.smb_base == NULL) + sm_makebuf(fp); + if (fp->f_flags & SMLBF) + { + /* + ** It is line buffered, so make lbfsize be -bufsize + ** for the sm_putc() macro. We will change lbfsize back + ** to 0 whenever we turn off SMWR. + */ + + fp->f_w = 0; + fp->f_lbfsize = -fp->f_bf.smb_size; + } + else + fp->f_w = fp->f_flags & SMNBF ? 0 : fp->f_bf.smb_size; + return 0; +} diff --git a/gnu/dist/sendmail/libsm/xtrap.c b/gnu/dist/sendmail/libsm/xtrap.c new file mode 100644 index 000000000000..df2727312870 --- /dev/null +++ b/gnu/dist/sendmail/libsm/xtrap.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2000 Sendmail, Inc. and its suppliers. + * 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. + */ + +#include +SM_RCSID("@(#)Id: xtrap.c,v 1.5 2001/09/11 04:04:49 gshapiro Exp") + +#include + +SM_ATOMIC_UINT_T SmXtrapCount; + +SM_DEBUG_T SmXtrapDebug = SM_DEBUG_INITIALIZER("sm_xtrap", + "@(#)$Debug: sm_xtrap - raise exception at N'th xtrap point $"); + +SM_DEBUG_T SmXtrapReport = SM_DEBUG_INITIALIZER("sm_xtrap_report", + "@(#)$Debug: sm_xtrap_report - report xtrap count on exit $"); diff --git a/gnu/dist/sendmail/libsmdb/Makefile.m4 b/gnu/dist/sendmail/libsmdb/Makefile.m4 index f24c0a0d63c3..0bfb9c640baa 100644 --- a/gnu/dist/sendmail/libsmdb/Makefile.m4 +++ b/gnu/dist/sendmail/libsmdb/Makefile.m4 @@ -1,5 +1,7 @@ +dnl Id: Makefile.m4,v 8.13.4.1 2002/06/21 21:58:33 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') diff --git a/gnu/dist/sendmail/libsmutil/Makefile.m4 b/gnu/dist/sendmail/libsmutil/Makefile.m4 index 93a344c48ce0..feb0e9e941c0 100644 --- a/gnu/dist/sendmail/libsmutil/Makefile.m4 +++ b/gnu/dist/sendmail/libsmutil/Makefile.m4 @@ -1,12 +1,14 @@ +dnl Id: Makefile.m4,v 8.16.4.1 2002/06/21 21:58:35 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`library', `libsmutil') -define(`bldSOURCES', `debug.c errstring.c lockfile.c safefile.c snprintf.c strl.c ') +define(`bldSOURCES', `debug.c err.c lockfile.c safefile.c snprintf.c cf.c ') APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') bldPRODUCT_END diff --git a/gnu/dist/sendmail/libsmutil/cf.c b/gnu/dist/sendmail/libsmutil/cf.c new file mode 100644 index 000000000000..227f911e8646 --- /dev/null +++ b/gnu/dist/sendmail/libsmutil/cf.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: cf.c,v 8.18.2.1 2002/09/24 21:48:23 ca Exp") +#include + +/* +** GETCFNAME -- return the name of the .cf file to use. +** +** Some systems (e.g., NeXT) determine this dynamically. +** +** For others: returns submit.cf or sendmail.cf depending +** on the modes. +** +** Parameters: +** opmode -- operation mode. +** submitmode -- submit mode. +** cftype -- may request a certain cf file. +** conffile -- if set, return it. +** +** Returns: +** name of .cf file. +*/ + +char * +getcfname(opmode, submitmode, cftype, conffile) + int opmode; + int submitmode; + int cftype; + char *conffile; +{ +#if NETINFO + char *cflocation; +#endif /* NETINFO */ + + if (conffile != NULL) + return conffile; + + if (cftype == SM_GET_SUBMIT_CF || + ((submitmode != SUBMIT_UNKNOWN || + opmode == MD_DELIVER || + opmode == MD_ARPAFTP || + opmode == MD_SMTP) && + cftype != SM_GET_SENDMAIL_CF)) + { + struct stat sbuf; + static char cf[MAXPATHLEN]; + +#if NETINFO + cflocation = ni_propval("/locations", NULL, "sendmail", + "submit.cf", '\0'); + if (cflocation != NULL) + (void) sm_strlcpy(cf, cflocation, sizeof cf); + else +#endif /* NETINFO */ + (void) sm_strlcpyn(cf, sizeof cf, 2, _DIR_SENDMAILCF, + "submit.cf"); + if (cftype == SM_GET_SUBMIT_CF || stat(cf, &sbuf) == 0) + return cf; + } +#if NETINFO + cflocation = ni_propval("/locations", NULL, "sendmail", + "sendmail.cf", '\0'); + if (cflocation != NULL) + return cflocation; +#endif /* NETINFO */ + return _PATH_SENDMAILCF; +} diff --git a/gnu/dist/sendmail/libsmutil/err.c b/gnu/dist/sendmail/libsmutil/err.c new file mode 100644 index 000000000000..bdbe71ad686e --- /dev/null +++ b/gnu/dist/sendmail/libsmutil/err.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include + +SM_RCSID("@(#)Id: err.c,v 8.5 2001/09/11 04:04:55 gshapiro Exp") + +#include + +/*VARARGS1*/ +void +#ifdef __STDC__ +message(const char *msg, ...) +#else /* __STDC__ */ +message(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + const char *m; + SM_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; + SM_VA_START(ap, msg); + (void) vfprintf(stderr, m, ap); + SM_VA_END(ap); + (void) fprintf(stderr, "\n"); +} + +/*VARARGS1*/ +void +#ifdef __STDC__ +syserr(const char *msg, ...) +#else /* __STDC__ */ +syserr(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + const char *m; + SM_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; + SM_VA_START(ap, msg); + (void) vfprintf(stderr, m, ap); + SM_VA_END(ap); + (void) fprintf(stderr, "\n"); +} diff --git a/gnu/dist/sendmail/mail.local/Makefile.m4 b/gnu/dist/sendmail/mail.local/Makefile.m4 index 516850f5edff..aadb2fcf95f2 100644 --- a/gnu/dist/sendmail/mail.local/Makefile.m4 +++ b/gnu/dist/sendmail/mail.local/Makefile.m4 @@ -1,14 +1,17 @@ +dnl Id: Makefile.m4,v 8.49.2.1 2002/06/21 21:58:36 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`executable', `mail.local') -define(`bldNO_INSTALL') +define(`bldNO_INSTALL', `true') define(`bldSOURCES', `mail.local.c ') -bldPUSH_SMLIB(`smutil') +bldPUSH_SMLIB(`sm') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') bldPRODUCT_END bldPRODUCT_START(`manpage', `mail.local') diff --git a/gnu/dist/sendmail/mailstats/Makefile.m4 b/gnu/dist/sendmail/mailstats/Makefile.m4 index 5a9259d13188..7ccec821ae9a 100644 --- a/gnu/dist/sendmail/mailstats/Makefile.m4 +++ b/gnu/dist/sendmail/mailstats/Makefile.m4 @@ -1,5 +1,7 @@ +dnl Id: Makefile.m4,v 8.34.4.1 2002/06/21 21:58:37 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') @@ -8,6 +10,7 @@ PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`executable', `mailstats') define(`bldINSTALL_DIR', `S') define(`bldSOURCES', `mailstats.c ') +bldPUSH_SMLIB(`sm') bldPUSH_SMLIB(`smutil') APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') bldPRODUCT_END diff --git a/gnu/dist/sendmail/mailstats/mailstats.0 b/gnu/dist/sendmail/mailstats/mailstats.0 index 0db00a3d1567..ba36e270cb5a 100644 --- a/gnu/dist/sendmail/mailstats/mailstats.0 +++ b/gnu/dist/sendmail/mailstats/mailstats.0 @@ -1,12 +1,14 @@ -MAILSTATS(8) MAILSTATS(8) +MAILSTATS(8) MAILSTATS(8) + + NNAAMMEE mailstats - display mail statistics SSYYNNOOPPSSIISS - mmaaiillssttaattss [--oo] [--pp] [--CC _c_f_f_i_l_e] [--ff _s_t_f_i_l_e] + mmaaiillssttaattss [--cc] [--oo] [--pp] [--PP] [--CC _c_f_f_i_l_e] [--ff _s_t_f_i_l_e] DDEESSCCRRIIPPTTIIOONN The mmaaiillssttaattss utility displays the current mail statis- @@ -30,17 +32,23 @@ DDEESSCCRRIIPPTTIIOONN the mailers is displayed (preceded with a ``T''), sepa- rated from the previous information by a line containing only equals (``='') characters. Another line preceded - with a ``C'' lists the number of connections. + with a ``C'' lists the number of TCP connections. The options are as follows: --CC Read the specified file instead of the default sseennddmmaaiill configuration file. - --ff Read the specified statistics file instead of the - statistics file specified in the sseennddmmaaiill configu- + --cc Try to use submit.cf instead of the default sseenndd-- + mmaaiill configuration file. + + --ff Read the specified statistics file instead of the + statistics file specified in the sseennddmmaaiill configu- ration file. + --PP Output information in program-readable mode without + clearing statistics. + --pp Output information in program-readable mode and clear statistics. @@ -49,6 +57,19 @@ DDEESSCCRRIIPPTTIIOONN The mmaaiillssttaattss utility exits 0 on success, and >0 if an error occurs. + + + + + Date: 2002/09/26 23:03:39 1 + + + + + +MAILSTATS(8) MAILSTATS(8) + + FFIILLEESS /etc/mail/sendmail.cf The default sseennddmmaaiill configura- tion file. @@ -60,4 +81,52 @@ SSEEEE AALLSSOO - Date: 2001/05/07 22:06:38 MAILSTATS(8) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: 2002/09/26 23:03:39 2 + + diff --git a/gnu/dist/sendmail/makemap/Makefile.m4 b/gnu/dist/sendmail/makemap/Makefile.m4 index 407723906363..aa97ba1c0e0c 100644 --- a/gnu/dist/sendmail/makemap/Makefile.m4 +++ b/gnu/dist/sendmail/makemap/Makefile.m4 @@ -1,5 +1,7 @@ +dnl Id: Makefile.m4,v 8.42.4.1 2002/06/21 21:58:38 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') @@ -8,6 +10,7 @@ PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`executable', `makemap') define(`bldSOURCES', `makemap.c ') define(`bldINSTALL_DIR', `S') +bldPUSH_SMLIB(`sm') bldPUSH_SMLIB(`smutil') bldPUSH_SMLIB(`smdb') APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') diff --git a/gnu/dist/sendmail/makemap/makemap.0 b/gnu/dist/sendmail/makemap/makemap.0 index 9e64e9a9e23e..f2cfff7d0d2f 100644 --- a/gnu/dist/sendmail/makemap/makemap.0 +++ b/gnu/dist/sendmail/makemap/makemap.0 @@ -1,13 +1,15 @@ -MAKEMAP(8) MAKEMAP(8) +MAKEMAP(8) MAKEMAP(8) + + NNAAMMEE makemap - create database maps for sendmail SSYYNNOOPPSSIISS mmaakkeemmaapp [--CC _f_i_l_e] [--NN] [--cc _c_a_c_h_e_s_i_z_e] [--dd] [--ee] [--ff] [--ll] - [--oo] [--rr] [--ss] [--uu] [--vv] _m_a_p_t_y_p_e _m_a_p_n_a_m + [--oo] [--rr] [--ss] [--tt _d_e_l_i_m] [--uu] [--vv] _m_a_p_t_y_p_e _m_a_p_n_a_m DDEESSCCRRIIPPTTIIOONN MMaakkeemmaapp creates the database maps used by the keyed map @@ -35,6 +37,10 @@ DDEESSCCRRIIPPTTIIOONN (``%%''). Blank lines and lines beginning with ``#'' are ignored. + Notice: do nnoott use mmaakkeemmaapp to create the aliases data + base, but nneewwaalliiaasseess which puts a special token into the + data base that is required by sseennddmmaaiill.. + If the _T_r_u_s_t_e_d_U_s_e_r option is set in the sendmail configu- ration file and mmaakkeemmaapp is invoked as root, the generated files will be owned by the specified _T_r_u_s_t_e_d_U_s_e_r_. @@ -52,6 +58,18 @@ DDEESSCCRRIIPPTTIIOONN --dd Allow duplicate keys in the map. This is only allowed on B-Tree format maps. If two identical keys are read, they will both be inserted into the + + + + Date: 2001/10/10 03:23:02 1 + + + + + +MAKEMAP(8) MAKEMAP(8) + + map. --ee Allow empty value (right hand side). @@ -75,17 +93,40 @@ DDEESSCCRRIIPPTTIIOONN includes checking for hard or symbolic links in world writable directories. - --uu dump (unmap) the content of the database to stan- + --tt Use the specified delimiter instead of white space. + + --uu dump (unmap) the content of the database to stan- dard output. --vv Verbosely print what it is doing. SSEEEE AALLSSOO - sendmail(8) + sendmail(8), newaliases(1) HHIISSTTOORRYY The mmaakkeemmaapp command appeared in 4.4BSD. - Date: 2000/12/29 18:12:20 MAKEMAP(8) + + + + + + + + + + + + + + + + + + + + Date: 2001/10/10 03:23:02 2 + + diff --git a/gnu/dist/sendmail/praliases/Makefile.m4 b/gnu/dist/sendmail/praliases/Makefile.m4 index 670c2ccf9747..297304194f28 100644 --- a/gnu/dist/sendmail/praliases/Makefile.m4 +++ b/gnu/dist/sendmail/praliases/Makefile.m4 @@ -1,5 +1,7 @@ +dnl Id: Makefile.m4,v 8.34.4.1 2002/06/21 21:58:39 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') @@ -8,6 +10,7 @@ PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`executable', `praliases') define(`bldINSTALL_DIR', `S') define(`bldSOURCES', `praliases.c ') +bldPUSH_SMLIB(`sm') bldPUSH_SMLIB(`smutil') bldPUSH_SMLIB(`smdb') APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') diff --git a/gnu/dist/sendmail/praliases/praliases.0 b/gnu/dist/sendmail/praliases/praliases.0 index 88403f13454c..3981c4788eb3 100644 --- a/gnu/dist/sendmail/praliases/praliases.0 +++ b/gnu/dist/sendmail/praliases/praliases.0 @@ -1,7 +1,9 @@ -PRALIASES(8) PRALIASES(8) +PRALIASES(8) PRALIASES(8) + + NNAAMMEE praliases - display system mail aliases @@ -36,4 +38,29 @@ SSEEEE AALLSSOO - Date: 2000/12/15 19:50:45 PRALIASES(8) + + + + + + + + + + + + + + + + + + + + + + + + Date: 2000/12/15 19:53:45 1 + + diff --git a/gnu/dist/sendmail/rmail/Makefile.m4 b/gnu/dist/sendmail/rmail/Makefile.m4 index deed4497f00a..a2ecd659329a 100644 --- a/gnu/dist/sendmail/rmail/Makefile.m4 +++ b/gnu/dist/sendmail/rmail/Makefile.m4 @@ -1,14 +1,16 @@ +dnl Id: Makefile.m4,v 8.42.4.1 2002/06/21 21:58:46 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`executable', `rmail') -define(`bldNO_INSTALL') +define(`bldNO_INSTALL', `true') define(`bldSOURCES', `rmail.c ') -bldPUSH_SMLIB(`smutil') +bldPUSH_SMLIB(`sm') bldPRODUCT_END bldPRODUCT_START(`manpage', `rmail') diff --git a/gnu/dist/sendmail/sendmail/Makefile.m4 b/gnu/dist/sendmail/sendmail/Makefile.m4 index 3fe070354c9e..427f16206b02 100644 --- a/gnu/dist/sendmail/sendmail/Makefile.m4 +++ b/gnu/dist/sendmail/sendmail/Makefile.m4 @@ -1,12 +1,18 @@ +dnl Id: Makefile.m4,v 8.91.2.4 2002/09/09 02:48:54 gshapiro Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') bldPRODUCT_START(`executable', `sendmail') -define(`bldBIN_TYPE', `S') +define(`bldBIN_TYPE', `G') define(`bldINSTALL_DIR', `') -define(`bldSOURCES', `main.c alias.c arpadate.c bf_'ifdef(`confSTDIO_TYPE', `confSTDIO_TYPE', `portable')`.c clock.c collect.c conf.c control.c convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c macro.c map.c mci.c milter.c mime.c parseaddr.c queue.c readcf.c recipient.c savemail.c sfsasl.c shmticklib.c srvrsmtp.c stab.c stats.c sysexits.c timers.c trace.c udb.c usersmtp.c util.c version.c ') +define(`bldSOURCES', `main.c alias.c arpadate.c bf.c collect.c conf.c control.c convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c macro.c map.c mci.c milter.c mime.c parseaddr.c queue.c readcf.c recipient.c sasl.c savemail.c sfsasl.c shmticklib.c sm_resolve.c srvrsmtp.c stab.c stats.c sysexits.c timers.c tls.c trace.c udb.c usersmtp.c util.c version.c ') PREPENDDEF(`confENVDEF', `confMAPDEF') +bldPUSH_SMLIB(`sm') bldPUSH_SMLIB(`smutil') +dnl hack: /etc/mail is not defined as "location of .cf" in the build system +define(`bldTARGET_INST_DEP', ifdef(`confINST_DEP', `confINST_DEP', +`${DESTDIR}/etc/mail/submit.cf ${DESTDIR}${MSPQ}'))dnl define(`bldTARGET_LINKS', ifdef(`confLINKS', `confLINKS', `${DESTDIR}${UBINDIR}/newaliases ${DESTDIR}${UBINDIR}/mailq ${DESTDIR}${UBINDIR}/hoststat ${DESTDIR}${UBINDIR}/purgestat') )dnl @@ -14,8 +20,12 @@ define(`bldTARGET_LINKS', ifdef(`confLINKS', `confLINKS', # location of sendmail statistics file (usually /etc/mail/ or /var/log) STDIR= ifdef(`confSTDIR', `confSTDIR', `/etc/mail') +# statistics file name +STFILE= ifdef(`confSTFILE', `confSTFILE', `statistics') +MSPSTFILE=ifdef(`confMSP_STFILE', `confMSP_STFILE', `sm-client.st') + # full path to installed statistics file (usually ${STDIR}/statistics) -STFILE= ${STDIR}/ifdef(`confSTFILE', `confSTFILE', `statistics') +STPATH= ${STDIR}/${STFILE} # location of sendmail helpfile file (usually /etc/mail) HFDIR= ifdef(`confHFDIR', `confHFDIR', `/etc/mail') @@ -31,18 +41,56 @@ divert(bldTARGETS_SECTION) statistics: ${CP} /dev/null statistics +${DESTDIR}/etc/mail/submit.cf: + @echo "Please read INSTALL if anything fails while installing the binary." + @echo "${DESTDIR}/etc/mail/submit.cf will be installed now." + cd ${SRCDIR}/cf/cf && make install-submit-cf + +MSPQ=ifdef(`confMSP_QUEUE_DIR', `confMSP_QUEUE_DIR', `/var/spool/clientmqueue') + +${DESTDIR}${MSPQ}: + @echo "Please read INSTALL if anything fails while installing the binary." + @echo "You must have setup a new user ${MSPQOWN} and a new group ${GBINGRP}" + @echo "as explained in sendmail/SECURITY." + mkdir -p ${DESTDIR}${MSPQ} + chown ${MSPQOWN} ${DESTDIR}${MSPQ} + chgrp ${GBINGRP} ${DESTDIR}${MSPQ} + chmod 0770 ${DESTDIR}${MSPQ} + divert(0) +ifdef(`confSETUSERID_INSTALL', `bldPUSH_INSTALL_TARGET(`install-set-user-id')') +ifdef(`confMTA_INSTALL', `bldPUSH_INSTALL_TARGET(`install-sm-mta')') ifdef(`confNO_HELPFILE_INSTALL',, `bldPUSH_INSTALL_TARGET(`install-hf')') ifdef(`confNO_STATISTICS_INSTALL',, `bldPUSH_INSTALL_TARGET(`install-st')') divert(bldTARGETS_SECTION) + +install-set-user-id: bldCURRENT_PRODUCT ifdef(`confNO_HELPFILE_INSTALL',, `install-hf') ifdef(`confNO_STATISTICS_INSTALL',, `install-st') ifdef(`confNO_MAN_BUILD',, `install-docs') + ${INSTALL} -c -o ${S`'BINOWN} -g ${S`'BINGRP} -m ${S`'BINMODE} bldCURRENT_PRODUCT ${DESTDIR}${M`'BINDIR} + for i in ${sendmailTARGET_LINKS}; do \ + rm -f $$i; \ + ${LN} ${LNOPTS} ${M`'BINDIR}/sendmail $$i; \ + done + +define(`confMTA_LINKS', `${DESTDIR}${UBINDIR}/newaliases ${DESTDIR}${UBINDIR}/mailq ${DESTDIR}${UBINDIR}/hoststat ${DESTDIR}${UBINDIR}/purgestat') +install-sm-mta: bldCURRENT_PRODUCT + ${INSTALL} -c -o ${M`'BINOWN} -g ${M`'BINGRP} -m ${M`'BINMODE} bldCURRENT_PRODUCT ${DESTDIR}${M`'BINDIR}/sm-mta + for i in confMTA_LINKS; do \ + rm -f $$i; \ + ${LN} ${LNOPTS} ${M`'BINDIR}/sm-mta $$i; \ + done + install-hf: if [ ! -d ${DESTDIR}${HFDIR} ]; then mkdir -p ${DESTDIR}${HFDIR}; else :; fi ${INSTALL} -c -o ${UBINOWN} -g ${UBINGRP} -m 444 helpfile ${DESTDIR}${HFFILE} install-st: statistics if [ ! -d ${DESTDIR}${STDIR} ]; then mkdir -p ${DESTDIR}${STDIR}; else :; fi - ${INSTALL} -c -o ${SBINOWN} -g ${UBINGRP} -m 644 statistics ${DESTDIR}${STFILE} + ${INSTALL} -c -o ${SBINOWN} -g ${UBINGRP} -m ifdef(`confSTMODE', `confSTMODE', `0600') statistics ${DESTDIR}${STPATH} + +install-submit-st: statistics ${DESTDIR}${MSPQ} + ${INSTALL} -c -o ${MSPQOWN} -g ${GBINGRP} -m ifdef(`confSTMODE', `confSTMODE', `0600') statistics ${DESTDIR}${MSPQ}/${MSPSTFILE} + divert(0) bldPRODUCT_END diff --git a/gnu/dist/sendmail/sendmail/SECURITY b/gnu/dist/sendmail/sendmail/SECURITY new file mode 100644 index 000000000000..9eca678e0827 --- /dev/null +++ b/gnu/dist/sendmail/sendmail/SECURITY @@ -0,0 +1,203 @@ +# Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. +# 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. +# +# Id: SECURITY,v 1.50.2.1 2002/09/23 21:28:48 ca Exp +# + +This file gives some hints how to configure and run sendmail for +people who are very security conscious (you should be...). + +Even though sendmail goes through great lengths to assure that it +can't be compromised even if the system it is running on is +incorrectly or insecurely configured, it can't work around everything. +This has been demonstrated by recent OS problems which have +subsequently been used to compromise the root account using sendmail +as a vector. One way to minimize the possibility of such problems +is to install sendmail without set-user-ID root, which avoids local +exploits. This configuration, which is the default starting with +8.12, is described in the first section of this security guide. + + +***************************************************** +** sendmail configuration without set-user-ID root ** +***************************************************** + +sendmail needs to run as root for several purposes: + +- bind to port 25 +- call the local delivery agent (LDA) as root (or other user) if the LDA + isn't set-user-ID root (unless some other method of storing e-mail in + local mailboxes is used). +- read .forward files +- write e-mail submitted via the command line to the queue directory. + +Only the last item requires a set-user-ID/set-group-ID program to +avoid problems with a world-writable directory. It is however +sufficient to have a set-group-ID program and a group-writable +queue directory. The other requirements listed above can be +fulfilled by a sendmail daemon that is started by root. Hence this +section explains how to use two sendmail configurations to accomplish +the goal to have a sendmail binary that is not set-user-ID root, +and hence is not open to system configuration/OS problems or at +least less problematic in presence of those. + +The default configuration starting with sendmail 8.12 uses one +sendmail binary which acts differently based on operation mode and +supplied options. + +sendmail must be a set-group-ID (default group: smmsp, recommended +gid: 25) program to allow for queueing mail in a group-writable +directory. Two .cf files are required: sendmail.cf for the daemon +and submit.cf for the submission program. The following permissions +should be used: + +-r-xr-sr-x root smmsp ... /PATH/TO/sendmail +drwxrwx--- smmsp smmsp ... /var/spool/clientmqueue +drwx------ root wheel ... /var/spool/mqueue +-r--r--r-- root wheel ... /etc/mail/sendmail.cf +-r--r--r-- root wheel ... /etc/mail/submit.cf + +[Notice: On some OS "wheel" is not used but "bin" or "root" instead, +however, this is not important here.] + +That is, the owner of sendmail is root, the group is smmsp, and +the binary is set-group-ID. The client mail queue is owned by +smmsp with group smmsp and is group writable. The client mail +queue directory must be writable by smmsp, but it must not be +accessible for others. That is, do not use world read or execute +permissions. In submit.cf the option UseMSP must be set, and +QueueFileMode must be set to 0660. submit.cf is available in +cf/cf/, which has been built from cf/cf/submit.mc. The file can +be used as-is, if you want to add more options, use cf/cf/submit.mc +as starting point and read cf/README: MESSAGE SUBMISSION PROGRAM +carefully. + +The .cf file is chosen based on the operation mode. For -bm (default), +-bs, and -t it is submit.cf (if it exists) for all others it is +sendmail.cf. This selection can be changed by -Ac or -Am (alternative +.cf file: client or mta). + +The daemon must be started by root as usual, e.g., + +/PATH/TO/sendmail -L sm-mta -bd -q1h + +(replace /PATH/TO with the right path for your OS, e.g., +/usr/sbin or /usr/lib). + +Notice: if you run sendmail from inetd (which in general is not a +good idea), you must specify -Am in addition to -bs. + +Mail will end up in the client queue if the daemon doesn't accept +connections or if an address is temporarily not resolvable. The +latter problem can be minimized by using + + FEATURE(`nocanonify', `canonify_hosts') + define(`confDIRECT_SUBMISSION_MODIFIERS', `C') + +which, however, may have undesired side effects. See cf/README for +a discussion. In general it is necessary to clean the queue either +via a cronjob or by running a daemon, e.g., + +/PATH/TO/sendmail -L sm-msp-queue -Ac -q30m + +If the option UseMSP is not set, sendmail will complain during +queue runs about bogus file permission. If you want a queue runner +for the client queue, you probably have to change OS specific +scripts to accomplish this (check the man pages of your OS for more +information.) You can start this program as root, it will change +its user id to RunAsUser (smmsp by default, recommended uid: 25). +This way smmsp does not need a valid shell. + +Summary +------- + +This is a brief summary how the two configuration files are used: + +sendmail.cf For the MTA (mail transmission agent) + The MTA is started by root as daemon: + + /PATH/TO/sendmail -L sm-mta -bd -q1h + + it accepts SMTP connections (on ports 25 and 587 by default); + it runs the main queue (/var/spool/mqueue by default). + +submit.cf For the MSP (mail submission program) + The MSP is used to submit e-mails, hence it is invoked + by programs (and maybe users); it does not run as SMTP + daemon; it uses /var/spool/clientmqueue by default; it + can be started to run that queue periodically: + + /PATH/TO/sendmail -L sm-msp-queue -Ac -q30m + + +Hints and Troubleshooting +------------------------- + +RunAsUser: FEATURE(`msp') sets the option RunAsUser to smmsp. +This user must have the group smmsp, i.e., the same group as the +clientmqueue directory. If you specify a user whose primary group +is not the same as that of the clientmqueue directory, then you +should explicitly set the group, e.g., + + FEATURE(`msp') + define(`confRUN_AS_USER', `mailmsp:smmsp') + +STARTTLS: If sendmail is compiled with STARTTLS support on a platform +that does not have HASURANDOMDEV defined, you either need to specify +the RandFile option (as for the MTA), or you have to turn off +STARTTLS in the MSP, e.g., + + DAEMON_OPTIONS(`Name=NoMTA, Addr=127.0.0.1, M=S') + FEATURE(`msp') + CLIENT_OPTIONS(`Family=inet, Address=0.0.0.0, M=S') + +The first option is used to turn off STARTTLS when the MSP is +invoked with -bs as some MUAs do. + + +What doesn't work anymore +------------------------- + +Normal users can't use mailq anymore to see the MTA mail queue. +There are several ways around it, e.g., changing QueueFileMode +or giving users access via a program like sudo. + +sendmail -bv may give misleading output for normal users since it +may not be able to access certain files, e.g., .forward files of +other users. + + +Alternative +----------- + +Instead of having one set-group-ID binary, it is possible to use +two with different permissions: one for message submission +(set-group-ID), one acting as daemon etc, which is only executable +by root. In that case it is possible to remove features from +the message submission program to have a smaller binary. +You can use + + sh ./Build install-sm-mta + +to install a sendmail program to act as daemon etc under the name +sm-mta. + +Set-User-Id +----------- + +If you really have to install sendmail set-user-ID root, first build +the sendmail package normally using + + sh ./Build + +Then you can use + + sh ./Build install-set-user-id + +to install the package in the old (pre-8.12) way. Make sure that +no submit.cf file is installed. See devtools/README about +confSETUSERID_INSTALL which you need to define. diff --git a/gnu/dist/sendmail/sendmail/TUNING b/gnu/dist/sendmail/sendmail/TUNING new file mode 100644 index 000000000000..9a349b41e590 --- /dev/null +++ b/gnu/dist/sendmail/sendmail/TUNING @@ -0,0 +1,230 @@ +# Copyright (c) 2001-2003 Sendmail, Inc. and its suppliers. +# 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. +# +# Id: TUNING,v 1.18.4.1 2003/02/07 18:19:51 ca Exp +# + +******************************************** +** This is a DRAFT, comments are welcome! ** +******************************************** + + +If the default configuration of sendmail does not achieve the +required performance, there are several configuration options that +can be changed to accomplish higher performance. However, before +those options are changed it is necessary to understand why the +performance is not as good as desired. This may also involve hardware +and software (OS) configurations which are not extensively explored +in this document. We assume that your system is not limited by +network bandwidth because optimizing for this situation is beyond +the scope of this guide. In almost all other cases performance will +be limited by disk I/O. + + +This text assumes that all options which are mentioned here are +familiar to the reader, they are explained in the Sendmail Installation +and Operations Guide; doc/op/op.txt. + +There are basically three different scenarios which are treated +in the following: +* Mailing Lists and Large Aliases (1-n Mailing) +* 1-1 Mass Mailing +* High Volume Mail + +Depending on your requirements, these may need different options +to optimize sendmail for the particular purpose. It is also possible +to configure sendmail to achieve good performance in all cases, but +it will not be optimal for any specific purpose. For example, it +is non-trivival to combine low latency (fast delivery of incoming +mail) with high overall throughput. + +Before we explore the different scenarios, a basic discussion about +disk I/O, delivery modes, and queue control is required. + + +* Disk I/O +----------------------------------------------- + +In general mail will be written to disk up before a delivery attempt +is made. This is required for reliability and should only be changed +in a few specific cases that are mentioned later on. To achieve +better disk I/O performance the queue directories can be spread +over several disks to distribute the load. This is some basic tuning +that should be done in all cases where the I/O speed of a single +disk is exceeded, which is true for almost every high-volume +situation except if a special disk subsystem with large (NV)RAM +buffer is used. + +Depending on your OS there might be ways to speed up I/O, e.g., +using softupdates or turning on the noatime mount option. If this +is done make sure the filesystem is still reliable, i.e., if fsync() +returns without an error, the file has really been committed to +disk. + + +* Queueing Strategies and DeliveryMode +----------------------------------------------- + +There are basically three delivery modes: + +background: incoming mail will be immediately delivered by a new process +interactive: incoming mail will be immediately delivered by the same process +queue: incoming mail will be queued and delivered by a queue runner later on + +The first offers the lowest latency without the disadvantage of the +second, which keep the connection from the sender open until the +delivery to the next hop succeeded or failed. However, it does not +allow for a good control over the number of delivery processes other +than limiting the total number of direct children of the daemon +processes (MaxChildren) or by load control options (RefuseLA, +DelayLA). Moreover, it can't make as good use as 'queue' mode can +for connection caching. + +Interactive DeliveryMode should only be used in rare cases, e.g., +if the delivery time to the next hop is a known quantity or if the +sender is under local control and it does not matter if it has to +wait for delivery. + +Queueing up e-mail before delivery is done by a queue runner allows +the best load control but does not achieve as low latency as the +other two modes. However, this mode is probably also best for +concurrent delivery since the number of queue runners can be specified +on a queue group basis. Persistent queue runners (-qp) can be used +to minimize the overhead for creating processes because they just +sleep for the specified interval (which shold be short) instead of +exiting after a queue run. + + +* Queue Groups +----------------------------------------------- + +In most situations disk I/O is a bottleneck which can be mitigated +by spreading the load over several disks. This can easily be achieved +with different queue directories. sendmail 8.12 introduces queue +groups which are collections of queue directories with similar +properties, i.e., number of processes to run the queues in the +group, maximum number of recipients within an e-mail (envelope), +etc. Queue groups allow control over the behaviour of different +queues. Depending on the setup, it is usually possible to have +several queue runners delivering mails concurrently which should +increase throughput. The number of queue runners can be controlled +per queue group (Runner=) and overall (MaxQueueChildren). + + +* DNS Lookups +----------------------------------------------- + +sendmail performs by default host name canonifications by using +host name lookups. This process is meant to replace unqualified +host name with qualified host names, and CNAMEs with the non-aliased +name. However, these lookups can take a while for large address +lists, e.g., mailing lists. If you can assure by other means that +host names are canonical, you should use + + FEATURE(`nocanonify', `canonify_hosts') + +in your .mc file. For further information on this feature and +additional options see cf/README. If sendmail is invoked directly +to send e-mail then either the -G option should be used or + + define(`confDIRECT_SUBMISSION_MODIFIERS', `C') + +should be added to the .mc file. + + +* Mailing Lists and Large Aliases (1-n Mailing) +----------------------------------------------- + +Before 8.12 sendmail delivers an e-mail sequentially to all its +recipients. For mailing lists or large aliases the overall delivery +time can be substantial, especially if some of the recipients are +located at hosts that are slow to accept e-mail. Some mailing list +software therefore "split" up e-mails into smaller pieces with +fewer recipients. sendmail 8.12 can do this itself, either across +queue groups or within a queue directory. The latter is controlled +by the 'r=' field of a queue group declaration. + +Let's assume a simple example: a mailing lists where most of +the recipients are at three domains: the local one (local.domain) +and two remotes (one.domain, two.domain) and the rest is splittered +over several other domains. For this case it is useful to specify +three queue groups: + +QUEUE_GROUP(`local', `P=/var/spool/mqueue/local, F=f, R=2, I=1m')dnl +QUEUE_GROUP(`one', `P=/var/spool/mqueue/one, F=f, r=50, R=3')dnl +QUEUE_GROUP(`two', `P=/var/spool/mqueue/two, F=f, r=30, R=4')dnl +QUEUE_GROUP(`remote', `P=/var/spool/mqueue/remote, F=f, r=5, R=8, I=2m')dnl +define(`ESMTP_MAILER_QGRP', `remote')dnl +define(`confDELIVERY_MODE', `q')dnl +define(`confMAX_QUEUE_CHILDREN', `50')dnl +define(`confMIN_QUEUE_AGE', `27m')dnl + +and specify the queuegroup ruleset as follows: + +LOCAL_RULESETS +Squeuegroup +R$* @ local.domain $# local +R$* @ $* one.domain $# one +R$* @ $* two.domain $# two +R$* @ $* $# remote +R$* $# mqueue + +Now it is necessary to control the number of queue runners, which +is done by MaxQueueChildren. Starting the daemon with the option +-q5m assures that the first delivery attempt for each e-mail is +done within 5 minutes, however, there are also individual queue +intervals for the queue groups as specified above. MinQueueAge +is set to 27 minutes to avoid that entries are run too often. + +Notice: if envelope splitting happens due to alias expansion, and +DeliveryMode is not 'i'nteractive, then only one envelope is sent +immediately. The rest (after splitting) are queued up and queue +runners must come along and take care of them. Hence it is essential +that the queue interval is very short. + + +* 1-1 Mass Mailing +----------------------------------------------- + +In this case some program generates e-mails which are sent to +individual recipients (or at most very few per e-mail). A simple +way to achieve high throughput is to set the delivery mode to +'interactive', turn off the SuperSafe option and make sure that the +program that generates the mails can deal with mail losses if the +server loses power. In no other case should SuperSafe be set to +'false'. If these conditions are met, sendmail does not need to +commit mails to disk but can buffer them in memory which will greatly +enhance performance, especially compared to normal disk subsystems, e.g., +non solid-state disks. + + +* High Volume Mail +----------------------------------------------- + +For high volume mail it is necessary to be able to control the load +on the system. Therefore the 'queue' delivery mode should be used, +and all options related to number of processes and the load should +be set to reasonable values. It is important not to accept mail +faster than it can be delivered otherwise the system will be +overwhelmed. Hence RefuseLA should be lower than QueueLA, the number +of daemon children should probably be lower than the number of queue +runnners (MaxChildren vs. MaxQueueChildren). DelayLA is a new option +in 8.12 which allows delaying connections instead of rejecting them. +This may result in a smoother load distribution depending on how +the mails are submitted to sendmail. + + +* Miscellaneous +----------------------------------------------- + +Other options that are interesting to tweak performance are +(in no particular order): + +SuperSafe: if interactive DeliveryMode is used, then this can +be set to the new value "interactive" in 8.12 to save some disk +synchronizations which are not really necessary in that mode. + diff --git a/gnu/dist/sendmail/sendmail/bf.c b/gnu/dist/sendmail/sendmail/bf.c new file mode 100644 index 000000000000..0880a6d28b41 --- /dev/null +++ b/gnu/dist/sendmail/sendmail/bf.c @@ -0,0 +1,858 @@ +/* + * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers. + * 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. + * + * Contributed by Exactis.com, Inc. + * + */ + +/* +** This is in transition. Changed from the original bf_torek.c code +** to use sm_io function calls directly rather than through stdio +** translation layer. Will be made a built-in file type of libsm +** next (once safeopen() linkable from libsm). +*/ + +#include +SM_RCSID("@(#)Id: bf.c,v 8.54.2.2 2002/06/21 19:58:40 gshapiro Exp") + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sendmail.h" +#include "bf.h" + +#include + +/* bf io functions */ +static ssize_t sm_bfread __P((SM_FILE_T *, char *, size_t)); +static ssize_t sm_bfwrite __P((SM_FILE_T *, const char *, size_t)); +static off_t sm_bfseek __P((SM_FILE_T *, off_t, int)); +static int sm_bfclose __P((SM_FILE_T *)); + +static int sm_bfopen __P((SM_FILE_T *, const void *, int, const void *)); +static int sm_bfsetinfo __P((SM_FILE_T *, int , void *)); +static int sm_bfgetinfo __P((SM_FILE_T *, int , void *)); + +/* +** Data structure for storing information about each buffered file +** (Originally in sendmail/bf_torek.h for the curious.) +*/ + +struct bf +{ + bool bf_committed; /* Has this buffered file been committed? */ + bool bf_ondisk; /* On disk: committed or buffer overflow */ + long bf_flags; + int bf_disk_fd; /* If on disk, associated file descriptor */ + char *bf_buf; /* Memory buffer */ + int bf_bufsize; /* Length of above buffer */ + int bf_buffilled; /* Bytes of buffer actually filled */ + char *bf_filename; /* Name of buffered file, if ever committed */ + MODE_T bf_filemode; /* Mode of buffered file, if ever committed */ + off_t bf_offset; /* Currect file offset */ + int bf_size; /* Total current size of file */ +}; + +#ifdef BF_STANDALONE +# define OPEN(fn, omode, cmode, sff) open(fn, omode, cmode) +#else /* BF_STANDALONE */ +# define OPEN(fn, omode, cmode, sff) safeopen(fn, omode, cmode, sff) +#endif /* BF_STANDALONE */ + +struct bf_info +{ + char *bi_filename; + MODE_T bi_fmode; + size_t bi_bsize; + long bi_flags; +}; + +/* +** SM_BFOPEN -- the "base" open function called by sm_io_open() for the +** internal, file-type-specific info setup. +** +** Parameters: +** fp -- file pointer being filled-in for file being open'd +** info -- information about file being opened +** flags -- ignored +** rpool -- ignored (currently) +** +** Returns: +** Failure: -1 and sets errno +** Success: 0 (zero) +*/ + +static int +sm_bfopen(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + char *filename; + MODE_T fmode; + size_t bsize; + long sflags; + struct bf *bfp; + int l; + struct stat st; + + filename = ((struct bf_info *) info)->bi_filename; + fmode = ((struct bf_info *) info)->bi_fmode; + bsize = ((struct bf_info *) info)->bi_bsize; + sflags = ((struct bf_info *) info)->bi_flags; + + /* Sanity checks */ + if (*filename == '\0') + { + /* Empty filename string */ + errno = ENOENT; + return -1; + } + if (stat(filename, &st) == 0) + { + /* File already exists on disk */ + errno = EEXIST; + return -1; + } + + /* Allocate memory */ + bfp = (struct bf *) sm_malloc(sizeof(struct bf)); + if (bfp == NULL) + { + errno = ENOMEM; + return -1; + } + + /* Assign data buffer */ + /* A zero bsize is valid, just don't allocate memory */ + if (bsize > 0) + { + bfp->bf_buf = (char *) sm_malloc(bsize); + if (bfp->bf_buf == NULL) + { + bfp->bf_bufsize = 0; + sm_free(bfp); + errno = ENOMEM; + return -1; + } + } + else + bfp->bf_buf = NULL; + + /* Nearly home free, just set all the parameters now */ + bfp->bf_committed = false; + bfp->bf_ondisk = false; + bfp->bf_flags = sflags; + bfp->bf_bufsize = bsize; + bfp->bf_buffilled = 0; + l = strlen(filename) + 1; + bfp->bf_filename = (char *) sm_malloc(l); + if (bfp->bf_filename == NULL) + { + if (bfp->bf_buf != NULL) + sm_free(bfp->bf_buf); + sm_free(bfp); + errno = ENOMEM; + return -1; + } + (void) sm_strlcpy(bfp->bf_filename, filename, l); + bfp->bf_filemode = fmode; + bfp->bf_offset = 0; + bfp->bf_size = 0; + bfp->bf_disk_fd = -1; + fp->f_cookie = bfp; + + if (tTd(58, 8)) + sm_dprintf("sm_bfopen(%s)\n", filename); + + return 0; +} + +/* +** BFOPEN -- create a new buffered file +** +** Parameters: +** filename -- the file's name +** fmode -- what mode the file should be created as +** bsize -- amount of buffer space to allocate (may be 0) +** flags -- if running under sendmail, passed directly to safeopen +** +** Returns: +** a SM_FILE_T * which may then be used with stdio functions, +** or NULL on failure. SM_FILE_T * is opened for writing +** "SM_IO_WHAT_VECTORS"). +** +** Side Effects: +** none. +** +** Sets errno: +** any value of errno specified by sm_io_setinfo_type() +** any value of errno specified by sm_io_open() +** any value of errno specified by sm_io_setinfo() +*/ + +#ifdef __STDC__ +/* +** XXX This is a temporary hack since MODE_T on HP-UX 10.x is short. +** If we use K&R here, the compiler will complain about +** Inconsistent parameter list declaration +** due to the change from short to int. +*/ + +SM_FILE_T * +bfopen(char *filename, MODE_T fmode, size_t bsize, long flags) +#else /* __STDC__ */ +SM_FILE_T * +bfopen(filename, fmode, bsize, flags) + char *filename; + MODE_T fmode; + size_t bsize; + long flags; +#endif /* __STDC__ */ +{ + MODE_T omask; + SM_FILE_T SM_IO_SET_TYPE(vector, BF_FILE_TYPE, sm_bfopen, sm_bfclose, + sm_bfread, sm_bfwrite, sm_bfseek, sm_bfgetinfo, sm_bfsetinfo, + SM_TIME_FOREVER); + struct bf_info info; + + /* + ** Apply current umask to fmode as it may change by the time + ** the file is actually created. fmode becomes the true + ** permissions of the file, which OPEN() must obey. + */ + + omask = umask(0); + fmode &= ~omask; + (void) umask(omask); + + SM_IO_INIT_TYPE(vector, BF_FILE_TYPE, sm_bfopen, sm_bfclose, + sm_bfread, sm_bfwrite, sm_bfseek, sm_bfgetinfo, sm_bfsetinfo, + SM_TIME_FOREVER); + info.bi_filename = filename; + info.bi_fmode = fmode; + info.bi_bsize = bsize; + info.bi_flags = flags; + + return sm_io_open(&vector, SM_TIME_DEFAULT, &info, SM_IO_RDWR, NULL); +} + +/* +** SM_BFGETINFO -- returns info about an open file pointer +** +** Parameters: +** fp -- file pointer to get info about +** what -- type of info to obtain +** valp -- thing to return the info in +*/ + +static int +sm_bfgetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + struct bf *bfp; + + bfp = (struct bf *) fp->f_cookie; + switch (what) + { + case SM_IO_WHAT_FD: + return bfp->bf_disk_fd; + case SM_IO_WHAT_SIZE: + return bfp->bf_size; + default: + return -1; + } +} + +/* +** SM_BFCLOSE -- close a buffered file +** +** Parameters: +** fp -- cookie of file to close +** +** Returns: +** 0 to indicate success +** +** Side Effects: +** deletes backing file, sm_frees memory. +** +** Sets errno: +** never. +*/ + +static int +sm_bfclose(fp) + SM_FILE_T *fp; +{ + struct bf *bfp; + + /* Cast cookie back to correct type */ + bfp = (struct bf *) fp->f_cookie; + + /* Need to clean up the file */ + if (bfp->bf_ondisk && !bfp->bf_committed) + unlink(bfp->bf_filename); + sm_free(bfp->bf_filename); + + if (bfp->bf_disk_fd != -1) + close(bfp->bf_disk_fd); + + /* Need to sm_free the buffer */ + if (bfp->bf_bufsize > 0) + sm_free(bfp->bf_buf); + + /* Finally, sm_free the structure */ + sm_free(bfp); + return 0; +} + +/* +** SM_BFREAD -- read a buffered file +** +** Parameters: +** cookie -- cookie of file to read +** buf -- buffer to fill +** nbytes -- how many bytes to read +** +** Returns: +** number of bytes read or -1 indicate failure +** +** Side Effects: +** none. +** +*/ + +static ssize_t +sm_bfread(fp, buf, nbytes) + SM_FILE_T *fp; + char *buf; + size_t nbytes; +{ + struct bf *bfp; + ssize_t count = 0; /* Number of bytes put in buf so far */ + int retval; + + /* Cast cookie back to correct type */ + bfp = (struct bf *) fp->f_cookie; + + if (bfp->bf_offset < bfp->bf_buffilled) + { + /* Need to grab some from buffer */ + count = nbytes; + if ((bfp->bf_offset + count) > bfp->bf_buffilled) + count = bfp->bf_buffilled - bfp->bf_offset; + + memcpy(buf, bfp->bf_buf + bfp->bf_offset, count); + } + + if ((bfp->bf_offset + nbytes) > bfp->bf_buffilled) + { + /* Need to grab some from file */ + if (!bfp->bf_ondisk) + { + /* Oops, the file doesn't exist. EOF. */ + if (tTd(58, 8)) + sm_dprintf("sm_bfread(%s): to disk\n", + bfp->bf_filename); + goto finished; + } + + /* Catch a read() on an earlier failed write to disk */ + if (bfp->bf_disk_fd < 0) + { + errno = EIO; + return -1; + } + + if (lseek(bfp->bf_disk_fd, + bfp->bf_offset + count, SEEK_SET) < 0) + { + if ((errno == EINVAL) || (errno == ESPIPE)) + { + /* + ** stdio won't be expecting these + ** errnos from read()! Change them + ** into something it can understand. + */ + + errno = EIO; + } + return -1; + } + + while (count < nbytes) + { + retval = read(bfp->bf_disk_fd, + buf + count, + nbytes - count); + if (retval < 0) + { + /* errno is set implicitly by read() */ + return -1; + } + else if (retval == 0) + goto finished; + else + count += retval; + } + } + +finished: + bfp->bf_offset += count; + return count; +} + +/* +** SM_BFSEEK -- seek to a position in a buffered file +** +** Parameters: +** fp -- fp of file to seek +** offset -- position to seek to +** whence -- how to seek +** +** Returns: +** new file offset or -1 indicate failure +** +** Side Effects: +** none. +** +*/ + +static off_t +sm_bfseek(fp, offset, whence) + SM_FILE_T *fp; + off_t offset; + int whence; + +{ + struct bf *bfp; + + /* Cast cookie back to correct type */ + bfp = (struct bf *) fp->f_cookie; + + switch (whence) + { + case SEEK_SET: + bfp->bf_offset = offset; + break; + + case SEEK_CUR: + bfp->bf_offset += offset; + break; + + case SEEK_END: + bfp->bf_offset = bfp->bf_size + offset; + break; + + default: + errno = EINVAL; + return -1; + } + return bfp->bf_offset; +} + +/* +** SM_BFWRITE -- write to a buffered file +** +** Parameters: +** fp -- fp of file to write +** buf -- data buffer +** nbytes -- how many bytes to write +** +** Returns: +** number of bytes written or -1 indicate failure +** +** Side Effects: +** may create backing file if over memory limit for file. +** +*/ + +static ssize_t +sm_bfwrite(fp, buf, nbytes) + SM_FILE_T *fp; + const char *buf; + size_t nbytes; +{ + struct bf *bfp; + ssize_t count = 0; /* Number of bytes written so far */ + int retval; + + /* Cast cookie back to correct type */ + bfp = (struct bf *) fp->f_cookie; + + /* If committed, go straight to disk */ + if (bfp->bf_committed) + { + if (lseek(bfp->bf_disk_fd, bfp->bf_offset, SEEK_SET) < 0) + { + if ((errno == EINVAL) || (errno == ESPIPE)) + { + /* + ** stdio won't be expecting these + ** errnos from write()! Change them + ** into something it can understand. + */ + + errno = EIO; + } + return -1; + } + + count = write(bfp->bf_disk_fd, buf, nbytes); + if (count < 0) + { + /* errno is set implicitly by write() */ + return -1; + } + goto finished; + } + + if (bfp->bf_offset < bfp->bf_bufsize) + { + /* Need to put some in buffer */ + count = nbytes; + if ((bfp->bf_offset + count) > bfp->bf_bufsize) + count = bfp->bf_bufsize - bfp->bf_offset; + + memcpy(bfp->bf_buf + bfp->bf_offset, buf, count); + if ((bfp->bf_offset + count) > bfp->bf_buffilled) + bfp->bf_buffilled = bfp->bf_offset + count; + } + + if ((bfp->bf_offset + nbytes) > bfp->bf_bufsize) + { + /* Need to put some in file */ + if (!bfp->bf_ondisk) + { + MODE_T omask; + + /* Clear umask as bf_filemode are the true perms */ + omask = umask(0); + retval = OPEN(bfp->bf_filename, + O_RDWR | O_CREAT | O_TRUNC, + bfp->bf_filemode, bfp->bf_flags); + (void) umask(omask); + + /* Couldn't create file: failure */ + if (retval < 0) + { + /* + ** stdio may not be expecting these + ** errnos from write()! Change to + ** something which it can understand. + ** Note that ENOSPC and EDQUOT are saved + ** because they are actually valid for + ** write(). + */ + + if (!(errno == ENOSPC +#ifdef EDQUOT + || errno == EDQUOT +#endif /* EDQUOT */ + )) + errno = EIO; + + return -1; + } + bfp->bf_disk_fd = retval; + bfp->bf_ondisk = true; + } + + /* Catch a write() on an earlier failed write to disk */ + if (bfp->bf_ondisk && bfp->bf_disk_fd < 0) + { + errno = EIO; + return -1; + } + + if (lseek(bfp->bf_disk_fd, + bfp->bf_offset + count, SEEK_SET) < 0) + { + if ((errno == EINVAL) || (errno == ESPIPE)) + { + /* + ** stdio won't be expecting these + ** errnos from write()! Change them into + ** something which it can understand. + */ + + errno = EIO; + } + return -1; + } + + while (count < nbytes) + { + retval = write(bfp->bf_disk_fd, buf + count, + nbytes - count); + if (retval < 0) + { + /* errno is set implicitly by write() */ + return -1; + } + else + count += retval; + } + } + +finished: + bfp->bf_offset += count; + if (bfp->bf_offset > bfp->bf_size) + bfp->bf_size = bfp->bf_offset; + return count; +} + +/* +** BFREWIND -- rewinds the SM_FILE_T * +** +** Parameters: +** fp -- SM_FILE_T * to rewind +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** rewinds the SM_FILE_T * and puts it into read mode. Normally +** one would bfopen() a file, write to it, then bfrewind() and +** fread(). If fp is not a buffered file, this is equivalent to +** rewind(). +** +** Sets errno: +** any value of errno specified by sm_io_rewind() +*/ + +int +bfrewind(fp) + SM_FILE_T *fp; +{ + (void) sm_io_flush(fp, SM_TIME_DEFAULT); + sm_io_clearerr(fp); /* quicker just to do it */ + return sm_io_seek(fp, SM_TIME_DEFAULT, 0, SM_IO_SEEK_SET); +} + +/* +** SM_BFCOMMIT -- "commits" the buffered file +** +** Parameters: +** fp -- SM_FILE_T * to commit to disk +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** Forces the given SM_FILE_T * to be written to disk if it is not +** already, and ensures that it will be kept after closing. If +** fp is not a buffered file, this is a no-op. +** +** Sets errno: +** any value of errno specified by open() +** any value of errno specified by write() +** any value of errno specified by lseek() +*/ + +static int +sm_bfcommit(fp) + SM_FILE_T *fp; +{ + struct bf *bfp; + int retval; + int byteswritten; + + /* Get associated bf structure */ + bfp = (struct bf *) fp->f_cookie; + + /* If already committed, noop */ + if (bfp->bf_committed) + return 0; + + /* Do we need to open a file? */ + if (!bfp->bf_ondisk) + { + int save_errno; + MODE_T omask; + struct stat st; + + if (tTd(58, 8)) + { + sm_dprintf("bfcommit(%s): to disk\n", bfp->bf_filename); + if (tTd(58, 32)) + sm_dprintf("bfcommit(): filemode %o flags %ld\n", + bfp->bf_filemode, bfp->bf_flags); + } + + if (stat(bfp->bf_filename, &st) == 0) + { + errno = EEXIST; + return -1; + } + + /* Clear umask as bf_filemode are the true perms */ + omask = umask(0); + retval = OPEN(bfp->bf_filename, O_RDWR | O_CREAT | O_EXCL, + bfp->bf_filemode, bfp->bf_flags); + save_errno = errno; + (void) umask(omask); + + /* Couldn't create file: failure */ + if (retval < 0) + { + /* errno is set implicitly by open() */ + errno = save_errno; + return -1; + } + + bfp->bf_disk_fd = retval; + bfp->bf_ondisk = true; + } + + /* Write out the contents of our buffer, if we have any */ + if (bfp->bf_buffilled > 0) + { + byteswritten = 0; + + if (lseek(bfp->bf_disk_fd, 0, SEEK_SET) < 0) + { + /* errno is set implicitly by lseek() */ + return -1; + } + + while (byteswritten < bfp->bf_buffilled) + { + retval = write(bfp->bf_disk_fd, + bfp->bf_buf + byteswritten, + bfp->bf_buffilled - byteswritten); + if (retval < 0) + { + /* errno is set implicitly by write() */ + return -1; + } + else + byteswritten += retval; + } + } + bfp->bf_committed = true; + + /* Invalidate buf; all goes to file now */ + bfp->bf_buffilled = 0; + if (bfp->bf_bufsize > 0) + { + /* Don't need buffer anymore; free it */ + bfp->bf_bufsize = 0; + sm_free(bfp->bf_buf); + } + return 0; +} + +/* +** SM_BFTRUNCATE -- rewinds and truncates the SM_FILE_T * +** +** Parameters: +** fp -- SM_FILE_T * to truncate +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** rewinds the SM_FILE_T *, truncates it to zero length, and puts +** it into write mode. +** +** Sets errno: +** any value of errno specified by fseek() +** any value of errno specified by ftruncate() +*/ + +static int +sm_bftruncate(fp) + SM_FILE_T *fp; +{ + struct bf *bfp; + + if (bfrewind(fp) < 0) + return -1; + + /* Get bf structure */ + bfp = (struct bf *) fp->f_cookie; + bfp->bf_buffilled = 0; + bfp->bf_size = 0; + + /* Need to zero the buffer */ + if (bfp->bf_bufsize > 0) + memset(bfp->bf_buf, '\0', bfp->bf_bufsize); + if (bfp->bf_ondisk) + { +#if NOFTRUNCATE + /* XXX: Not much we can do except rewind it */ + errno = EINVAL; + return -1; +#else /* NOFTRUNCATE */ + return ftruncate(bfp->bf_disk_fd, 0); +#endif /* NOFTRUNCATE */ + } + return 0; +} + +/* +** SM_BFSETINFO -- set/change info for an open file pointer +** +** Parameters: +** fp -- file pointer to get info about +** what -- type of info to set/change +** valp -- thing to set/change the info to +** +*/ + +static int +sm_bfsetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + struct bf *bfp; + int bsize; + + /* Get bf structure */ + bfp = (struct bf *) fp->f_cookie; + switch (what) + { + case SM_BF_SETBUFSIZE: + bsize = *((int *) valp); + bfp->bf_bufsize = bsize; + + /* A zero bsize is valid, just don't allocate memory */ + if (bsize > 0) + { + bfp->bf_buf = (char *) sm_malloc(bsize); + if (bfp->bf_buf == NULL) + { + bfp->bf_bufsize = 0; + errno = ENOMEM; + return -1; + } + } + else + bfp->bf_buf = NULL; + return 0; + case SM_BF_COMMIT: + return sm_bfcommit(fp); + case SM_BF_TRUNCATE: + return sm_bftruncate(fp); + case SM_BF_TEST: + return 1; /* always */ + default: + errno = EINVAL; + return -1; + } +} diff --git a/gnu/dist/sendmail/sendmail/sasl.c b/gnu/dist/sendmail/sendmail/sasl.c new file mode 100644 index 000000000000..fd6061dccda4 --- /dev/null +++ b/gnu/dist/sendmail/sendmail/sasl.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include +SM_RCSID("@(#)Id: sasl.c,v 8.19.2.2 2002/09/26 23:03:40 gshapiro Exp") + +#if SASL +# include +# include +# include + +/* +** In order to ensure that storage leaks are tracked, and to prevent +** conflicts between the sm_heap package and sasl, we tell sasl to +** use the following heap allocation functions. Unfortunately, +** the sasl package incorrectly specifies the size of a block +** using unsigned long: for portability, it should be size_t. +*/ + +void *sm_sasl_malloc __P((unsigned long)); +static void *sm_sasl_calloc __P((unsigned long, unsigned long)); +static void *sm_sasl_realloc __P((void *, unsigned long)); +void sm_sasl_free __P((void *)); + +/* +** SASLv1: +** We can't use an rpool for Cyrus-SASL memory management routines, +** since the encryption/decryption routines in Cyrus-SASL +** allocate/deallocate a buffer each time. Since rpool +** don't release memory until the very end, memory consumption is +** proportional to the size of an e-mail, which is unacceptable. +*/ + +/* +** SM_SASL_MALLOC -- malloc() for SASL +** +** Parameters: +** size -- size of requested memory. +** +** Returns: +** pointer to memory. +*/ + +void * +sm_sasl_malloc(size) + unsigned long size; +{ + return sm_malloc((size_t) size); +} + +/* +** SM_SASL_CALLOC -- calloc() for SASL +** +** Parameters: +** nelem -- number of elements. +** elemsize -- size of each element. +** +** Returns: +** pointer to memory. +** +** Notice: +** this isn't currently used by SASL. +*/ + +static void * +sm_sasl_calloc(nelem, elemsize) + unsigned long nelem; + unsigned long elemsize; +{ + size_t size; + void *p; + + size = (size_t) nelem * (size_t) elemsize; + p = sm_malloc(size); + if (p == NULL) + return NULL; + memset(p, '\0', size); + return p; +} + +/* +** SM_SASL_REALLOC -- realloc() for SASL +** +** Parameters: +** p -- pointer to old memory. +** size -- size of requested memory. +** +** Returns: +** pointer to new memory. +*/ + +static void * +sm_sasl_realloc(o, size) + void *o; + unsigned long size; +{ + return sm_realloc(o, (size_t) size); +} + +/* +** SM_SASL_FREE -- free() for SASL +** +** Parameters: +** p -- pointer to free. +** +** Returns: +** none +*/ + +void +sm_sasl_free(p) + void *p; +{ + sm_free(p); +} + +/* +** SM_SASL_INIT -- sendmail specific SASL initialization +** +** Parameters: +** none. +** +** Returns: +** none +** +** Side Effects: +** installs memory management routines for SASL. +*/ + +void +sm_sasl_init() +{ + sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc, + sm_sasl_realloc, sm_sasl_free); +} +/* +** INTERSECT -- create the intersection between two lists +** +** Parameters: +** s1, s2 -- lists of items (separated by single blanks). +** rpool -- resource pool from which result is allocated. +** +** Returns: +** the intersection of both lists. +*/ + +char * +intersect(s1, s2, rpool) + char *s1, *s2; + SM_RPOOL_T *rpool; +{ + char *hr, *h1, *h, *res; + int l1, l2, rl; + + if (s1 == NULL || s2 == NULL) /* NULL string(s) -> NULL result */ + return NULL; + l1 = strlen(s1); + l2 = strlen(s2); + rl = SM_MIN(l1, l2); + res = (char *) sm_rpool_malloc(rpool, rl + 1); + if (res == NULL) + return NULL; + *res = '\0'; + if (rl == 0) /* at least one string empty? */ + return res; + hr = res; + h1 = s1; + h = s1; + + /* walk through s1 */ + while (h != NULL && *h1 != '\0') + { + /* is there something after the current word? */ + if ((h = strchr(h1, ' ')) != NULL) + *h = '\0'; + l1 = strlen(h1); + + /* does the current word appear in s2 ? */ + if (iteminlist(h1, s2, " ") != NULL) + { + /* add a blank if not first item */ + if (hr != res) + *hr++ = ' '; + + /* copy the item */ + memcpy(hr, h1, l1); + + /* advance pointer in result list */ + hr += l1; + *hr = '\0'; + } + if (h != NULL) + { + /* there are more items */ + *h = ' '; + h1 = h + 1; + } + } + return res; +} +# if SASL >= 20000 +/* +** IPTOSTRING -- create string for SASL_IP*PORT property +** (borrowed from lib/iptostring.c in Cyrus-IMAP) +** +** Parameters: +** addr -- (pointer to) socket address +** addrlen -- length of socket address +** out -- output string (result) +** outlen -- maximum length of output string +** +** Returns: +** true iff successful. +** +** Side Effects: +** creates output string if successful. +** sets errno if unsuccessful. +*/ + +# include + +# ifndef NI_WITHSCOPEID +# define NI_WITHSCOPEID 0 +# endif +# ifndef NI_MAXHOST +# define NI_MAXHOST 1025 +# endif +# ifndef NI_MAXSERV +# define NI_MAXSERV 32 +# endif + +bool +iptostring(addr, addrlen, out, outlen) + SOCKADDR *addr; + SOCKADDR_LEN_T addrlen; + char *out; + unsigned outlen; +{ + char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; + + if (addr == NULL || out == NULL) + { + errno = EINVAL; + return false; + } + +# if NETINET6 + if (getnameinfo((struct sockaddr *) addr, addrlen, + hbuf, sizeof hbuf, pbuf, sizeof pbuf, + NI_NUMERICHOST | NI_WITHSCOPEID | NI_NUMERICSERV) != 0) + return false; +# else /* NETINET6 */ + if (addr->sa.sa_family != AF_INET) + { + errno = EINVAL; + return false; + } + if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf)) + >= sizeof(hbuf)) + { + errno = ENOMEM; + return false; + } + sm_snprintf(pbuf, sizeof pbuf, "%d", ntohs(addr->sin.sin_port)); +# endif /* NETINET6 */ + + if (outlen < strlen(hbuf) + strlen(pbuf) + 2) + { + errno = ENOMEM; + return false; + } + sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf); + return true; +} +# endif /* SASL >= 20000 */ +#endif /* SASL */ diff --git a/gnu/dist/sendmail/sendmail/sm_resolve.c b/gnu/dist/sendmail/sendmail/sm_resolve.c new file mode 100644 index 000000000000..31d788a23674 --- /dev/null +++ b/gnu/dist/sendmail/sendmail/sm_resolve.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if DNSMAP +# if NAMED_BIND +# include "sm_resolve.h" + +SM_RCSID("Id: sm_resolve.c,v 8.24.4.6 2002/06/25 04:22:41 ca Exp") + +static struct stot +{ + const char *st_name; + int st_type; +} stot[] = +{ +# if NETINET + { "A", T_A }, +# endif /* NETINET */ +# if NETINET6 + { "AAAA", T_AAAA }, +# endif /* NETINET6 */ + { "NS", T_NS }, + { "CNAME", T_CNAME }, + { "PTR", T_PTR }, + { "MX", T_MX }, + { "TXT", T_TXT }, + { "AFSDB", T_AFSDB }, + { "SRV", T_SRV }, + { NULL, 0 } +}; + +/* +** DNS_STRING_TO_TYPE -- convert resource record name into type +** +** Parameters: +** name -- name of resource record type +** +** Returns: +** type if succeeded. +** -1 otherwise. +*/ + +int +dns_string_to_type(name) + const char *name; +{ + struct stot *p = stot; + + for (p = stot; p->st_name != NULL; p++) + if (sm_strcasecmp(name, p->st_name) == 0) + return p->st_type; + return -1; +} + +/* +** DNS_TYPE_TO_STRING -- convert resource record type into name +** +** Parameters: +** type -- resource record type +** +** Returns: +** name if succeeded. +** NULL otherwise. +*/ + +const char * +dns_type_to_string(type) + int type; +{ + struct stot *p = stot; + + for (p = stot; p->st_name != NULL; p++) + if (type == p->st_type) + return p->st_name; + return NULL; +} + +/* +** DNS_FREE_DATA -- free all components of a DNS_REPLY_T +** +** Parameters: +** r -- pointer to DNS_REPLY_T +** +** Returns: +** none. +*/ + +void +dns_free_data(r) + DNS_REPLY_T *r; +{ + RESOURCE_RECORD_T *rr; + + if (r->dns_r_q.dns_q_domain != NULL) + sm_free(r->dns_r_q.dns_q_domain); + for (rr = r->dns_r_head; rr != NULL; ) + { + RESOURCE_RECORD_T *tmp = rr; + + if (rr->rr_domain != NULL) + sm_free(rr->rr_domain); + if (rr->rr_u.rr_data != NULL) + sm_free(rr->rr_u.rr_data); + rr = rr->rr_next; + sm_free(tmp); + } + sm_free(r); +} + +/* +** PARSE_DNS_REPLY -- parse DNS reply data. +** +** Parameters: +** data -- pointer to dns data +** len -- len of data +** +** Returns: +** pointer to DNS_REPLY_T if succeeded. +** NULL otherwise. +*/ + +static DNS_REPLY_T * +parse_dns_reply(data, len) + unsigned char *data; + int len; +{ + unsigned char *p; + int status; + size_t l; + char host[MAXHOSTNAMELEN]; + DNS_REPLY_T *r; + RESOURCE_RECORD_T **rr; + + r = (DNS_REPLY_T *) xalloc(sizeof(*r)); + memset(r, 0, sizeof(*r)); + if (r == NULL) + return NULL; + + p = data; + + /* doesn't work on Crays? */ + memcpy(&r->dns_r_h, p, sizeof(r->dns_r_h)); + p += sizeof(r->dns_r_h); + status = dn_expand(data, data + len, p, host, sizeof host); + if (status < 0) + { + dns_free_data(r); + return NULL; + } + r->dns_r_q.dns_q_domain = sm_strdup(host); + if (r->dns_r_q.dns_q_domain == NULL) + { + dns_free_data(r); + return NULL; + } + p += status; + GETSHORT(r->dns_r_q.dns_q_type, p); + GETSHORT(r->dns_r_q.dns_q_class, p); + rr = &r->dns_r_head; + while (p < data + len) + { + int type, class, ttl, size, txtlen; + + status = dn_expand(data, data + len, p, host, sizeof host); + if (status < 0) + { + dns_free_data(r); + return NULL; + } + p += status; + GETSHORT(type, p); + GETSHORT(class, p); + GETLONG(ttl, p); + GETSHORT(size, p); + if (p + size > data + len) + { + /* + ** announced size of data exceeds length of + ** data paket: someone is cheating. + */ + + if (LogLevel > 5) + sm_syslog(LOG_WARNING, NOQID, + "ERROR: DNS RDLENGTH=%d > data len=%d", + size, len - (p - data)); + dns_free_data(r); + return NULL; + } + *rr = (RESOURCE_RECORD_T *) xalloc(sizeof(**rr)); + if (*rr == NULL) + { + dns_free_data(r); + return NULL; + } + (*rr)->rr_domain = sm_strdup(host); + if ((*rr)->rr_domain == NULL) + { + dns_free_data(r); + return NULL; + } + (*rr)->rr_type = type; + (*rr)->rr_class = class; + (*rr)->rr_ttl = ttl; + (*rr)->rr_size = size; + switch (type) + { + case T_NS: + case T_CNAME: + case T_PTR: + status = dn_expand(data, data + len, p, host, + sizeof host); + if (status < 0) + { + dns_free_data(r); + return NULL; + } + (*rr)->rr_u.rr_txt = sm_strdup(host); + if ((*rr)->rr_u.rr_txt == NULL) + { + dns_free_data(r); + return NULL; + } + break; + + case T_MX: + case T_AFSDB: + status = dn_expand(data, data + len, p + 2, host, + sizeof host); + if (status < 0) + { + dns_free_data(r); + return NULL; + } + l = strlen(host) + 1; + (*rr)->rr_u.rr_mx = (MX_RECORD_T *) + xalloc(sizeof(*((*rr)->rr_u.rr_mx)) + l); + if ((*rr)->rr_u.rr_mx == NULL) + { + dns_free_data(r); + return NULL; + } + (*rr)->rr_u.rr_mx->mx_r_preference = (p[0] << 8) | p[1]; + (void) sm_strlcpy((*rr)->rr_u.rr_mx->mx_r_domain, + host, l); + break; + + case T_SRV: + status = dn_expand(data, data + len, p + 6, host, + sizeof host); + if (status < 0) + { + dns_free_data(r); + return NULL; + } + l = strlen(host) + 1; + (*rr)->rr_u.rr_srv = (SRV_RECORDT_T*) + xalloc(sizeof(*((*rr)->rr_u.rr_srv)) + l); + if ((*rr)->rr_u.rr_srv == NULL) + { + dns_free_data(r); + return NULL; + } + (*rr)->rr_u.rr_srv->srv_r_priority = (p[0] << 8) | p[1]; + (*rr)->rr_u.rr_srv->srv_r_weight = (p[2] << 8) | p[3]; + (*rr)->rr_u.rr_srv->srv_r_port = (p[4] << 8) | p[5]; + (void) sm_strlcpy((*rr)->rr_u.rr_srv->srv_r_target, + host, l); + break; + + case T_TXT: + + /* + ** The TXT record contains the length as + ** leading byte, hence the value is restricted + ** to 255, which is less than the maximum value + ** of RDLENGTH (size). Nevertheless, txtlen + ** must be less than size because the latter + ** specifies the length of the entire TXT + ** record. + */ + + txtlen = *p; + if (txtlen >= size) + { + if (LogLevel > 5) + sm_syslog(LOG_WARNING, NOQID, + "ERROR: DNS TXT record size=%d <= text len=%d", + size, txtlen); + dns_free_data(r); + return NULL; + } + (*rr)->rr_u.rr_txt = (char *) xalloc(txtlen + 1); + if ((*rr)->rr_u.rr_txt == NULL) + { + dns_free_data(r); + return NULL; + } + (void) sm_strlcpy((*rr)->rr_u.rr_txt, (char*) p + 1, + txtlen + 1); + break; + + default: + (*rr)->rr_u.rr_data = (unsigned char*) xalloc(size); + if (size != 0 && (*rr)->rr_u.rr_data == NULL) + { + dns_free_data(r); + return NULL; + } + (void) memcpy((*rr)->rr_u.rr_data, p, size); + break; + } + p += size; + rr = &(*rr)->rr_next; + } + *rr = NULL; + return r; +} + +/* +** DNS_LOOKUP_INT -- perform dns map lookup (internal helper routine) +** +** Parameters: +** domain -- name to lookup +** rr_class -- resource record class +** rr_type -- resource record type +** retrans -- retransmission timeout +** retry -- number of retries +** +** Returns: +** result of lookup if succeeded. +** NULL otherwise. +*/ + +DNS_REPLY_T * +dns_lookup_int(domain, rr_class, rr_type, retrans, retry) + const char *domain; + int rr_class; + int rr_type; + time_t retrans; + int retry; +{ + int len; + unsigned long old_options = 0; + time_t save_retrans = 0; + int save_retry = 0; + DNS_REPLY_T *r = NULL; + unsigned char reply[1024]; + + if (tTd(8, 16)) + { + old_options = _res.options; + _res.options |= RES_DEBUG; + sm_dprintf("dns_lookup(%s, %d, %s)\n", domain, + rr_class, dns_type_to_string(rr_type)); + } + if (retrans > 0) + { + save_retrans = _res.retrans; + _res.retrans = retrans; + } + if (retry > 0) + { + save_retry = _res.retry; + _res.retry = retry; + } + errno = 0; + SM_SET_H_ERRNO(0); + len = res_search(domain, rr_class, rr_type, reply, sizeof reply); + if (tTd(8, 16)) + { + _res.options = old_options; + sm_dprintf("dns_lookup(%s, %d, %s) --> %d\n", + domain, rr_class, dns_type_to_string(rr_type), len); + } + if (len >= 0) + r = parse_dns_reply(reply, len); + if (retrans > 0) + _res.retrans = save_retrans; + if (retry > 0) + _res.retry = save_retry; + return r; +} + +# if 0 +DNS_REPLY_T * +dns_lookup(domain, type_name, retrans, retry) + const char *domain; + const char *type_name; + time_t retrans; + int retry; +{ + int type; + + type = dns_string_to_type(type_name); + if (type == -1) + { + if (tTd(8, 16)) + sm_dprintf("dns_lookup: unknown resource type: `%s'\n", + type_name); + return NULL; + } + return dns_lookup_int(domain, C_IN, type, retrans, retry); +} +# endif /* 0 */ +# endif /* NAMED_BIND */ +#endif /* DNSMAP */ diff --git a/gnu/dist/sendmail/sendmail/sm_resolve.h b/gnu/dist/sendmail/sendmail/sm_resolve.h new file mode 100644 index 000000000000..dd3f41587dfe --- /dev/null +++ b/gnu/dist/sendmail/sendmail/sm_resolve.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Id: sm_resolve.h,v 8.8 2001/09/01 00:06:02 gshapiro Exp */ + +#if DNSMAP +# ifndef __ROKEN_RESOLVE_H__ +# define __ROKEN_RESOLVE_H__ + +/* We use these, but they are not always present in */ + +# ifndef T_TXT +# define T_TXT 16 +# endif /* ! T_TXT */ +# ifndef T_AFSDB +# define T_AFSDB 18 +# endif /* ! T_AFSDB */ +# ifndef T_SRV +# define T_SRV 33 +# endif /* ! T_SRV */ +# ifndef T_NAPTR +# define T_NAPTR 35 +# endif /* ! T_NAPTR */ + +typedef struct +{ + char *dns_q_domain; + unsigned int dns_q_type; + unsigned int dns_q_class; +} DNS_QUERY_T; + +typedef struct +{ + unsigned int mx_r_preference; + char mx_r_domain[1]; +} MX_RECORD_T; + +typedef struct +{ + unsigned int srv_r_priority; + unsigned int srv_r_weight; + unsigned int srv_r_port; + char srv_r_target[1]; +} SRV_RECORDT_T; + + +typedef struct resource_record RESOURCE_RECORD_T; + +struct resource_record +{ + char *rr_domain; + unsigned int rr_type; + unsigned int rr_class; + unsigned int rr_ttl; + unsigned int rr_size; + union + { + void *rr_data; + MX_RECORD_T *rr_mx; + MX_RECORD_T *rr_afsdb; /* mx and afsdb are identical */ + SRV_RECORDT_T *rr_srv; +# if NETINET + struct in_addr *rr_a; +# endif /* NETINET */ +# if NETINET6 + struct in6_addr *rr_aaaa; +# endif /* NETINET6 */ + char *rr_txt; + } rr_u; + RESOURCE_RECORD_T *rr_next; +}; + +# if !defined(T_A) && !defined(T_AAAA) +/* XXX if isn't included */ +typedef int HEADER; /* will never be used */ +# endif /* !defined(T_A) && !defined(T_AAAA) */ + +typedef struct +{ + HEADER dns_r_h; + DNS_QUERY_T dns_r_q; + RESOURCE_RECORD_T *dns_r_head; +} DNS_REPLY_T; + + +extern void dns_free_data __P((DNS_REPLY_T *)); +extern int dns_string_to_type __P((const char *)); +extern const char *dns_type_to_string __P((int)); +extern DNS_REPLY_T *dns_lookup_int __P((const char *, + int, + int, + time_t, + int)); +# if 0 +extern DNS_REPLY_T *dns_lookup __P((const char *domain, + const char *type_name, + time_t retrans, + int retry)); +# endif /* 0 */ + +# endif /* ! __ROKEN_RESOLVE_H__ */ +#endif /* DNSMAP */ diff --git a/gnu/dist/sendmail/sendmail/tls.c b/gnu/dist/sendmail/sendmail/tls.c new file mode 100644 index 000000000000..219b811e9b30 --- /dev/null +++ b/gnu/dist/sendmail/sendmail/tls.c @@ -0,0 +1,1483 @@ +/* + * Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +#include + +SM_RCSID("@(#)Id: tls.c,v 8.79.4.2 2003/01/23 23:16:24 ca Exp") + +#if STARTTLS +# include +# include +# include +# ifndef HASURANDOMDEV +# include +# endif /* ! HASURANDOMDEV */ +# if !TLS_NO_RSA +static RSA *rsa_tmp = NULL; /* temporary RSA key */ +static RSA *tmp_rsa_key __P((SSL *, int, int)); +# endif /* !TLS_NO_RSA */ +# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L +static int tls_verify_cb __P((X509_STORE_CTX *)); +# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +static int tls_verify_cb __P((X509_STORE_CTX *, void *)); +# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ + +# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L +# define CONST097 +# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +# define CONST097 const +# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +static void apps_ssl_info_cb __P((CONST097 SSL *, int , int)); + +# if !NO_DH +static DH *get_dh512 __P((void)); + +static unsigned char dh512_p[] = +{ + 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, + 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, + 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, + 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, + 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, + 0x47,0x74,0xE8,0x33 +}; +static unsigned char dh512_g[] = +{ + 0x02 +}; + +static DH * +get_dh512() +{ + DH *dh = NULL; + + if ((dh = DH_new()) == NULL) + return NULL; + dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL); + dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL); + if ((dh->p == NULL) || (dh->g == NULL)) + return NULL; + return dh; +} +# endif /* !NO_DH */ + + +/* +** TLS_RAND_INIT -- initialize STARTTLS random generator +** +** Parameters: +** randfile -- name of file with random data +** logl -- loglevel +** +** Returns: +** success/failure +** +** Side Effects: +** initializes PRNG for tls library. +*/ + +# define MIN_RAND_BYTES 128 /* 1024 bits */ + +# define RF_OK 0 /* randfile OK */ +# define RF_MISS 1 /* randfile == NULL || *randfile == '\0' */ +# define RF_UNKNOWN 2 /* unknown prefix for randfile */ + +# define RI_NONE 0 /* no init yet */ +# define RI_SUCCESS 1 /* init was successful */ +# define RI_FAIL 2 /* init failed */ + +static bool tls_rand_init __P((char *, int)); + +static bool +tls_rand_init(randfile, logl) + char *randfile; + int logl; +{ +# ifndef HASURANDOMDEV + /* not required if /dev/urandom exists, OpenSSL does it internally */ + + bool ok; + int randdef; + static int done = RI_NONE; + + /* + ** initialize PRNG + */ + + /* did we try this before? if yes: return old value */ + if (done != RI_NONE) + return done == RI_SUCCESS; + + /* set default values */ + ok = false; + done = RI_FAIL; + randdef = (randfile == NULL || *randfile == '\0') ? RF_MISS : RF_OK; +# if EGD + if (randdef == RF_OK && sm_strncasecmp(randfile, "egd:", 4) == 0) + { + randfile += 4; + if (RAND_egd(randfile) < 0) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: RAND_egd(%s) failed: random number generator not seeded", + randfile); + } + else + ok = true; + } + else +# endif /* EGD */ + if (randdef == RF_OK && sm_strncasecmp(randfile, "file:", 5) == 0) + { + int fd; + long sff; + struct stat st; + + randfile += 5; + sff = SFF_SAFEDIRPATH | SFF_NOWLINK + | SFF_NOGWFILES | SFF_NOWWFILES + | SFF_NOGRFILES | SFF_NOWRFILES + | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT; + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + if ((fd = safeopen(randfile, O_RDONLY, 0, sff)) >= 0) + { + if (fstat(fd, &st) < 0) + { + if (LogLevel > logl) + sm_syslog(LOG_ERR, NOQID, + "STARTTLS: can't fstat(%s)", + randfile); + } + else + { + bool use, problem; + + use = true; + problem = false; + + /* max. age of file: 10 minutes */ + if (st.st_mtime + 600 < curtime()) + { + use = bitnset(DBS_INSUFFICIENTENTROPY, + DontBlameSendmail); + problem = true; + if (LogLevel > logl) + sm_syslog(LOG_ERR, NOQID, + "STARTTLS: RandFile %s too old: %s", + randfile, + use ? "unsafe" : + "unusable"); + } + if (use && st.st_size < MIN_RAND_BYTES) + { + use = bitnset(DBS_INSUFFICIENTENTROPY, + DontBlameSendmail); + problem = true; + if (LogLevel > logl) + sm_syslog(LOG_ERR, NOQID, + "STARTTLS: size(%s) < %d: %s", + randfile, + MIN_RAND_BYTES, + use ? "unsafe" : + "unusable"); + } + if (use) + ok = RAND_load_file(randfile, -1) >= + MIN_RAND_BYTES; + if (use && !ok) + { + if (LogLevel > logl) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: RAND_load_file(%s) failed: random number generator not seeded", + randfile); + } + if (problem) + ok = false; + } + if (ok || bitnset(DBS_INSUFFICIENTENTROPY, + DontBlameSendmail)) + { + /* add this even if fstat() failed */ + RAND_seed((void *) &st, sizeof st); + } + (void) close(fd); + } + else + { + if (LogLevel > logl) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: Warning: safeopen(%s) failed", + randfile); + } + } + else if (randdef == RF_OK) + { + if (LogLevel > logl) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: Error: no proper random file definition %s", + randfile); + randdef = RF_UNKNOWN; + } + if (randdef == RF_MISS) + { + if (LogLevel > logl) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: Error: missing random file definition"); + } + if (!ok && bitnset(DBS_INSUFFICIENTENTROPY, DontBlameSendmail)) + { + int i; + long r; + unsigned char buf[MIN_RAND_BYTES]; + + /* assert((MIN_RAND_BYTES % sizeof(long)) == 0); */ + for (i = 0; i <= sizeof(buf) - sizeof(long); i += sizeof(long)) + { + r = get_random(); + (void) memcpy(buf + i, (void *) &r, sizeof(long)); + } + RAND_seed(buf, sizeof buf); + if (LogLevel > logl) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: Warning: random number generator not properly seeded"); + ok = true; + } + done = ok ? RI_SUCCESS : RI_FAIL; + return ok; +# else /* ! HASURANDOMDEV */ + return true; +# endif /* ! HASURANDOMDEV */ +} +/* +** INIT_TLS_LIBRARY -- Calls functions which setup TLS library for global use. +** +** Parameters: +** none. +** +** Returns: +** succeeded? +*/ + +bool +init_tls_library() +{ + /* basic TLS initialization, ignore result for now */ + SSL_library_init(); + SSL_load_error_strings(); +# if 0 + /* this is currently a macro for SSL_library_init */ + SSLeay_add_ssl_algorithms(); +# endif /* 0 */ + + return tls_rand_init(RandFile, 7); +} +/* +** TLS_SET_VERIFY -- request client certificate? +** +** Parameters: +** ctx -- TLS context +** ssl -- TLS structure +** vrfy -- require certificate? +** +** Returns: +** none. +** +** Side Effects: +** Sets verification state for TLS +** +# if TLS_VRFY_PER_CTX +** Notice: +** This is per TLS context, not per TLS structure; +** the former is global, the latter per connection. +** It would be nice to do this per connection, but this +** doesn't work in the current TLS libraries :-( +# endif * TLS_VRFY_PER_CTX * +*/ + +void +tls_set_verify(ctx, ssl, vrfy) + SSL_CTX *ctx; + SSL *ssl; + bool vrfy; +{ +# if !TLS_VRFY_PER_CTX + SSL_set_verify(ssl, vrfy ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); +# else /* !TLS_VRFY_PER_CTX */ + SSL_CTX_set_verify(ctx, vrfy ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, + NULL); +# endif /* !TLS_VRFY_PER_CTX */ +} + +/* +** status in initialization +** these flags keep track of the status of the initialization +** i.e., whether a file exists (_EX) and whether it can be used (_OK) +** [due to permissions] +*/ + +# define TLS_S_NONE 0x00000000 /* none yet */ +# define TLS_S_CERT_EX 0x00000001 /* cert file exists */ +# define TLS_S_CERT_OK 0x00000002 /* cert file is ok */ +# define TLS_S_KEY_EX 0x00000004 /* key file exists */ +# define TLS_S_KEY_OK 0x00000008 /* key file is ok */ +# define TLS_S_CERTP_EX 0x00000010 /* CA cert path exists */ +# define TLS_S_CERTP_OK 0x00000020 /* CA cert path is ok */ +# define TLS_S_CERTF_EX 0x00000040 /* CA cert file exists */ +# define TLS_S_CERTF_OK 0x00000080 /* CA cert file is ok */ + +# if _FFR_TLS_1 +# define TLS_S_CERT2_EX 0x00001000 /* 2nd cert file exists */ +# define TLS_S_CERT2_OK 0x00002000 /* 2nd cert file is ok */ +# define TLS_S_KEY2_EX 0x00004000 /* 2nd key file exists */ +# define TLS_S_KEY2_OK 0x00008000 /* 2nd key file is ok */ +# endif /* _FFR_TLS_1 */ + +# define TLS_S_DH_OK 0x00200000 /* DH cert is ok */ +# define TLS_S_DHPAR_EX 0x00400000 /* DH param file exists */ +# define TLS_S_DHPAR_OK 0x00800000 /* DH param file is ok to use */ + +/* +** TLS_OK_F -- can var be an absolute filename? +** +** Parameters: +** var -- filename +** fn -- what is the filename used for? +** srv -- server side? +** +** Returns: +** ok? +*/ + +static bool +tls_ok_f(var, fn, srv) + char *var; + char *fn; + bool srv; +{ + /* must be absolute pathname */ + if (var != NULL && *var == '/') + return true; + if (LogLevel > 12) + sm_syslog(LOG_WARNING, NOQID, "STARTTLS: %s%s missing", + srv ? "Server" : "Client", fn); + return false; +} +/* +** TLS_SAFE_F -- is a file safe to use? +** +** Parameters: +** var -- filename +** sff -- flags for safefile() +** srv -- server side? +** +** Returns: +** ok? +*/ + +static bool +tls_safe_f(var, sff, srv) + char *var; + long sff; + bool srv; +{ + int ret; + + if ((ret = safefile(var, RunAsUid, RunAsGid, RunAsUserName, sff, + S_IRUSR, NULL)) == 0) + return true; + if (LogLevel > 7) + sm_syslog(LOG_WARNING, NOQID, "STARTTLS=%s: file %s unsafe: %s", + srv ? "server" : "client", var, sm_errstring(ret)); + return false; +} + +/* +** TLS_OK_F -- macro to simplify calls to tls_ok_f +** +** Parameters: +** var -- filename +** fn -- what is the filename used for? +** req -- is the file required? +** st -- status bit to set if ok +** srv -- server side? +** +** Side Effects: +** uses r, ok; may change ok and status. +** +*/ + +# define TLS_OK_F(var, fn, req, st, srv) if (ok) \ + { \ + r = tls_ok_f(var, fn, srv); \ + if (r) \ + status |= st; \ + else if (req) \ + ok = false; \ + } + +/* +** TLS_UNR -- macro to return whether a file should be unreadable +** +** Parameters: +** bit -- flag to test +** req -- flags +** +** Returns: +** 0/SFF_NORFILES +*/ +# define TLS_UNR(bit, req) (bitset(bit, req) ? SFF_NORFILES : 0) +# define TLS_OUNR(bit, req) (bitset(bit, req) ? SFF_NOWRFILES : 0) +# define TLS_KEYSFF(req) \ + (bitnset(DBS_GROUPREADABLEKEYFILE, DontBlameSendmail) ? \ + TLS_OUNR(TLS_I_KEY_OUNR, req) : \ + TLS_UNR(TLS_I_KEY_UNR, req)) + +/* +** TLS_SAFE_F -- macro to simplify calls to tls_safe_f +** +** Parameters: +** var -- filename +** sff -- flags for safefile() +** req -- is the file required? +** ex -- does the file exist? +** st -- status bit to set if ok +** srv -- server side? +** +** Side Effects: +** uses r, ok, ex; may change ok and status. +** +*/ + +# define TLS_SAFE_F(var, sff, req, ex, st, srv) if (ex && ok) \ + { \ + r = tls_safe_f(var, sff, srv); \ + if (r) \ + status |= st; \ + else if (req) \ + ok = false; \ + } + +/* +** INITTLS -- initialize TLS +** +** Parameters: +** ctx -- pointer to context +** req -- requirements for initialization (see sendmail.h) +** srv -- server side? +** certfile -- filename of certificate +** keyfile -- filename of private key +** cacertpath -- path to CAs +** cacertfile -- file with CA(s) +** dhparam -- parameters for DH +** +** Returns: +** succeeded? +*/ + +bool +inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam) + SSL_CTX **ctx; + unsigned long req; + bool srv; + char *certfile, *keyfile, *cacertpath, *cacertfile, *dhparam; +{ +# if !NO_DH + static DH *dh = NULL; +# endif /* !NO_DH */ + int r; + bool ok; + long sff, status; + char *who; +# if _FFR_TLS_1 + char *cf2, *kf2; +# endif /* _FFR_TLS_1 */ +# if SM_CONF_SHM + extern int ShmId; +# endif /* SM_CONF_SHM */ + + status = TLS_S_NONE; + who = srv ? "server" : "client"; + if (ctx == NULL) + syserr("STARTTLS=%s, inittls: ctx == NULL", who); + + /* already initialized? (we could re-init...) */ + if (*ctx != NULL) + return true; + ok = true; + +# if _FFR_TLS_1 + /* + ** look for a second filename: it must be separated by a ',' + ** no blanks allowed (they won't be skipped). + ** we change a global variable here! this change will be undone + ** before return from the function but only if it returns true. + ** this isn't a problem since in a failure case this function + ** won't be called again with the same (overwritten) values. + ** otherwise each return must be replaced with a goto endinittls. + */ + + cf2 = NULL; + kf2 = NULL; + if (certfile != NULL && (cf2 = strchr(certfile, ',')) != NULL) + { + *cf2++ = '\0'; + if (keyfile != NULL && (kf2 = strchr(keyfile, ',')) != NULL) + *kf2++ = '\0'; + } +# endif /* _FFR_TLS_1 */ + + /* + ** Check whether files/paths are defined + */ + + TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req), + TLS_S_CERT_EX, srv); + TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req), + TLS_S_KEY_EX, srv); + TLS_OK_F(cacertpath, "CACertPath", bitset(TLS_I_CERTP_EX, req), + TLS_S_CERTP_EX, srv); + TLS_OK_F(cacertfile, "CACertFile", bitset(TLS_I_CERTF_EX, req), + TLS_S_CERTF_EX, srv); + +# if _FFR_TLS_1 + /* + ** if the second file is specified it must exist + ** XXX: it is possible here to define only one of those files + */ + + if (cf2 != NULL) + { + TLS_OK_F(cf2, "CertFile", bitset(TLS_I_CERT_EX, req), + TLS_S_CERT2_EX, srv); + } + if (kf2 != NULL) + { + TLS_OK_F(kf2, "KeyFile", bitset(TLS_I_KEY_EX, req), + TLS_S_KEY2_EX, srv); + } +# endif /* _FFR_TLS_1 */ + + /* + ** valid values for dhparam are (only the first char is checked) + ** none no parameters: don't use DH + ** 512 generate 512 bit parameters (fixed) + ** 1024 generate 1024 bit parameters + ** /file/name read parameters from /file/name + ** default is: 1024 for server, 512 for client (OK? XXX) + */ + + if (bitset(TLS_I_TRY_DH, req)) + { + if (dhparam != NULL) + { + char c = *dhparam; + + if (c == '1') + req |= TLS_I_DH1024; + else if (c == '5') + req |= TLS_I_DH512; + else if (c != 'n' && c != 'N' && c != '/') + { + if (LogLevel > 12) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: illegal value '%s' for DHParam", + who, dhparam); + dhparam = NULL; + } + } + if (dhparam == NULL) + dhparam = srv ? "1" : "5"; + else if (*dhparam == '/') + { + TLS_OK_F(dhparam, "DHParameters", + bitset(TLS_I_DHPAR_EX, req), + TLS_S_DHPAR_EX, srv); + } + } + if (!ok) + return ok; + + /* certfile etc. must be "safe". */ + sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK + | SFF_NOGWFILES | SFF_NOWWFILES + | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT; + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + + TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req), + bitset(TLS_I_CERT_EX, req), + bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK, srv); + TLS_SAFE_F(keyfile, sff | TLS_KEYSFF(req), + bitset(TLS_I_KEY_EX, req), + bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK, srv); + TLS_SAFE_F(cacertfile, sff | TLS_UNR(TLS_I_CERTF_UNR, req), + bitset(TLS_I_CERTF_EX, req), + bitset(TLS_S_CERTF_EX, status), TLS_S_CERTF_OK, srv); + TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req), + bitset(TLS_I_DHPAR_EX, req), + bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv); + if (!ok) + return ok; +# if _FFR_TLS_1 + if (cf2 != NULL) + { + TLS_SAFE_F(cf2, sff | TLS_UNR(TLS_I_CERT_UNR, req), + bitset(TLS_I_CERT_EX, req), + bitset(TLS_S_CERT2_EX, status), TLS_S_CERT2_OK, srv); + } + if (kf2 != NULL) + { + TLS_SAFE_F(kf2, sff | TLS_KEYSFF(req), + bitset(TLS_I_KEY_EX, req), + bitset(TLS_S_KEY2_EX, status), TLS_S_KEY2_OK, srv); + } +# endif /* _FFR_TLS_1 */ + + /* create a method and a new context */ + if ((*ctx = SSL_CTX_new(srv ? SSLv23_server_method() : + SSLv23_client_method())) == NULL) + { + if (LogLevel > 7) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_CTX_new(SSLv23_%s_method()) failed", + who, who); + if (LogLevel > 9) + tlslogerr(who); + return false; + } + +# if TLS_NO_RSA + /* turn off backward compatibility, required for no-rsa */ + SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2); +# endif /* TLS_NO_RSA */ + + +# if !TLS_NO_RSA + /* + ** Create a temporary RSA key + ** XXX Maybe we shouldn't create this always (even though it + ** is only at startup). + ** It is a time-consuming operation and it is not always necessary. + ** maybe we should do it only on demand... + */ + + if (bitset(TLS_I_RSA_TMP, req) +# if SM_CONF_SHM + && ShmId != SM_SHM_NO_ID && + (rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL, + NULL)) == NULL +# else /* SM_CONF_SHM */ + && 0 /* no shared memory: no need to generate key now */ +# endif /* SM_CONF_SHM */ + ) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: RSA_generate_key failed", + who); + if (LogLevel > 9) + tlslogerr(who); + } + return false; + } +# endif /* !TLS_NO_RSA */ + + /* + ** load private key + ** XXX change this for DSA-only version + */ + + if (bitset(TLS_S_KEY_OK, status) && + SSL_CTX_use_PrivateKey_file(*ctx, keyfile, + SSL_FILETYPE_PEM) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_CTX_use_PrivateKey_file(%s) failed", + who, keyfile); + if (LogLevel > 9) + tlslogerr(who); + } + if (bitset(TLS_I_USE_KEY, req)) + return false; + } + + /* get the certificate file */ + if (bitset(TLS_S_CERT_OK, status) && + SSL_CTX_use_certificate_file(*ctx, certfile, + SSL_FILETYPE_PEM) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_CTX_use_certificate_file(%s) failed", + who, certfile); + if (LogLevel > 9) + tlslogerr(who); + } + if (bitset(TLS_I_USE_CERT, req)) + return false; + } + + /* check the private key */ + if (bitset(TLS_S_KEY_OK, status) && + (r = SSL_CTX_check_private_key(*ctx)) <= 0) + { + /* Private key does not match the certificate public key */ + if (LogLevel > 5) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_CTX_check_private_key failed(%s): %d", + who, keyfile, r); + if (LogLevel > 9) + tlslogerr(who); + } + if (bitset(TLS_I_USE_KEY, req)) + return false; + } + +# if _FFR_TLS_1 + /* XXX this code is pretty much duplicated from above! */ + + /* load private key */ + if (bitset(TLS_S_KEY2_OK, status) && + SSL_CTX_use_PrivateKey_file(*ctx, kf2, SSL_FILETYPE_PEM) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_CTX_use_PrivateKey_file(%s) failed", + who, kf2); + if (LogLevel > 9) + tlslogerr(who); + } + } + + /* get the certificate file */ + if (bitset(TLS_S_CERT2_OK, status) && + SSL_CTX_use_certificate_file(*ctx, cf2, SSL_FILETYPE_PEM) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_CTX_use_certificate_file(%s) failed", + who, cf2); + if (LogLevel > 9) + tlslogerr(who); + } + } + + /* also check the private key */ + if (bitset(TLS_S_KEY2_OK, status) && + (r = SSL_CTX_check_private_key(*ctx)) <= 0) + { + /* Private key does not match the certificate public key */ + if (LogLevel > 5) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_CTX_check_private_key 2 failed: %d", + who, r); + if (LogLevel > 9) + tlslogerr(who); + } + } +# endif /* _FFR_TLS_1 */ + + /* SSL_CTX_set_quiet_shutdown(*ctx, 1); violation of standard? */ + SSL_CTX_set_options(*ctx, SSL_OP_ALL); /* XXX bug compatibility? */ + +# if !NO_DH + /* Diffie-Hellman initialization */ + if (bitset(TLS_I_TRY_DH, req)) + { + if (bitset(TLS_S_DHPAR_OK, status)) + { + BIO *bio; + + if ((bio = BIO_new_file(dhparam, "r")) != NULL) + { + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (dh == NULL && LogLevel > 7) + { + unsigned long err; + + err = ERR_get_error(); + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: cannot read DH parameters(%s): %s", + who, dhparam, + ERR_error_string(err, NULL)); + if (LogLevel > 9) + tlslogerr(who); + } + } + else + { + if (LogLevel > 5) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: BIO_new_file(%s) failed", + who, dhparam); + if (LogLevel > 9) + tlslogerr(who); + } + } + } + if (dh == NULL && bitset(TLS_I_DH1024, req)) + { + DSA *dsa; + + /* this takes a while! (7-130s on a 450MHz AMD K6-2) */ + dsa = DSA_generate_parameters(1024, NULL, 0, NULL, + NULL, 0, NULL); + dh = DSA_dup_DH(dsa); + DSA_free(dsa); + } + else + if (dh == NULL && bitset(TLS_I_DH512, req)) + dh = get_dh512(); + + if (dh == NULL) + { + if (LogLevel > 9) + { + unsigned long err; + + err = ERR_get_error(); + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: cannot read or set DH parameters(%s): %s", + who, dhparam, + ERR_error_string(err, NULL)); + } + if (bitset(TLS_I_REQ_DH, req)) + return false; + } + else + { + SSL_CTX_set_tmp_dh(*ctx, dh); + + /* important to avoid small subgroup attacks */ + SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_DH_USE); + if (LogLevel > 13) + sm_syslog(LOG_INFO, NOQID, + "STARTTLS=%s, Diffie-Hellman init, key=%d bit (%c)", + who, 8 * DH_size(dh), *dhparam); + DH_free(dh); + } + } +# endif /* !NO_DH */ + + + /* XXX do we need this cache here? */ + if (bitset(TLS_I_CACHE, req)) + SSL_CTX_sess_set_cache_size(*ctx, 128); + /* timeout? SSL_CTX_set_timeout(*ctx, TimeOut...); */ + + /* load certificate locations and default CA paths */ + if (bitset(TLS_S_CERTP_EX, status) && bitset(TLS_S_CERTF_EX, status)) + { + if ((r = SSL_CTX_load_verify_locations(*ctx, cacertfile, + cacertpath)) == 1) + { +# if !TLS_NO_RSA + if (bitset(TLS_I_RSA_TMP, req)) + SSL_CTX_set_tmp_rsa_callback(*ctx, tmp_rsa_key); +# endif /* !TLS_NO_RSA */ + + /* + ** We have to install our own verify callback: + ** SSL_VERIFY_PEER requests a client cert but even + ** though *FAIL_IF* isn't set, the connection + ** will be aborted if the client presents a cert + ** that is not "liked" (can't be verified?) by + ** the TLS library :-( + */ + + /* + ** XXX currently we could call tls_set_verify() + ** but we hope that that function will later on + ** only set the mode per connection. + */ + SSL_CTX_set_verify(*ctx, + bitset(TLS_I_NO_VRFY, req) ? SSL_VERIFY_NONE + : SSL_VERIFY_PEER, + NULL); + + /* install verify callback */ + SSL_CTX_set_cert_verify_callback(*ctx, tls_verify_cb, + NULL); + SSL_CTX_set_client_CA_list(*ctx, + SSL_load_client_CA_file(cacertfile)); + } + else + { + /* + ** can't load CA data; do we care? + ** the data is necessary to authenticate the client, + ** which in turn would be necessary + ** if we want to allow relaying based on it. + */ + if (LogLevel > 5) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: load verify locs %s, %s failed: %d", + who, cacertpath, cacertfile, r); + if (LogLevel > 9) + tlslogerr(who); + } + if (bitset(TLS_I_VRFY_LOC, req)) + return false; + } + } + + /* XXX: make this dependent on an option? */ + if (tTd(96, 9)) + SSL_CTX_set_info_callback(*ctx, apps_ssl_info_cb); + +# if _FFR_TLS_1 + /* install our own cipher list */ + if (CipherList != NULL && *CipherList != '\0') + { + if (SSL_CTX_set_cipher_list(*ctx, CipherList) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_CTX_set_cipher_list(%s) failed, list ignored", + who, CipherList); + + if (LogLevel > 9) + tlslogerr(who); + } + /* failure if setting to this list is required? */ + } + } +# endif /* _FFR_TLS_1 */ + if (LogLevel > 12) + sm_syslog(LOG_INFO, NOQID, "STARTTLS=%s, init=%d", who, ok); + +# if _FFR_TLS_1 +# if 0 + /* + ** this label is required if we want to have a "clean" exit + ** see the comments above at the initialization of cf2 + */ + + endinittls: +# endif /* 0 */ + + /* undo damage to global variables */ + if (cf2 != NULL) + *--cf2 = ','; + if (kf2 != NULL) + *--kf2 = ','; +# endif /* _FFR_TLS_1 */ + + return ok; +} +/* +** TLS_GET_INFO -- get information about TLS connection +** +** Parameters: +** ssl -- TLS connection structure +** srv -- server or client +** host -- hostname of other side +** mac -- macro storage +** certreq -- did we ask for a cert? +** +** Returns: +** result of authentication. +** +** Side Effects: +** sets macros: {cipher}, {tls_version}, {verify}, +** {cipher_bits}, {alg_bits}, {cert}, {cert_subject}, +** {cert_issuer}, {cn_subject}, {cn_issuer} +*/ + +int +tls_get_info(ssl, srv, host, mac, certreq) + SSL *ssl; + bool srv; + char *host; + MACROS_T *mac; + bool certreq; +{ + SSL_CIPHER *c; + int b, r; + char *s, *who; + char bitstr[16]; + X509 *cert; + + c = SSL_get_current_cipher(ssl); + + /* cast is just workaround for compiler warning */ + macdefine(mac, A_TEMP, macid("{cipher}"), + (char *) SSL_CIPHER_get_name(c)); + b = SSL_CIPHER_get_bits(c, &r); + (void) sm_snprintf(bitstr, sizeof bitstr, "%d", b); + macdefine(mac, A_TEMP, macid("{cipher_bits}"), bitstr); + (void) sm_snprintf(bitstr, sizeof bitstr, "%d", r); + macdefine(mac, A_TEMP, macid("{alg_bits}"), bitstr); + s = SSL_CIPHER_get_version(c); + if (s == NULL) + s = "UNKNOWN"; + macdefine(mac, A_TEMP, macid("{tls_version}"), s); + + who = srv ? "server" : "client"; + cert = SSL_get_peer_certificate(ssl); + if (LogLevel > 14) + sm_syslog(LOG_INFO, NOQID, + "STARTTLS=%s, get_verify: %ld get_peer: 0x%lx", + who, SSL_get_verify_result(ssl), + (unsigned long) cert); + if (cert != NULL) + { + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + char buf[MAXNAME]; + + X509_NAME_oneline(X509_get_subject_name(cert), + buf, sizeof buf); + macdefine(mac, A_TEMP, macid("{cert_subject}"), + xtextify(buf, "<>\")")); + X509_NAME_oneline(X509_get_issuer_name(cert), + buf, sizeof buf); + macdefine(mac, A_TEMP, macid("{cert_issuer}"), + xtextify(buf, "<>\")")); + X509_NAME_get_text_by_NID(X509_get_subject_name(cert), + NID_commonName, buf, sizeof buf); + macdefine(mac, A_TEMP, macid("{cn_subject}"), + xtextify(buf, "<>\")")); + X509_NAME_get_text_by_NID(X509_get_issuer_name(cert), + NID_commonName, buf, sizeof buf); + macdefine(mac, A_TEMP, macid("{cn_issuer}"), + xtextify(buf, "<>\")")); + if (X509_digest(cert, EVP_md5(), md, &n)) + { + char md5h[EVP_MAX_MD_SIZE * 3]; + static const char hexcodes[] = "0123456789ABCDEF"; + + SM_ASSERT((n * 3) + 2 < sizeof(md5h)); + for (r = 0; r < (int) n; r++) + { + md5h[r * 3] = hexcodes[(md[r] & 0xf0) >> 4]; + md5h[(r * 3) + 1] = hexcodes[(md[r] & 0x0f)]; + md5h[(r * 3) + 2] = ':'; + } + md5h[(n * 3) - 1] = '\0'; + macdefine(mac, A_TEMP, macid("{cert_md5}"), md5h); + } + else + macdefine(mac, A_TEMP, macid("{cert_md5}"), ""); + } + else + { + macdefine(mac, A_PERM, macid("{cert_subject}"), ""); + macdefine(mac, A_PERM, macid("{cert_issuer}"), ""); + macdefine(mac, A_PERM, macid("{cn_subject}"), ""); + macdefine(mac, A_PERM, macid("{cn_issuer}"), ""); + macdefine(mac, A_TEMP, macid("{cert_md5}"), ""); + } + switch (SSL_get_verify_result(ssl)) + { + case X509_V_OK: + if (cert != NULL) + { + s = "OK"; + r = TLS_AUTH_OK; + } + else + { + s = certreq ? "NO" : "NOT", + r = TLS_AUTH_NO; + } + break; + default: + s = "FAIL"; + r = TLS_AUTH_FAIL; + break; + } + macdefine(mac, A_PERM, macid("{verify}"), s); + if (cert != NULL) + X509_free(cert); + + /* do some logging */ + if (LogLevel > 8) + { + char *vers, *s1, *s2, *cbits, *algbits; + + vers = macget(mac, macid("{tls_version}")); + cbits = macget(mac, macid("{cipher_bits}")); + algbits = macget(mac, macid("{alg_bits}")); + s1 = macget(mac, macid("{verify}")); + s2 = macget(mac, macid("{cipher}")); + + /* XXX: maybe cut off ident info? */ + sm_syslog(LOG_INFO, NOQID, + "STARTTLS=%s, relay=%.100s, version=%.16s, verify=%.16s, cipher=%.64s, bits=%.6s/%.6s", + who, + host == NULL ? "local" : host, + vers, s1, s2, /* sm_snprintf() can deal with NULL */ + algbits == NULL ? "0" : algbits, + cbits == NULL ? "0" : cbits); + if (LogLevel > 11) + { + /* + ** Maybe run xuntextify on the strings? + ** That is easier to read but makes it maybe a bit + ** more complicated to figure out the right values + ** for the access map... + */ + + s1 = macget(mac, macid("{cert_subject}")); + s2 = macget(mac, macid("{cert_issuer}")); + sm_syslog(LOG_INFO, NOQID, + "STARTTLS=%s, cert-subject=%.128s, cert-issuer=%.128s", + who, s1, s2); + } + } + return r; +} +/* +** ENDTLS -- shutdown secure connection +** +** Parameters: +** ssl -- SSL connection information. +** side -- server/client (for logging). +** +** Returns: +** success? (EX_* code) +*/ + +int +endtls(ssl, side) + SSL *ssl; + char *side; +{ + int ret = EX_OK; + + if (ssl != NULL) + { + int r; + + if ((r = SSL_shutdown(ssl)) < 0) + { + if (LogLevel > 11) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, SSL_shutdown failed: %d", + side, r); + tlslogerr(side); + } + ret = EX_SOFTWARE; + } +# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER > 0x0090602fL + + /* + ** Bug in OpenSSL (at least up to 0.9.6b): + ** From: Lutz.Jaenicke@aet.TU-Cottbus.DE + ** Message-ID: <20010723152244.A13122@serv01.aet.tu-cottbus.de> + ** To: openssl-users@openssl.org + ** Subject: Re: SSL_shutdown() woes (fwd) + ** + ** The side sending the shutdown alert first will + ** not care about the answer of the peer but will + ** immediately return with a return value of "0" + ** (ssl/s3_lib.c:ssl3_shutdown()). SSL_get_error will evaluate + ** the value of "0" and as the shutdown alert of the peer was + ** not received (actually, the program did not even wait for + ** the answer), an SSL_ERROR_SYSCALL is flagged, because this + ** is the default rule in case everything else does not apply. + ** + ** For your server the problem is different, because it + ** receives the shutdown first (setting SSL_RECEIVED_SHUTDOWN), + ** then sends its response (SSL_SENT_SHUTDOWN), so for the + ** server the shutdown was successfull. + ** + ** As is by know, you would have to call SSL_shutdown() once + ** and ignore an SSL_ERROR_SYSCALL returned. Then call + ** SSL_shutdown() again to actually get the server's response. + ** + ** In the last discussion, Bodo Moeller concluded that a + ** rewrite of the shutdown code would be necessary, but + ** probably with another API, as the change would not be + ** compatible to the way it is now. Things do not become + ** easier as other programs do not follow the shutdown + ** guidelines anyway, so that a lot error conditions and + ** compitibility issues would have to be caught. + ** + ** For now the recommondation is to ignore the error message. + */ + + else if (r == 0) + { + if (LogLevel > 15) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, SSL_shutdown not done", + side); + tlslogerr(side); + } + ret = EX_SOFTWARE; + } +# endif /* !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER > 0x0090602fL */ + SSL_free(ssl); + ssl = NULL; + } + return ret; +} + +# if !TLS_NO_RSA +/* +** TMP_RSA_KEY -- return temporary RSA key +** +** Parameters: +** s -- TLS connection structure +** export -- +** keylength -- +** +** Returns: +** temporary RSA key. +*/ + +# ifndef MAX_RSA_TMP_CNT +# define MAX_RSA_TMP_CNT 1000 /* XXX better value? */ +# endif /* ! MAX_RSA_TMP_CNT */ + +/* ARGUSED0 */ +static RSA * +tmp_rsa_key(s, export, keylength) + SSL *s; + int export; + int keylength; +{ +# if SM_CONF_SHM + extern int ShmId; + extern int *PRSATmpCnt; + + if (ShmId != SM_SHM_NO_ID && rsa_tmp != NULL && + ++(*PRSATmpCnt) < MAX_RSA_TMP_CNT) + return rsa_tmp; +# endif /* SM_CONF_SHM */ + + if (rsa_tmp != NULL) + RSA_free(rsa_tmp); + rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL, NULL); + if (rsa_tmp == NULL) + { + if (LogLevel > 0) + sm_syslog(LOG_ERR, NOQID, + "STARTTLS=server, tmp_rsa_key: RSA_generate_key failed!"); + } + else + { +# if SM_CONF_SHM +# if 0 + /* + ** XXX we can't (yet) share the new key... + ** The RSA structure contains pointers hence it can't be + ** easily kept in shared memory. It must be transformed + ** into a continous memory region first, then stored, + ** and later read out again (each time re-transformed). + */ + + if (ShmId != SM_SHM_NO_ID) + *PRSATmpCnt = 0; +# endif /* 0 */ +# endif /* SM_CONF_SHM */ + if (LogLevel > 9) + sm_syslog(LOG_ERR, NOQID, + "STARTTLS=server, tmp_rsa_key: new temp RSA key"); + } + return rsa_tmp; +} +# endif /* !TLS_NO_RSA */ +/* +** APPS_SSL_INFO_CB -- info callback for TLS connections +** +** Parameters: +** s -- TLS connection structure +** where -- state in handshake +** ret -- return code of last operation +** +** Returns: +** none. +*/ + +static void +apps_ssl_info_cb(s, where, ret) + CONST097 SSL *s; + int where; + int ret; +{ + int w; + char *str; + BIO *bio_err = NULL; + + if (LogLevel > 14) + sm_syslog(LOG_INFO, NOQID, + "STARTTLS: info_callback where=0x%x, ret=%d", + where, ret); + + w = where & ~SSL_ST_MASK; + if (bio_err == NULL) + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + + if (bitset(SSL_ST_CONNECT, w)) + str = "SSL_connect"; + else if (bitset(SSL_ST_ACCEPT, w)) + str = "SSL_accept"; + else + str = "undefined"; + + if (bitset(SSL_CB_LOOP, where)) + { + if (LogLevel > 12) + sm_syslog(LOG_NOTICE, NOQID, + "STARTTLS: %s:%s", + str, SSL_state_string_long(s)); + } + else if (bitset(SSL_CB_ALERT, where)) + { + str = bitset(SSL_CB_READ, where) ? "read" : "write"; + if (LogLevel > 12) + sm_syslog(LOG_NOTICE, NOQID, + "STARTTLS: SSL3 alert %s:%s:%s", + str, SSL_alert_type_string_long(ret), + SSL_alert_desc_string_long(ret)); + } + else if (bitset(SSL_CB_EXIT, where)) + { + if (ret == 0) + { + if (LogLevel > 7) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: %s:failed in %s", + str, SSL_state_string_long(s)); + } + else if (ret < 0) + { + if (LogLevel > 7) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: %s:error in %s", + str, SSL_state_string_long(s)); + } + } +} +/* +** TLS_VERIFY_LOG -- log verify error for TLS certificates +** +** Parameters: +** ok -- verify ok? +** ctx -- x509 context +** +** Returns: +** 0 -- fatal error +** 1 -- ok +*/ + +static int +tls_verify_log(ok, ctx) + int ok; + X509_STORE_CTX *ctx; +{ + SSL *ssl; + X509 *cert; + int reason, depth; + char buf[512]; + + cert = X509_STORE_CTX_get_current_cert(ctx); + reason = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + ssl = (SSL *) X509_STORE_CTX_get_ex_data(ctx, + SSL_get_ex_data_X509_STORE_CTX_idx()); + + if (ssl == NULL) + { + /* internal error */ + sm_syslog(LOG_ERR, NOQID, + "STARTTLS: internal error: tls_verify_cb: ssl == NULL"); + return 0; + } + + X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof buf); + sm_syslog(LOG_INFO, NOQID, + "STARTTLS: cert verify: depth=%d %s, state=%d, reason=%s", + depth, buf, ok, X509_verify_cert_error_string(reason)); + return 1; +} +/* +** TLS_VERIFY_CB -- verify callback for TLS certificates +** +** Parameters: +** ctx -- x509 context +** +** Returns: +** accept connection? +** currently: always yes. +*/ + +static int +# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L +tls_verify_cb(ctx) + X509_STORE_CTX *ctx; +# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +tls_verify_cb(ctx, unused) + X509_STORE_CTX *ctx; + void *unused; +# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +{ + int ok; + + ok = X509_verify_cert(ctx); + if (ok == 0) + { + if (LogLevel > 13) + return tls_verify_log(ok, ctx); + return 1; /* override it */ + } + return ok; +} +/* +** TLSLOGERR -- log the errors from the TLS error stack +** +** Parameters: +** who -- server/client (for logging). +** +** Returns: +** none. +*/ + +void +tlslogerr(who) + char *who; +{ + unsigned long l; + int line, flags; + unsigned long es; + char *file, *data; + char buf[256]; +# define CP (const char **) + + es = CRYPTO_thread_id(); + while ((l = ERR_get_error_line_data(CP &file, &line, CP &data, &flags)) + != 0) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s: %lu:%s:%s:%d:%s", who, es, + ERR_error_string(l, buf), + file, line, + bitset(ERR_TXT_STRING, flags) ? data : ""); + } +} +#endif /* STARTTLS */ diff --git a/gnu/dist/sendmail/smrsh/Makefile.m4 b/gnu/dist/sendmail/smrsh/Makefile.m4 index 7e4718ffa622..e8d14f7036bf 100644 --- a/gnu/dist/sendmail/smrsh/Makefile.m4 +++ b/gnu/dist/sendmail/smrsh/Makefile.m4 @@ -1,5 +1,7 @@ +dnl Id: Makefile.m4,v 8.34.2.1 2002/06/21 21:58:48 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') @@ -8,7 +10,8 @@ PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`executable', `smrsh') define(`bldINSTALL_DIR', `E') define(`bldSOURCES', `smrsh.c ') -bldPUSH_SMLIB(`smutil') +bldPUSH_SMLIB(`sm') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') bldPRODUCT_END bldPRODUCT_START(`manpage', `smrsh') diff --git a/gnu/dist/sendmail/smrsh/smrsh.0 b/gnu/dist/sendmail/smrsh/smrsh.0 index 60cd60d25b77..62e78787c77d 100644 --- a/gnu/dist/sendmail/smrsh/smrsh.0 +++ b/gnu/dist/sendmail/smrsh/smrsh.0 @@ -1,7 +1,9 @@ -SMRSH(8) SMRSH(8) +SMRSH(8) SMRSH(8) + + NNAAMMEE smrsh - restricted shell for sendmail @@ -45,10 +47,10 @@ DDEESSCCRRIIPPTTIIOONN CCOOMMPPIILLAATTIIOONN Compilation should be trivial on most systems. You may - need to use -DPATH=\"_p_a_t_h\" to adjust the default search - path (defaults to ``/bin:/usr/bin:/usr/ucb'') and/or - -DCMDBIN=\"_d_i_r\" to change the default program directory - (defaults to ``/usr/adm/sm.bin''). + need to use -DSMRSH_PATH=\"_p_a_t_h\" to adjust the default + search path (defaults to ``/bin:/usr/bin:/usr/ucb'') + and/or -DSMRSH_CMDDIR=\"_d_i_r\" to change the default pro- + gram directory (defaults to ``/usr/adm/sm.bin''). FFIILLEESS /usr/adm/sm.bin - directory for restricted programs @@ -58,4 +60,7 @@ SSEEEE AALLSSOO - Date: 2000/12/15 19:50:46 SMRSH(8) + + Date: 2002/04/25 13:33:40 1 + + diff --git a/gnu/dist/sendmail/test/Build b/gnu/dist/sendmail/test/Build new file mode 100644 index 000000000000..3cdc8ceaa72b --- /dev/null +++ b/gnu/dist/sendmail/test/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 2001 Sendmail, Inc. and its suppliers. +# 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. +# +# +# Id: Build,v 1.1 2001/09/23 22:39:24 ca Exp + +exec sh ../devtools/bin/Build $* diff --git a/gnu/dist/sendmail/test/Makefile b/gnu/dist/sendmail/test/Makefile new file mode 100644 index 000000000000..ddab297dfa9c --- /dev/null +++ b/gnu/dist/sendmail/test/Makefile @@ -0,0 +1,17 @@ +# Id: Makefile,v 1.1 2001/09/23 22:39:24 ca Exp + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/dist/sendmail/test/Makefile.m4 b/gnu/dist/sendmail/test/Makefile.m4 new file mode 100644 index 000000000000..4622f8d9235a --- /dev/null +++ b/gnu/dist/sendmail/test/Makefile.m4 @@ -0,0 +1,19 @@ +dnl Id: Makefile.m4,v 1.3.2.1 2002/06/21 21:58:49 ca Exp +include(confBUILDTOOLSDIR`/M4/switch.m4') + +bldPRODUCT_START(`executable', `test') +define(`bldSOURCES', `t_dropgid.c ') +bldPRODUCT_END + +include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/sm-test.m4') +dnl smtest(`getipnode') +smtest(`t_dropgid') +smtest(`t_exclopen') +smtest(`t_pathconf') +smtest(`t_seteuid') +smtest(`t_setgid') +smtest(`t_setreuid') +smtest(`t_setuid') +dnl smtest(`t_snprintf') + +bldFINISH diff --git a/gnu/dist/sendmail/test/README b/gnu/dist/sendmail/test/README new file mode 100644 index 000000000000..070af23057d6 --- /dev/null +++ b/gnu/dist/sendmail/test/README @@ -0,0 +1,27 @@ +# Copyright (c) 2001 Sendmail, Inc. and its suppliers. +# 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. +# +# Id: README,v 1.2 2001/09/28 16:36:28 ca Exp +# + +This directory contains several programs to test various OS calls. +If your OS is not listed in the Results file, you should run those +test programs. Most of them have instructions at the begin of source +code, at least those which are important. + +Notice: most of these programs require set-user-ID or set-group-ID +installation. Hence they are not tested automatically. + +t_dropgid.c test how to drop saved-gid for a set-group-ID program +t_exclopen.c test for security-defeating semantics that an open with + O_CREAT|O_EXCL set will successfully open a file named + by a symbolic link that to a non-existent file +t_seteuid.c test whether seteuid works +t_setgid.c test whether setgid works +t_setreuid.c test whether setreuid works +t_setuid.c test whether setuid works + diff --git a/gnu/dist/sendmail/test/t_dropgid.c b/gnu/dist/sendmail/test/t_dropgid.c new file mode 100644 index 000000000000..d7f103a6b05c --- /dev/null +++ b/gnu/dist/sendmail/test/t_dropgid.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +/* +** This program checks to see if your version of setgid works. +** Compile it, make it set-group-ID guest, and run it as yourself (NOT as +** root and not as member of the group guest). +** +** Compilation is trivial -- just "cc t_dropgid.c". Make it set-group-ID +** guest and then execute it as a non-root user. +*/ + +#include +#include +#include + +#ifndef lint +static char id[] = "@(#)Id: t_dropgid.c,v 1.6 2001/09/28 16:36:28 ca Exp"; +#endif /* ! lint */ + +static void +printgids(str, r, e) + char *str; + gid_t r, e; +{ + printf("%s (should be %d/%d): r/egid=%d/%d\n", str, (int) r, (int) e, + (int) getgid(), (int) getegid()); +} + +/* define only one of these */ +#if HASSETEGID +# define SETGIDCALL "setegid" +#endif /* HASSETEGID */ +#if HASSETREGID +# define SETGIDCALL "setregid" +#endif /* HASSETREGID */ +#if HASSETRESGID +# define SETGIDCALL "setresgid" +#endif /* HASSETRESGID */ + +#ifndef SETGIDCALL +# define SETGIDCALL "setgid" +#endif /* ! SETGIDCALL */ + +int +main(argc, argv) + int argc; + char **argv; +{ + int fail = 0; + int res; + gid_t realgid = getgid(); + gid_t effgid = getegid(); + char *prg = argv[0]; + + printgids("initial gids", realgid, effgid); + + if (effgid == realgid) + { + printf("SETUP ERROR: re-run set-group-ID guest\n"); + printf("Use chgrp(1) and chmod(1)\n"); + printf("For example, do this as root "); + printf("(nobody is the name of a group in this example):\n"); + printf("# chgrp nobody %s\n", prg); + printf("# chmod g+s nobody %s\n", prg); + exit(1); + } + +#if HASSETREGID + res = setregid(realgid, realgid); + printf("setregid(%d)=%d %s\n", (int) realgid, res, + res < 0 ? "failure" : "ok"); + printgids("after setregid()", realgid, realgid); +#endif /* HASSETREGID */ +#if HASSETRESGID + res = setresgid(realgid, realgid, realgid); + printf("setresgid(%d)=%d %s\n", (int) realgid, res, + res < 0 ? "failure" : "ok"); + printgids("after setresgid()", realgid, realgid); +#endif /* HASSETRESGID */ +#if HASSETEGID + res = setegid(realgid); + printf("setegid(%d)=%d %s\n", (int) realgid, res, + res < 0 ? "failure" : "ok"); + printgids("after setegid()", realgid, realgid); +#endif /* HASSETEGID */ + res = setgid(realgid); + printf("setgid(%d)=%d %s\n", (int) realgid, res, + res < 0 ? "failure" : "ok"); + printgids("after setgid()", realgid, realgid); + + if (getegid() != realgid) + { + fail++; + printf("MAYDAY! Wrong effective gid\n"); + } + + if (getgid() != realgid) + { + fail++; + printf("MAYDAY! Wrong real gid\n"); + } + + /* do activity here */ + if (setgid(effgid) == 0) + { + fail++; + printf("MAYDAY! setgid(%d) succeeded (should have failed)\n", + effgid); + } + else + { + printf("setgid(%d) failed (this is correct)\n", effgid); + } + printgids("after setgid() to egid", realgid, realgid); + + if (getegid() != realgid) + { + fail++; + printf("MAYDAY! Wrong effective gid\n"); + } + if (getgid() != realgid) + { + fail++; + printf("MAYDAY! Wrong real gid\n"); + } + printf("\n"); + + if (fail > 0) + { + printf("\nThis system cannot use %s to give up set-group-ID rights\n", + SETGIDCALL); +#if !HASSETEGID + printf("Maybe compile with -DHASSETEGID and try again\n"); +#endif /* !HASSETEGID */ +#if !HASSETREGID + printf("Maybe compile with -DHASSETREGID and try again\n"); +#endif /* !HASSETREGID */ +#if !HASSETRESGID + printf("Maybe compile with -DHASSETRESGID and try again\n"); +#endif /* !HASSETRESGID */ + exit(1); + } + + printf("\nIt is possible to use %s on this system\n", SETGIDCALL); + exit(0); +} diff --git a/gnu/dist/sendmail/test/t_setgid.c b/gnu/dist/sendmail/test/t_setgid.c new file mode 100644 index 000000000000..e448af4e0c2b --- /dev/null +++ b/gnu/dist/sendmail/test/t_setgid.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + +/* +** This program checks to see if your version of setgid works. +** Compile it, make it set-group-ID guest, and run it as yourself (NOT as +** root and not as member of the group guest). +** +** Compilation is trivial -- just "cc t_setgid.c". Make it set-group-ID, +** guest and then execute it as a non-root user. +*/ + +#include +#include +#include + +#ifndef lint +static char id[] = "@(#)Id: t_setgid.c,v 1.6 2001/09/23 03:35:41 ca Exp"; +#endif /* ! lint */ + +static void +printgids(str, r, e) + char *str; + gid_t r, e; +{ + printf("%s (should be %d/%d): r/egid=%d/%d\n", str, (int) r, (int) e, + (int) getgid(), (int) getegid()); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + int fail = 0; + int res; + gid_t realgid = getgid(); + gid_t effgid = getegid(); + + printgids("initial gids", realgid, effgid); + + if (effgid == realgid) + { + printf("SETUP ERROR: re-run set-group-ID guest\n"); + exit(1); + } + +#if SM_CONF_SETREGID + res = setregid(effgid, effgid); +#else /* SM_CONF_SETREGID */ + res = setgid(effgid); +#endif /* SM_CONF_SETREGID */ + + printf("setgid(%d)=%d %s\n", (int) effgid, res, + res < 0 ? "failure" : "ok"); +#if SM_CONF_SETREGID + printgids("after setregid()", effgid, effgid); +#else /* SM_CONF_SETREGID */ + printgids("after setgid()", effgid, effgid); +#endif /* SM_CONF_SETREGID */ + + if (getegid() != effgid) + { + fail++; + printf("MAYDAY! Wrong effective gid\n"); + } + + if (getgid() != effgid) + { + fail++; + printf("MAYDAY! Wrong real gid\n"); + } + + /* do activity here */ + if (setgid(0) == 0) + { + fail++; + printf("MAYDAY! setgid(0) succeeded (should have failed)\n"); + } + else + { + printf("setgid(0) failed (this is correct)\n"); + } + printgids("after setgid(0)", effgid, effgid); + + if (getegid() != effgid) + { + fail++; + printf("MAYDAY! Wrong effective gid\n"); + } + if (getgid() != effgid) + { + fail++; + printf("MAYDAY! Wrong real gid\n"); + } + printf("\n"); + + if (fail > 0) + { + printf("\nThis system cannot use %s to set the real gid to the effective gid\nand clear the saved gid.\n", +#if SM_CONF_SETREGID + "setregid" +#else /* SM_CONF_SETREGID */ + "setgid" +#endif /* SM_CONF_SETREGID */ + ); + exit(1); + } + + printf("\nIt is possible to use setgid on this system\n"); + exit(0); +} diff --git a/gnu/dist/sendmail/test/t_setuid.c b/gnu/dist/sendmail/test/t_setuid.c index f3cf5f871bc4..969a700d8a6a 100644 --- a/gnu/dist/sendmail/test/t_setuid.c +++ b/gnu/dist/sendmail/test/t_setuid.c @@ -1,12 +1,22 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * 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. + * + */ + /* ** This program checks to see if your version of setuid works. -** Compile it, make it setuid root, and run it as yourself (NOT as +** Compile it, make it set-user-ID root, and run it as yourself (NOT as ** root). ** ** NOTE: This should work everywhere, but Linux has the ability ** to use the undocumented setcap() call to make this break. ** -** Compilation is trivial -- just "cc t_setuid.c". Make it setuid, +** Compilation is trivial -- just "cc t_setuid.c". Make it set-user-ID, ** root and then execute it as a non-root user. */ @@ -15,16 +25,16 @@ #include #ifndef lint -static char id[] = "@(#)Id: t_setuid.c,v 8.2.2.1 2000/05/31 00:29:47 gshapiro Exp"; +static char id[] = "@(#)Id: t_setuid.c,v 8.7 2001/09/23 03:35:41 ca Exp"; #endif /* ! lint */ static void printuids(str, r, e) char *str; - int r, e; + uid_t r, e; { - printf("%s (should be %d/%d): r/euid=%d/%d\n", str, r, e, - getuid(), geteuid()); + printf("%s (should be %d/%d): r/euid=%d/%d\n", str, (int) r, (int) e, + (int) getuid(), (int) geteuid()); } int @@ -39,7 +49,7 @@ main(argc, argv) if (geteuid() != 0) { - printf("SETUP ERROR: re-run setuid root\n"); + printf("SETUP ERROR: re-run set-user-ID root\n"); exit(1); } diff --git a/gnu/dist/sendmail/vacation/Makefile.m4 b/gnu/dist/sendmail/vacation/Makefile.m4 index 71430eb2c1b0..3450879dc0a6 100644 --- a/gnu/dist/sendmail/vacation/Makefile.m4 +++ b/gnu/dist/sendmail/vacation/Makefile.m4 @@ -1,5 +1,7 @@ +dnl Id: Makefile.m4,v 8.24.4.1 2002/06/21 21:58:50 ca Exp include(confBUILDTOOLSDIR`/M4/switch.m4') +define(`confREQUIRE_LIBSM', `true') # sendmail dir SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') PREPENDDEF(`confENVDEF', `confMAPDEF') @@ -7,6 +9,7 @@ PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') bldPRODUCT_START(`executable', `vacation') define(`bldSOURCES', `vacation.c ') +bldPUSH_SMLIB(`sm') bldPUSH_SMLIB(`smutil') bldPUSH_SMLIB(`smdb') APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL')