qmail 1.02
This commit is contained in:
parent
af9625ddf9
commit
d15ee51c9d
134 changed files with 5642 additions and 5536 deletions
6
BLURB2
6
BLURB2
|
|
@ -16,11 +16,11 @@ out-of-the-box configuration.
|
||||||
|
|
||||||
* qmail automatically prevents mailing list loops, even across hosts.
|
* qmail automatically prevents mailing list loops, even across hosts.
|
||||||
|
|
||||||
* qlist, included in the qmail package, deals with subscription requests
|
|
||||||
safely and automatically.
|
|
||||||
|
|
||||||
* qmail allows inconceivably gigantic mailing lists. No random limits.
|
* qmail allows inconceivably gigantic mailing lists. No random limits.
|
||||||
|
|
||||||
* qmail handles aliasing and forwarding with the same simple mechanism.
|
* qmail handles aliasing and forwarding with the same simple mechanism.
|
||||||
For example, Postmaster is controlled by ~alias/.qmail-postmaster. This
|
For example, Postmaster is controlled by ~alias/.qmail-postmaster. This
|
||||||
means that cross-host loop detection also applies to aliases.
|
means that cross-host loop detection also applies to aliases.
|
||||||
|
|
||||||
|
* qmail supports the ezmlm mailing list manager, which easily and
|
||||||
|
automatically handles bounces, subscription requests, and archives.
|
||||||
|
|
|
||||||
15
BLURB3
15
BLURB3
|
|
@ -3,7 +3,7 @@ Here are some of qmail's features.
|
||||||
Setup:
|
Setup:
|
||||||
* automatic adaptation to your UNIX variant---no configuration needed
|
* automatic adaptation to your UNIX variant---no configuration needed
|
||||||
* AIX, BSD/OS, FreeBSD, HP/UX, Irix, Linux, OSF/1, SunOS, Solaris, and more
|
* AIX, BSD/OS, FreeBSD, HP/UX, Irix, Linux, OSF/1, SunOS, Solaris, and more
|
||||||
* automatic per-host configuration (qmail-config)
|
* automatic per-host configuration (config, config-fast)
|
||||||
* quick installation---no big list of decisions to make
|
* quick installation---no big list of decisions to make
|
||||||
|
|
||||||
Security:
|
Security:
|
||||||
|
|
@ -16,11 +16,12 @@ Security:
|
||||||
Message construction (qmail-inject):
|
Message construction (qmail-inject):
|
||||||
* RFC 822, RFC 1123
|
* RFC 822, RFC 1123
|
||||||
* full support for address groups
|
* full support for address groups
|
||||||
* automatic conversion of old-style headers to RFC 822 format
|
* automatic conversion of old-style address lists to RFC 822 format
|
||||||
|
* sendmail hook for compatibility with current user agents
|
||||||
* header line length limited only by memory
|
* header line length limited only by memory
|
||||||
* host masquerading (control/defaulthost)
|
* host masquerading (control/defaulthost)
|
||||||
* user masquerading (MAILUSER, MAILHOST)
|
* user masquerading ($MAILUSER, $MAILHOST)
|
||||||
* sendmail hook for compatibility with current user agents
|
* automatic Mail-Followup-To creation ($QMAILMFTFILE)
|
||||||
|
|
||||||
SMTP service (qmail-smtpd):
|
SMTP service (qmail-smtpd):
|
||||||
* RFC 821, RFC 1123, RFC 1651, RFC 1652, RFC 1854
|
* RFC 821, RFC 1123, RFC 1651, RFC 1652, RFC 1854
|
||||||
|
|
@ -67,11 +68,13 @@ SMTP delivery (qmail-remote):
|
||||||
|
|
||||||
Forwarding and mailing lists (qmail-local):
|
Forwarding and mailing lists (qmail-local):
|
||||||
* address wildcards (.qmail-default, .qmail-foo-default, etc.)
|
* address wildcards (.qmail-default, .qmail-foo-default, etc.)
|
||||||
* sendmail/smail /etc/aliases compatibility (qmsmac, available separately)
|
* sendmail .forward compatibility (dot-forward, available separately)
|
||||||
|
* fast forwarding databases (fastforward, available separately)
|
||||||
|
* sendmail /etc/aliases compatibility (fastforward/newaliases)
|
||||||
* mailing list owners---automatically divert bounces and vacation messages
|
* mailing list owners---automatically divert bounces and vacation messages
|
||||||
* VERPs---automatic recipient identification for mailing list bounces
|
* VERPs---automatic recipient identification for mailing list bounces
|
||||||
* Delivered-To---automatic loop prevention, even across hosts
|
* Delivered-To---automatic loop prevention, even across hosts
|
||||||
* automatic subscription management (qlist)
|
* automatic mailing list management (ezmlm, available separately)
|
||||||
|
|
||||||
Local delivery (qmail-local):
|
Local delivery (qmail-local):
|
||||||
* user-controlled address hierarchy---fred controls fred-anything
|
* user-controlled address hierarchy---fred controls fred-anything
|
||||||
|
|
|
||||||
4
BLURB4
4
BLURB4
|
|
@ -4,7 +4,7 @@ against the competition in five different speed measurements.
|
||||||
|
|
||||||
* Scheduling: I sent a message to 8192 ``trash'' recipients on my home
|
* Scheduling: I sent a message to 8192 ``trash'' recipients on my home
|
||||||
machine. All the deliveries were done in a mere 78 seconds---a rate of
|
machine. All the deliveries were done in a mere 78 seconds---a rate of
|
||||||
over 9 MILLION deliveries a day! Compare this to the speed advertised
|
over 9 million deliveries a day! Compare this to the speed advertised
|
||||||
for Zmailer's scheduling: 1.1 million deliveries a day on a
|
for Zmailer's scheduling: 1.1 million deliveries a day on a
|
||||||
SparcStation-10/50. (My home machine is a 16MB Pentium-100 under BSD/OS,
|
SparcStation-10/50. (My home machine is a 16MB Pentium-100 under BSD/OS,
|
||||||
with the default qmail configuration. qmail's logs were piped through
|
with the default qmail configuration. qmail's logs were piped through
|
||||||
|
|
@ -14,7 +14,7 @@ accustamp and written to disk as usual.)
|
||||||
it physically writes the message to disk before it announces success---
|
it physically writes the message to disk before it announces success---
|
||||||
that way, mail doesn't get lost if the power goes out. I tried sending a
|
that way, mail doesn't get lost if the power goes out. I tried sending a
|
||||||
message to 1024 local mailboxes on the same disk on my home machine; all
|
message to 1024 local mailboxes on the same disk on my home machine; all
|
||||||
the deliveries were done in 25.5 seconds. That's more than 3.4 MILLION
|
the deliveries were done in 25.5 seconds. That's more than 3.4 million
|
||||||
deliveries a day! Sending 1024 copies to a _single_ mailbox was just as
|
deliveries a day! Sending 1024 copies to a _single_ mailbox was just as
|
||||||
fast. Compare these figures to Zmailer's advertised rate for throwing
|
fast. Compare these figures to Zmailer's advertised rate for throwing
|
||||||
recipients away without even delivering the message---only 0.48 million
|
recipients away without even delivering the message---only 0.48 million
|
||||||
|
|
|
||||||
217
CHANGES
217
CHANGES
|
|
@ -1,3 +1,220 @@
|
||||||
|
19980430 version: qmail 1.02.
|
||||||
|
19980430 doc: updated SECURITY.
|
||||||
|
19980430 doc: fixed FAQ 4.9. tnx KB.
|
||||||
|
19980430 code: changed quote2() to avoid quoting <>.
|
||||||
|
19980429 code: changed quote_need() to quote empty local parts. tnx HHO.
|
||||||
|
19980428 doc: added status notes to INSTALL and UPGRADE.
|
||||||
|
19980428 code: skip setting environment in sendmail.c if PROTO is set.
|
||||||
|
19980428 code: eliminated recipientmap.
|
||||||
|
19980428 code: added virtual users to qmail-send.c. tnx RN.
|
||||||
|
19980428 code: eliminated domain from rewrite() in qmail-send.c.
|
||||||
|
19980428 code: added binm1, binm1+df, binm2, binm2+df, binm3, binm3+df.
|
||||||
|
19980428 doc: eliminated most Mailbox references from INSTALL, UPGRADE.
|
||||||
|
19980428 code: added config-fast.
|
||||||
|
19980428 code: renamed qmail-config as config.
|
||||||
|
19980428 code: supported QMAILMFTFILE in qmail-inject.c.
|
||||||
|
19980428 code: recognized Mail-Followup-To in hfield.c.
|
||||||
|
19980428 code: replaced rwrecip() with rwappend() in qmail-inject.c.
|
||||||
|
19980428 code: cleaned up doheaderfile() in qmail-inject.c.
|
||||||
|
19980426 code: eliminated -type test from qmail-qstat to speed it up.
|
||||||
|
tnx FT.
|
||||||
|
19980421 doc: eliminated remove-rcpthosts comments from FAQ.
|
||||||
|
19980421 doc: updated FAQ 4.3 to point to Russ Allbery's FAQ.
|
||||||
|
19980421 doc: took account of /var/qmail/boot in INSTALL, UPGRADE, and
|
||||||
|
INSTALL.vsm.
|
||||||
|
19980421 code: added /var/qmail/boot, with home, home+df, proc, proc+df.
|
||||||
|
19980421 doc: skipped make and make man in INSTALL.
|
||||||
|
19980420 doc: cleaned up mbox description in SENDMAIL.
|
||||||
|
19980420 code: changed QMQP port to official port 628.
|
||||||
|
19980402 doc: updated qmsmac references to fastforward.
|
||||||
|
19980402 doc: replaced qmail-upgrade man page with doc/SENDMAIL.
|
||||||
|
19980402 code: added qmqpservers output to qmail-showctl.
|
||||||
|
19980402 code: added qmail-qmqpd.
|
||||||
|
19980402 code: added qmail-qmqpc.
|
||||||
|
19980304 code: eliminated del_saywhynoexit in qmail-send.c.
|
||||||
|
19980304 code: eliminated concurrencynodel in qmail-send.c.
|
||||||
|
19980222 code: added status() to qmail-send.c.
|
||||||
|
19980222 code: added concurrencyused to qmail-send.c.
|
||||||
|
19980128 doc: added note to qmail-getpw.9 about ETXTBSY.
|
||||||
|
19980127 code: eliminated err_seenmail() in qmail-smtpd.c. tnx PO.
|
||||||
|
19980126 doc: used $DEFAULT in FAQ where possible.
|
||||||
|
19980126 code: added DEFAULT in qmail-local.
|
||||||
|
19980126 code: added -/ to qmail-pw2u.
|
||||||
|
19980126 code: revamped qmeopen() as qmesearch() with more sensible
|
||||||
|
semantics, separating dash from ext cleanly.
|
||||||
|
19980126 code: split qmeexists() out of qmeopen() in qmail-local.c.
|
||||||
|
19980126 code: introduced safeext in qmail-local.c.
|
||||||
|
19980126 code: changed ~alias to mode 2755, to put files into group
|
||||||
|
qmail rather than group nofiles under System V.
|
||||||
|
19980126 doc: switched to /var/qmail/rc in INSTALL*, UPGRADE, FAQ.
|
||||||
|
19980126 code: added rc.
|
||||||
|
19980119 doc: added .qmail creation warning to condredirect.1.
|
||||||
|
19980118 code: made auto_uids.c creation atomic in Makefile. tnx HHO.
|
||||||
|
19980118 doc: added PIC.*.
|
||||||
|
19980117 portability problem: Solaris 2.5.1 incorrectly converts
|
||||||
|
O_NDELAY into O_NONBLOCK for sockets, so that ndelay_off()
|
||||||
|
fails to undo ndelay_on(). impact: none, since all the network
|
||||||
|
readers here use select() via timeoutread(). fix: use
|
||||||
|
O_NONBLOCK if it is defined.
|
||||||
|
19980115 code: reformatted qmail-qmtpd.c.
|
||||||
|
19980115 doc: changed tcpcontrol references in FAQ.
|
||||||
|
19980115 doc: documented morercpthosts in qmail-qmtpd.9.
|
||||||
|
19980115 code: eliminated unused datetime in qmail-qmtpd.c.
|
||||||
|
19980115 code: eliminated sigalrm() in qmail-qmtpd.c.
|
||||||
|
19980115 code: used rcpthosts() in qmail-smtpd.c, qmail-qmtpd.c.
|
||||||
|
19980115 code: introduced rcpthosts.c.
|
||||||
|
19980115 code: added morercpthosts.cdb support to qmail-showctl.
|
||||||
|
19980115 code: added morercpthosts support to qmail-showctl.
|
||||||
|
19980115 code: do_lst now returns file-exists in qmail-showctl.
|
||||||
|
19980112 doc: documented morercpthosts in qmail-smtpd.9.
|
||||||
|
19980112 code: added qmail-newmrh.
|
||||||
|
19980112 code: used commands.c in qmail-popup.
|
||||||
|
19980112 code: used commands.c in qmail-pop3d.
|
||||||
|
19980112 code: introduced fakehelo in qmail-smtpd.
|
||||||
|
19980112 code: moved flagbarf setting out of bmfcheck().
|
||||||
|
19980112 code: allowed more address misformatting in qmail-smtpd.
|
||||||
|
19980112 code: eliminated qmail@pobox.com help address in qmail-smtpd.
|
||||||
|
19980112 code: reorganized qmail-smtpd.
|
||||||
|
19980112 code: reformatted qmail-smtpd.
|
||||||
|
19980112 code: used commands.c in qmail-smtpd.
|
||||||
|
19980112 code: switched from 0 to "" for no arg in commands().
|
||||||
|
19980112 code: added commands.c.
|
||||||
|
19971230 doc: added -s to FreeBSD commands in INSTALL.ids. tnx TM.
|
||||||
|
19971224 doc: added pointer to qmail pictures in README.
|
||||||
|
19971223 doc: added note in FAQ about qmail-pop3d using maildir.
|
||||||
|
19971219 code: added HOST2, HOST3, HOST4.
|
||||||
|
19971219 code: renamed extx as x in qmail-local.c.
|
||||||
|
19971219 doc: partitioned qmail-command.0.
|
||||||
|
19971219 doc: updated FAQ 4.3 to point to newer majordomo patches.
|
||||||
|
19971219 doc: eliminated qlist2 from FAQ.
|
||||||
|
19971219 doc: eliminated qlist discussion from SECURITY.
|
||||||
|
19971219 code: moved qlist, qlist2 to separate package.
|
||||||
|
19971213 doc: added FAQ 4.10 on qmail-users generally.
|
||||||
|
19971213 doc: added FAQ 4.9 on dealing with NFS outages.
|
||||||
|
19971031 doc: added Linux and FreeBSD commands to INSTALL.ids. tnx TM.
|
||||||
|
19971026 doc: added note about smtplf in qmail-smtpd.8. tnx S2S.
|
||||||
|
19971014 doc: some tweaks to THOUGHTS.
|
||||||
|
19971012 doc: used MAILER-DAEMON in UUCP example in INSTALL.
|
||||||
|
19971003 code: eliminated dataline and getln() from qmail-remote.c.
|
||||||
|
19971003 code: revamped blast() in qmail-remote.c.
|
||||||
|
19971002 doc: added FAQ entries for .forward and /etc/aliases.
|
||||||
|
19971002 doc: rewrote INSTALL.mbox and INSTALL.vsm.
|
||||||
|
19971002 doc: renamed INSTALL.qsmhook as INSTALL.vsm.
|
||||||
|
19971002 doc: emphasized the qmail-popup argv0 in FAQ.
|
||||||
|
19971001 doc: added dot-forward note to BLURB3.
|
||||||
|
19971001 doc: added more configuration notes to qmail-upgrade.9.
|
||||||
|
19971001 doc: added note in INSTALL.qsmhook about dot-forward.
|
||||||
|
19970930 code: token822_parse() now supports backslash as a quoting
|
||||||
|
character in atoms.
|
||||||
|
19970929 doc: suggested symbolic links in INSTALL.mbox.
|
||||||
|
19970925 doc: added note to INTERNALS about bounce stability.
|
||||||
|
19970925 doc: added section to THOUGHTS discussing CNAME lookups.
|
||||||
|
19970925 code: qmail-remote no longer does CNAME lookup on sender. tnx
|
||||||
|
C2F.
|
||||||
|
19970923 portability problem: under SCO OSR5, splogger needs socket
|
||||||
|
libraries. impact: couldn't compile. fix: socket.lib. tnx RB.
|
||||||
|
19970906 portability problem: under RISC/OS, Mail invokes sendmail -bm.
|
||||||
|
impact: can't send mail using Mail on RISC/OS. fix: ignore -bm.
|
||||||
|
tnx NW.
|
||||||
|
19970813 code: implemented databytes in qmail-qmtpd.
|
||||||
|
19970813 code: implemented databytes. tnx M4S for sample code.
|
||||||
|
19970813 code: replaced execvp() with execv() for sh in qmail-local.
|
||||||
|
19970813 doc: said in qmail-control.9 that recipientmap allows comments.
|
||||||
|
19970813 code: used strerr in qmail-local.c.
|
||||||
|
19970813 code: changed timeoutread(), timeoutwrite() interface.
|
||||||
|
19970813 code: eliminated shutdown() in timeoutread(), timeoutwrite().
|
||||||
|
19970813 code: revamped I/O in qmail-smtpd.c.
|
||||||
|
19970813 code: used timeoutread(), timeoutwrite() in qmail-smtpd.c.
|
||||||
|
19970813 code: simplified getcontrol() logic in qmail-remote.c; some
|
||||||
|
out-of-memory messages are now cannot-read-control messages.
|
||||||
|
19970813 code: eliminated scan_nbblong().
|
||||||
|
19970813 code: reformatted qmail-remote.c.
|
||||||
|
19970813 code: renamed flaganyrecipok as flagbother in qmail-remote.c.
|
||||||
|
19970813 code: integrated status report into quit() in qmail-remote.c.
|
||||||
|
19970813 code: revamped smtpcode() in qmail-remote.c.
|
||||||
|
19970813 code: added flagcritical in qmail-remote.c. eliminates
|
||||||
|
possible-duplicate warning if dot has not yet been sent.
|
||||||
|
19970813 code: revamped I/O in qmail-remote.c.
|
||||||
|
19970813 code: quit immediately after sending QUIT in qmail-remote.c.
|
||||||
|
19970813 code: made many more globals in qmail-remote.c.
|
||||||
|
19970813 code: switched qmail-remote.c from subfdin to home-grown.
|
||||||
|
19970813 code: switched qmail-remote.c from subfdout to subfdoutsmall.
|
||||||
|
19970813 code: added LAST support to qmail-pop3d.
|
||||||
|
19970812 code: changed qmail_close() success return from 0 to "".
|
||||||
|
19970812 code: revamped I/O in qmail-qmtpd.c.
|
||||||
|
19970812 code: added qmail-tcpok.
|
||||||
|
19970812 code: used strerr in maildirmake.c.
|
||||||
|
19970812 code: reformatted maildirmake.c.
|
||||||
|
19970812 code: printed qp in condredirect.c.
|
||||||
|
19970812 code: printed qqx in condredirect.c.
|
||||||
|
19970812 code: revamped I/O in condredirect.c.
|
||||||
|
19970812 code: reformatted condredirect.c.
|
||||||
|
19970812 code: used strerr in preline.c.
|
||||||
|
19970812 code: revamped I/O in preline.c.
|
||||||
|
19970812 code: reformatted preline.c.
|
||||||
|
19970812 code: printed qp in forward.c.
|
||||||
|
19970812 code: printed qqx in forward.c.
|
||||||
|
19970812 code: revamped I/O in forward.c.
|
||||||
|
19970812 code: used strerr in forward.c.
|
||||||
|
19970812 code: reformatted forward.c.
|
||||||
|
19970812 code: used strerr in predate.c.
|
||||||
|
19970812 code: forced failure in qmail-qmtpd if no recipients; saves
|
||||||
|
time for qmail-send.
|
||||||
|
19970812 code: added smtpd() to sendmail.c.
|
||||||
|
19970812 code: added mailq() to sendmail.c.
|
||||||
|
19970812 code: added die_usage() to sendmail.c.
|
||||||
|
19970812 code: reformatted sendmail.c.
|
||||||
|
19970812 code: used byte_zero() in qmail-popup.c.
|
||||||
|
19970812 code: reformatted qmail-popup.c.
|
||||||
|
19970812 code: eliminated unused header files in qmail-popup.c.
|
||||||
|
19970812 code: changed I/O system in qmail-popup.c to match qmail-pop3d.
|
||||||
|
19970812 doc: pointed people to the mailing list in INSTALL and UPGRADE.
|
||||||
|
19970810 code: added TXTBSY check to qmail-getpw.c. this gives vendors
|
||||||
|
the opportunity to make getpwnam() reliable.
|
||||||
|
19970810 code: moved non-deleted messages from new/ to cur/ in
|
||||||
|
qmail-pop3d. tnx to various people.
|
||||||
|
19970810 code: introduced list() in qmail-pop3d.c.
|
||||||
|
19970810 code: reformatted qmail-pop3d.c.
|
||||||
|
19970810 code: merged dataline and newname into line in qmail-pop3d.c.
|
||||||
|
19970810 code: chopped filenames in qmail-pop3d at colons for UIDL. tnx
|
||||||
|
to various people.
|
||||||
|
19970810 code: eliminated printint(), printlong() in qmail-pop3d.c.
|
||||||
|
19970810 code: revamped I/O in qmail-pop3d.c.
|
||||||
|
19970810 code: used timeoutread(), timeoutwrite() in qmail-pop3d.c.
|
||||||
|
19970810 code: eliminated die_prot() in qmail-pop3d.c.
|
||||||
|
19970810 code: eliminated unused header files in qmail-pop3d.c.
|
||||||
|
19970810 code: switched qmail-pop3d to use maildir.c. tnx MD.
|
||||||
|
19970809 code: added uid/gid printing to qmail-showctl. tnx PGF.
|
||||||
|
19970808 code: switched control.c from scan_nbblong to scan_ulong.
|
||||||
|
19970808 code: cleaned up wait_pid to use waitpid() when possible, and
|
||||||
|
to support at least one extra child otherwise.
|
||||||
|
19970807 code: in qmail-smtpd, treat long envelope addresses as a syntax
|
||||||
|
error, instead of waiting for qmail-queue to reject them.
|
||||||
|
19970803 code: changed condredirect, forward, qlist, qmail-inject,
|
||||||
|
qmail-local, qmail-qmtpd, qmail-send, qmail-smtpd, qreceipt for
|
||||||
|
new qmail_close() interface.
|
||||||
|
19970803 code: revised qmail_close() to handle qmail-queue exit codes.
|
||||||
|
19970802 doc: documented SMTP-related exit codes in qmail-queue.8.
|
||||||
|
19970802 doc: documented qmail-queue exit codes in qmail-queue.8.
|
||||||
|
19970802 code: revamped qmail-queue exit codes.
|
||||||
|
19970802 doc: noted linking restrictions in qmail-queue.8.
|
||||||
|
19970802 doc: rewrote INSTALL.mbox.
|
||||||
|
19970802 doc: split INSTALL.maildir off of INSTALL.mbox.
|
||||||
|
19970802 code: added /var/qmail/doc/ creation to qmail-hier.
|
||||||
|
19970802 doc: added ezmlm note to FAQ.
|
||||||
|
19970802 doc: replaced qlist blurbs with ezmlm blurbs in BLURB*.
|
||||||
|
19970802 doc: added various notes to qmail-start.9.
|
||||||
|
19970728 doc: eliminated RFC*.
|
||||||
|
19970714 doc: added daemontools notes to FAQ.
|
||||||
|
19970714 code: eliminated ESMTP parameter syntax checking.
|
||||||
|
19970701 doc: changed ``forwarded'' to ``resent'' in qmail-header.5.
|
||||||
|
19970629 code: reformatted constmap.c.
|
||||||
|
19970628 code: changed straynewline() message in qmail-smtpd.c to point
|
||||||
|
to http://pobox.com/~djb/smtplf.html. tnx RDM.
|
||||||
|
19970609 doc: added preline to vacation example in dot-qmail.9. tnx C2S.
|
||||||
|
19970421 code: cleaned up slurpclose to handle interrupts.
|
||||||
|
19970421 code: set qmail-popup to mode 711. tnx MD.
|
||||||
|
19970421 doc: fixed qmail-local -n example in dot-qmail.9.
|
||||||
19970415 version: qmail 1.01.
|
19970415 version: qmail 1.01.
|
||||||
19970414 doc: tightened up qmail-upgrade.7.
|
19970414 doc: tightened up qmail-upgrade.7.
|
||||||
19970414 code: rewrote rewrite().
|
19970414 code: rewrote rewrite().
|
||||||
|
|
|
||||||
180
FAQ
180
FAQ
|
|
@ -21,6 +21,10 @@
|
||||||
4.4. How do I use procmail with qmail?
|
4.4. How do I use procmail with qmail?
|
||||||
4.5. How do I use elm's filter with qmail?
|
4.5. How do I use elm's filter with qmail?
|
||||||
4.6. How do I create aliases with dots?
|
4.6. How do I create aliases with dots?
|
||||||
|
4.7. How do I use sendmail's .forward files with qmail?
|
||||||
|
4.8. How do I use sendmail's /etc/aliases with qmail?
|
||||||
|
4.9. How do I make qmail defer messages during NFS or NIS outages?
|
||||||
|
4.10. How do I change which account controls an address?
|
||||||
|
|
||||||
5. Setting up servers
|
5. Setting up servers
|
||||||
5.1. How do I run qmail-smtpd under tcpserver?
|
5.1. How do I run qmail-smtpd under tcpserver?
|
||||||
|
|
@ -31,7 +35,7 @@
|
||||||
|
|
||||||
6. Configuring MUAs to work with qmail
|
6. Configuring MUAs to work with qmail
|
||||||
6.1. How do I make BSD mail generate a Date with the local time zone?
|
6.1. How do I make BSD mail generate a Date with the local time zone?
|
||||||
6.2. How do I stop pine from crashing?
|
6.2. How do I make pine work with qmail?
|
||||||
6.3. How do I make MH work with qmail?
|
6.3. How do I make MH work with qmail?
|
||||||
6.4. How do I stop Sun's dtcm from hanging?
|
6.4. How do I stop Sun's dtcm from hanging?
|
||||||
|
|
||||||
|
|
@ -41,6 +45,8 @@
|
||||||
7.3. How do I rejuvenate a message?
|
7.3. How do I rejuvenate a message?
|
||||||
7.4. How do I organize a big network?
|
7.4. How do I organize a big network?
|
||||||
7.5. How do I back up and restore the queue disk?
|
7.5. How do I back up and restore the queue disk?
|
||||||
|
7.6. How do I run a supervised copy of qmail?
|
||||||
|
7.7. How do I avoid syslog?
|
||||||
|
|
||||||
8. Miscellany
|
8. Miscellany
|
||||||
8.1. How do I tell qmail to do more deliveries at once?
|
8.1. How do I tell qmail to do more deliveries at once?
|
||||||
|
|
@ -102,11 +108,11 @@ Answer: Put
|
||||||
|
|
||||||
into control/virtualdomains and
|
into control/virtualdomains and
|
||||||
|
|
||||||
|preline -df /usr/bin/uux - -r -gC -a"$SENDER" gonzo!rmail "($EXT2@$HOST)"
|
|preline -df /usr/bin/uux - -r -gC
|
||||||
|
-a"${SENDER:-MAILER-DAEMON}" gonzo!rmail "($DEFAULT@$HOST)"
|
||||||
|
|
||||||
into ~alias/.qmail-uucp-default. (For some UUCP software you will need
|
(all on one line) into ~alias/.qmail-uucp-default. (For some UUCP
|
||||||
to use -d instead of -df. Also, you may need to insert a space between
|
software you will need to use -d instead of -df.) If qmail-send is
|
||||||
-a and "$SENDER" for bounces to work properly.) If qmail-send is
|
|
||||||
running, give it a HUP.
|
running, give it a HUP.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -120,9 +126,9 @@ showed that a message was deferred for this reason. Why is qmail doing
|
||||||
CNAME lookups, anyway?
|
CNAME lookups, anyway?
|
||||||
|
|
||||||
Answer: The SMTP standard does not permit aliased hostnames, so qmail
|
Answer: The SMTP standard does not permit aliased hostnames, so qmail
|
||||||
has to do a CNAME lookup in DNS for every sender and recipient host. If
|
has to do a CNAME lookup in DNS for every recipient host. If the
|
||||||
the relevant DNS server is down, qmail defers the message. It will try
|
relevant DNS server is down, qmail defers the message. It will try again
|
||||||
again soon.
|
soon.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -135,7 +141,8 @@ an MX from af.mil to pokey.af.mil, but how do I get pokey to treat
|
||||||
af.mil as a name for the local host?
|
af.mil as a name for the local host?
|
||||||
|
|
||||||
Answer: Add af.mil to /var/qmail/control/locals and to
|
Answer: Add af.mil to /var/qmail/control/locals and to
|
||||||
/var/qmail/control/rcpthosts. If qmail-send is running, give it a HUP.
|
/var/qmail/control/rcpthosts. If qmail-send is running, give it a HUP
|
||||||
|
(or do svc -h /var/run/qmail if qmail is supervised).
|
||||||
|
|
||||||
|
|
||||||
3.2. How do I set up a virtual domain? I'd like any mail for
|
3.2. How do I set up a virtual domain? I'd like any mail for
|
||||||
|
|
@ -147,7 +154,8 @@ Answer: Put
|
||||||
nowhere.mil:bob
|
nowhere.mil:bob
|
||||||
|
|
||||||
into control/virtualdomains. Add nowhere.mil to control/rcpthosts. If
|
into control/virtualdomains. Add nowhere.mil to control/rcpthosts. If
|
||||||
qmail-send is running, give it a HUP.
|
qmail-send is running, give it a HUP (or do svc -h /var/run/qmail if
|
||||||
|
qmail is supervised).
|
||||||
|
|
||||||
Now mail for whatever@nowhere.mil will be delivered locally to
|
Now mail for whatever@nowhere.mil will be delivered locally to
|
||||||
bob-whatever. Bob can set up ~bob/.qmail-default to catch all the
|
bob-whatever. Bob can set up ~bob/.qmail-default to catch all the
|
||||||
|
|
@ -165,7 +173,8 @@ Answer: Put two lines into control/virtualdomains:
|
||||||
everywhere.org:bob-everywhere
|
everywhere.org:bob-everywhere
|
||||||
|
|
||||||
Add nowhere.mil and everywhere.org to control/rcpthosts. If qmail-send
|
Add nowhere.mil and everywhere.org to control/rcpthosts. If qmail-send
|
||||||
is running, give it a HUP.
|
is running, give it a HUP (or do svc -h /var/run/qmail if qmail is
|
||||||
|
supervised).
|
||||||
|
|
||||||
Now Bob can set up separate .qmail-nowhere-* and everywhere-* files. He
|
Now Bob can set up separate .qmail-nowhere-* and everywhere-* files. He
|
||||||
can even set up .qmail-nowhere-default and .qmail-everywhere-default.
|
can even set up .qmail-nowhere-default and .qmail-everywhere-default.
|
||||||
|
|
@ -191,21 +200,22 @@ forwarded to a bunch of people.
|
||||||
Answer: Put a list of addresses into ~me/.qmail-sos, one per line. Then
|
Answer: Put a list of addresses into ~me/.qmail-sos, one per line. Then
|
||||||
incoming mail for me-sos will be forwarded to each of those addresses.
|
incoming mail for me-sos will be forwarded to each of those addresses.
|
||||||
You should also touch ~me/.qmail-sos-owner so that bounces come back to
|
You should also touch ~me/.qmail-sos-owner so that bounces come back to
|
||||||
you rather than the original sender. If you want subscriptions to be
|
you rather than the original sender.
|
||||||
handled automatically, put
|
|
||||||
|
|
||||||
| qlist2 sos my.host.name
|
Alternative: ezmlm (http://pobox.com/~djb/ezmlm.html) is a modern
|
||||||
|
mailing list manager, supporting automatic subscriptions, confirmations,
|
||||||
into ~me/.qmail-sos-request. Anyone who wants to subscribe can simply
|
archives, fully automatic bounce handling (including warnings to
|
||||||
send a message to me-sos-request@my.host.name.
|
subscribers saying which messages they've missed), and more.
|
||||||
|
|
||||||
|
|
||||||
4.3. How do I use majordomo with qmail?
|
4.3. How do I use majordomo with qmail?
|
||||||
|
|
||||||
Answer: You need to patch majordomo so that it creates qmail-style
|
Answer: See ftp://ftp.eyrie.org/pub/software/majordomo/mjqmail and
|
||||||
lists. See ftp://koobera.math.uic.edu/pub/software/majordomo+qmail.gz.
|
http://www.qmail.org for various methods. majordomo 2.0 is expected to
|
||||||
Exception: qmsmac understands sendmail-style :include: files, so you
|
support qmail directly.
|
||||||
shouldn't patch majordomo if you're using qmsmac.
|
|
||||||
|
Beware that majordomo's lists are not crashproof.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
4.4. How do I use procmail with qmail?
|
4.4. How do I use procmail with qmail?
|
||||||
|
|
@ -237,6 +247,48 @@ Answer: Use .qmail-p:d:q:bach. Dots are converted to colons, and
|
||||||
uppercase is converted to lowercase.
|
uppercase is converted to lowercase.
|
||||||
|
|
||||||
|
|
||||||
|
4.7. How do I use sendmail's .forward files with qmail?
|
||||||
|
|
||||||
|
Answer: Install the dot-forward package
|
||||||
|
(http://pobox.com/~djb/dot-forward.html).
|
||||||
|
|
||||||
|
|
||||||
|
4.8. How do I use sendmail's /etc/aliases with qmail?
|
||||||
|
|
||||||
|
Answer: Install the fastforward package
|
||||||
|
(http://pobox.com/~djb/fastforward.html).
|
||||||
|
|
||||||
|
|
||||||
|
4.9. How do I make qmail defer messages during NFS or NIS outages? If
|
||||||
|
~joe suddenly disappears, I'd like mail for joe to be deferred.
|
||||||
|
|
||||||
|
Answer: Build a qmail-users database, so that qmail no longer checks
|
||||||
|
home directories and the password database. This takes three steps.
|
||||||
|
First, put your complete user list (including local and NIS passwords)
|
||||||
|
into /var/qmail/users/passwd. Second, run
|
||||||
|
|
||||||
|
# qmail-pw2u -h < /var/qmail/users/passwd > /var/qmail/users/assign
|
||||||
|
|
||||||
|
Here -h means that every user must have a home directory; if you happen
|
||||||
|
to run qmail-pw2u during an NFS outage, it will print an error message
|
||||||
|
and stop. Third, run
|
||||||
|
|
||||||
|
# qmail-newu
|
||||||
|
|
||||||
|
Make sure to rebuild the database whenever you change your user list.
|
||||||
|
|
||||||
|
|
||||||
|
4.10. How do I change which account controls an address? I set up
|
||||||
|
~alias/.qmail-www, but qmail is looking at ~www/.qmail instead.
|
||||||
|
|
||||||
|
Answer: If you do
|
||||||
|
|
||||||
|
# chown root ~www
|
||||||
|
|
||||||
|
then qmail will no longer consider www to be a user; see qmail-getpw.0.
|
||||||
|
For more precise control over address assignments, see qmail-users.0.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
5. Setting up servers
|
5. Setting up servers
|
||||||
|
|
||||||
|
|
@ -284,17 +336,20 @@ replacing 7770 and 2108 with the qmaild uid and nofiles gid. See
|
||||||
question 5.1 for more details.
|
question 5.1 for more details.
|
||||||
|
|
||||||
|
|
||||||
5.3. How do I set up qmail-pop3d?
|
5.3. How do I set up qmail-pop3d? My old POP server works with mbox
|
||||||
|
delivery; I'd like to switch to maildir delivery.
|
||||||
|
|
||||||
Answer: Four steps. First, install the checkpassword program
|
Answer: Four steps. First, install the checkpassword program
|
||||||
(http://pobox.com/~djb/checkpwd.html). Second, make sure you have a
|
(http://pobox.com/~djb/checkpwd.html). Second, make sure you have a
|
||||||
|
|
||||||
pop3 110/tcp
|
pop3 110/tcp
|
||||||
|
|
||||||
line in /etc/services. Third, put (all on one line)
|
line in /etc/services. Third, put (all on one line, including
|
||||||
|
qmail-popup twice)
|
||||||
|
|
||||||
pop3 stream tcp nowait root /var/qmail/bin/qmail-popup
|
pop3 stream tcp nowait root
|
||||||
qmail-popup YOURHOST /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir
|
/var/qmail/bin/qmail-popup qmail-popup
|
||||||
|
YOURHOST /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir
|
||||||
|
|
||||||
into /etc/inetd.conf, and give inetd a HUP; replace YOURHOST with your
|
into /etc/inetd.conf, and give inetd a HUP; replace YOURHOST with your
|
||||||
host's fully qualified domain name. Fourth, set up Maildir delivery for
|
host's fully qualified domain name. Fourth, set up Maildir delivery for
|
||||||
|
|
@ -315,8 +370,7 @@ otherwise an eavesdropper can steal passwords.
|
||||||
|
|
||||||
5.4. How do I allow selected clients to use this host as a relay? I see
|
5.4. How do I allow selected clients to use this host as a relay? I see
|
||||||
that qmail-smtpd rejects messages to any host not listed in
|
that qmail-smtpd rejects messages to any host not listed in
|
||||||
control/rcpthosts. I know I could entirely disable this feature by
|
control/rcpthosts.
|
||||||
removing control/rcpthosts, but I want to be more selective.
|
|
||||||
|
|
||||||
Answer: Three steps. First, install tcp-wrappers, available separately,
|
Answer: Three steps. First, install tcp-wrappers, available separately,
|
||||||
including hosts_options. Second, change your qmail-smtpd line in
|
including hosts_options. Second, change your qmail-smtpd line in
|
||||||
|
|
@ -336,21 +390,21 @@ ignores control/rcpthosts when RELAYCLIENT is set. (It also appends
|
||||||
RELAYCLIENT to each envelope recipient address. See question 5.5 for an
|
RELAYCLIENT to each envelope recipient address. See question 5.5 for an
|
||||||
application.)
|
application.)
|
||||||
|
|
||||||
Alternative procedure, if you are using tcpserver: Install tcpcontrol
|
Alternative procedure, if you are using tcpserver 0.80 or above: Create
|
||||||
(http://pobox.com/~djb/tcpcontrol.html). Create /etc/tcp.smtp containing
|
/etc/tcp.smtp containing
|
||||||
|
|
||||||
1.2.3.6:allow,RELAYCLIENT=""
|
1.2.3.6:allow,RELAYCLIENT=""
|
||||||
127.:allow,RELAYCLIENT=""
|
127.:allow,RELAYCLIENT=""
|
||||||
|
|
||||||
to allow clients with IP addresses 1.2.3.6 and 127.*. Run
|
to allow clients with IP addresses 1.2.3.6 and 127.*. Run
|
||||||
|
|
||||||
tcpmakectl /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
|
tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
|
||||||
|
|
||||||
Finally, insert
|
Finally, insert
|
||||||
|
|
||||||
tcpcontrol /etc/tcp.smtp.cdb
|
-x /etc/tcp.smtp.cdb
|
||||||
|
|
||||||
before /var/qmail/bin/qmail-smtpd in your tcpserver line.
|
after tcpserver in your qmail-smtpd invocation.
|
||||||
|
|
||||||
|
|
||||||
5.5. How do I fix up messages from broken SMTP clients?
|
5.5. How do I fix up messages from broken SMTP clients?
|
||||||
|
|
@ -358,7 +412,7 @@ before /var/qmail/bin/qmail-smtpd in your tcpserver line.
|
||||||
Answer: Three steps. First, put
|
Answer: Three steps. First, put
|
||||||
|
|
||||||
| [ "@$HOST" = "@fixme" ] || ( echo Permission denied; exit 100 )
|
| [ "@$HOST" = "@fixme" ] || ( echo Permission denied; exit 100 )
|
||||||
| qmail-inject -f "$SENDER" -- "$EXT2"
|
| qmail-inject -f "$SENDER" -- "$DEFAULT"
|
||||||
|
|
||||||
into ~alias/.qmail-fixup-default. Second, put
|
into ~alias/.qmail-fixup-default. Second, put
|
||||||
|
|
||||||
|
|
@ -371,12 +425,12 @@ string ``@fixme'':
|
||||||
tcp-env: 1.2.3.6, 1.2.3.7: setenv = RELAYCLIENT @fixme
|
tcp-env: 1.2.3.6, 1.2.3.7: setenv = RELAYCLIENT @fixme
|
||||||
|
|
||||||
Here 1.2.3.6 and 1.2.3.7 are the clients' IP addresses. If you are using
|
Here 1.2.3.6 and 1.2.3.7 are the clients' IP addresses. If you are using
|
||||||
tcpserver and tcpcontrol instead of inetd and tcpd, put
|
tcpserver instead of inetd and tcpd, put
|
||||||
|
|
||||||
1.2.3.6:allow,RELAYCLIENT="@fixme"
|
1.2.3.6:allow,RELAYCLIENT="@fixme"
|
||||||
1.2.3.7:allow,RELAYCLIENT="@fixme"
|
1.2.3.7:allow,RELAYCLIENT="@fixme"
|
||||||
|
|
||||||
into /etc/tcp.smtp, and run tcpmakectl as in question 5.4.
|
into /etc/tcp.smtp, and run tcprules as in question 5.4.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -395,8 +449,7 @@ into your .mailrc or your system-wide Mail.rc. Beware that BSD mail is
|
||||||
neither secure nor reliable.
|
neither secure nor reliable.
|
||||||
|
|
||||||
|
|
||||||
6.2. How do I stop pine from crashing? When I ask any version of pine
|
6.2. How do I make pine work with qmail?
|
||||||
past 3.91 to send mail, it crashes.
|
|
||||||
|
|
||||||
Answer: Put
|
Answer: Put
|
||||||
|
|
||||||
|
|
@ -432,14 +485,25 @@ sendmail, it was always tricky to kill sendmail without risking the loss
|
||||||
of current deliveries; what should I do with qmail-send?
|
of current deliveries; what should I do with qmail-send?
|
||||||
|
|
||||||
Answer: Go ahead and kill the qmail-send process. It will shut down
|
Answer: Go ahead and kill the qmail-send process. It will shut down
|
||||||
cleanly. Wait for ``exiting'' to show up in the log. To restart it, run
|
cleanly. Wait for ``exiting'' to show up in the log. To restart qmail,
|
||||||
qmail-start the same way as it's run from your system boot scripts.
|
run /var/qmail/rc the same way it is run from your system boot scripts,
|
||||||
|
with the proper PATH, resource limits, etc.
|
||||||
|
|
||||||
|
Alternative, if qmail is supervised: svc -t /var/run/qmail. The
|
||||||
|
supervise process will kill qmail, wait for it to stop, and restart it.
|
||||||
|
Use -d instead of -t if you don't want qmail to restart automatically;
|
||||||
|
to manually restart it, use -u.
|
||||||
|
|
||||||
|
|
||||||
7.2. How do I manually run the queue? I'd like qmail to try delivering
|
7.2. How do I manually run the queue? I'd like qmail to try delivering
|
||||||
all the remote messages right now.
|
all the remote messages right now.
|
||||||
|
|
||||||
Answer: Give the qmail-send process an ALRM.
|
Answer: Give the qmail-send process an ALRM. (Do svc -a /var/run/qmail
|
||||||
|
if qmail is supervised.)
|
||||||
|
|
||||||
|
You may want to run qmail-tcpok first, to guarantee that qmail-remote
|
||||||
|
will try all addresses. Normally, if an address fails repeatedly,
|
||||||
|
qmail-remote leaves it alone for an hour.
|
||||||
|
|
||||||
|
|
||||||
7.3. How do I rejuvenate a message? Somebody broke into Eric's computer
|
7.3. How do I rejuvenate a message? Somebody broke into Eric's computer
|
||||||
|
|
@ -521,6 +585,42 @@ battery backups. RAID boxes let you replace dead disks without losing
|
||||||
any data.
|
any data.
|
||||||
|
|
||||||
|
|
||||||
|
7.6. How do I run a supervised copy of qmail? svc sounds useful.
|
||||||
|
|
||||||
|
Answer: Install daemontools (http://pobox.com/~djb/daemontools.html).
|
||||||
|
Create a /var/run/qmail directory. Change
|
||||||
|
|
||||||
|
/var/qmail/rc
|
||||||
|
|
||||||
|
to
|
||||||
|
|
||||||
|
supervise /var/run/qmail /var/qmail/rc
|
||||||
|
|
||||||
|
in your boot scripts. Make sure that supervise is in the startup PATH.
|
||||||
|
Now you can use svc to stop or restart qmail, and svstat to check
|
||||||
|
whether qmail is running.
|
||||||
|
|
||||||
|
|
||||||
|
7.7. How do I avoid syslog? It chews up a lot of CPU time and isn't
|
||||||
|
reliable.
|
||||||
|
|
||||||
|
Answer: Install daemontools (http://pobox.com/~djb/daemontools.html).
|
||||||
|
Make a /var/log/qmail directory, owned by qmaill, mode 2700. Do
|
||||||
|
|
||||||
|
qmail-start ./Mailbox /usr/local/bin/accustamp \
|
||||||
|
| setuser qmaill /usr/local/bin/cyclog /var/log/qmail &
|
||||||
|
|
||||||
|
in /var/qmail/rc.
|
||||||
|
|
||||||
|
If you are logging tcpserver connections, make a /var/log/smtpd
|
||||||
|
directory, and use cyclog /var/log/smtpd for tcpserver. You shouldn't
|
||||||
|
run several copies of cyclog with the same log directory.
|
||||||
|
|
||||||
|
By default, cyclog keeps 10 automatically rotated log files, each
|
||||||
|
containing up to 100KB of log data. To keep 20 files with 1MB each, use
|
||||||
|
cyclog -s 1000000 -n 20.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
8. Miscellany
|
8. Miscellany
|
||||||
|
|
||||||
|
|
|
||||||
55
FILES
55
FILES
|
|
@ -9,23 +9,26 @@ INSTALL.alias
|
||||||
INSTALL.boot
|
INSTALL.boot
|
||||||
INSTALL.ctl
|
INSTALL.ctl
|
||||||
INSTALL.ids
|
INSTALL.ids
|
||||||
|
INSTALL.maildir
|
||||||
INSTALL.mbox
|
INSTALL.mbox
|
||||||
INSTALL.qsmhook
|
INSTALL.vsm
|
||||||
UPGRADE
|
UPGRADE
|
||||||
THOUGHTS
|
THOUGHTS
|
||||||
TODO
|
TODO
|
||||||
THANKS
|
THANKS
|
||||||
CHANGES
|
CHANGES
|
||||||
RFCHCSC
|
|
||||||
RFCLOOPS
|
|
||||||
RFCMXPS
|
|
||||||
RFCNETSTR
|
|
||||||
RFCNRUDT
|
|
||||||
RFCQMTP
|
|
||||||
RFCQSBMF
|
|
||||||
RFCVERP
|
|
||||||
SECURITY
|
SECURITY
|
||||||
INTERNALS
|
INTERNALS
|
||||||
|
SENDMAIL
|
||||||
|
PIC.local2alias
|
||||||
|
PIC.local2ext
|
||||||
|
PIC.local2local
|
||||||
|
PIC.local2rem
|
||||||
|
PIC.local2virt
|
||||||
|
PIC.nullclient
|
||||||
|
PIC.relaybad
|
||||||
|
PIC.relaygood
|
||||||
|
PIC.rem2local
|
||||||
FILES
|
FILES
|
||||||
VERSION
|
VERSION
|
||||||
SYSDEPS
|
SYSDEPS
|
||||||
|
|
@ -58,7 +61,6 @@ mailsubj.1
|
||||||
mbox.5
|
mbox.5
|
||||||
preline.1
|
preline.1
|
||||||
qbiff.1
|
qbiff.1
|
||||||
qlist.1
|
|
||||||
qmail-clean.8
|
qmail-clean.8
|
||||||
qmail-command.8
|
qmail-command.8
|
||||||
qmail-control.9
|
qmail-control.9
|
||||||
|
|
@ -69,10 +71,13 @@ qmail-limits.9
|
||||||
qmail-local.8
|
qmail-local.8
|
||||||
qmail-log.5
|
qmail-log.5
|
||||||
qmail-lspawn.8
|
qmail-lspawn.8
|
||||||
|
qmail-newmrh.9
|
||||||
qmail-newu.9
|
qmail-newu.9
|
||||||
qmail-pop3d.8
|
qmail-pop3d.8
|
||||||
qmail-popup.8
|
qmail-popup.8
|
||||||
qmail-pw2u.9
|
qmail-pw2u.9
|
||||||
|
qmail-qmqpc.8
|
||||||
|
qmail-qmqpd.8
|
||||||
qmail-qmtpd.8
|
qmail-qmtpd.8
|
||||||
qmail-qread.8
|
qmail-qread.8
|
||||||
qmail-qstat.8
|
qmail-qstat.8
|
||||||
|
|
@ -83,24 +88,28 @@ qmail-send.9
|
||||||
qmail-showctl.8
|
qmail-showctl.8
|
||||||
qmail-smtpd.8
|
qmail-smtpd.8
|
||||||
qmail-start.9
|
qmail-start.9
|
||||||
|
qmail-tcpok.8
|
||||||
qmail-tcpto.8
|
qmail-tcpto.8
|
||||||
qmail-upgrade.9
|
|
||||||
qmail-users.9
|
qmail-users.9
|
||||||
qmail.7
|
qmail.7
|
||||||
qreceipt.1
|
qreceipt.1
|
||||||
splogger.8
|
splogger.8
|
||||||
tcp-env.1
|
tcp-env.1
|
||||||
|
config.sh
|
||||||
|
config-fast.sh
|
||||||
qmail-clean.c
|
qmail-clean.c
|
||||||
qmail-config.sh
|
|
||||||
qmail-getpw.c
|
qmail-getpw.c
|
||||||
qmail-hier.c
|
qmail-hier.c
|
||||||
qmail-inject.c
|
qmail-inject.c
|
||||||
qmail-local.c
|
qmail-local.c
|
||||||
qmail-lspawn.c
|
qmail-lspawn.c
|
||||||
|
qmail-newmrh.c
|
||||||
qmail-newu.c
|
qmail-newu.c
|
||||||
qmail-pop3d.c
|
qmail-pop3d.c
|
||||||
qmail-popup.c
|
qmail-popup.c
|
||||||
qmail-pw2u.c
|
qmail-pw2u.c
|
||||||
|
qmail-qmqpc.c
|
||||||
|
qmail-qmqpd.c
|
||||||
qmail-qmtpd.c
|
qmail-qmtpd.c
|
||||||
qmail-qread.c
|
qmail-qread.c
|
||||||
qmail-qstat.sh
|
qmail-qstat.sh
|
||||||
|
|
@ -111,6 +120,7 @@ qmail-send.c
|
||||||
qmail-showctl.c
|
qmail-showctl.c
|
||||||
qmail-smtpd.c
|
qmail-smtpd.c
|
||||||
qmail-start.c
|
qmail-start.c
|
||||||
|
qmail-tcpok.c
|
||||||
qmail-tcpto.c
|
qmail-tcpto.c
|
||||||
spawn.c
|
spawn.c
|
||||||
dnscname.c
|
dnscname.c
|
||||||
|
|
@ -122,7 +132,6 @@ hostname.c
|
||||||
ipmeprint.c
|
ipmeprint.c
|
||||||
tcp-env.c
|
tcp-env.c
|
||||||
sendmail.c
|
sendmail.c
|
||||||
qlist.c
|
|
||||||
qreceipt.c
|
qreceipt.c
|
||||||
qsmhook.c
|
qsmhook.c
|
||||||
qbiff.c
|
qbiff.c
|
||||||
|
|
@ -137,13 +146,14 @@ splogger.c
|
||||||
qail.sh
|
qail.sh
|
||||||
elq.sh
|
elq.sh
|
||||||
pinq.sh
|
pinq.sh
|
||||||
qlist2.sh
|
|
||||||
qmail-upq.sh
|
qmail-upq.sh
|
||||||
datemail.sh
|
datemail.sh
|
||||||
mailsubj.sh
|
mailsubj.sh
|
||||||
qlx.h
|
qlx.h
|
||||||
constmap.h
|
rcpthosts.h
|
||||||
constmap.c
|
rcpthosts.c
|
||||||
|
commands.h
|
||||||
|
commands.c
|
||||||
dnsdoe.h
|
dnsdoe.h
|
||||||
dnsdoe.c
|
dnsdoe.c
|
||||||
fmtqfn.h
|
fmtqfn.h
|
||||||
|
|
@ -171,6 +181,16 @@ trynpbg1.c
|
||||||
trysyslog.c
|
trysyslog.c
|
||||||
conf-cc
|
conf-cc
|
||||||
conf-ld
|
conf-ld
|
||||||
|
home.sh
|
||||||
|
home+df.sh
|
||||||
|
proc.sh
|
||||||
|
proc+df.sh
|
||||||
|
binm1.sh
|
||||||
|
binm2.sh
|
||||||
|
binm3.sh
|
||||||
|
binm1+df.sh
|
||||||
|
binm2+df.sh
|
||||||
|
binm3+df.sh
|
||||||
find-systype.sh
|
find-systype.sh
|
||||||
make-compile.sh
|
make-compile.sh
|
||||||
make-load.sh
|
make-load.sh
|
||||||
|
|
@ -348,7 +368,6 @@ fmt_ulong.c
|
||||||
scan.h
|
scan.h
|
||||||
scan_ulong.c
|
scan_ulong.c
|
||||||
scan_8long.c
|
scan_8long.c
|
||||||
scan_nbblong.c
|
|
||||||
slurpclose.h
|
slurpclose.h
|
||||||
slurpclose.c
|
slurpclose.c
|
||||||
quote.h
|
quote.h
|
||||||
|
|
@ -399,3 +418,5 @@ maildir.5
|
||||||
maildir.h
|
maildir.h
|
||||||
maildir.c
|
maildir.c
|
||||||
tcp-environ.5
|
tcp-environ.5
|
||||||
|
constmap.h
|
||||||
|
constmap.c
|
||||||
|
|
|
||||||
84
INSTALL
84
INSTALL
|
|
@ -16,80 +16,100 @@ Installation steps that won't interfere with sendmail:
|
||||||
|
|
||||||
1. Create the qmail home directory:
|
1. Create the qmail home directory:
|
||||||
# mkdir /var/qmail
|
# mkdir /var/qmail
|
||||||
|
|
||||||
2. Read INSTALL.ids. You must set up the qmail group and the qmail
|
2. Read INSTALL.ids. You must set up the qmail group and the qmail
|
||||||
users before compiling the programs.
|
users before compiling the programs.
|
||||||
3. Compile the programs:
|
|
||||||
# make
|
3. Compile the programs and create the qmail directory tree:
|
||||||
4. Create the formatted man pages, *.0:
|
|
||||||
# make man
|
|
||||||
5. Create the qmail directory tree:
|
|
||||||
# make setup
|
# make setup
|
||||||
6. Run instcheck to make sure it doesn't print any warnings:
|
|
||||||
|
4. Run instcheck to make sure it doesn't print any warnings:
|
||||||
# make check
|
# make check
|
||||||
7. Read INSTALL.ctl and FAQ. Minimal survival command:
|
|
||||||
# ./qmail-config
|
5. Read INSTALL.ctl and FAQ. Minimal survival command:
|
||||||
8. Read INSTALL.alias. Minimal survival command:
|
# ./config
|
||||||
|
|
||||||
|
6. Read INSTALL.alias. Minimal survival command:
|
||||||
# (cd ~alias; touch .qmail-postmaster .qmail-mailer-daemon .qmail-root)
|
# (cd ~alias; touch .qmail-postmaster .qmail-mailer-daemon .qmail-root)
|
||||||
# chmod 644 ~alias/.qmail*
|
# chmod 644 ~alias/.qmail*
|
||||||
9. Read INSTALL.mbox.
|
|
||||||
10. Read qmail-upgrade.0. This is what your users will need to know
|
7. Read INSTALL.mbox and INSTALL.vsm.
|
||||||
about the switch from sendmail to qmail.
|
|
||||||
|
8. Read INSTALL.maildir.
|
||||||
|
|
||||||
|
9. Read SENDMAIL. This is what your users will want to know about the
|
||||||
|
switch from sendmail to qmail.
|
||||||
|
|
||||||
|
10. Copy /var/qmail/boot/home (or proc) to /var/qmail/rc.
|
||||||
|
|
||||||
|
|
||||||
Pre-upgrade tests:
|
Pre-upgrade tests:
|
||||||
|
|
||||||
11. Enable deliveries of messages injected into qmail:
|
11. Enable deliveries of messages injected into qmail:
|
||||||
# env - PATH="/var/qmail/bin:$PATH" \
|
# /var/qmail/rc &
|
||||||
qmail-start ./Mailbox splogger qmail &
|
|
||||||
Make sure to include the ./ in ./Mailbox.
|
|
||||||
12. Look for a
|
12. Look for a
|
||||||
qmail: running
|
qmail: status: local 0/10 remote 0/20
|
||||||
line in syslog. qmail-send always prints either ``cannot start'' or
|
line in syslog. qmail-send always prints either ``cannot start'' or
|
||||||
``running''. (The big number is a splogger timestamp.)
|
``status''. (The big number is a splogger timestamp.)
|
||||||
|
|
||||||
13. Do a ps and look for the qmail daemons. There should be four of
|
13. Do a ps and look for the qmail daemons. There should be four of
|
||||||
them, all idle: qmail-send, running as qmails; qmail-lspawn, running
|
them, all idle: qmail-send, running as qmails; qmail-lspawn, running
|
||||||
as root; qmail-rspawn, running as qmailr; and qmail-clean, running
|
as root; qmail-rspawn, running as qmailr; and qmail-clean, running
|
||||||
as qmailq. You will also see the splogger process.
|
as qmailq. You will also see splogger, running as qmaill.
|
||||||
|
|
||||||
14. Local-local test: Send yourself an empty message. (Replace ``me''
|
14. Local-local test: Send yourself an empty message. (Replace ``me''
|
||||||
with your username. Make sure to include the ``to:'' colon.)
|
with your username. Make sure to include the ``to:'' colon.)
|
||||||
% echo to: me | /var/qmail/bin/qmail-inject
|
% echo to: me | /var/qmail/bin/qmail-inject
|
||||||
The message will show up immediately in ~/Mailbox, and syslog will
|
The message will show up immediately in your mailbox, and syslog
|
||||||
show something like this:
|
will show something like this:
|
||||||
qmail: new msg 53
|
qmail: new msg 53
|
||||||
qmail: info msg 53: bytes 246 from <me@domain> qp 20345 uid 666
|
qmail: info msg 53: bytes 246 from <me@domain> qp 20345 uid 666
|
||||||
qmail: starting delivery 1: msg 53 to local me@domain
|
qmail: starting delivery 1: msg 53 to local me@domain
|
||||||
|
qmail: status: local 1/10 remote 0/20
|
||||||
qmail: delivery 1: success: did_1+0+0/
|
qmail: delivery 1: success: did_1+0+0/
|
||||||
|
qmail: status: local 0/10 remote 0/20
|
||||||
qmail: end msg 53
|
qmail: end msg 53
|
||||||
(53 is an inode number; 20345 is a process ID; your numbers will
|
(53 is an inode number; 20345 is a process ID; your numbers will
|
||||||
probably be different.)
|
probably be different.)
|
||||||
|
|
||||||
15. Local-error test: Send a message to a nonexistent local address.
|
15. Local-error test: Send a message to a nonexistent local address.
|
||||||
% echo to: nonexistent | /var/qmail/bin/qmail-inject
|
% echo to: nonexistent | /var/qmail/bin/qmail-inject
|
||||||
qmail: new msg 53
|
qmail: new msg 53
|
||||||
qmail: info msg 53: bytes 246 from <me@domain> qp 20351 uid 666
|
qmail: info msg 53: bytes 246 from <me@domain> qp 20351 uid 666
|
||||||
qmail: starting delivery 2: msg 53 to local nonexistent@domain
|
qmail: starting delivery 2: msg 53 to local nonexistent@domain
|
||||||
|
qmail: status: local 1/10 remote 0/20
|
||||||
qmail: delivery 2: failure: No_such_address.__#5.1.1_/
|
qmail: delivery 2: failure: No_such_address.__#5.1.1_/
|
||||||
|
qmail: status: local 0/10 remote 0/20
|
||||||
qmail: bounce msg 53 qp 20357
|
qmail: bounce msg 53 qp 20357
|
||||||
qmail: end msg 53
|
qmail: end msg 53
|
||||||
qmail: new msg 54
|
qmail: new msg 54
|
||||||
qmail: info msg 54: bytes 743 from <> qp 20357 uid 666
|
qmail: info msg 54: bytes 743 from <> qp 20357 uid 666
|
||||||
qmail: starting delivery 3: msg 54 to local me@domain
|
qmail: starting delivery 3: msg 54 to local me@domain
|
||||||
|
qmail: status: local 1/10 remote 0/20
|
||||||
qmail: delivery 3: success: did_1+0+0/
|
qmail: delivery 3: success: did_1+0+0/
|
||||||
|
qmail: status: local 0/10 remote 0/20
|
||||||
qmail: end msg 54
|
qmail: end msg 54
|
||||||
You will now have a bounce message in ~/Mailbox.
|
You will now have a bounce message in your mailbox.
|
||||||
|
|
||||||
16. Local-remote test: Send an empty message to your account on another
|
16. Local-remote test: Send an empty message to your account on another
|
||||||
machine.
|
machine.
|
||||||
% echo to: me@wherever | /var/qmail/bin/qmail-inject
|
% echo to: me@wherever | /var/qmail/bin/qmail-inject
|
||||||
qmail: new msg 53
|
qmail: new msg 53
|
||||||
qmail: info msg 53: bytes 246 from <me@domain> qp 20372 uid 666
|
qmail: info msg 53: bytes 246 from <me@domain> qp 20372 uid 666
|
||||||
qmail: starting delivery 4: msg 53 to remote me@wherever
|
qmail: starting delivery 4: msg 53 to remote me@wherever
|
||||||
|
qmail: status: local 0/10 remote 1/20
|
||||||
qmail: delivery 4: success: 1.2.3.4_accepted_message./...
|
qmail: delivery 4: success: 1.2.3.4_accepted_message./...
|
||||||
|
qmail: status: local 0/10 remote 0/20
|
||||||
qmail: end msg 53
|
qmail: end msg 53
|
||||||
There will be a pause between ``starting delivery'' and ``success'';
|
There will be a pause between ``starting delivery'' and ``success'';
|
||||||
SMTP is slow. Check that the message is in your mailbox on the other
|
SMTP is slow. Check that the message is in your mailbox on the other
|
||||||
machine.
|
machine.
|
||||||
|
|
||||||
17. Local-postmaster test: Send mail to postmaster, any capitalization.
|
17. Local-postmaster test: Send mail to postmaster, any capitalization.
|
||||||
% echo to: POSTmaster | /var/qmail/bin/qmail-inject
|
% echo to: POSTmaster | /var/qmail/bin/qmail-inject
|
||||||
Look for the message in ~alias/Mailbox.
|
Look for the message in the alias mailbox, normally ~alias/Mailbox.
|
||||||
|
|
||||||
18. Double-bounce test: Send a message with a completely bad envelope.
|
18. Double-bounce test: Send a message with a completely bad envelope.
|
||||||
% /var/qmail/bin/qmail-inject -f nonexistent
|
% /var/qmail/bin/qmail-inject -f nonexistent
|
||||||
To: unknownuser
|
To: unknownuser
|
||||||
|
|
@ -98,7 +118,8 @@ Pre-upgrade tests:
|
||||||
This is a test. This is only a test.
|
This is a test. This is only a test.
|
||||||
%
|
%
|
||||||
(Use end-of-file, not dot, to end the message.) Look for the double
|
(Use end-of-file, not dot, to end the message.) Look for the double
|
||||||
bounce in ~alias/Mailbox.
|
bounce in the alias mailbox.
|
||||||
|
|
||||||
19. Group membership test:
|
19. Group membership test:
|
||||||
% cat > ~me/.qmail-groups
|
% cat > ~me/.qmail-groups
|
||||||
|groups >> MYGROUPS; exit 0
|
|groups >> MYGROUPS; exit 0
|
||||||
|
|
@ -112,28 +133,35 @@ Upgrading from sendmail to qmail:
|
||||||
|
|
||||||
20. Read INSTALL.boot. You must replace the sendmail invocation in your
|
20. Read INSTALL.boot. You must replace the sendmail invocation in your
|
||||||
boot scripts with an appropriate qmail invocation.
|
boot scripts with an appropriate qmail invocation.
|
||||||
|
|
||||||
21. Kill the sendmail daemon. You should first kill -STOP the daemon; if
|
21. Kill the sendmail daemon. You should first kill -STOP the daemon; if
|
||||||
any children are running, you should kill -CONT, wait, kill -STOP
|
any children are running, you should kill -CONT, wait, kill -STOP
|
||||||
again, and repeat ad nauseam. If there aren't any children, kill
|
again, and repeat ad nauseam. If there aren't any children, kill
|
||||||
-TERM and then kill -CONT.
|
-TERM and then kill -CONT.
|
||||||
|
|
||||||
22. Replace sendmail with a link to qmail's ``sendmail'' wrapper:
|
22. Replace sendmail with a link to qmail's ``sendmail'' wrapper:
|
||||||
# mv /usr/lib/sendmail /usr/lib/sendmail.bak
|
# mv /usr/lib/sendmail /usr/lib/sendmail.bak
|
||||||
# ln -s /var/qmail/bin/sendmail /usr/lib/sendmail
|
# ln -s /var/qmail/bin/sendmail /usr/lib/sendmail
|
||||||
|
|
||||||
23. Set up qmail-smtpd in /etc/inetd.conf (all on one line):
|
23. Set up qmail-smtpd in /etc/inetd.conf (all on one line):
|
||||||
smtp stream tcp nowait qmaild /var/qmail/bin/tcp-env
|
smtp stream tcp nowait qmaild /var/qmail/bin/tcp-env
|
||||||
tcp-env /var/qmail/bin/qmail-smtpd
|
tcp-env /var/qmail/bin/qmail-smtpd
|
||||||
Also comment out comsat in /etc/inetd.conf.
|
Also comment out comsat in /etc/inetd.conf.
|
||||||
|
|
||||||
24. Reboot. (Or kill -HUP your inetd and make sure the qmail daemons
|
24. Reboot. (Or kill -HUP your inetd and make sure the qmail daemons
|
||||||
are running.)
|
are running.)
|
||||||
|
|
||||||
25. Try to flush the sendmail queue:
|
25. Try to flush the sendmail queue:
|
||||||
# /usr/lib/sendmail.bak -q
|
# /usr/lib/sendmail.bak -q
|
||||||
You can safely run sendmail.bak -q (or even sendmail.bak -q15m)
|
You can safely run sendmail.bak -q (or even sendmail.bak -q15m)
|
||||||
while qmail is running. Do this until the sendmail queue is empty.
|
while qmail is running. Do this until the sendmail queue is empty.
|
||||||
This may take several days.
|
This may take several days.
|
||||||
|
|
||||||
26. Disable all the sendmail and binmail programs in your system. The
|
26. Disable all the sendmail and binmail programs in your system. The
|
||||||
safest approach is to chmod 0 everything. Some locations to check:
|
safest approach is to chmod 0 everything. Some locations to check:
|
||||||
/usr/sbin/sendmail, /usr/lib/sendmail.bak, /usr/lib/sendmail.mx,
|
/usr/sbin/sendmail, /usr/lib/sendmail.bak, /usr/lib/sendmail.mx,
|
||||||
/bin/mail, /usr/libexec/mail.local.
|
/bin/mail, /usr/libexec/mail.local.
|
||||||
|
|
||||||
27. Make sure that ``mail'' still invokes a reasonable mailer. Under
|
27. Make sure that ``mail'' still invokes a reasonable mailer. Under
|
||||||
SVR4 you may want to link mail to mailx.
|
SVR4 you may want to link mail to mailx.
|
||||||
|
|
||||||
|
|
@ -166,16 +194,20 @@ Post-upgrade tests (can be done immediately after step 24):
|
||||||
Connection closed by foreign host.
|
Connection closed by foreign host.
|
||||||
%
|
%
|
||||||
Look for the message in your mailbox.
|
Look for the message in your mailbox.
|
||||||
|
|
||||||
29. Remote-local test: Send yourself some mail from another machine.
|
29. Remote-local test: Send yourself some mail from another machine.
|
||||||
|
|
||||||
30. Remote-error test: I think you can figure this one out.
|
30. Remote-error test: I think you can figure this one out.
|
||||||
|
|
||||||
31. UA test: Try sending mail, first to a local account, then to a
|
31. UA test: Try sending mail, first to a local account, then to a
|
||||||
remote account, with your normal user agent.
|
remote account, with your normal user agent.
|
||||||
|
|
||||||
32. Remote-postmaster test: Send mail from another machine to
|
32. Remote-postmaster test: Send mail from another machine to
|
||||||
PoStMaStEr@domain. Look for the message in ~alias/Mailbox.
|
PoStMaStEr@domain. Look for the message in the alias mailbox.
|
||||||
|
|
||||||
|
|
||||||
That's it! To report success:
|
That's it! To report success:
|
||||||
% ( echo 'First M. Last'; cat `cat SYSDEPS` ) \
|
% ( echo 'First M. Last'; cat `cat SYSDEPS` ) \
|
||||||
| mail djb-qst@koobera.math.uic.edu
|
| mail djb-qst@cr.yp.to
|
||||||
Replace First M. Last with your name. If you have questions about qmail,
|
Replace First M. Last with your name. If you have questions about qmail,
|
||||||
contact qmail@pobox.com.
|
join the qmail mailing list; see http://pobox.com/~djb/qmail.html.
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ qmail lets each user control all addresses of the form user-anything.
|
||||||
Addresses that don't start with a username are controlled by a special
|
Addresses that don't start with a username are controlled by a special
|
||||||
user, alias. Delivery instructions for foo go into ~alias/.qmail-foo;
|
user, alias. Delivery instructions for foo go into ~alias/.qmail-foo;
|
||||||
delivery instructions for user-foo go into ~user/.qmail-foo. See
|
delivery instructions for user-foo go into ~user/.qmail-foo. See
|
||||||
qmail-upgrade.0 and dot-qmail.0 for the full story.
|
dot-qmail.0 for the full story.
|
||||||
|
|
||||||
qmail doesn't have any built-in support for /etc/aliases. If you have a
|
qmail doesn't have any built-in support for /etc/aliases. If you have a
|
||||||
big /etc/aliases and you'd like to keep it, install the qmsmac package,
|
big /etc/aliases and you'd like to keep it, install the fastforward
|
||||||
available separately. /etc/aliases should already include the aliases
|
package, available separately. /etc/aliases should already include the
|
||||||
discussed below---Postmaster, MAILER-DAEMON, and root.
|
aliases discussed below---Postmaster, MAILER-DAEMON, and root.
|
||||||
|
|
||||||
If you don't have a big /etc/aliases, you'll find it easier to use
|
If you don't have a big /etc/aliases, you'll find it easier to use
|
||||||
qmail's native alias mechanism. Here's a checklist of aliases you should
|
qmail's native alias mechanism. Here's a checklist of aliases you should
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ Find sendmail in your boot scripts. It's usually in either /etc/rc or
|
||||||
-q15m means it should run the queue every 15 minutes; you may see a
|
-q15m means it should run the queue every 15 minutes; you may see a
|
||||||
different number. Comment out this line, and replace it with
|
different number. Comment out this line, and replace it with
|
||||||
|
|
||||||
env - PATH="/var/qmail/bin:$PATH" \
|
csh -cf '/var/qmail/rc &'
|
||||||
csh -cf 'qmail-start ./Mailbox splogger qmail &'
|
|
||||||
|
|
||||||
That's it. (Make sure you include the ./ and the &.)
|
That's it. (Make sure you include the &.)
|
||||||
|
|
|
||||||
19
INSTALL.ctl
19
INSTALL.ctl
|
|
@ -10,13 +10,22 @@ But this is all optional---if control/smtpgreeting doesn't exist, qmail
|
||||||
will do something reasonable by default. You shouldn't worry much about
|
will do something reasonable by default. You shouldn't worry much about
|
||||||
configuration right now. You can always come back and tune things later.
|
configuration right now. You can always come back and tune things later.
|
||||||
|
|
||||||
There's one big exception. You MUST tell qmail your hostname. The easy
|
There's one big exception. You MUST tell qmail your hostname. Just run
|
||||||
way to do this is to run the qmail-config script:
|
the config-fast script:
|
||||||
|
|
||||||
# ./qmail-config
|
# ./config-fast your.full.host.name
|
||||||
|
|
||||||
qmail-config finds your fully-qualified hostname in DNS and puts it into
|
config-fast puts your.full.host.name into control/me. It also puts it
|
||||||
control/me. It also selects good defaults for a few other controls.
|
into control/locals and control/rcpthosts, so that qmail will accept
|
||||||
|
mail for your.full.host.name.
|
||||||
|
|
||||||
|
You can instead use the config script, which looks up your host name in
|
||||||
|
DNS:
|
||||||
|
|
||||||
|
# ./config
|
||||||
|
|
||||||
|
config also looks up your local IP addresses in DNS to decide which
|
||||||
|
hosts to accept mail for.
|
||||||
|
|
||||||
(Why doesn't qmail do these lookups on the fly? This was a deliberate
|
(Why doesn't qmail do these lookups on the fly? This was a deliberate
|
||||||
design decision. qmail does all its local functions---header rewriting,
|
design decision. qmail does all its local functions---header rewriting,
|
||||||
|
|
|
||||||
15
INSTALL.ids
15
INSTALL.ids
|
|
@ -1,6 +1,7 @@
|
||||||
Here's how to set up the qmail groups and the qmail users.
|
Here's how to set up the qmail groups and the qmail users.
|
||||||
|
|
||||||
On some systems there are commands that make this easy. Solaris:
|
On some systems there are commands that make this easy. Solaris and
|
||||||
|
Linux:
|
||||||
|
|
||||||
# groupadd nofiles
|
# groupadd nofiles
|
||||||
# useradd -g nofiles -d /var/qmail/alias alias
|
# useradd -g nofiles -d /var/qmail/alias alias
|
||||||
|
|
@ -12,6 +13,18 @@ On some systems there are commands that make this easy. Solaris:
|
||||||
# useradd -g qmail -d /var/qmail qmailr
|
# useradd -g qmail -d /var/qmail qmailr
|
||||||
# useradd -g qmail -d /var/qmail qmails
|
# useradd -g qmail -d /var/qmail qmails
|
||||||
|
|
||||||
|
FreeBSD 2.2:
|
||||||
|
|
||||||
|
# pw groupadd nofiles
|
||||||
|
# pw useradd alias -g nofiles -d /var/qmail/alias -s /nonexistent
|
||||||
|
# pw useradd qmaild -g nofiles -d /var/qmail -s /nonexistent
|
||||||
|
# pw useradd qmaill -g nofiles -d /var/qmail -s /nonexistent
|
||||||
|
# pw useradd qmailp -g nofiles -d /var/qmail -s /nonexistent
|
||||||
|
# pw groupadd qmail
|
||||||
|
# pw useradd qmailq -g qmail -d /var/qmail -s /nonexistent
|
||||||
|
# pw useradd qmailr -g qmail -d /var/qmail -s /nonexistent
|
||||||
|
# pw useradd qmails -g qmail -d /var/qmail -s /nonexistent
|
||||||
|
|
||||||
BSDI 2.0:
|
BSDI 2.0:
|
||||||
|
|
||||||
# addgroup nofiles
|
# addgroup nofiles
|
||||||
|
|
|
||||||
64
INSTALL.maildir
Normal file
64
INSTALL.maildir
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
This file points out some reasons that you might want to switch from
|
||||||
|
mbox format to a new format, maildir.
|
||||||
|
|
||||||
|
|
||||||
|
1. The trouble with mbox
|
||||||
|
|
||||||
|
The mbox format---the format of ~user/Mailbox, understood by BSD Mail
|
||||||
|
and lots of other MUAs---is inherently unreliable.
|
||||||
|
|
||||||
|
Think about it: what happens if the system crashes while a program is
|
||||||
|
appending a new message to ~user/Mailbox? The message will be truncated.
|
||||||
|
Even worse, if it was truncated in the middle of a line, it will end up
|
||||||
|
being merged with the next message! Sure, the mailer understands that it
|
||||||
|
wasn't successful, so it'll try delivering the message again later, but
|
||||||
|
it can't fix your corrupted mbox.
|
||||||
|
|
||||||
|
Other formats, such as mh folders, are just as unreliable.
|
||||||
|
|
||||||
|
qmail supports maildir, a crashproof format for incoming mail messages.
|
||||||
|
maildir is fast and easy for MUAs to use. Even better, maildir works
|
||||||
|
wonders over NFS---see below.
|
||||||
|
|
||||||
|
I don't want to cram maildir down people's throats, so it's not the
|
||||||
|
default. Nevertheless, I encourage you to start asking for maildir
|
||||||
|
versions of your favorite MUAs, and to switch over to maildir as soon as
|
||||||
|
you can.
|
||||||
|
|
||||||
|
WARNING: qmail uses flock() to lock ~user/Mailbox. This agrees with the
|
||||||
|
modern mail.local locking choice. If your MUA doesn't use flock(), your
|
||||||
|
best bet is to switch to maildir, and to set up synchronous maildir2mbox
|
||||||
|
execution, as described below.
|
||||||
|
|
||||||
|
|
||||||
|
2. Sun's Network F_ail_u_re System
|
||||||
|
|
||||||
|
Anyone who tells you that mail can be safely delivered in mbox format
|
||||||
|
over NFS is pulling your leg---as explained above, mbox format is
|
||||||
|
inherently unreliable even on a single machine.
|
||||||
|
|
||||||
|
Anyway, NFS is the most unreliable computing environment ever invented,
|
||||||
|
and qmail doesn't even pretend to support mbox over NFS.
|
||||||
|
|
||||||
|
You should switch to maildir, which works fine over NFS without any
|
||||||
|
locking. You can safely read your mail over NFS if it's in maildir
|
||||||
|
format. Any number of machines can deliver mail to you at the same time.
|
||||||
|
(On the other hand, for efficiency, it's better to get NFS out of the
|
||||||
|
picture---your mail should be delivered on the server that contains your
|
||||||
|
home directory.)
|
||||||
|
|
||||||
|
Here's how to set up qmail to use maildir for your incoming mail:
|
||||||
|
|
||||||
|
% maildirmake $HOME/Maildir
|
||||||
|
% echo ./Maildir/ > ~/.qmail
|
||||||
|
|
||||||
|
Make sure you include the trailing slash on Maildir/.
|
||||||
|
|
||||||
|
The system administrator can set up Maildir as the default for everybody
|
||||||
|
by creating a maildir in the new-user template directory and replacing
|
||||||
|
./Mailbox with ./Maildir/ in /var/qmail/rc.
|
||||||
|
|
||||||
|
Until your MUA supports maildir, you'll probably want to convert maildir
|
||||||
|
format to (gaaack) mbox format. I've supplied a maildir2mbox utility
|
||||||
|
that does the trick, along with some tiny qail and elq and pinq wrappers
|
||||||
|
that call maildir2mbox before calling Mail or elm or pine.
|
||||||
124
INSTALL.mbox
124
INSTALL.mbox
|
|
@ -3,110 +3,46 @@ provides user-controlled mailing lists, cross-host alias loop detection,
|
||||||
and many other important qmail features.
|
and many other important qmail features.
|
||||||
|
|
||||||
There's one part of qmail-local that you need to know about right now:
|
There's one part of qmail-local that you need to know about right now:
|
||||||
qmail-local doesn't support an insecure central mail spool. It delivers
|
qmail-local delivers mail by default into ~user/Mailbox (in mbox format,
|
||||||
mail by default into ~user/Mailbox (in mbox format).
|
using flock), rather than /var/spool/mail/user.
|
||||||
|
|
||||||
This file explains what you should do to deal with this change. It also
|
For an explanation of the problems with /var/spool/mail, and a list of
|
||||||
points out some reasons that you might want to make an even bigger
|
options if you want to continue delivering to /var/spool/mail, see
|
||||||
change, switching from mbox format to a new format, maildir.
|
INSTALL.vsm.
|
||||||
|
|
||||||
If you desperately don't want to change anything, see INSTALL.qsmhook.
|
This file explains how to handle the change to ~user/Mailbox. The basic
|
||||||
|
procedure is simple:
|
||||||
|
|
||||||
|
* Move each /var/spool/mail/user to ~user/Mailbox. For safety, do
|
||||||
|
this in single-user mode.
|
||||||
|
|
||||||
Contents:
|
* As root, set up a symbolic link from /var/spool/mail/user to
|
||||||
1. Throw away /usr/spool/mail!
|
~user/Mailbox for each user. /var/spool/mail should be mode 1777,
|
||||||
2. The trouble with mbox
|
so users will not be able to accidentally remove these links.
|
||||||
3. Sun's Network F_ail_u_re System
|
|
||||||
|
|
||||||
|
An alternative to symbolic links is hlfsd. Consult the documentation for
|
||||||
|
hlfsd if it is included in your operating system.
|
||||||
|
|
||||||
1. Throw away /usr/spool/mail!
|
If /var/spool/mail is large, you can gain extra speed by configuring
|
||||||
|
your mail software to look at ~user/Mailbox directly:
|
||||||
|
|
||||||
/usr/spool/mail, often called /var/spool/mail or /var/mail, is a
|
* Most MUAs: Put ``setenv MAIL $HOME/Mailbox'' in your system-wide
|
||||||
security disaster. A user's mailbox belongs in his home directory, not a
|
.cshrc and ``MAIL=$HOME/Mailbox; export MAIL'' in your system-wide
|
||||||
shared directory. Even if you don't install qmail, you should destroy
|
.profile.
|
||||||
/usr/spool/mail. This takes four steps:
|
|
||||||
|
|
||||||
A. Convince your local mailer to deliver to ~user/Mailbox. If you're
|
* elm: Change "mailbox" to "Mailbox" around line 388 of newmbox.c and
|
||||||
using something like procmail, this is easy---just change SYSTEM_MBOX
|
recompile. (elm looks at $MAIL, but without this change elm will
|
||||||
in config.h. If you're installing qmail, you don't have to do
|
fail if two users try to read mail simultaneously.)
|
||||||
anything. Otherwise, take a look at hlfsd from
|
|
||||||
ftp.cs.columbia.edu/pub/amd.
|
|
||||||
|
|
||||||
B. Move each /usr/spool/mail/user to ~user/Mailbox. For safety, do
|
* pine: Put ``inbox-path=Mailbox'' in your system-wide pine.conf.
|
||||||
this in single-user mode---you don't want to risk corrupting
|
(For pine versions more recent than 3.91, see also FAQ 6.2.)
|
||||||
mailboxes. (qmail makes it easy to turn off deliveries temporarily:
|
|
||||||
just kill the qmail-send daemon. But you aren't running qmail yet.)
|
|
||||||
When you're done, remove /usr/spool/mail.
|
|
||||||
|
|
||||||
C. Put ``setenv MAIL $HOME/Mailbox'' in your system-wide .cshrc,
|
* procmail: Change SYSTEM_MBOX in config.h and recompile.
|
||||||
``MAIL=$HOME/Mailbox; export MAIL'' in your system-wide .profile,
|
|
||||||
``inbox-path=Mailbox'' in your system-wide pine.conf. If you're using
|
|
||||||
qpopper 2.2, you'll have to recompile with -DHOMEDIRMAIL in CFLAGS
|
|
||||||
and with /.mail changed to /Mailbox in pop_dropcopy.c. If you're
|
|
||||||
using elm on a multiuser system, you'll have to recompile elm with
|
|
||||||
"mailbox" changed to "Mailbox" around line 388 of newmbox.c.
|
|
||||||
|
|
||||||
D. Announce the change.
|
* qpopper 2.2: Change /.mail to /Mailbox in pop_dropcopy.c and
|
||||||
|
recompile with -DHOMEDIRMAIL in CFLAGS.
|
||||||
|
|
||||||
Some vendors, in a misguided attempt to solve the security problems of
|
Some vendors, in a misguided attempt to solve the security problems of
|
||||||
/usr/spool/mail, have made all MUAs (e.g., /usr/ucb/Mail) setgid mail.
|
/var/spool/mail, have made all their mail software setgid mail. After
|
||||||
After you get rid of /usr/spool/mail, you can also disable those
|
you move the mailboxes, you can---and, for security, should---remove
|
||||||
setgid-mail bits.
|
those setgid-mail bits.
|
||||||
|
|
||||||
|
|
||||||
2. The trouble with mbox
|
|
||||||
|
|
||||||
The mbox format---the format of ~user/Mailbox, understood by BSD Mail
|
|
||||||
and lots of other MUAs---is inherently unreliable.
|
|
||||||
|
|
||||||
Think about it: what happens if the system crashes while a program is
|
|
||||||
appending a new message to ~user/Mailbox? The message will be truncated.
|
|
||||||
Even worse, if it was truncated in the middle of a line, it will end up
|
|
||||||
being merged with the next message! Sure, the mailer understands that it
|
|
||||||
wasn't successful, so it'll try delivering the message again later, but
|
|
||||||
it can't fix your corrupted mbox.
|
|
||||||
|
|
||||||
Other formats, such as mh folders, are just as unreliable.
|
|
||||||
|
|
||||||
qmail supports maildir, a crashproof format for incoming mail messages.
|
|
||||||
maildir is fast and easy for MUAs to use. Even better, maildir works
|
|
||||||
wonders over NFS---see below.
|
|
||||||
|
|
||||||
I don't want to cram maildir down people's throats, so it's not the
|
|
||||||
default. Nevertheless, I encourage you to start asking for maildir
|
|
||||||
versions of your favorite MUAs, and to switch over to maildir as soon as
|
|
||||||
you can.
|
|
||||||
|
|
||||||
WARNING: qmail uses flock() to lock ~user/Mailbox. This agrees with the
|
|
||||||
modern mail.local locking choice. If your MUA doesn't use flock(), your
|
|
||||||
best bet is to switch to maildir, and to set up synchronous maildir2mbox
|
|
||||||
execution, as described below.
|
|
||||||
|
|
||||||
|
|
||||||
3. Sun's Network F_ail_u_re System
|
|
||||||
|
|
||||||
Anyone who tells you that mail can be safely delivered in mbox format
|
|
||||||
over NFS is pulling your leg---as explained above, mbox format is
|
|
||||||
inherently unreliable even on a single machine.
|
|
||||||
|
|
||||||
Anyway, NFS is the most unreliable computing environment ever invented,
|
|
||||||
and qmail doesn't even pretend to support mbox over NFS.
|
|
||||||
|
|
||||||
You should switch to maildir, which works fine over NFS without any
|
|
||||||
locking. You can safely read your mail over NFS if it's in maildir
|
|
||||||
format. Any number of machines can deliver mail to you at the same time.
|
|
||||||
(On the other hand, for efficiency, it's better to get NFS out of the
|
|
||||||
picture---your mail should be delivered on the server that contains your
|
|
||||||
home directory.)
|
|
||||||
|
|
||||||
Here's how to set up qmail to use maildir for your incoming mail:
|
|
||||||
|
|
||||||
% maildirmake $HOME/Maildir
|
|
||||||
% echo ./Maildir/ > ~/.qmail
|
|
||||||
|
|
||||||
Make sure you include the trailing slash on Maildir/.
|
|
||||||
|
|
||||||
Until your MUA supports maildir, you'll probably want to convert maildir
|
|
||||||
format to (gaaack) mbox format. I've supplied a maildir2mbox utility
|
|
||||||
that does the trick, along with some tiny qail and elq and pinq wrappers
|
|
||||||
that call maildir2mbox before calling Mail or elm or pine.
|
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
You can set up qmail to use the same local delivery agent as sendmail,
|
|
||||||
through a mechanism called qsmhook. This file says how.
|
|
||||||
|
|
||||||
Before you do this, may I ask why? If you simply don't want the hassle
|
|
||||||
of moving user mailboxes from /usr/spool/mail to ~, please reconsider---
|
|
||||||
/usr/spool/mail has always been a big security problem. See, for
|
|
||||||
example, CERT advisory 95:02.
|
|
||||||
|
|
||||||
If you're trying to preserve /etc/aliases and ~user/.forward, you're
|
|
||||||
looking the wrong way---those are handled by sendmail internally, not by
|
|
||||||
the local delivery agent. You can use your old /etc/aliases with qmail
|
|
||||||
by installing the qmsmac package.
|
|
||||||
|
|
||||||
Perhaps you've set up an advanced agent like procmail. But most people
|
|
||||||
use procmail for nothing more than sorting mail into several mailboxes;
|
|
||||||
and that's much easier with qmail's local forwarding mechanism, which
|
|
||||||
gives each user control over user-anything. If you have a few users who
|
|
||||||
really do need procmail, they can easily run procmail from their own
|
|
||||||
.qmail files.
|
|
||||||
|
|
||||||
Do you still want to set up qsmhook? Send me some e-mail and let me know
|
|
||||||
why. Perhaps I can provide something for you in a future qmail release.
|
|
||||||
|
|
||||||
Here's what to do. First, tack ``:alias'' onto the end of each address
|
|
||||||
in /var/qmail/control/locals, and put the results into
|
|
||||||
/var/qmail/control/virtualdomains. For example, if control/locals has
|
|
||||||
|
|
||||||
localhost
|
|
||||||
silverton.berkeley.edu
|
|
||||||
|
|
||||||
then control/virtualdomains should now have (without extra spaces)
|
|
||||||
|
|
||||||
localhost:alias
|
|
||||||
silverton.berkeley.edu:alias
|
|
||||||
|
|
||||||
Second, cp /dev/null control/locals.
|
|
||||||
|
|
||||||
Third, put a line into ~alias/.qmail-default, based on sendmail's Mlocal
|
|
||||||
line. For example, if sendmail.cf has
|
|
||||||
|
|
||||||
Mlocal, P=/bin/mail, F=lsDFMPrmn, S=10, R=20, A=mail -d $u
|
|
||||||
|
|
||||||
then ~alias/.qmail-default should have
|
|
||||||
|
|
||||||
|qsmhook -x alias- -lsDFMPmn /bin/mail -r %g -d %u
|
|
||||||
|
|
||||||
As another example, if sendmail.cf has
|
|
||||||
|
|
||||||
Mlocal, P=/usr/lib/mail.local, F=flsSDFMmnP, S=10, R=20, A=mail.local -d $u
|
|
||||||
|
|
||||||
then ~alias/.qmail-default should have
|
|
||||||
|
|
||||||
|qsmhook -x alias- -lsDFMmnP /usr/lib/mail.local -f %g -d %u
|
|
||||||
50
INSTALL.vsm
Normal file
50
INSTALL.vsm
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
UNIX has traditionally delivered mail into a central spool directory,
|
||||||
|
/var/spool/mail. (The original name was /usr/spool/mail; some systems
|
||||||
|
now use /var/mail.) There are two basic problems with /var/spool/mail:
|
||||||
|
|
||||||
|
* It's slow. On systems with thousands of users, /var/spool/mail has
|
||||||
|
thousands of entries. A few UNIX systems support fast operations on
|
||||||
|
large directories, but most don't.
|
||||||
|
|
||||||
|
* It's insecure. Writing code that works safely in a world-writable
|
||||||
|
directory is not easy. See, for example, CERT advisory 95:02.
|
||||||
|
|
||||||
|
These may not be problems at your site, so you may want to leave your
|
||||||
|
mailboxes in /var/spool/mail.
|
||||||
|
|
||||||
|
This file explains several ways that you can configure qmail to use
|
||||||
|
existing /var/spool/mail delivery tools. Please note that I do not vouch
|
||||||
|
for the security or reliability of any of those tools.
|
||||||
|
|
||||||
|
|
||||||
|
1. What to configure
|
||||||
|
|
||||||
|
The qmail system is started from /var/qmail/rc with
|
||||||
|
|
||||||
|
qmail-start ./Mailbox splogger qmail
|
||||||
|
|
||||||
|
The first argument to qmail-start, ./Mailbox, is the default delivery
|
||||||
|
instruction. You can change it to run a program such as binmail or
|
||||||
|
procmail. (See dot-qmail.0 for the format of delivery instructions.)
|
||||||
|
|
||||||
|
|
||||||
|
2. Using procmail
|
||||||
|
|
||||||
|
You may already have installed procmail for mail filtering. procmail
|
||||||
|
delivers to /var/spool/mail by default.
|
||||||
|
|
||||||
|
To set up qmail to use procmail, simply copy /var/qmail/boot/proc to
|
||||||
|
/var/qmail/rc.
|
||||||
|
|
||||||
|
Note that procmail must be in your system's boot PATH; if it isn't, you
|
||||||
|
will have edit /var/qmail/rc to include the full path.
|
||||||
|
|
||||||
|
|
||||||
|
3. Using sendmail's delivery agent
|
||||||
|
|
||||||
|
sendmail uses binmail to deliver to /var/spool/mail. binmail is shipped
|
||||||
|
with the operating system as /bin/mail or /usr/libexec/mail.local.
|
||||||
|
|
||||||
|
There is some variation in binmail syntax among systems. The most common
|
||||||
|
interfaces are shown in /var/qmail/boot/binm1, /var/qmail/boot/binm2,
|
||||||
|
and /var/qmail/boot/binm3.
|
||||||
|
|
@ -96,7 +96,8 @@ qmail-send may at its leisure try to deliver a message to a NOT DONE
|
||||||
address. If the message is successfully delivered, qmail-send marks the
|
address. If the message is successfully delivered, qmail-send marks the
|
||||||
address as DONE. If the delivery attempt meets with permanent failure,
|
address as DONE. If the delivery attempt meets with permanent failure,
|
||||||
qmail-send first appends a note to bounce/457, creating bounce/457 if
|
qmail-send first appends a note to bounce/457, creating bounce/457 if
|
||||||
necessary; then it marks the address as DONE.
|
necessary; then it marks the address as DONE. Note that bounce/457 is
|
||||||
|
not crashproof.
|
||||||
|
|
||||||
qmail-send may handle bounce/457 at any time, as follows: it (1) injects
|
qmail-send may handle bounce/457 at any time, as follows: it (1) injects
|
||||||
a new bounce message, created from bounce/457 and mess/457; (2) deletes
|
a new bounce message, created from bounce/457 and mess/457; (2) deletes
|
||||||
|
|
|
||||||
37
PIC.local2alias
Normal file
37
PIC.local2alias
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
Original message:
|
||||||
|
|
||||||
|
To: help
|
||||||
|
Hi.
|
||||||
|
|
||||||
|
qmail-inject Fill in the complete envelope and header:
|
||||||
|
|
||||||
|
| (envelope) from joe@heaven.af.mil to help@heaven.af.mil
|
||||||
|
| From: joe@heaven.af.mil
|
||||||
|
| To: help@heaven.af.mil
|
||||||
|
|
|
||||||
|
| Hi.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-queue Store message safely on disk.
|
||||||
|
Trigger qmail-send.
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-send Look at envelope recipient, help@heaven.af.mil.
|
||||||
|
| Is heaven.af.mil in locals? Yes.
|
||||||
|
| Deliver locally to help@heaven.af.mil.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-lspawn ./Mailbox
|
||||||
|
|
||||||
|
| Look at mailbox name, help.
|
||||||
|
| Is help listed in qmail-users? No.
|
||||||
|
| Is there a help account? No.
|
||||||
|
| Give control of the message to alias.
|
||||||
|
| Run qmail-local.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-local alias ~alias help - help heaven.af.mil joe@heaven.af.mil ./Mailbox
|
||||||
|
|
||||||
|
Does ~alias/.qmail-help exist? Yes: "john".
|
||||||
|
Forward message to john.
|
||||||
41
PIC.local2ext
Normal file
41
PIC.local2ext
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
Original message:
|
||||||
|
|
||||||
|
To: fred-sos
|
||||||
|
Hi.
|
||||||
|
|
||||||
|
qmail-inject Fill in the complete envelope and header:
|
||||||
|
|
||||||
|
| (envelope) from joe@heaven.af.mil to fred-sos@heaven.af.mil
|
||||||
|
| From: joe@heaven.af.mil
|
||||||
|
| To: fred-sos@heaven.af.mil
|
||||||
|
|
|
||||||
|
| Hi.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-queue Store message safely on disk.
|
||||||
|
Trigger qmail-send.
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-send Look at envelope recipient, fred-sos@heaven.af.mil.
|
||||||
|
| Is heaven.af.mil in locals? Yes.
|
||||||
|
| Deliver locally to fred-sos@heaven.af.mil.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-lspawn ./Mailbox
|
||||||
|
|
||||||
|
| Look at mailbox name, fred-sos.
|
||||||
|
| Is fred-sos listed in qmail-users? No.
|
||||||
|
| Is there a fred-sos account? No.
|
||||||
|
| Is there a fred account? Yes.
|
||||||
|
| Is fred's uid nonzero? Yes.
|
||||||
|
| Is ~fred visible to the qmailp user? Yes.
|
||||||
|
| Is ~fred owned by fred? Yes.
|
||||||
|
| Give control of the message to fred.
|
||||||
|
| Run qmail-local.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-local fred ~fred fred-sos - sos heaven.af.mil joe@heaven.af.mil ./Mailbox
|
||||||
|
|
||||||
|
Does ~fred/.qmail-sos exist? Yes: "./Extramail".
|
||||||
|
Write message to ./Extramail in mbox format.
|
||||||
40
PIC.local2local
Normal file
40
PIC.local2local
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
Original message:
|
||||||
|
|
||||||
|
To: fred
|
||||||
|
Hi.
|
||||||
|
|
||||||
|
qmail-inject Fill in the complete envelope and header:
|
||||||
|
|
||||||
|
| (envelope) from joe@heaven.af.mil to fred@heaven.af.mil
|
||||||
|
| From: joe@heaven.af.mil
|
||||||
|
| To: fred@heaven.af.mil
|
||||||
|
|
|
||||||
|
| Hi.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-queue Store message safely on disk.
|
||||||
|
Trigger qmail-send.
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-send Look at envelope recipient, fred@heaven.af.mil.
|
||||||
|
| Is heaven.af.mil in locals? Yes.
|
||||||
|
| Deliver locally to fred@heaven.af.mil.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-lspawn ./Mailbox
|
||||||
|
|
||||||
|
| Look at mailbox name, fred.
|
||||||
|
| Is fred listed in qmail-users? No.
|
||||||
|
| Is there a fred account? Yes.
|
||||||
|
| Is fred's uid nonzero? Yes.
|
||||||
|
| Is ~fred visible to the qmailp user? Yes.
|
||||||
|
| Is ~fred owned by fred? Yes.
|
||||||
|
| Give control of the message to fred.
|
||||||
|
| Run qmail-local.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-local fred ~fred fred '' '' heaven.af.mil joe@heaven.af.mil ./Mailbox
|
||||||
|
|
||||||
|
Does ~fred/.qmail exist? No.
|
||||||
|
Write message to ./Mailbox in mbox format.
|
||||||
38
PIC.local2rem
Normal file
38
PIC.local2rem
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
Original message:
|
||||||
|
|
||||||
|
To: bill@irs.gov
|
||||||
|
Hi.
|
||||||
|
|
||||||
|
qmail-inject Fill in the complete envelope and header:
|
||||||
|
|
||||||
|
| (envelope) from joe@heaven.af.mil to bill@irs.gov
|
||||||
|
| From: joe@heaven.af.mil
|
||||||
|
| To: bill@irs.gov
|
||||||
|
|
|
||||||
|
| Hi.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-queue Store message safely on disk.
|
||||||
|
Trigger qmail-send.
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-send Look at envelope recipient, bill@irs.gov.
|
||||||
|
| Is irs.gov in locals? No.
|
||||||
|
| Is bill@irs.gov in virtualdomains? No.
|
||||||
|
| Is irs.gov in virtualdomains? No.
|
||||||
|
| Is .gov in virtualdomains? No.
|
||||||
|
| Deliver remotely to bill@irs.gov.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-rspawn Run qmail-remote.
|
||||||
|
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-remote Look at host name, irs.gov.
|
||||||
|
Is irs.gov listed in smtproutes? No.
|
||||||
|
Look up DNS MX/A for irs.gov and connect to it by SMTP:
|
||||||
|
|
||||||
|
MAIL FROM:<joe@heaven.af.mil>
|
||||||
|
RCPT TO:<bill@irs.gov>
|
||||||
44
PIC.local2virt
Normal file
44
PIC.local2virt
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
Original message:
|
||||||
|
|
||||||
|
To: dude@tommy.gov
|
||||||
|
Hi.
|
||||||
|
|
||||||
|
qmail-inject Fill in the complete envelope and header:
|
||||||
|
|
||||||
|
| (envelope) from joe@heaven.af.mil to dude@tommy.gov
|
||||||
|
| From: joe@heaven.af.mil
|
||||||
|
| To: dude@tommy.gov
|
||||||
|
|
|
||||||
|
| Hi.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-queue Store message safely on disk.
|
||||||
|
Trigger qmail-send.
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-send Look at envelope recipient, dude@tommy.gov.
|
||||||
|
| Is tommy.gov in locals? No.
|
||||||
|
| Is dude@tommy.gov in virtualdomains? No.
|
||||||
|
| Is tommy.gov in virtualdomains? Yes: "tommy.gov:fred".
|
||||||
|
| Deliver locally to fred-dude@tommy.gov.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-lspawn ./Mailbox
|
||||||
|
|
||||||
|
| Look at mailbox name, fred-dude.
|
||||||
|
| Is fred-dude listed in qmail-users? No.
|
||||||
|
| Is there a fred-dude account? No.
|
||||||
|
| Is there a fred account? Yes.
|
||||||
|
| Is fred's uid nonzero? Yes.
|
||||||
|
| Is ~fred visible to the qmailp user? Yes.
|
||||||
|
| Is ~fred owned by fred? Yes.
|
||||||
|
| Give control of the message to fred.
|
||||||
|
| Run qmail-local.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-local fred ~fred fred-dude - dude tommy.gov joe@heaven.af.mil ./Mailbox
|
||||||
|
|
||||||
|
Does ~fred/.qmail-dude exist? No.
|
||||||
|
Does ~fred/.qmail-default exist? Yes: "./Mail.tommy".
|
||||||
|
Write message to ./Mail.tommy in mbox format.
|
||||||
38
PIC.nullclient
Normal file
38
PIC.nullclient
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
Original message:
|
||||||
|
|
||||||
|
To: bill@irs.gov
|
||||||
|
Hi.
|
||||||
|
|
||||||
|
qmail-inject Fill in the complete envelope and header:
|
||||||
|
|
||||||
|
| (envelope) from joe@heaven.af.mil to bill@irs.gov
|
||||||
|
| From: joe@heaven.af.mil
|
||||||
|
| To: bill@irs.gov
|
||||||
|
|
|
||||||
|
| Hi.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-queue Store message safely on disk.
|
||||||
|
Trigger qmail-send.
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-send Look at envelope recipient, bill@irs.gov.
|
||||||
|
| Is irs.gov in locals? No.
|
||||||
|
| Is bill@irs.gov in virtualdomains? No.
|
||||||
|
| Is irs.gov in virtualdomains? No.
|
||||||
|
| Is .gov in virtualdomains? No.
|
||||||
|
| Deliver remotely to bill@irs.gov.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-rspawn Run qmail-remote.
|
||||||
|
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-remote Look at host name, irs.gov.
|
||||||
|
Is irs.gov listed in smtproutes? Yes: ":bigbang.af.mil".
|
||||||
|
Look up DNS A for bigbang.af.mil and connect by SMTP:
|
||||||
|
|
||||||
|
MAIL FROM:<joe@heaven.af.mil>
|
||||||
|
RCPT TO:<bill@irs.gov>
|
||||||
8
PIC.relaybad
Normal file
8
PIC.relaybad
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
qmail-smtpd Receive message by SMTP from another host:
|
||||||
|
|
||||||
|
MAIL FROM:<spammer@aol.com>
|
||||||
|
RCPT TO:<bill@irs.gov>
|
||||||
|
|
||||||
|
Is $RELAYCLIENT set? No.
|
||||||
|
Is irs.gov in rcpthosts? No.
|
||||||
|
Reject RCPT.
|
||||||
33
PIC.relaygood
Normal file
33
PIC.relaygood
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
qmail-smtpd Receive message by SMTP from another host:
|
||||||
|
|
||||||
|
| MAIL FROM:<joe@heaven.af.mil>
|
||||||
|
| RCPT TO:<bill@irs.gov>
|
||||||
|
|
|
||||||
|
| Is $RELAYCLIENT set? Yes: "".
|
||||||
|
| Accept RCPT.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-queue Store message safely on disk.
|
||||||
|
Trigger qmail-send.
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-send Look at envelope recipient, bill@irs.gov.
|
||||||
|
| Is irs.gov in locals? No.
|
||||||
|
| Is bill@irs.gov in virtualdomains? No.
|
||||||
|
| Is irs.gov in virtualdomains? No.
|
||||||
|
| Is .gov in virtualdomains? No.
|
||||||
|
| Deliver remotely to bill@irs.gov.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-rspawn Run qmail-remote.
|
||||||
|
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-remote Look at host name, irs.gov.
|
||||||
|
Is irs.gov listed in smtproutes? No.
|
||||||
|
Look up DNS MX/A for irs.gov and connect to it by SMTP:
|
||||||
|
|
||||||
|
MAIL FROM:<joe@heaven.af.mil>
|
||||||
|
RCPT TO:<bill@irs.gov>
|
||||||
36
PIC.rem2local
Normal file
36
PIC.rem2local
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
qmail-smtpd Receive message by SMTP from another host:
|
||||||
|
|
||||||
|
| MAIL FROM:<bill@irs.gov>
|
||||||
|
| RCPT TO:<joe@heaven.af.mil>
|
||||||
|
|
|
||||||
|
| Is $RELAYCLIENT set? No.
|
||||||
|
| Is heaven.af.mil in rcpthosts? Yes.
|
||||||
|
| Accept RCPT.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-queue Store message safely on disk.
|
||||||
|
Trigger qmail-send.
|
||||||
|
|
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-send Look at envelope recipient, joe@heaven.af.mil.
|
||||||
|
| Is heaven.af.mil in locals? Yes.
|
||||||
|
| Deliver locally to joe@heaven.af.mil.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-lspawn ./Mailbox
|
||||||
|
|
||||||
|
| Look at mailbox name, joe.
|
||||||
|
| Is joe listed in qmail-users? No.
|
||||||
|
| Is there a joe account? Yes.
|
||||||
|
| Is joe's uid nonzero? Yes.
|
||||||
|
| Is ~joe visible to the qmailp user? Yes.
|
||||||
|
| Is ~joe owned by joe? Yes.
|
||||||
|
| Give control of the message to joe.
|
||||||
|
| Run qmail-local.
|
||||||
|
V
|
||||||
|
|
||||||
|
qmail-local joe ~joe joe '' '' heaven.af.mil bill@irs.gov ./Mailbox
|
||||||
|
|
||||||
|
Does ~joe/.qmail exist? No.
|
||||||
|
Write message to ./Mailbox in mbox format.
|
||||||
358
README
358
README
|
|
@ -1,6 +1,6 @@
|
||||||
qmail 1.01
|
qmail 1.02
|
||||||
19970413
|
19980430
|
||||||
Copyright 1997
|
Copyright 1998
|
||||||
D. J. Bernstein, qmail@pobox.com
|
D. J. Bernstein, qmail@pobox.com
|
||||||
|
|
||||||
qmail is a secure, reliable, efficient, simple message transfer agent.
|
qmail is a secure, reliable, efficient, simple message transfer agent.
|
||||||
|
|
@ -9,191 +9,261 @@ typical Internet-connected UNIX hosts. See BLURB, BLURB2, BLURB3, and
|
||||||
BLURB4 for more detailed advertisements.
|
BLURB4 for more detailed advertisements.
|
||||||
|
|
||||||
INSTALL says how to set up and test qmail. If you're upgrading from
|
INSTALL says how to set up and test qmail. If you're upgrading from
|
||||||
1.00, read UPGRADE instead.
|
1.01, read UPGRADE instead.
|
||||||
|
|
||||||
|
See PIC.* for some ``end-to-end'' pictures of mail flowing through the
|
||||||
|
qmail system.
|
||||||
|
|
||||||
See http://pobox.com/~djb/qmail.html for other qmail-related software
|
See http://pobox.com/~djb/qmail.html for other qmail-related software
|
||||||
and a pointer to the qmail mailing list.
|
and a pointer to the qmail mailing list.
|
||||||
|
|
||||||
Other documentation here: RFC* explain solutions to several Internet
|
Other documentation: http://pobox.com/~djb/proto.html shows solutions to
|
||||||
mail problems; all of these except RFCMXPS are implemented in qmail.
|
several Internet mail problems; many of these solutions are implemented
|
||||||
CHANGES and THANKS show how qmail has changed since it was first
|
in qmail. CHANGES and THANKS show how qmail has changed since it was
|
||||||
released. SECURITY, INTERNALS, THOUGHTS, and TODO record many of the
|
first released. SECURITY, INTERNALS, THOUGHTS, and TODO record many of
|
||||||
qmail design decisions.
|
the qmail design decisions.
|
||||||
|
|
||||||
The rest of this file is a list of systypes where various versions of
|
The rest of this file is a list of systypes where various versions of
|
||||||
qmail have been reported to work. 0.90 was the first gamma version. 0.96
|
qmail have been reported to work. 0.96 was the final gamma version; 1.00
|
||||||
was the final gamma version. 1.00 had exactly the same code as 0.96. To
|
had exactly the same code as 0.96. To see your systype, make systype;
|
||||||
see your systype, make systype; cat systype.
|
cat systype.
|
||||||
|
|
||||||
1.00: a.ux-3.0-svr2-:-:-:mc68030-:- (tnx RF)
|
1.00: a.ux-3.0-svr2-:-:-:mc68030-:- (tnx RF)
|
||||||
0.96: aix-3-2-:-:-:000011216700-:- (tnx JLB)
|
1.01: aix-3-2-:-:-:000000406300-:- (tnx DG)
|
||||||
0.91: aix-3-2-:-:-:000109257500-:-
|
1.01: aix-3-2-:-:-:000011216700-:- (tnx JLB)
|
||||||
0.96: aix-4-1-:-:-:000088581000-:- (tnx HJB)
|
1.01: aix-4-1-:-:-:000041574c00-:- (tnx M2H)
|
||||||
0.95: aix-4-1-:-:-:00061176a600-:- (tnx JS)
|
1.01: aix-4-1-:-:-:000088581000-:- (tnx HJB)
|
||||||
1.00: aix-4-1-:-:-:00910033a000-:- (tnx K2J)
|
1.01: aix-4-1-:-:-:002b51134c00-:- (tnx MP)
|
||||||
0.91: aix-4-2-:-:-:006030934c00-:-
|
1.00: aix-4-1-:-:-:00910033a000-:- (tnx KJJ)
|
||||||
1.00: bsd.os-2.0.1-:i386-:-:i486-:- (tnx KR)
|
1.01: aix-4-2-:-:-:000055247900-:- (tnx JLB)
|
||||||
0.93: bsd.os-2.0.1-:i386-:-:pentium-:-
|
1.01: aix-4-2-:-:-:000062295800-:- (tnx TD)
|
||||||
|
1.01: aix-4-2-:-:-:000136094c00-:- (tnx T2U)
|
||||||
|
1.00: aix-4-2-:-:-:000205254600-:- (tnx MGM)
|
||||||
|
1.01: aix-4-2-:-:-:005255bc4c00-:- (tnx DS)
|
||||||
|
1.01: aix-4-2-:-:-:006030944c00-:-
|
||||||
|
1.01: bsd.386-1.1-0-:i386-:-:i386-:- (tnx T2M)
|
||||||
|
1.01: bsd.os-2.0-:i386-:-:pentium-:- (tnx MSS)
|
||||||
|
1.01: bsd.os-2.0.1-:i386-:-:i486-:- (tnx KR)
|
||||||
0.96: bsd.os-2.1-:i386-:-:-:- (tnx DAR)
|
0.96: bsd.os-2.1-:i386-:-:-:- (tnx DAR)
|
||||||
1.00: bsd.os-2.1-:i386-:-:i486-:- (tnx RJC)
|
1.00: bsd.os-2.1-:i386-:-:i486-:- (tnx RJC)
|
||||||
0.96: bsd.os-2.1-:i386-:-:pentium-:- (tnx DAR)
|
0.96: bsd.os-2.1-:i386-:-:pentium-:- (tnx UO)
|
||||||
|
1.01: bsd.os-3.0-:i386-:-:-:- (tnx VU)
|
||||||
|
1.01: bsd.os-3.0-:i386-:-:pentium-:- (tnx RJO)
|
||||||
|
1.01: bsd.os-3.1-:i386-:-:pentium-:- (tnx ABC)
|
||||||
|
1.01: bsd.os-3.1-:i386-:-:pentium.ii-:- (tnx UO)
|
||||||
0.96: dgux-5.4r2.01-generic-:-:-:aviion-:- (tnx HWM)
|
0.96: dgux-5.4r2.01-generic-:-:-:aviion-:- (tnx HWM)
|
||||||
0.93: dgux-5.4r3.10-generic-:-:-:aviion-:- (tnx HWM)
|
1.01: freebsd-2.1.0-release-:i386-:-:i486-dx-:- (tnx VV)
|
||||||
0.91: freebsd-2.0.5-release-:i386-:-:-:- (tnx TG)
|
1.01: freebsd-2.1.0-release-:i386-:-:i486.dx2-:- (tnx JLB)
|
||||||
0.92: freebsd-2.1-stable-:i386-:-:pentium.815\100-:-
|
1.00: freebsd-2.1.0-release-:i386-:-:i486dx-:- (tnx chrisj=???)
|
||||||
0.90: freebsd-2.1.0-release-:i386-:-:cy486dlc-:- (tnx G2A)
|
1.01: freebsd-2.1.0-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MBS)
|
||||||
1.00: freebsd-2.1.0-release-:i386-:-:i486-dx2-:- (tnx JLB)
|
1.01: freebsd-2.1.5-release-:i386-:-:i486-dx-:- (tnx B1F)
|
||||||
1.00: freebsd-2.1.0-release-:i386-:-:i486-dx-:- (tnx chrisj=???)
|
0.96: freebsd-2.1.5-release-:i386-:-:i486dx-:- (tnx FN)
|
||||||
0.96: freebsd-2.1.0-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MBS)
|
1.01: freebsd-2.1.5-release-:i386-:-:unknown.-:- (tnx BMF)
|
||||||
0.95: freebsd-2.1.5-release-:i386-:-:-:- (tnx NAA)
|
|
||||||
0.96: freebsd-2.1.5-release-:i386-:-:i486-dx-:- (tnx FN)
|
|
||||||
0.95: freebsd-2.1.5-release-:i386-:-:pentium.510\60.or.567\66-:- (tnx M2L)
|
|
||||||
0.95: freebsd-2.1.5-release-:i386-:-:pentium.735\90-:- (tnx AG)
|
|
||||||
0.92: freebsd-2.1.5-stable-:i386-:-:pentium.735\90.or.815\100-:- (tnx FE)
|
|
||||||
1.00: freebsd-2.1.6-release-:i386-:-:-:- (tnx TM)
|
1.00: freebsd-2.1.6-release-:i386-:-:-:- (tnx TM)
|
||||||
0.96: freebsd-2.1.6-release-:i386-:-:Pentium-Pro.150-:- (tnx CH)
|
0.96: freebsd-2.1.6-release-:i386-:-:Pentium-Pro.150-:- (tnx CH)
|
||||||
0.96: freebsd-2.1.6-release-:i386-:-:i486-dx-:- (tnx HCJ)
|
1.01: freebsd-2.1.6-release-:i386-:-:cy486dlc-:- (tnx M3H)
|
||||||
0.95: freebsd-2.1.6-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx M2L)
|
|
||||||
0.96: freebsd-2.1.6.1-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MF)
|
0.96: freebsd-2.1.6.1-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MF)
|
||||||
|
1.01: freebsd-2.1.7-release-:i386-:-:i486-dx-:- (tnx AAF)
|
||||||
1.00: freebsd-2.1.7-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx JBB)
|
1.00: freebsd-2.1.7-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx JBB)
|
||||||
0.95: freebsd-2.2-beta_a-:i386-:-:i486-dx2-:- (tnx DA)
|
1.01: freebsd-2.1.7-release-:i386-:-:pentium.815\100-:- (tnx B1F)
|
||||||
0.91: freebsd-2.2-current-:i386-:-:i486-dx-:- (tnx DC)
|
1.01: freebsd-2.2-970422-releng-:i386-:-:-:- (tnx TM)
|
||||||
1.00: freebsd-2.2-release-:i386-:-:-:- (tnx MT)
|
1.00: freebsd-2.2-release-:i386-:-:-:- (tnx MT)
|
||||||
1.00: freebsd-2.2.1-release-:i386-:-:-:- (tnx TM)
|
1.01: freebsd-2.2-stable-:i386-:-:cyrix.5x86-:- (tnx A2B)
|
||||||
1.00: freebsd-2.2.1-release-:i386-:-:i486-dx2-:- (tnx BR)
|
1.01: freebsd-2.2-stable-:i386-:-:pentium-:- (tnx gary@systemics=???)
|
||||||
1.00: freebsd-2.2.1-release-:i386-:-:pentium-:- (tnx IW)
|
1.01: freebsd-2.2.1-release-:i386-:-:-:- (tnx M2R)
|
||||||
0.92: freebsd-3.0-current-:i386-:-:pentium-:- (tnx J2M)
|
1.01: freebsd-2.2.1-release-:i386-:-:i486-dx-:- (tnx PGR)
|
||||||
|
1.00: freebsd-2.2.1-release-:i386-:-:i486.dx2-:- (tnx BR)
|
||||||
|
1.01: freebsd-2.2.1-release-:i386-:-:pentium-:- (tnx REB)
|
||||||
|
1.01: freebsd-2.2.1-release-:i386-:-:pentium.pro-:- (tnx JS)
|
||||||
|
1.01: freebsd-2.2.2-release-:i386-:-:amd.am5x86.write-through-:- (tnx AGB)
|
||||||
|
1.01: freebsd-2.2.2-release-:i386-:-:i486-dx-:- (tnx A2L)
|
||||||
|
1.01: freebsd-2.2.2-release-:i386-:-:i486.dx2-:- (tnx D3S)
|
||||||
|
1.01: freebsd-2.2.2-release-:i386-:-:pentium-:- (tnx B2F)
|
||||||
|
1.01: freebsd-2.2.2-release-:i386-:-:pentium.pro-:- (tnx M2G)
|
||||||
|
1.01: freebsd-2.2.5-release-:i386-:-:i486-dx-:- (tnx R2N)
|
||||||
|
1.01: freebsd-2.2.5-release-:i386-:-:i486.dx2-:- (tnx AY)
|
||||||
|
1.01: freebsd-2.2.5-release-:i386-:-:pentium.pro-:- (tnx AI)
|
||||||
|
1.01: freebsd-2.2.5-stable-:i386-:-:i486.dx2-:- (tnx JK)
|
||||||
|
1.01: freebsd-2.2.5-stable-:i386-:-:pentium-:- (tnx root@defiant=???)
|
||||||
|
1.01: freebsd-2.2.6-release-:i386-:-:-:- (tnx TM)
|
||||||
|
1.01: freebsd-2.2.6-release-:i386-:-:amd.am5x86.write-through-:- (tnx root@skully=???)
|
||||||
|
1.00: freebsd-3.0-970209-snap-:i386-:-:-:- (tnx YF)
|
||||||
|
1.01: freebsd-3.0-970428-snap-:i386-:-:pentium-:- (tnx M3S)
|
||||||
|
1.01: freebsd-3.0-970807-snap-:i386-:-:amd.k6-:- (tnx KMD)
|
||||||
|
1.01: freebsd-3.0-980309-snap-:i386-:-:pentium-:- (tnx MM)
|
||||||
|
1.01: freebsd-3.0-current-:i386-:-:pentium-:- (tnx KB)
|
||||||
|
1.01: hp-ux-a.09.05-a-:-:-:9000.712-:- (tnx SV)
|
||||||
|
1.01: hp-ux-a.09.07-a-:-:-:9000.712-:- (tnx LB)
|
||||||
1.00: hp-ux-b.09.00-a-:-:-:9000.360-:- (tnx VV)
|
1.00: hp-ux-b.09.00-a-:-:-:9000.360-:- (tnx VV)
|
||||||
0.91: hp-ux-b.10.01-a-:-:-:9000.712-:- (tnx S2R)
|
1.01: hp-ux-b.10.20-a-:-:-:9000.755-:- (tnx BCK)
|
||||||
0.94: hp-ux-b.10.01-a-:-:-:9000.715-:- (tnx BG)
|
1.01: irix-5.3-11091812-:-:-:ip22-:- (tnx JL)
|
||||||
0.91: hp-ux-b.10.01-a-:-:-:9000.801-:- (tnx S2T)
|
1.01: irix-6.2-03131015-:-:-:ip22-:- (tnx DS)
|
||||||
0.93: irix-5.3-02091401-:-:-:ip22-:- (tnx PW)
|
1.01: irix64-6.2-03131016-:-:-:ip19-:- (tnx AH)
|
||||||
0.91: irix-5.3-11091811-:sgi-:-:ip19-:- (tnx BS)
|
1.01: irix64-6.2-06101031-:-:-:ip28-:- (tnx DB)
|
||||||
0.96: irix-5.3-11091812-:-:-:ip22-:- (tnx JL)
|
1.01: linux-1.2.13-:i386-:-:i486-:- (tnx RF)
|
||||||
1.00: irix-6.2-03131015-:-:-:ip22-:- (tnx SAS)
|
1.01: linux-1.2.13-:i386-:-:pentium-:- (tnx MEE)
|
||||||
0.92: linux-1.2.13-:i386-:-:i386-:- (tnx RN)
|
1.01: linux-1.99.4-:i386-:-:pentium-:- (tnx C2H)
|
||||||
1.00: linux-1.2.13-:i386-:-:i486-:- (tnx RF)
|
1.01: linux-2.0.0-:i386-:-:i486-:- (tnx kragen@gentle=???)
|
||||||
0.96: linux-1.2.13-:i386-:-:pentium-:- (tnx MEE)
|
1.01: linux-2.0.0-:i386-:-:pentium-:- (tnx MJD)
|
||||||
0.91: linux-1.3.90-:alpha-:-:alpha-:- (tnx ES)
|
1.01: linux-2.0.6-:i386-:-:pentium-:-
|
||||||
0.93: linux-1.99.6-:i386-:-:pentium-:- (tnx TG)
|
|
||||||
0.94: linux-2.0.0-:i386-:-:i486-:- (tnx PCO)
|
|
||||||
1.00: linux-2.0.0-:i386-:-:pentium-:- (tnx JJR)
|
|
||||||
0.91: linux-2.0.1-:alpha-:-:alpha-:- (tnx BET)
|
|
||||||
0.90: linux-2.0.1-:i386-:-:i486-:- (tnx DF)
|
|
||||||
0.93: linux-2.0.1-:i386-:-:pentium-:- (tnx FW)
|
|
||||||
0.95: linux-2.0.6-:i386-:-:pentium-:-
|
|
||||||
1.00: linux-2.0.6-:i386-:-:ppro-:- (tnx MR)
|
1.00: linux-2.0.6-:i386-:-:ppro-:- (tnx MR)
|
||||||
0.96: linux-2.0.7-:i386-:-:i486-:- (tnx TLM)
|
1.01: linux-2.0.7-:i386-:-:i486-:- (tnx TLM)
|
||||||
0.90: linux-2.0.7-:i386-:-:pentium-:- (tnx K2J)
|
1.01: linux-2.0.9-:i386-:-:i486-:- (tnx VBM)
|
||||||
0.94: linux-2.0.8-:i386-:-:i486-:- (tnx EP)
|
|
||||||
0.90: linux-2.0.9-:i386-:-:pentium-:- (tnx JM)
|
|
||||||
0.90: linux-2.0.10-:i386-:-:i486-:- (tnx JL)
|
|
||||||
0.90: linux-2.0.10-:i386-:-:pentium-:- (tnx S2R)
|
|
||||||
0.90: linux-2.0.11-:i386-:-:i486-:- (tnx ET)
|
|
||||||
0.92: linux-2.0.12-:i386-:-:i486-:- (tnx TRR)
|
|
||||||
0.90: linux-2.0.12-:i386-:-:ppro-:- (tnx SS)
|
|
||||||
0.96: linux-2.0.13-:i386-:-:pentium-:- (tnx BW)
|
0.96: linux-2.0.13-:i386-:-:pentium-:- (tnx BW)
|
||||||
0.90: linux-2.0.14-:i386-:-:pentium-:- (tnx PS)
|
1.01: linux-2.0.15-:i386-:-:i486-:- (tnx JCD)
|
||||||
0.91: linux-2.0.15-:i386-:-:pentium-:- (tnx CL)
|
1.01: linux-2.0.18-:i386-:-:i486-:- (tnx tk@avalon=???)
|
||||||
0.90: linux-2.0.16-:i386-:-:i486-:- (tnx AP)
|
1.01: linux-2.0.18-:i386-:-:pentium-:- (tnx root@webtvchat=???)
|
||||||
0.91: linux-2.0.17-:i386-:-:i486-:- (tnx JL)
|
|
||||||
0.91: linux-2.0.17-:i386-:-:pentium-:- (tnx SS)
|
|
||||||
0.95: linux-2.0.18-:i386-:-:i386-:- (tnx RN)
|
|
||||||
1.00: linux-2.0.18-:i386-:-:i486-:- (tnx JMS)
|
|
||||||
1.00: linux-2.0.18-:i386-:-:pentium-:- (tnx D2S)
|
|
||||||
0.92: linux-2.0.19-:alpha-:-:alpha-:- (tnx BET)
|
|
||||||
0.92: linux-2.0.20-:i386-:-:pentium-:- (tnx RJH)
|
|
||||||
0.92: linux-2.0.21-:i386-:-:i486-:- (tnx DCC)
|
|
||||||
0.91: linux-2.0.21-:i386-:-:pentium-:- (tnx root@contact=???)
|
|
||||||
0.92: linux-2.0.22-:i386-:-:i486-:- (tnx root@attila=???)
|
|
||||||
1.00: linux-2.0.22-:i386-:-:pentium-:- (tnx MDI)
|
1.00: linux-2.0.22-:i386-:-:pentium-:- (tnx MDI)
|
||||||
1.00: linux-2.0.23-:i386-:-:i486-:- (tnx B2L)
|
1.00: linux-2.0.23-:i386-:-:i486-:- (tnx B2L)
|
||||||
0.93: linux-2.0.23-:i386-:-:pentium-:- (tnx IW)
|
1.01: linux-2.0.24-:i386-:-:i486-:- (tnx GLM)
|
||||||
0.93: linux-2.0.24-:i386-:-:i486-:- (tnx root@cerberus=???)
|
|
||||||
1.00: linux-2.0.24-:i386-:-:pentium-:- (tnx VV)
|
1.00: linux-2.0.24-:i386-:-:pentium-:- (tnx VV)
|
||||||
0.96: linux-2.0.25-:i386-:-:i486-:- (tnx BDB)
|
0.96: linux-2.0.25-:i386-:-:i486-:- (tnx BDB)
|
||||||
1.00: linux-2.0.25-:i386-:-:pentium-:- (tnx AP)
|
1.01: linux-2.0.25-:i386-:-:pentium-:- (tnx KA)
|
||||||
0.93: linux-2.0.25-:i386-:-:ppro-:- (tnx CS)
|
0.93: linux-2.0.26-:i386-:-:i486-:- (tnx blynch@texas=???)
|
||||||
0.93: linux-2.0.26-:i386-:-:i486-:- (tnx blynch=???)
|
1.01: linux-2.0.26-:i386-:-:pentium-:- (tnx robbie@opus=???)
|
||||||
0.96: linux-2.0.26-:i386-:-:pentium-:- (tnx ESM)
|
|
||||||
0.93: linux-2.0.26-:i386-:-:ppro-:- (tnx modus@enews=???)
|
|
||||||
1.00: linux-2.0.27-:-:-:sparc-:- (tnx SVD)
|
1.00: linux-2.0.27-:-:-:sparc-:- (tnx SVD)
|
||||||
1.00: linux-2.0.27-:i386-:-:i486-:- (tnx FPL)
|
1.00: linux-2.0.27-:i386-:-:i386-:- (tnx ECG)
|
||||||
1.00: linux-2.0.27-:i386-:-:pentium-:- (tnx root@bullwinkle=???)
|
1.01: linux-2.0.27-:i386-:-:i486-:- (tnx BN)
|
||||||
1.00: linux-2.0.27-:i386-:-:ppro-:- (tnx DE)
|
1.01: linux-2.0.27-:i386-:-:pentium-:- (tnx EK)
|
||||||
1.00: linux-2.0.28-:i386-:-:i486-:- (tnx H2S)
|
1.01: linux-2.0.27-:i386-:-:ppro-:- (tnx L3L)
|
||||||
|
1.01: linux-2.0.28-:i386-:-:i486-:- (tnx AAF)
|
||||||
1.00: linux-2.0.28-:i386-:-:pentium-:- (tnx root@duggy=???)
|
1.00: linux-2.0.28-:i386-:-:pentium-:- (tnx root@duggy=???)
|
||||||
1.00: linux-2.0.28-:i386-:-:ppro-:- (tnx KJS)
|
1.01: linux-2.0.28-:i386-:-:ppro-:- (tnx S3T)
|
||||||
1.00: linux-2.0.29-:i386-:-:i486-:- (tnx PK)
|
1.01: linux-2.0.28-osfmach3-:-:-:ppc-:- (tnx CG)
|
||||||
1.00: linux-2.0.29-:i386-:-:pentium-:- (tnx CL)
|
1.01: linux-2.0.29-:alpha-:-:alpha-:- (tnx MB)
|
||||||
|
1.01: linux-2.0.29-:i386-:-:i386-:- (tnx AJK)
|
||||||
|
1.01: linux-2.0.29-:i386-:-:i486-:- (tnx FPL)
|
||||||
|
1.01: linux-2.0.29-:i386-:-:pentium-:- (tnx FW)
|
||||||
1.00: linux-2.0.29-:i386-:-:ppro-:- (tnx MMM)
|
1.00: linux-2.0.29-:i386-:-:ppro-:- (tnx MMM)
|
||||||
0.92: linux-2.1.1-:i386-:-:i486-:- (tnx nick@sga2=???)
|
1.01: linux-2.0.30-:-:-:sparc-:- (tnx J2P)
|
||||||
0.92: linux-2.1.7-:i386-:-:ppro-:- (tnx JL)
|
1.01: linux-2.0.30-:alpha-:-:alpha-:- (tnx WS)
|
||||||
0.92: linux-2.1.9-:i386-:-:pentium-:- (tnx AC)
|
1.01: linux-2.0.30-:i386-:-:i386-:- (tnx OK)
|
||||||
0.92: linux-2.1.10-:i386-:-:ppro-:- (tnx S3T)
|
1.00: linux-2.0.30-:i386-:-:i486-:- (tnx KUT)
|
||||||
|
1.01: linux-2.0.30-:i386-:-:i486-:- (tnx PK)
|
||||||
|
1.01: linux-2.0.30-:i386-:-:pentium-:- (tnx AV)
|
||||||
|
1.00: linux-2.0.30-:i386-:-:ppro-:- (tnx root@gate=???)
|
||||||
|
1.01: linux-2.0.30-osfmach3-:-:-:ppc-:- (tnx PTW)
|
||||||
|
1.01: linux-2.0.30u11-:i386-:-:pentium-:- (tnx JTB)
|
||||||
|
1.01: linux-2.0.31-:i386-:-:i486-:- (tnx SAE)
|
||||||
|
1.01: linux-2.0.31-:i386-:-:pentium-:- (tnx B3W)
|
||||||
|
1.01: linux-2.0.31-:i386-:-:ppro-:- (tnx JAK)
|
||||||
|
1.01: linux-2.0.32-:-:-:ie86-:- (tnx root@vmlinuz=???)
|
||||||
|
1.01: linux-2.0.32-:alpha-:-:alpha-:- (tnx NR)
|
||||||
|
1.01: linux-2.0.32-:i386-:-:i486-:- (tnx SC)
|
||||||
|
1.01: linux-2.0.32-:i386-:-:pentium-:- (tnx HT)
|
||||||
|
1.01: linux-2.0.32-:i386-:-:ppro-:- (tnx RK)
|
||||||
|
1.01: linux-2.0.33-:i386-:-:i486-:- (tnx RAB)
|
||||||
|
1.01: linux-2.0.33-:i386-:-:pentium-:- (tnx AF)
|
||||||
|
1.01: linux-2.0.33-:i386-:-:ppro-:- (tnx B2W)
|
||||||
|
1.01: linux-2.1.9-:i386-:-:i486-:- (tnx SJB)
|
||||||
|
1.01: linux-2.1.10-:i386-:-:i486-:- (tnx JB)
|
||||||
0.96: linux-2.1.13-:i386-:-:i486-:- (tnx ML)
|
0.96: linux-2.1.13-:i386-:-:i486-:- (tnx ML)
|
||||||
0.93: linux-2.1.13-:i386-:-:ppro-:- (tnx JL)
|
|
||||||
0.96: linux-2.1.14-:i386-:-:pentium-:- (tnx SCW)
|
0.96: linux-2.1.14-:i386-:-:pentium-:- (tnx SCW)
|
||||||
0.96: linux-2.1.23-:i386-:-:pentium-:- (tnx JF)
|
0.96: linux-2.1.23-:i386-:-:pentium-:- (tnx JF)
|
||||||
|
1.01: linux-2.1.24-:-:-:ppc-:- (tnx meta=???)
|
||||||
0.96: linux-2.1.25-:i386-:-:i486-:- (tnx JBF)
|
0.96: linux-2.1.25-:i386-:-:i486-:- (tnx JBF)
|
||||||
0.96: linux-2.1.25-:i386-:-:pentium-:- (tnx UO)
|
0.96: linux-2.1.25-:i386-:-:pentium-:- (tnx UO)
|
||||||
1.00: linux-2.1.26-:i386-:-:i486-:- (tnx DK)
|
1.00: linux-2.1.26-:i386-:-:i486-:- (tnx DK)
|
||||||
1.00: linux-2.1.27-:i386-:-:pentium-:- (tnx JF)
|
1.00: linux-2.1.27-:i386-:-:pentium-:- (tnx JF)
|
||||||
|
1.01: linux-2.1.28-:i386-:-:i486-:- (tnx HDG)
|
||||||
1.00: linux-2.1.28-:i386-:-:pentium-:- (tnx RGS)
|
1.00: linux-2.1.28-:i386-:-:pentium-:- (tnx RGS)
|
||||||
1.00: linux-2.1.29-:i386-:-:i486-:- (tnx SJW)
|
1.00: linux-2.1.29-:i386-:-:i486-:- (tnx SJW)
|
||||||
0.93: netbsd-1.2-:amiga-:-:amiga.4000.(m68040.cpu/mmu/fpu)-:- (tnx OS)
|
1.01: linux-2.1.35-:i386-:-:pentium-:- (tnx JF)
|
||||||
|
1.01: linux-2.1.36-:i386-:-:i486-:- (tnx ML)
|
||||||
|
1.01: linux-2.1.42-:i386-:-:i486-:- (tnx wtanaka=???)
|
||||||
|
1.01: linux-2.1.46-:i386-:-:pentium-:- (tnx VR)
|
||||||
|
1.01: linux-2.1.51-:i386-:-:pentium-:- (tnx KO)
|
||||||
|
1.01: linux-2.1.61-:i386-:-:i486-:- (tnx RO)
|
||||||
|
1.01: linux-2.1.65-:i386-:-:i486-:- (tnx F2T)
|
||||||
|
1.01: linux-2.1.71-:i386-:-:ppro-:- (tnx MJG)
|
||||||
|
1.01: linux-2.1.78-:i386-:-:pentium-:- (tnx AS)
|
||||||
|
1.01: linux-2.1.82-:i386-:-:pentium-:- (tnx AY)
|
||||||
|
1.01: linux-2.1.85-:i386-:-:pentium-:- (tnx PJH)
|
||||||
|
1.00: machten-4-0.4-:-:-:powerpc-:- (tnx RAM)
|
||||||
|
1.01: netbsd-1.1-:i386-:-:pentium.(genuineintel.586-class.cpu)-:- (tnx GL)
|
||||||
|
1.01: netbsd-1.2-:hp300-:-:-:- (tnx ML)
|
||||||
|
1.01: netbsd-1.2-:i386-:-:i486dx.(genuineintel.486-class.cpu)-:- (tnx T2K)
|
||||||
0.96: netbsd-1.2-:i386-:-:pentium.(genuineintel.586-class.cpu)-:- (tnx GH)
|
0.96: netbsd-1.2-:i386-:-:pentium.(genuineintel.586-class.cpu)-:- (tnx GH)
|
||||||
0.91: netbsd-1.2-:mac68k-:-:apple.macintosh.se/30..(68030)-:- (tnx hauke=???)
|
1.01: netbsd-1.2.1-:mac68k-:-:apple.macintosh.se/30..(68030)-:- (tnx HM)
|
||||||
0.92: netbsd-1.2b-:i386-:-:-:- (tnx MG)
|
1.01: netbsd-1.2.1-:sparc-:-:fmi,mb86904.@.110.mhz,.on-chip.fpu-:- (tnx ZU)
|
||||||
0.93: netbsd-1.2b-:i386-:-:pentium.(genuineintel.586-class.cpu)-:- (tnx MG)
|
|
||||||
0.96: netbsd-1.2c-:pmax-:-:-:- (tnx JLW)
|
0.96: netbsd-1.2c-:pmax-:-:-:- (tnx JLW)
|
||||||
0.92: nextstep-3.3-:hppa-:-:7100lc-:-
|
1.01: netbsd-1.3-:hp300-:-:hp.9000/433.(33mhz.mc68040.cpu+mmu+fpu,.4k.on-chip.physical.i/d.caches)-:- (tnx TB)
|
||||||
0.92: nextstep-3.3-:i386-:-:pentium-:-
|
1.01: netbsd-1.3.1-:sun3-:-:sun.3/60-:- (tnx MBS)
|
||||||
0.91: openbsd-1.2-:openbsd.m68k-:-:mac68k-:- (tnx AKB)
|
1.01: netbsd-1.3_alpha-:i386-:-:intel.pentium.(p54c).(586-class)-:- (tnx GL)
|
||||||
0.95: openbsd-2.0-:openbsd.i386-:-:i386-:- (tnx JPH)
|
1.01: nextstep-3.1-:mc680x0-:-:68040-:- (tnx JRY)
|
||||||
0.96: openbsd-2.0-:openbsd.m68k-:-:mac68k-:- (tnx AKB)
|
1.01: nextstep-3.3-:hppa-:-:7100lc-:-
|
||||||
|
1.01: nextstep-3.3-:i386-:-:pentium-:- (tnx HM)
|
||||||
|
1.01: nextstep-3.3-:mc680x0-:-:68040-:- (tnx WEB)
|
||||||
|
1.01: nextstep-4.1-:mc680x0-:-:68040-:- (tnx FN)
|
||||||
1.00: openbsd-2.0-hoth#0-:openbsd.i386-:-:i386-:- (tnx MBS)
|
1.00: openbsd-2.0-hoth#0-:openbsd.i386-:-:i386-:- (tnx MBS)
|
||||||
1.00: openbsd-2.0-mr_potatoe_head#2-:openbsd.i386-:-:i386-:- (JJMK)
|
1.00: openbsd-2.0-mr_potatoe_head#2-:openbsd.i386-:-:i386-:- (tnx JJMK)
|
||||||
0.96: openbsd-2.0-puma#1-:openbsd.m68k-:-:mac68k-:- (tnx AB)
|
0.96: openbsd-2.0-puma#1-:openbsd.m68k-:-:mac68k-:- (tnx AKB)
|
||||||
0.92: osf1-v3.0-347-:-:-:alpha-:- (tnx B2H)
|
1.01: openbsd-2.1-asgard#1-:openbsd.i386-:-:i386-:- (tnx ETT)
|
||||||
0.92: osf1-v4.0-386-:-:-:alpha-:- (tnx WW)
|
1.01: openbsd-2.1-generic#71-:openbsd.sparc-:-:sparc-:- (tnx MMM2)
|
||||||
0.96: sco_sv-3.2-2-:-:-:i386-:- (tnx DEH)
|
1.01: openbsd-2.1-katana#2-:openbsd.i386-:-:i386-:- (tnx CHR)
|
||||||
0.96: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4c-:sun4c- (tnx MBS)
|
1.01: openbsd-2.1-puma#0-:openbsd.m68k-:-:mac68k-:- (tnx AKB)
|
||||||
0.91: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4m-:sun4m- (tnx IS)
|
1.01: openbsd-2.2-ele#2-:openbsd.i386-:-:i386-:- (tnx RC)
|
||||||
0.92: sunos-4.1.3_u1-2-:sparc-:sun4-:sun4c-:sun4c- (tnx ANR)
|
1.01: openbsd-2.2-generic#424-:openbsd.i386-:-:i386-:- (tnx ETT)
|
||||||
0.93: sunos-4.1.3_u1-4-:sparc-:sun4-:sun4m-:sun4m- (tnx J2B)
|
1.01: osf1-v2.0-240-:-:-:alpha-:- (tnx JF)
|
||||||
|
1.00: osf1-v3.2-148-:-:-:alpha-:- (tnx DL)
|
||||||
|
1.01: osf1-v3.2-148-:-:-:alpha-:- (tnx RSK)
|
||||||
|
1.01: osf1-v3.2-41-:-:-:alpha-:- (tnx MSD)
|
||||||
|
1.01: osf1-v3.2-mp-4.2-:-:-:alpha-:- (tnx MSD)
|
||||||
|
1.01: osf1-v4.0-386-:-:-:alpha-:- (tnx TEE)
|
||||||
|
1.01: osf1-v4.0-464-:-:-:alpha-:- (tnx AWB)
|
||||||
|
1.01: osf1-v4.0-564-:-:-:alpha-:- (tnx A2P)
|
||||||
|
1.01: osf1-v4.0-564.32-:-:-:alpha-:- (tnx TLF)
|
||||||
|
1.01: osf1-v4.0-878-:-:-:alpha-:- (tnx BJM)
|
||||||
|
1.01: sco_sv-3.2-2-:-:-:i386-:- (tnx PW)
|
||||||
|
1.01: sinix-l-5.41-d0005-:-:-:mx300i-:- (tnx IH)
|
||||||
|
1.01: sunos-4.1.1-1-:mc68020-:sun3-:sun3-:sun3- (tnx JWB)
|
||||||
|
1.01: sunos-4.1.1-1-:mc68020-:sun3-:sun3x-:sun3x- (tnx TT)
|
||||||
|
1.01: sunos-4.1.3-jl-2-:sparc-:sun4-:sun4c-:sun4c- (tnx T2K)
|
||||||
|
1.01: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4c-:sun4c- (tnx MBS)
|
||||||
|
1.01: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4m-:sun4m- (tnx RSK)
|
||||||
|
1.01: sunos-4.1.3_u1-10-:sparc-:sun4-:sun4m-:sun4m- (tnx aoki=???)
|
||||||
1.00: sunos-4.1.3_u1-4-:unknown-:sun4-:sun4m-:sun4m- (tnx J2B)
|
1.00: sunos-4.1.3_u1-4-:unknown-:sun4-:sun4m-:sun4m- (tnx J2B)
|
||||||
0.91: sunos-4.1.3_u1-9-:sparc-:sun4-:sun4m-:sun4m- (tnx TA)
|
1.01: sunos-4.1.3_u1-6-:sparc-:sun4-:sun4m-:sun4m- (tnx RD)
|
||||||
0.91: sunos-4.1.4-2-:sparc-:sun4-:sun4c-:sun4c- (tnx ST)
|
1.01: sunos-4.1.4-1-:unknown-:sun4-:sun4m-:sun4m- (tnx M3S)
|
||||||
0.95: sunos-4.1.4-2-:sparc-:sun4-:sun4m-:sun4m- (tnx TG)
|
1.01: sunos-4.1.4-2-:sparc-:sun4-:sun4m-:sun4m-
|
||||||
0.95: sunos-4.1c-4.1.3-:sparc-:sun4-:sun4-:s4000- (tnx DBK)
|
1.01: sunos-5.3-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx JDJ)
|
||||||
0.91: sunos-5.4-generic-:sparc-:sun4-:sun4m-:sun4m-
|
1.01: sunos-5.4-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx jimo=???)
|
||||||
0.96: sunos-5.4-generic_101945-10-:sparc-:sun4-:sun4m-:sun4m- (tnx W2K)
|
0.96: sunos-5.4-generic_101945-10-:sparc-:sun4-:sun4m-:sun4m- (tnx W2K)
|
||||||
0.93: sunos-5.4-generic_101945-23-:-:sun4-:sun4m-:sun4m- (tnx JP)
|
|
||||||
0.92: sunos-5.4-generic_101945-23-:sparc-:-:sun4c-:- (tnx BH)
|
|
||||||
1.00: sunos-5.4-generic_101945-34-:sparc-:sun4-:sun4m-:sun4m- (tnx ACB)
|
1.00: sunos-5.4-generic_101945-34-:sparc-:sun4-:sun4m-:sun4m- (tnx ACB)
|
||||||
0.92: sunos-5.4-generic_101945-36-:-:sun4-:sun4c-:sun4c- (tnx JP)
|
|
||||||
0.95: sunos-5.4-generic_101945-43-:-:sun4-:sun4m-:sun4m- (tnx JP)
|
|
||||||
0.90: sunos-5.4-generic_101946-07-:-:i86pc-:i86pc-:i86pc- (tnx CR)
|
|
||||||
0.96: sunos-5.4-generic_101946-35-:i386-:i86pc-:i86pc-:i86pc- (tnx CK)
|
0.96: sunos-5.4-generic_101946-35-:i386-:i86pc-:i86pc-:i86pc- (tnx CK)
|
||||||
0.96: sunos-5.5-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx M2G)
|
1.01: sunos-5.5-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx seong=???)
|
||||||
0.93: sunos-5.5-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx CG)
|
1.01: sunos-5.5-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx SPM)
|
||||||
1.00: sunos-5.5-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx SG)
|
1.01: sunos-5.5-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx RDM)
|
||||||
1.00: sunos-5.5-generic_103093-02-:sparc-:sun4-:sun4m-:sun4m- (tnx RF)
|
1.01: sunos-5.5-generic-:sparc-:sun4-:sun4u-:sun4u- (tnx YC)
|
||||||
0.91: sunos-5.5-generic_103093-03-:sparc-:sun4-:sun4d-:sun4d- (tnx M3S)
|
1.01: sunos-5.5-generic_103093-02-:sparc-:sun4-:sun4m-:sun4m- (tnx RF)
|
||||||
0.96: sunos-5.5-generic_103093-03-:sparc-:sun4-:sun4m-:sun4m- (tnx RDM)
|
0.96: sunos-5.5-generic_103093-03-:sparc-:sun4-:sun4m-:sun4m- (tnx RDM)
|
||||||
0.91: sunos-5.5-generic_103093-03-:sparc-:sun4-:sun4u-:sun4u- (tnx olav=???)
|
1.01: sunos-5.5-generic_103093-06-:sparc-:sun4-:sun4m-:sun4m- (tnx ERH)
|
||||||
0.92: sunos-5.5-generic_103093-05-:sparc-:sun4-:sun4m-:sun4m- (tnx KE)
|
1.01: sunos-5.5-generic_103093-10-:sparc-:sun4-:sun4d-:sun4d- (tnx KT)
|
||||||
0.93: sunos-5.5-generic_103093-06-:sparc-:sun4-:sun4d-:sun4d- (tnx KT)
|
1.01: sunos-5.5-generic_103094-05-:i386-:i86pc-:i86pc-:i86pc- (tnx M2G)
|
||||||
1.00: sunos-5.5-generic_103093-06-:sparc-:sun4-:sun4m-:sun4m- (tnx TEE)
|
1.01: sunos-5.5.1-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx cro=???)
|
||||||
0.94: sunos-5.5-generic_103094-01-:i386-:i86pc-:i86pc-:i86pc- (tnx MD)
|
1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx CG)
|
||||||
0.91: sunos-5.5-generic_103094-03-:i386-:i86pc-:i86pc-:i86pc- (tnx ding=???)
|
1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx MBS)
|
||||||
1.00: sunos-5.5.1-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx DML)
|
1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4u-:sun4u-
|
||||||
1.00: sunos-5.5.1-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx JMT)
|
|
||||||
1.00: sunos-5.5.1-generic-:sparc-:sun4-:sun4u-:sun4u- (tnx TH)
|
|
||||||
0.96: sunos-5.5.1-generic_103640-02-:sparc-:sun4-:sun4m-:sun4m- (tnx SGC)
|
0.96: sunos-5.5.1-generic_103640-02-:sparc-:sun4-:sun4m-:sun4m- (tnx SGC)
|
||||||
0.95: sunos-5.5.1-generic_103640-03-:sparc-:sun4-:sun4m-:sun4m- (tnx MRG)
|
|
||||||
1.00: sunos-5.5.1-generic_103640-03-:sparc-:sun4-:sun4u-:sun4u- (tnx EG)
|
1.00: sunos-5.5.1-generic_103640-03-:sparc-:sun4-:sun4u-:sun4u- (tnx EG)
|
||||||
1.00: sunos-5.5.1-generic_103640-05-:sparc-:sun4-:sun4m-:sun4m- (tnx L2L)
|
1.00: sunos-5.5.1-generic_103640-05-:sparc-:sun4-:sun4m-:sun4m- (tnx L2L)
|
||||||
0.96: sunos-5.5.1-generic_patch-:i386-:i86pc-:i86pc-:i86pc- (tnx DK)
|
1.01: sunos-5.5.1-generic_103640-05-:sparc-:sun4-:sun4u-:sun4u- (tnx KY)
|
||||||
|
1.01: sunos-5.5.1-generic_103640-06-:sparc-:sun4-:sun4u-:sun4u- (tnx RA)
|
||||||
|
1.01: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4c-:sun4c- (tnx RA)
|
||||||
|
1.01: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4d-:sun4d- (tnx MS)
|
||||||
|
1.01: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4m-:sun4m- (tnx S2P)
|
||||||
|
1.01: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4u-:sun4u- (tnx CM)
|
||||||
|
1.01: sunos-5.5.1-generic_103640-12-:sparc-:sun4-:sun4m-:sun4m- (tnx IK)
|
||||||
|
1.01: sunos-5.5.1-generic_103640-18-:sparc-:sun4-:sun4u-:sun4u- (tnx PMH)
|
||||||
|
1.01: sunos-5.5.1-generic_103641-08-:i386-:i86pc-:i86pc-:i86pc- (tnx TL)
|
||||||
|
1.01: sunos-5.5.1-generic_103641-12-:i386-:i86pc-:i86pc-:i86pc- (tnx JS)
|
||||||
|
1.01: sunos-5.5.1-generic_105428-01-:sparc-:sun4-:sun4u-:sun4u- (tnx BCM)
|
||||||
|
0.96: sunos-5.5.1-generic_patch-:i386-:i86pc-:i86pc-:i86pc- (tnx D2K)
|
||||||
|
1.01: sunos-5.6-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx DS)
|
||||||
|
1.01: sunos-5.6-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx BDM)
|
||||||
|
1.01: sunos-5.6-generic-:sparc-:sun4-:sun4u-:sun4u- (tnx RPS)
|
||||||
|
1.01: sunos-5.6-generic_105182-01-:i386-:i86pc-:i86pc-:i86pc- (tnx JFK)
|
||||||
|
1.01: sunos-5.6-generic_105182-04-:i386-:i86pc-:i86pc-:i86pc- (tnx YC)
|
||||||
0.96: ultrix-4.3-1-:pmax-:-:risc-:- (tnx YF)
|
0.96: ultrix-4.3-1-:pmax-:-:risc-:- (tnx YF)
|
||||||
|
1.01: ultrix-4.4-0-:-:-:risc-:- (tnx RSK)
|
||||||
|
1.01: unix_sv-4.2mp-2.1.2-:i386-:-:i386-:- (tnx J2W)
|
||||||
|
|
|
||||||
37
RFCHCSC
37
RFCHCSC
|
|
@ -1,37 +0,0 @@
|
||||||
The Hash Convention For Mail System Status Codes (HCMSSC)
|
|
||||||
D. J. Bernstein, djb@pobox.com
|
|
||||||
19970201
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
RFC 1893 defines codes for mail delivery failures. For example,
|
|
||||||
code 5.1.1 means that the specified mailbox does not exist.
|
|
||||||
|
|
||||||
The qmail package sprays these codes all over the place, by adding a
|
|
||||||
code to the text of every error message, preceded by a hash mark and
|
|
||||||
surrounded by parentheses. It avoids using hash marks elsewhere.
|
|
||||||
|
|
||||||
|
|
||||||
2. Examples
|
|
||||||
|
|
||||||
Here is a typical HCMSSC SMTP error message:
|
|
||||||
|
|
||||||
421 load average too high, please come back later (#4.3.2)
|
|
||||||
|
|
||||||
Here is part of a typical HCMSSC bounce message:
|
|
||||||
|
|
||||||
<mail-loop@silverton.berkeley.edu>:
|
|
||||||
This is looping; it already has my Delivered-To line. (#5.7.1)
|
|
||||||
|
|
||||||
But qmail doesn't use HCMSSC when it repeats another MTA's error
|
|
||||||
message:
|
|
||||||
|
|
||||||
<foo@heaven.af.mil>:
|
|
||||||
127.3.4.5 does not like recipient.
|
|
||||||
Remote host said: 550 <foo>... User unknown (#5.1.1)
|
|
||||||
|
|
||||||
|
|
||||||
3. Security considerations
|
|
||||||
|
|
||||||
Don't take drastic action upon seeing "(#"; it might not be HCMSSC.
|
|
||||||
338
RFCLOOPS
338
RFCLOOPS
|
|
@ -1,338 +0,0 @@
|
||||||
Tools in the war on mail loops
|
|
||||||
D. J. Bernstein, djb@pobox.com
|
|
||||||
19970201
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
An automailer means any program that receives a mail message and
|
|
||||||
automatically sends one or more mail messages. This term is meant to
|
|
||||||
include not only a mail-based server, such as a mailing list exploder
|
|
||||||
or a vacation program, but also an SMTP server, which receives a
|
|
||||||
message from the network and relays it to a local or remote user.
|
|
||||||
|
|
||||||
In a network full of automailers, any mistake can cause a mail loop.
|
|
||||||
Since some automailers generate several outputs in response to a
|
|
||||||
single input, a loop can produce an exponential explosion of mail.
|
|
||||||
|
|
||||||
All the automailers in the qmail package follow a general philosophy
|
|
||||||
designed to prevent mail loops and limit the damage from any loops
|
|
||||||
that do occur. These automailers have been repeatedly observed to
|
|
||||||
fail safe: they stop loops in the face of typical failures by other
|
|
||||||
hosts. This document explains the philosophy and describes the
|
|
||||||
automailers.
|
|
||||||
|
|
||||||
To some extent the philosophy here simply repeats and amplifies
|
|
||||||
standard practice as codified in RFC 974 and RFC 1123. Unfortunately,
|
|
||||||
the standards do not adequately control bounce loops, since they do
|
|
||||||
not recognize that postmasters want to see double bounces; they do
|
|
||||||
not adequately control relaying loops; and they do not prevent
|
|
||||||
cross-host forwarding loops.
|
|
||||||
|
|
||||||
Terminology: The mail message received by an automailer is called
|
|
||||||
input. The mail messages sent by an automailer are called outputs.
|
|
||||||
For simplicity, this document focuses on the case that the input has
|
|
||||||
just one envelope recipient.
|
|
||||||
|
|
||||||
REMINDER: This document describes the automailers in the qmail
|
|
||||||
package. Other packages include automailers that do not fit the
|
|
||||||
descriptions given here.
|
|
||||||
|
|
||||||
Beware that the war on mail loops can never be won: any method of
|
|
||||||
preventing mail loops can be subverted by other hosts. I welcome
|
|
||||||
further development of techniques that work well in practice.
|
|
||||||
|
|
||||||
|
|
||||||
2. Basics
|
|
||||||
|
|
||||||
The output from an automailer is always further down the following
|
|
||||||
list than the input.
|
|
||||||
|
|
||||||
0 hops, <sender> is neither <> nor <#@[]> normal messages
|
|
||||||
1 hop, <sender> is neither <> nor <#@[]>
|
|
||||||
2 hops, <sender> is neither <> nor <#@[]>
|
|
||||||
etc.
|
|
||||||
0 hops, <sender> is <> bounces
|
|
||||||
1 hop, <sender> is <>
|
|
||||||
2 hops, <sender> is <>
|
|
||||||
etc.
|
|
||||||
0 hops, <sender> is <#@[]> double bounces
|
|
||||||
1 hop, <sender> is <#@[]>
|
|
||||||
2 hops, <sender> is <#@[]>
|
|
||||||
etc.
|
|
||||||
|
|
||||||
Here sender means the envelope sender address. Hops means the number
|
|
||||||
of Received and Delivered-To fields in the header. See sections 3.3
|
|
||||||
and 3.4 for an explanation of <> and <#@[]>.
|
|
||||||
|
|
||||||
Consequently, no automailer ever generates an entirely new normal
|
|
||||||
message in response to a normal message. If the output is a normal
|
|
||||||
message, it always has more hops than the input.
|
|
||||||
|
|
||||||
When input and output are both normal messages, both bounces, or both
|
|
||||||
double bounces, the output header is essentially the same as the
|
|
||||||
input header. However, when an automailer moves from a normal message
|
|
||||||
to a bounce, or from a bounce to a double bounce, it generates an
|
|
||||||
entirely new header.
|
|
||||||
|
|
||||||
An automailer may refuse to operate if the input has too many hops.
|
|
||||||
The definition of too many hops depends on the automailer. This
|
|
||||||
practice is called hop counting. Note that some existing messages
|
|
||||||
legitimately take as many as 20 hops. One automailer uses a limit of
|
|
||||||
100 hops; this will be adequate for all messages in the foreseeable
|
|
||||||
future.
|
|
||||||
|
|
||||||
Hop counting is a weapon of last resort. It will, if correctly
|
|
||||||
implemented, prevent all infinite loops; however, even a finite loop
|
|
||||||
can do practically infinite damage, as illustrated in section 4.3.
|
|
||||||
|
|
||||||
|
|
||||||
3. Pre-delivery automailers
|
|
||||||
|
|
||||||
Conceptually: The input is a message that has not yet reached its
|
|
||||||
envelope recipient address. It is fed to a relay, which attempts to
|
|
||||||
deliver the message directly to, or at least closer to, that address;
|
|
||||||
if the relay fails permanently, the message is fed to a bouncer or a
|
|
||||||
double-bouncer. Relays, bouncers, and double-bouncers are examples of
|
|
||||||
pre-delivery automailers.
|
|
||||||
|
|
||||||
A pre-delivery automailer produces at most one output.
|
|
||||||
|
|
||||||
The basic weapon against pre-delivery mail loops is gravity. A normal
|
|
||||||
message always moves closer to its envelope recipient, according to a
|
|
||||||
notion of distance defined in section 3.1. If it bounces before
|
|
||||||
reaching the recipient, it turns into a bounce message, which always
|
|
||||||
moves closer to the original envelope sender. If that in turn
|
|
||||||
bounces, it turns into a double bounce, which always moves closer to
|
|
||||||
a local postmaster. (Triple bounces do not exist.)
|
|
||||||
|
|
||||||
|
|
||||||
3.1. Distance
|
|
||||||
|
|
||||||
The distance from a DNS domain D to a recipient U@R is defined as
|
|
||||||
follows, when R has an MX list: the minimum preference of D in the
|
|
||||||
MX list, or 100000 if D does not appear in the list.
|
|
||||||
|
|
||||||
When R has no MX records, the distance from R to U@R is defined as 0,
|
|
||||||
and the distance from any other domain to U@R is defined as 100000.
|
|
||||||
|
|
||||||
Exception: If R is an alias, i.e., if R has a CNAME record, the
|
|
||||||
distance from any domain to U@R is defined as 500000.
|
|
||||||
|
|
||||||
The distance from a host H to U@R is defined as the minimum distance
|
|
||||||
to U@R from any domain that touches H. (``D touches H'' means ``D has
|
|
||||||
an A record listing one of H's IP addresses.'')
|
|
||||||
|
|
||||||
Exception: If H does not accept mail from the network, its distance
|
|
||||||
to any recipient is defined as 999999.
|
|
||||||
|
|
||||||
|
|
||||||
3.2. Relays
|
|
||||||
|
|
||||||
A relay is a pre-delivery automailer that sends the output towards
|
|
||||||
the envelope recipient. What this means for intra-host relays is not
|
|
||||||
discussed here. What this means for cross-host relays is the
|
|
||||||
following: if the relay is at host H, and it sends its output to host
|
|
||||||
T, then the distance from T to the output envelope recipient is
|
|
||||||
always smaller than the distance from H to the input envelope
|
|
||||||
recipient.
|
|
||||||
|
|
||||||
The following facts guarantee that certain cross-host relay behavior
|
|
||||||
is safe. For proofs of these facts, see Appendix A.
|
|
||||||
|
|
||||||
Fact 1: If R is an alias for X, X is not an alias, D touches T,
|
|
||||||
and T accepts mail from the network, then the distance from T to
|
|
||||||
U@X is smaller than the distance from H to U@R.
|
|
||||||
|
|
||||||
Fact 2: If R is not an alias, R has no MX records, H is not
|
|
||||||
touched by R, T is touched by R, and T accepts mail from the
|
|
||||||
network, then T is closer to U@R than H is.
|
|
||||||
|
|
||||||
Fact 3: If R is not an alias, R has an MX record with domain X and
|
|
||||||
preference p, H is not touched by any of the domains in the MX
|
|
||||||
list for R with preference <= p, T is touched by X, and T accepts
|
|
||||||
mail from the network, then T is closer to U@R than H is.
|
|
||||||
|
|
||||||
Also, a host that does not accept mail from the network can relay
|
|
||||||
messages to a nearby hub.
|
|
||||||
|
|
||||||
A relay adds a new Received header field to the top of the output.
|
|
||||||
Other than this, the output header, body, and envelope are exactly
|
|
||||||
the same as the input header, body, and envelope. Exception: If the
|
|
||||||
input envelope recipient is U@R, R is an alias for X, and X is not
|
|
||||||
an alias, the output envelope recipient is U@X.
|
|
||||||
|
|
||||||
|
|
||||||
3.3. Bouncers
|
|
||||||
|
|
||||||
A bouncer is a pre-delivery automailer that lets the envelope sender
|
|
||||||
know what happened to a message. Most bouncers send failure notices.
|
|
||||||
Some bouncers, such as vacation servers and echo servers, send
|
|
||||||
success notices.
|
|
||||||
|
|
||||||
In a bouncer's output, the envelope sender is <>, and the envelope
|
|
||||||
recipient is the input envelope sender. A bouncer refuses to operate
|
|
||||||
if the input envelope sender is <> or <#@[]>.
|
|
||||||
|
|
||||||
Some mailers on the Internet do not understand the <> convention. In
|
|
||||||
fact, some mailers will rewrite <> as <@host>. So any message with an
|
|
||||||
envelope recipient of <> or <@host> is discarded upon local delivery.
|
|
||||||
|
|
||||||
Unlike a relay, a bouncer produces output with a new header, not
|
|
||||||
simply a copy of the input header. For example:
|
|
||||||
|
|
||||||
(envelope) from <> to <djb@silverton.berkeley.edu>
|
|
||||||
Date: 2 Jan 1996 03:38:25 GMT
|
|
||||||
From: DELIVERY NOTICE SYSTEM <MAILER-DAEMON@heaven.af.mil>
|
|
||||||
To: djb@silverton.berkeley.edu
|
|
||||||
Subject: failure notice
|
|
||||||
|
|
||||||
However, the body of the bounce indicates the relevant input envelope
|
|
||||||
recipient, as well as the Message-ID of the input, if the input had a
|
|
||||||
Message-ID. The body of a failure notice includes a copy of the
|
|
||||||
entire input message.
|
|
||||||
|
|
||||||
|
|
||||||
3.4. Double-bouncers
|
|
||||||
|
|
||||||
A double-bouncer is a pre-delivery automailer that informs a local
|
|
||||||
postmaster of permanent failures to deliver bounce messages. Such
|
|
||||||
failures are generally caused by poorly configured hosts that produce
|
|
||||||
normal messages with faulty envelope sender addresses.
|
|
||||||
|
|
||||||
A double-bouncer refuses to operate unless the input envelope sender
|
|
||||||
is <>. The output envelope sender from a double-bouncer is <#@[]>;
|
|
||||||
note that <#@[]> cannot be used as an SMTP envelope sender under
|
|
||||||
RFC 821. The output envelope recipient is predetermined.
|
|
||||||
|
|
||||||
Note that double bounces are not suggested by RFC 1123. However,
|
|
||||||
faulty envelope sender addresses are usually configuration errors
|
|
||||||
that can and should be fixed. Some postmasters, faced with mail
|
|
||||||
software that throws away double bounces, resort to keeping copies of
|
|
||||||
all bounces; but single bounces are rarely the postmaster's problem.
|
|
||||||
|
|
||||||
|
|
||||||
4. Post-delivery automailers
|
|
||||||
|
|
||||||
Conceptually: The input is a message that has reached its envelope
|
|
||||||
recipient address. It is fed to a post-delivery automailer at that
|
|
||||||
address.
|
|
||||||
|
|
||||||
The basic weapon against post-delivery loops is a new header field,
|
|
||||||
Delivered-To, tracing all the forwarders and mailing lists that a
|
|
||||||
message has been through. This field has the side benefit of making
|
|
||||||
it much easier for a user (or for a postmaster seeing a bounce) to
|
|
||||||
figure out the path that the message took. Delivered-To is similar to
|
|
||||||
RFC 1327's DL-Expansion-History, but (1) it omits the time stamp,
|
|
||||||
removing any need for parsing, and (2) it has a much better name.
|
|
||||||
|
|
||||||
|
|
||||||
4.1. Exploders and repliers
|
|
||||||
|
|
||||||
There are two basic types of post-delivery automailers: exploders,
|
|
||||||
where the output envelope recipients are predetermined; and repliers,
|
|
||||||
where there is just one output, with envelope recipient determined
|
|
||||||
from the input.
|
|
||||||
|
|
||||||
Repliers normally determine the output envelope recipient as either
|
|
||||||
the input Reply-To header field, if it exists; or else the input
|
|
||||||
From header field, if it exists; or else the envelope sender. A
|
|
||||||
replier never produces an output to <> or <#@[]>.
|
|
||||||
|
|
||||||
Exploders are classified into mailing lists, where the output
|
|
||||||
envelope senders are predetermined, and forwarders, where every
|
|
||||||
output has envelope sender equal to the original envelope sender.
|
|
||||||
|
|
||||||
Exception: if the input envelope sender is <> or <#@[]>, then the
|
|
||||||
output envelope senders are equal to the input envelope sender, even
|
|
||||||
for a mailing list.
|
|
||||||
|
|
||||||
Note that, if the envelope sender of a mailing list with M bad
|
|
||||||
addresses is another exploder with E bad addresses, the local
|
|
||||||
postmaster will receive EM double bounces for each message to the
|
|
||||||
mailing list.
|
|
||||||
|
|
||||||
|
|
||||||
4.2. Delivered-To
|
|
||||||
|
|
||||||
Every post-delivery automailer adds a new Delivered-To header field
|
|
||||||
to the top of each output.
|
|
||||||
|
|
||||||
The contents of the Delivered-To field are typically the address of
|
|
||||||
the automailer, i.e., the input envelope recipient, conventionally
|
|
||||||
without any quoting. The contents of the Delivered-To field are in
|
|
||||||
any case entirely predetermined. The automailer checks if exactly the
|
|
||||||
same Delivered-To field already appears in the header; if so, it
|
|
||||||
refuses to operate.
|
|
||||||
|
|
||||||
A post-delivery automailer preserves existing Delivered-To and
|
|
||||||
Received fields. In fact, a post-delivery automailer generally
|
|
||||||
preserves all header fields. The exceptions are limited to known
|
|
||||||
fields that are not used for loop detection and that must be removed
|
|
||||||
for correct operation. For example, a replier generally changes the
|
|
||||||
body of a message and thus should not preserve the SVR4
|
|
||||||
Content-Length field.
|
|
||||||
|
|
||||||
|
|
||||||
4.3. An example
|
|
||||||
|
|
||||||
Aliases and mailing lists are highly dangerous, because they can
|
|
||||||
generate several outputs for each input.
|
|
||||||
|
|
||||||
Here is an extreme example. A user has three accounts, and wants any
|
|
||||||
message to any of the accounts to be delivered to all three. So he
|
|
||||||
forwards luser@host1 to luser@host2 and luser@host3, forwards
|
|
||||||
luser@host2 to luser@host1 and luser@host3, and forwards luser@host3
|
|
||||||
to luser@host1 and luser@host2.
|
|
||||||
|
|
||||||
Without Delivered-To, someone who sends a message to luser@host1 will
|
|
||||||
receive a practically infinite series of bounces. For example, with a
|
|
||||||
hop count limit of 50, the sender will receive 1125899906842624
|
|
||||||
bounces.
|
|
||||||
|
|
||||||
If all the hosts, or two out of the three, support Delivered-To, the
|
|
||||||
message will bounce just a few times. If just one of the hosts
|
|
||||||
supports Delivered-To, it will be the unfortunate victim of a loop
|
|
||||||
between the other two hosts---although the total number of bounces
|
|
||||||
will drop from practically infinite down to a few hundred, with
|
|
||||||
typical hop count limits.
|
|
||||||
|
|
||||||
|
|
||||||
Appendix A. Proofs of correctness for MX handling
|
|
||||||
|
|
||||||
Section 3.2 states three facts about the notion of distance defined
|
|
||||||
in section 3.1. Here are mathematical proofs of those facts.
|
|
||||||
|
|
||||||
Symbols: D, E, R, and X are domains; H and T are hosts; p and q are
|
|
||||||
nonnegative integers. {} is the empty set.
|
|
||||||
|
|
||||||
Hypotheses: M(R), the ``MX list for R,'' is a set of pairs (p,D)
|
|
||||||
where p <= 65535. There is a set A of domains, called ``aliases.''
|
|
||||||
There is a relation D->H, called ``D touches H.'' There is a set N of
|
|
||||||
hosts, called ``hosts that accept mail from the network.''
|
|
||||||
|
|
||||||
Definitions: m(D,R) = min { p: p = 100000 or (p,D) in M(R) } when
|
|
||||||
M(R) is nonempty. When M(R) is empty, m(D,R) is 0 if D = R, 100000
|
|
||||||
otherwise. f(D,R) is defined as 500000 if R is in A, m(D,R)
|
|
||||||
otherwise; this is the ``distance from D to U@R,'' for any U. g(H,R)
|
|
||||||
is defined as min { f(D,R): D->H } if H is in N, 999999 otherwise;
|
|
||||||
this is the ``distance from H to U@R,'' for any U.
|
|
||||||
|
|
||||||
Fact 1 (generalized): If R is in A, X is not in A, D->T, and T is in
|
|
||||||
N, then g(T,X) < g(H,R). Proof: R is in A, so f(E,R) = 500000 for any
|
|
||||||
E; thus g(H,R) >= 500000. X is not in A, so f(D,X) = m(D,X) <=
|
|
||||||
100000; hence g(T,X) <= f(D,X) <= 100000 < g(H,R).
|
|
||||||
|
|
||||||
Fact 2: If R is not in A, M(R) = {}, R->T, T is in N, and not R->H,
|
|
||||||
then g(T,R) < g(H,R). Proof: f(R,R) = m(R,R) = 0 since R is not in A
|
|
||||||
and M(R) = {}. T is in N so g(T,R) <= f(R,R) = 0 so g(T,R) = 0.
|
|
||||||
Suppose that g(H,R) <= g(T,R). Then g(H,R) = 0, so f(D,R) = 0 for
|
|
||||||
some D with D->H, so m(D,R) = 0. But then D = R by definition of m,
|
|
||||||
so R->H. Contradiction. Thus g(T,R) < g(H,R).
|
|
||||||
|
|
||||||
Fact 3: If R is not in A, (p,X) is in M(R), X->T, T is in N, and
|
|
||||||
(q,D) is not in M(R) whenever D->H and q <= p, then g(T,R) < g(H,R).
|
|
||||||
Proof: First m(X,R) <= p. R is not in A, so f(X,R) = m(X,R). T is in
|
|
||||||
N, so g(T,R) <= f(X,R). Thus g(T,R) <= p. Suppose that g(H,R) <= p.
|
|
||||||
Then f(D,R) <= p for some D with D->H, so m(D,R) <= p. But then
|
|
||||||
(m(D,R),D) is in M(R). Contradiction. Thus g(T,R) <= p < g(H,R).
|
|
||||||
122
RFCMXPS
122
RFCMXPS
|
|
@ -1,122 +0,0 @@
|
||||||
The Mail Exchanger Protocol Switch (MXPS)
|
|
||||||
D. J. Bernstein, djb@pobox.com
|
|
||||||
19970201
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
Mail messages today are transferred through the Simple Mail Transfer
|
|
||||||
Protocol (SMTP). One can imagine other protocols that achieve the
|
|
||||||
same results as SMTP but that, for example, use the network more
|
|
||||||
efficiently.
|
|
||||||
|
|
||||||
The Mail Exchanger Protocol Switch (MXPS) lets other protocols
|
|
||||||
compete with SMTP. A receiver can announce its support for another
|
|
||||||
protocol while operating properly with MXPS-ignorant senders. A
|
|
||||||
sender can check for support, with no overhead, while operating
|
|
||||||
properly with MXPS-ignorant receivers.
|
|
||||||
|
|
||||||
All receivers must support SMTP, i.e., must be able to receive
|
|
||||||
messages via SMTP. Similarly, all senders must be able to send
|
|
||||||
messages via SMTP.
|
|
||||||
|
|
||||||
|
|
||||||
2. The protocol switch
|
|
||||||
|
|
||||||
MXPS abuses the preference field of MX records. A protocol is
|
|
||||||
assigned to each possible preference.
|
|
||||||
|
|
||||||
SMTP is assigned to preferences 0 through 10000.
|
|
||||||
|
|
||||||
The initial MXPS experiment will involve preferences between 12800
|
|
||||||
and 13055 inclusive. These preferences are sliced into 16 portions:
|
|
||||||
|
|
||||||
12800, 12816, 12832, 12848, 12864, ..., 13040: slice #0 (SMTP)
|
|
||||||
12801, 12817, 12833, 12849, 12865, ..., 13041: slice #1 (QMTP)
|
|
||||||
12802, 12818, 12834, 12850, 12866, ..., 13042: slice #2
|
|
||||||
...
|
|
||||||
12815, 12831, 12847, 12863, 12879, ..., 13055: slice #15
|
|
||||||
|
|
||||||
Preferences in slice #0 are assigned SMTP. Preferences in slice #1
|
|
||||||
are assigned the Quick Mail Transfer Protocol (QMTP). Preferences in
|
|
||||||
the remaining slices may be assigned protocols in the future.
|
|
||||||
|
|
||||||
A receiver must support the protocol assigned to its preference. More
|
|
||||||
precisely, if an MX record points to domain D, and the MX preference
|
|
||||||
is assigned protocol P, then every host listed as an A record for D
|
|
||||||
must support protocol P.
|
|
||||||
|
|
||||||
When a sender, following the procedure outlined in RFC 974 (and
|
|
||||||
modified by RFC 1123), attempts to deliver a mail message as
|
|
||||||
specified by that MX record, it may use protocol P instead of SMTP.
|
|
||||||
If it does not support protocol P, it may treat the attempt as a
|
|
||||||
temporary failure and go on to the next MX record. However, the
|
|
||||||
sender must not skip every MX record.
|
|
||||||
|
|
||||||
MX records must never use unassigned preferences. A sender may treat
|
|
||||||
an unassigned preference as referring to SMTP.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
A.EXAMPLE.ORG IN MX 12801 A.EXAMPLE.ORG
|
|
||||||
B.EXAMPLE.ORG IN MX 12801 A.EXAMPLE.ORG
|
|
||||||
IN MX 12816 C.EXAMPLE.ORG
|
|
||||||
|
|
||||||
A sender with a message for A.EXAMPLE.ORG will try A.EXAMPLE.ORG by
|
|
||||||
QMTP. If it does not support QMTP, it will try SMTP instead. Note
|
|
||||||
that A.EXAMPLE.ORG must support both QMTP and SMTP.
|
|
||||||
|
|
||||||
A sender with a message for B.EXAMPLE.ORG will try A.EXAMPLE.ORG by
|
|
||||||
QMTP, then C.EXAMPLE.ORG by SMTP. If it does not support QMTP, it may
|
|
||||||
try SMTP instead of QMTP, or it may skip A.EXAMPLE.ORG.
|
|
||||||
|
|
||||||
Some of the above requirements might be violated if current
|
|
||||||
MXPS-ignorant domains use any preferences above 10000. Mail could be
|
|
||||||
unnecessarily rejected if any existing MXPS-ignorant domains have a
|
|
||||||
best-preference MX above 10000. I do not know any examples of such
|
|
||||||
domains.
|
|
||||||
|
|
||||||
|
|
||||||
3. Protocol requirements
|
|
||||||
|
|
||||||
MXPS operates purely at the link level. It does not change the
|
|
||||||
fundamental nature of Internet mail.
|
|
||||||
|
|
||||||
The function of a mail transfer protocol is to transmit a message, as
|
|
||||||
described below, together with an envelope sender address and one or
|
|
||||||
more envelope recipient addresses.
|
|
||||||
|
|
||||||
A recipient address is a sequence of characters---i.e., nonnegative
|
|
||||||
integers---including an ASCII @ (64). It is parsed as box@dom, where
|
|
||||||
dom does not contain an @. The interpretation of box is up to the
|
|
||||||
hosts listed as MX records for dom. A sender address may contain an
|
|
||||||
@, in which case it is also of the form box@dom; or it may be a
|
|
||||||
special address, such as the empty string.
|
|
||||||
|
|
||||||
A mail message is structured as a sequence of lines. A line is a
|
|
||||||
sequence of characters. Every mail transfer protocol must be able to
|
|
||||||
transmit all sufficiently short boring mail messages. A boring mail
|
|
||||||
message is one where (1) no line has more than 80 characters and (2)
|
|
||||||
each character is either 9 or between 32 and 127 inclusive. Note that
|
|
||||||
RFC 1341 defines a mechanism for encoding a message with characters
|
|
||||||
between 0 and 255 inclusive as a boring mail message of similar
|
|
||||||
length.
|
|
||||||
|
|
||||||
The receiver must indicate, for each recipient address, either
|
|
||||||
acceptance, permanent rejection, or temporary rejection of the
|
|
||||||
message. Acceptance means that the receiver has taken responsibility,
|
|
||||||
in the sense of RFC 1123, section 5.3.3, for delivering the message
|
|
||||||
to that recipient. Rejection means that the receiver will not deliver
|
|
||||||
the message to that recipient.
|
|
||||||
|
|
||||||
Mail transfer protocols may vary in many details, such as line
|
|
||||||
encodings, the means of expressing acceptance or rejection, the
|
|
||||||
maximum number of allowable recipients per envelope, the encoding of
|
|
||||||
envelope addresses, the nature of optional protocol extensions, etc.
|
|
||||||
|
|
||||||
|
|
||||||
4. Security considerations
|
|
||||||
|
|
||||||
MXPS does not change the following facts: An attacker who can subvert
|
|
||||||
the Domain Name System can steal or forge mail. An attacker who can
|
|
||||||
subvert TCP/IP can also steal or forge mail.
|
|
||||||
88
RFCNETSTR
88
RFCNETSTR
|
|
@ -1,88 +0,0 @@
|
||||||
Netstrings
|
|
||||||
D. J. Bernstein, djb@pobox.com
|
|
||||||
19970201
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
A netstring is a self-delimiting encoding of a string. Netstrings are
|
|
||||||
very easy to generate and to parse. Any string may be encoded as a
|
|
||||||
netstring; there are no restrictions on length or on allowed bytes.
|
|
||||||
Another virtue of a netstring is that it declares the string size up
|
|
||||||
front. Thus an application can check in advance whether it has enough
|
|
||||||
space to store the entire string.
|
|
||||||
|
|
||||||
Netstrings may be used as a basic building block for reliable network
|
|
||||||
protocols. Most high-level protocols, in effect, transmit a sequence
|
|
||||||
of strings; those strings may be encoded as netstrings and then
|
|
||||||
concatenated into a sequence of characters, which in turn may be
|
|
||||||
transmitted over a reliable stream protocol such as TCP.
|
|
||||||
|
|
||||||
Note that netstrings can be used recursively. The result of encoding
|
|
||||||
a sequence of strings is a single string. A series of those encoded
|
|
||||||
strings may in turn be encoded into a single string. And so on.
|
|
||||||
|
|
||||||
In this document, a string of 8-bit bytes may be written in two
|
|
||||||
different forms: as a series of hexadecimal numbers between angle
|
|
||||||
brackets, or as a sequence of ASCII characters between double quotes.
|
|
||||||
For example, <68 65 6c 6c 6f 20 77 6f 72 6c 64 21> is a string of
|
|
||||||
length 12; it is the same as the string "hello world!".
|
|
||||||
|
|
||||||
Although this document restricts attention to strings of 8-bit bytes,
|
|
||||||
netstrings could be used with any 6-bit-or-larger character set.
|
|
||||||
|
|
||||||
|
|
||||||
2. Definition
|
|
||||||
|
|
||||||
Any string of 8-bit bytes may be encoded as [len]":"[string]",".
|
|
||||||
Here [string] is the string and [len] is a nonempty sequence of ASCII
|
|
||||||
digits giving the length of [string] in decimal. The ASCII digits are
|
|
||||||
<30> for 0, <31> for 1, and so on up through <39> for 9. Extra zeros
|
|
||||||
at the front of [len] are prohibited: [len] begins with <30> exactly
|
|
||||||
when [string] is empty.
|
|
||||||
|
|
||||||
For example, the string "hello world!" is encoded as <31 32 3a 68
|
|
||||||
65 6c 6c 6f 20 77 6f 72 6c 64 21 2c>, i.e., "12:hello world!,". The
|
|
||||||
empty string is encoded as "0:,".
|
|
||||||
|
|
||||||
[len]":"[string]"," is called a netstring. [string] is called the
|
|
||||||
interpretation of the netstring.
|
|
||||||
|
|
||||||
|
|
||||||
3. Sample code
|
|
||||||
|
|
||||||
The following C code starts with a buffer buf of length len and
|
|
||||||
prints it as a netstring.
|
|
||||||
|
|
||||||
if (printf("%lu:",len) < 0) barf();
|
|
||||||
if (fwrite(buf,1,len,stdout) < len) barf();
|
|
||||||
if (putchar(',') < 0) barf();
|
|
||||||
|
|
||||||
The following C code reads a netstring and decodes it into a
|
|
||||||
dynamically allocated buffer buf of length len.
|
|
||||||
|
|
||||||
if (scanf("%9lu",&len) < 1) barf(); /* >999999999 bytes is bad */
|
|
||||||
if (getchar() != ':') barf();
|
|
||||||
buf = malloc(len + 1); /* malloc(0) is not portable */
|
|
||||||
if (!buf) barf();
|
|
||||||
if (fread(buf,1,len,stdin) < len) barf();
|
|
||||||
if (getchar() != ',') barf();
|
|
||||||
|
|
||||||
Both of these code fragments assume that the local character set is
|
|
||||||
ASCII, and that the relevant stdio streams are in binary mode.
|
|
||||||
|
|
||||||
|
|
||||||
4. Security considerations
|
|
||||||
|
|
||||||
The famous Finger security hole may be blamed on Finger's use of the
|
|
||||||
CRLF encoding. In that encoding, each string is simply terminated by
|
|
||||||
CRLF. This encoding has several problems. Most importantly, it does
|
|
||||||
not declare the string size in advance. This means that a correct
|
|
||||||
CRLF parser must be prepared to ask for more and more memory as it is
|
|
||||||
reading the string. In the case of Finger, a lazy implementor found
|
|
||||||
this to be too much trouble; instead he simply declared a fixed-size
|
|
||||||
buffer and used C's gets() function. The rest is history.
|
|
||||||
|
|
||||||
In contrast, as the above sample code shows, it is very easy to
|
|
||||||
handle netstrings without risking buffer overflow. Thus widespread
|
|
||||||
use of netstrings may improve network security.
|
|
||||||
89
RFCNRUDT
89
RFCNRUDT
|
|
@ -1,89 +0,0 @@
|
||||||
Notice-Requested-Upon-Delivery-To (NRUDT)
|
|
||||||
D. J. Bernstein, djb@pobox.com
|
|
||||||
19970201
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
The UNIX sendmail program has for many years supported a
|
|
||||||
Return-Receipt-To (RRT) header field that requests a notice of
|
|
||||||
successful final delivery.
|
|
||||||
|
|
||||||
Notice-Requested-Upon-Delivery-To (NRUDT) has the same basic
|
|
||||||
function. The big difference is that RRT lists the sender's address,
|
|
||||||
while NRUDT lists the recipient's address.
|
|
||||||
|
|
||||||
This change is critical. RRT works poorly for messages to multiple
|
|
||||||
recipients, because it requests a notice from every recipient. RRT in
|
|
||||||
a message to a large mailing list produces a giant, usually
|
|
||||||
unintentional, flood of mail. This problem is so severe that RRT has
|
|
||||||
been disabled in recent versions of sendmail.
|
|
||||||
|
|
||||||
NRUDT is designed to be adopted immediately, with minimal disruption,
|
|
||||||
as a solution to the problems of RRT. Note that NRUDT is merely a
|
|
||||||
request for notification; unlike the link-level Delivery Status
|
|
||||||
Notification SMTP extension, NRUDT does not provide a guarantee of
|
|
||||||
notification.
|
|
||||||
|
|
||||||
NRUDT is supported by the qreceipt program in the qmail package.
|
|
||||||
|
|
||||||
|
|
||||||
2. Syntax
|
|
||||||
|
|
||||||
NRUDT is a field in the header of an RFC 822 mail message. It has the
|
|
||||||
following syntax:
|
|
||||||
|
|
||||||
"Notice-Requested-Upon-Delivery-To" ":" 1#address
|
|
||||||
|
|
||||||
See RFC 822 for more information about header fields and addresses.
|
|
||||||
|
|
||||||
NRUDT requests that, upon final delivery of the message to any of the
|
|
||||||
specified addresses, the sender be notified. Note that more than one
|
|
||||||
address can appear in a single NRUDT header field. Multiple NRUDT
|
|
||||||
header fields should not appear in a single message.
|
|
||||||
|
|
||||||
|
|
||||||
3. Response
|
|
||||||
|
|
||||||
Upon successful final delivery of a message to any address listed in
|
|
||||||
an NRUDT header field, the host performing delivery may, if desired,
|
|
||||||
generate a success notice.
|
|
||||||
|
|
||||||
The success notice is similar to a failure notice as described in RFC
|
|
||||||
1123. Its envelope sender is <>. Its envelope recipient is the
|
|
||||||
envelope sender of the original message; however, if the envelope
|
|
||||||
sender of the original message is <>, a success notice is not sent.
|
|
||||||
|
|
||||||
The body of the success notice does not contain a copy of the
|
|
||||||
original message, but it does indicate the Message-ID of the original
|
|
||||||
message, as well as the relevant recipient address.
|
|
||||||
|
|
||||||
A success notice may indicate delivery to several addresses. For
|
|
||||||
example, given the following message:
|
|
||||||
|
|
||||||
(envelope) from djb@silverton.berkeley.edu
|
|
||||||
(envelope) to god@heaven.af.mil, angels@heaven.af.mil
|
|
||||||
Date: 1 Jan 1996 21:43:34 GMT
|
|
||||||
From: "D. J. Bernstein" <djb@silverton.berkeley.edu>
|
|
||||||
Message-Id: <19960101214334.8529.qmail@silverton.berkeley.edu>
|
|
||||||
Notice-Requested-Upon-Delivery-To: God <god@heaven.af.mil>,
|
|
||||||
angels@heaven.af.mil (You Know Who You Are)
|
|
||||||
...
|
|
||||||
|
|
||||||
a host may respond as follows:
|
|
||||||
|
|
||||||
(envelope) from <> to djb@silverton.berkeley.edu
|
|
||||||
Date: 1 Jan 1996 21:43:37 GMT
|
|
||||||
From: DELIVERY NOTICE SYSTEM <MAILER-DAEMON@heaven.af.mil>
|
|
||||||
To: djb@silverton.berkeley.edu
|
|
||||||
Subject: success notice
|
|
||||||
|
|
||||||
I delivered <19960101214334.8529.qmail@silverton.berkeley.edu>
|
|
||||||
to the following local mailboxes:
|
|
||||||
|
|
||||||
god@heaven.af.mil
|
|
||||||
angels@heaven.af.mil
|
|
||||||
|
|
||||||
Thanks for asking.
|
|
||||||
|
|
||||||
However, a success notice is never merged with a failure notice.
|
|
||||||
229
RFCQMTP
229
RFCQMTP
|
|
@ -1,229 +0,0 @@
|
||||||
Quick Mail Transfer Protocol (QMTP)
|
|
||||||
D. J. Bernstein, djb@pobox.com
|
|
||||||
19970201
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
The Quick Mail Transfer Protocol (QMTP) is a replacement for the
|
|
||||||
Simple Mail Transfer Protocol (SMTP). QMTP eliminates any need for
|
|
||||||
end-of-line scanning between hosts with the same end-of-line
|
|
||||||
convention. It features automatic pipelining and chunking, 8-bit
|
|
||||||
transmission, prior declaration of the message size, and efficient
|
|
||||||
batching. It is designed to be very easy to implement.
|
|
||||||
|
|
||||||
QMTP is supported by the qmail-qmtpd and maildir2qmtp programs in the
|
|
||||||
qmail package.
|
|
||||||
|
|
||||||
In this document, a string of 8-bit bytes may be written in two
|
|
||||||
different forms: as a series of hexadecimal numbers between angle
|
|
||||||
brackets, or as a sequence of ASCII characters between double quotes.
|
|
||||||
For example, <68 65 6c 6c 6f 20 77 6f 72 6c 64 21> is a string of
|
|
||||||
length 12; it is the same as the string "hello world!". Note that
|
|
||||||
these notations are part of this document, not part of the protocol.
|
|
||||||
|
|
||||||
|
|
||||||
2. Protocol
|
|
||||||
|
|
||||||
A QMTP client connects to a QMTP server, as discussed in section 7,
|
|
||||||
over a reliable stream protocol allowing transmission of 8-bit bytes.
|
|
||||||
|
|
||||||
Protocol outline: the client sends one or more packages; after each
|
|
||||||
package, the server sends back some responses.
|
|
||||||
|
|
||||||
The client begins by sending a package. A package contains a mail
|
|
||||||
message, an envelope sender address, and one or more envelope
|
|
||||||
recipient addresses. See section 4 for the format of a package.
|
|
||||||
|
|
||||||
When the server sees the end of the package, it sends back a series
|
|
||||||
of responses, one response for each envelope recipient address, in
|
|
||||||
the same order as given by the client. The server is not permitted to
|
|
||||||
change the order under any circumstances, even if two addresses are
|
|
||||||
the same. See section 5 for the format of a response.
|
|
||||||
|
|
||||||
The server is not permitted to send any portion of its responses to a
|
|
||||||
package until the client has sent the final byte of the package. The
|
|
||||||
client is permitted to close the connection before sending the final
|
|
||||||
byte of the package; in this case, the server must throw away the
|
|
||||||
package without attempting to deliver the message. However, the
|
|
||||||
server must not throw away previously accepted messages.
|
|
||||||
|
|
||||||
The client does NOT need to wait for a server response before sending
|
|
||||||
another package. The server must NOT throw away incoming data when it
|
|
||||||
sends a response. It is the client's responsibility to avoid
|
|
||||||
deadlock: if it sends a package before receiving all expected server
|
|
||||||
responses, it must continuously watch for those responses. The server
|
|
||||||
is permitted to delay its responses if further data has already shown
|
|
||||||
up from the client; while it is delaying responses, it must not pause
|
|
||||||
to wait for further data for the client.
|
|
||||||
|
|
||||||
The server is permitted to close the connection at any time, although
|
|
||||||
high-quality servers will try to avoid doing so. Any response not
|
|
||||||
received by the client indicates a temporary failure.
|
|
||||||
|
|
||||||
A QMTP session should take at most 1 hour. Both sides are expected
|
|
||||||
to close the connection after this time.
|
|
||||||
|
|
||||||
|
|
||||||
3. Messages
|
|
||||||
|
|
||||||
In this document, an ``8-bit mail message'' means a sequence of
|
|
||||||
lines. Each line is a string of zero or more 8-bit bytes.
|
|
||||||
|
|
||||||
A message is called ``safe'' if none of its bytes are <0a>.
|
|
||||||
|
|
||||||
Implementation note: Here is the intended interpretation of text
|
|
||||||
files as messages under some current operating systems. Under DOS, a
|
|
||||||
message is stored on disk as
|
|
||||||
|
|
||||||
first line, <0d 0a>, second line, <0d 0a> ... <0d 0a>, last line.
|
|
||||||
|
|
||||||
Under UNIX, a message is stored on disk as
|
|
||||||
|
|
||||||
first line, <0a>, second line, <0a> ... <0a>, last line.
|
|
||||||
|
|
||||||
Notice that both of these encodings are reversible for safe messages.
|
|
||||||
|
|
||||||
In practice, it is very common for the last line to be empty. Many
|
|
||||||
existing utilities refer to the last line as a ``partial line'' and
|
|
||||||
ignore it whether or not it is empty.
|
|
||||||
|
|
||||||
|
|
||||||
4. Packages
|
|
||||||
|
|
||||||
A package is the concatenation of three strings:
|
|
||||||
|
|
||||||
first, an encoded 8-bit mail message;
|
|
||||||
second, an encoded envelope sender address;
|
|
||||||
third, an encoded series of encoded envelope recipient addresses.
|
|
||||||
|
|
||||||
Each envelope address is a string of 8-bit bytes. The interpretation
|
|
||||||
of addresses depends on the environment in which QMTP is used and is
|
|
||||||
outside the scope of this document. Each address is encoded as a
|
|
||||||
netstring, as discussed in section 6. The series of encoded recipient
|
|
||||||
addresses is in turn encoded as a netstring.
|
|
||||||
|
|
||||||
A message is encoded as a string of 8-bit bytes in one of two ways:
|
|
||||||
|
|
||||||
Encoding #1 is <0d>, the first line, <0d 0a>, the second line,
|
|
||||||
<0d 0a>, the third line, ..., <0d 0a>, the last line.
|
|
||||||
|
|
||||||
Encoding #2 is <0a>, the first line, <0a>, the second line, <0a>,
|
|
||||||
the third line, ..., <0a>, the last line.
|
|
||||||
|
|
||||||
This string of 8-bit bytes is in turn encoded as a netstring, as
|
|
||||||
discussed in section 6.
|
|
||||||
|
|
||||||
Every server must be prepared to handle encoding #1 and encoding #2.
|
|
||||||
A server must not reject a message merely because of its encoding.
|
|
||||||
|
|
||||||
Implementation note: The intent of encoding #1 and encoding #2 is to
|
|
||||||
allow very straightforward handling of text files under DOS and UNIX
|
|
||||||
respectively. The programmer can print <0d> or <0a> and then simply
|
|
||||||
copy the file.
|
|
||||||
|
|
||||||
|
|
||||||
5. Responses
|
|
||||||
|
|
||||||
Each response is a nonempty string of 8-bit bytes, encoded as a
|
|
||||||
netstring. The first byte of the string is one of the following:
|
|
||||||
|
|
||||||
"K" The message has been accepted for delivery to this envelope
|
|
||||||
recipient. This is morally equivalent to the 250 response to
|
|
||||||
DATA in SMTP; it is subject to the reliability requirements
|
|
||||||
of RFC 1123, section 5.3.3.
|
|
||||||
|
|
||||||
"Z" Temporary failure. The client should try again later.
|
|
||||||
|
|
||||||
"D" Permanent failure.
|
|
||||||
|
|
||||||
The remaining bytes are a description of what happened. It is
|
|
||||||
expected that the description, when interpreted as UTF-2 characters,
|
|
||||||
(1) will be human-readable, (2) will not repeat the envelope
|
|
||||||
recipient address, and (3) will not include formatting characters
|
|
||||||
other than <20>. However, these expectations are not requirements,
|
|
||||||
and the client should be ready for arbitrary bytes from the server.
|
|
||||||
|
|
||||||
Descriptions beginning with <20> are reserved for future extensions.
|
|
||||||
In descriptions not beginning with <20>, the character "#" must not
|
|
||||||
appear except in HCMSSC codes.
|
|
||||||
|
|
||||||
A server must NOT accept a safe message unless it can store the
|
|
||||||
message without corruption. More precisely: if the encoded message
|
|
||||||
sent by the client matches the encoding of some safe message M, then
|
|
||||||
acceptance means that the server is accepting responsibility to
|
|
||||||
deliver M to the envelope recipient. (There is at most one
|
|
||||||
possibility for M, since encodings are reversible on safe messages.)
|
|
||||||
Deletion of nulls is NOT permissible; a server that deletes nulls
|
|
||||||
must reject any message containing nulls. Folding of long lines and
|
|
||||||
high-bit stripping are also NOT permissible.
|
|
||||||
|
|
||||||
Servers are permitted to change unsafe messages.
|
|
||||||
|
|
||||||
|
|
||||||
6. Netstrings
|
|
||||||
|
|
||||||
Any string of 8-bit bytes may be encoded as [len]":"[string]",".
|
|
||||||
Here [string] is the string and [len] is a nonempty sequence of ASCII
|
|
||||||
digits giving the length of [string] in decimal. The ASCII digits are
|
|
||||||
<30> for 0, <31> for 1, and so on up through <39> for 9. Extra zeros
|
|
||||||
at the front of [len] are prohibited: [len] begins with <30> exactly
|
|
||||||
when [string] is empty.
|
|
||||||
|
|
||||||
For example, the string "hello world!" is encoded as <31 32 3a 68
|
|
||||||
65 6c 6c 6f 20 77 6f 72 6c 64 21 2c>, i.e., "12:hello world!,". The
|
|
||||||
empty string is encoded as "0:,".
|
|
||||||
|
|
||||||
[len]":"[string]"," is called a netstring. [string] is called the
|
|
||||||
interpretation of the netstring.
|
|
||||||
|
|
||||||
|
|
||||||
7. Encapsulation
|
|
||||||
|
|
||||||
QMTP may be used on top of TCP. A QMTP-over-TCP server listens for
|
|
||||||
TCP connections on port 209.
|
|
||||||
|
|
||||||
|
|
||||||
8. Examples
|
|
||||||
|
|
||||||
A client opens a connection and sends the concatenation of the
|
|
||||||
following strings:
|
|
||||||
|
|
||||||
"246:" <0a>
|
|
||||||
"Received: (qmail-queue invoked by uid 0);"
|
|
||||||
" 29 Jul 1996 09:36:40 -0000" <0a>
|
|
||||||
"Date: 29 Jul 1996 11:35:35 -0000" <0a>
|
|
||||||
"Message-ID: <19960729113535.375.qmail@heaven.af.mil>" <0a>
|
|
||||||
"From: God@heaven.af.mil" <0a>
|
|
||||||
"To: djb@silverton.berkeley.edu (D. J. Bernstein)" <0a>
|
|
||||||
<0a>
|
|
||||||
"This is a test." <0a> ","
|
|
||||||
"24:" "God-DSN-37@heaven.af.mil" ","
|
|
||||||
"30:" "26:djb@silverton.berkeley.edu," ","
|
|
||||||
|
|
||||||
"356:" <0d>
|
|
||||||
"From: MAILER-DAEMON@heaven.af.mil" <0d 0a>
|
|
||||||
"To:" <0d 0a>
|
|
||||||
" Hate." <22> "The Quoting" <22>
|
|
||||||
"@SILVERTON.berkeley.edu," <0d 0a>
|
|
||||||
" " <22> "\\Backslashes!" <22>
|
|
||||||
"@silverton.BERKELEY.edu" <0d 0a>
|
|
||||||
<0d 0a>
|
|
||||||
"The recipient addresses here could"
|
|
||||||
" have been encoded in SMTP as" <0d 0a>
|
|
||||||
"" <0d 0a>
|
|
||||||
" RCPT TO:<Hate.The\ Quoting@silverton.berkeley.EDU>" <0d 0a>
|
|
||||||
" RCPT TO:<\\Backslashes!@silverton.berkeley.edu>" <0d 0a>
|
|
||||||
<0d 0a>
|
|
||||||
"This ends with a partial last line, right here" ","
|
|
||||||
"0:" ","
|
|
||||||
"83:" "39:Hate.The Quoting@silverton.berkeley.edu,"
|
|
||||||
"36:\Backslashes!@silverton.berkeley.EDU," ","
|
|
||||||
|
|
||||||
The server sends the following response, indicating acceptance:
|
|
||||||
|
|
||||||
"21:Kok 838640135 qp 1390,"
|
|
||||||
"21:Kok 838640135 qp 1391,"
|
|
||||||
"21:Kok 838640135 qp 1391,"
|
|
||||||
|
|
||||||
The client closes the connection.
|
|
||||||
155
RFCQSBMF
155
RFCQSBMF
|
|
@ -1,155 +0,0 @@
|
||||||
The qmail-send Bounce Message Format (QSBMF)
|
|
||||||
D. J. Bernstein, djb@pobox.com
|
|
||||||
19970201
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
When a message transport agent (MTA) finds itself permanently unable
|
|
||||||
to deliver a mail message, it generates a new message, generally
|
|
||||||
known as a bounce message, back to the envelope sender.
|
|
||||||
|
|
||||||
Bounce messages produced by the qmail-send program display the list
|
|
||||||
of failed recipient addresses, an explanation for each address, and a
|
|
||||||
copy of the original message, in a format that is easy for both
|
|
||||||
humans and programs to read. For example:
|
|
||||||
|
|
||||||
Date: 17 Mar 1996 03:54:40 -0000
|
|
||||||
From: MAILER-DAEMON@silverton.berkeley.edu
|
|
||||||
To: djb@silverton.berkeley.edu
|
|
||||||
Subject: failure notice
|
|
||||||
|
|
||||||
Hi. This is the qmail-send program at silverton.berkeley.edu.
|
|
||||||
I'm afraid I wasn't able to deliver your message to the
|
|
||||||
following addresses. This is a permanent error; I've given up.
|
|
||||||
Sorry it didn't work out.
|
|
||||||
|
|
||||||
<god@heaven.af.mil>:
|
|
||||||
Sorry, I couldn't find any host by that name.
|
|
||||||
|
|
||||||
--- Below this line is a copy of the message.
|
|
||||||
|
|
||||||
Return-Path: <djb@silverton.berkeley.edu>
|
|
||||||
Received: (qmail 317 invoked by uid 7); 17 Mar 1996 03:54:38 -0000
|
|
||||||
Date: 17 Mar 1996 03:54:38 -0000
|
|
||||||
Message-ID: <19960317035438.316.qmail@silverton.berkeley.edu>
|
|
||||||
From: djb@silverton.berkeley.edu (D. J. Bernstein)
|
|
||||||
To: god@heaven.af.mil
|
|
||||||
Subject: are you there?
|
|
||||||
|
|
||||||
Just checking.
|
|
||||||
|
|
||||||
This document defines qmail-send's format for bounce messages.
|
|
||||||
|
|
||||||
In this document, a string of 8-bit bytes may be written in two
|
|
||||||
different forms: as a series of hexadecimal numbers between angle
|
|
||||||
brackets, or as a sequence of ASCII characters between double quotes.
|
|
||||||
For example, <68 65 6c 6c 6f 20 77 6f 72 6c 64 21> is a string of
|
|
||||||
length 12; it is the same as the string "hello world!".
|
|
||||||
|
|
||||||
|
|
||||||
2. Format
|
|
||||||
|
|
||||||
A bounce message may be recognized as QSBMF as follows: its body
|
|
||||||
begins with the characters "Hi. This is the" exactly as shown.
|
|
||||||
|
|
||||||
The body of the message has four pieces: an introductory paragraph,
|
|
||||||
zero or more recipient paragraphs, a break paragraph, and the
|
|
||||||
original message.
|
|
||||||
|
|
||||||
Each paragraph is a series of non-blank lines followed by a single
|
|
||||||
blank line. The break paragraph begins with the character "-". All
|
|
||||||
other paragraphs begin with characters other than "-". The break
|
|
||||||
paragraph is human-readable but provides no interesting information.
|
|
||||||
|
|
||||||
The introductory paragraph is human-readable. It gives the name and
|
|
||||||
human-comprehensible location of the MTA, but parsers should not
|
|
||||||
attempt to use this information.
|
|
||||||
|
|
||||||
The only type of recipient paragraph described here is a failure
|
|
||||||
paragraph, which begins with the character "<". Paragraphs beginning
|
|
||||||
with other characters are reserved for future extensions.
|
|
||||||
|
|
||||||
The first line of a failure paragraph ends with the characters ">:".
|
|
||||||
Everything between the leading "<" and the trailing ">:" is an
|
|
||||||
(unquoted) Internet mail address.
|
|
||||||
|
|
||||||
A failure paragraph asserts that the MTA was permanently unable to
|
|
||||||
deliver the message to the mail address shown on the first line; the
|
|
||||||
MTA will not attempt further deliveries to that address. The
|
|
||||||
remaining lines of the paragraph give a human-readable description of
|
|
||||||
the reason for failure. Descriptions beginning with <20>, and
|
|
||||||
descriptions containing "#", are reserved for future extensions.
|
|
||||||
|
|
||||||
The envelope sender might not have sent his message to the address
|
|
||||||
shown. There are two reasons for this. First, the MTA may freely
|
|
||||||
replace unprintable characters with "_". Second, the original
|
|
||||||
recipient address may have been an alias for the address shown.
|
|
||||||
|
|
||||||
The original message is an exact copy of the message received by the
|
|
||||||
MTA, including both header and body, preceded by a Return-Path field
|
|
||||||
showing the envelope sender.
|
|
||||||
|
|
||||||
|
|
||||||
3. Comparison with 1892/1894
|
|
||||||
|
|
||||||
RFC 1892 and RFC 1894 together describe a format for delivery status
|
|
||||||
notifications. I have decided not to use that format, because I
|
|
||||||
believe that its complexity will prevent wide implementation and
|
|
||||||
increase the burden on people who manage mailing lists.
|
|
||||||
|
|
||||||
QSBMF is dedicated to failure reports, whereas RFC 1894 allows
|
|
||||||
success reports and deferral reports. Although it would be possible
|
|
||||||
to add deferral paragraphs and success paragraphs to QSBMF, it would
|
|
||||||
be even easier to design separate formats for such notices. I have
|
|
||||||
trouble reading mixed failure/deferral reports.
|
|
||||||
|
|
||||||
QSBMF always returns the entire original message. RFC 1892 allows
|
|
||||||
the MTA to return nothing or to return just the headers; it states
|
|
||||||
``Return of content may be wasteful of network bandwidth.'' However,
|
|
||||||
failure notices are very rare, so the overall loss of bandwidth in
|
|
||||||
this case is insignificant. A much more important issue is storage
|
|
||||||
space: someone who manages a big mailing list does not want to have
|
|
||||||
to store several copies of each message in the form of bounces. The
|
|
||||||
best solution is to have each bounce automatically fed through a
|
|
||||||
program that stores only the critical information. I expect such
|
|
||||||
programs to spring up quickly for QSBMF.
|
|
||||||
|
|
||||||
RFC 1894 provides language-independent error messages, as described
|
|
||||||
by RFC 1893. One can achieve the same results more easily by adding
|
|
||||||
structure to the human-readable failure descriptions, for example
|
|
||||||
with HCMSSC.
|
|
||||||
|
|
||||||
RFC 1894 is able to communicate an ``envelope ID'' and the original
|
|
||||||
envelope recipient address specified by the sender. Unfortunately,
|
|
||||||
this information will almost never be available, since it requires
|
|
||||||
support by every intermediate MTA. All of the applications of this
|
|
||||||
information can be handled reliably, right now, with VERPs; this
|
|
||||||
requires support from the sender's MTA but not from other hosts.
|
|
||||||
|
|
||||||
RFC 1894 includes several pieces of information that might be of
|
|
||||||
human interest but can be seen just as easily from Received lines:
|
|
||||||
the name of the MTA where delivery failed, the name of the previous
|
|
||||||
MTA, timestamps, etc.
|
|
||||||
|
|
||||||
All of these RFC 1894 features have a cost: complexity. A program
|
|
||||||
cannot parse an 1894 report without parsing RFC 822 header fields
|
|
||||||
and understanding quite a bit of MIME. This will limit the
|
|
||||||
availability of parsing software. In the meantime, such reports are
|
|
||||||
annoying to mailing list maintainers, since they are full of
|
|
||||||
uninteresting information and are difficult to parse visually.
|
|
||||||
|
|
||||||
|
|
||||||
4. Security considerations
|
|
||||||
|
|
||||||
Bounce messages may be forged. Never remove someone from a mailing
|
|
||||||
list without sending him a message stating that you are doing so,
|
|
||||||
even if the reason for removal is a series of apparent bounce
|
|
||||||
messages from his address.
|
|
||||||
|
|
||||||
If you send a message along a secret path, you should change the
|
|
||||||
envelope sender address of the message to yourself, so that a bounce
|
|
||||||
will not reveal anything to the original sender. In other words: for
|
|
||||||
secret forwarding, use a mailing list, not a forwarder.
|
|
||||||
|
|
||||||
See RFC 1894 for further discussion of these points.
|
|
||||||
88
RFCVERP
88
RFCVERP
|
|
@ -1,88 +0,0 @@
|
||||||
Variable Envelope Return Paths
|
|
||||||
D. J. Bernstein, djb@pobox.com
|
|
||||||
19970201
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
The fundamental problem in managing a large mailing list is matching
|
|
||||||
bounce messages to subscription addresses.
|
|
||||||
|
|
||||||
Often a bounce message refers to a failing address that does not
|
|
||||||
appear on the mailing list. One of the mailing list subscribers is
|
|
||||||
forwarding messages to that address. Which subscriber? As the list
|
|
||||||
grows, this question becomes more and more difficult to answer.
|
|
||||||
|
|
||||||
Sometimes a bounce message doesn't identify the address that failed.
|
|
||||||
On occasion it doesn't even include a copy of the original message.
|
|
||||||
See RFC 1211 for an extensive collection of horror stories.
|
|
||||||
|
|
||||||
In theory, one could solve this problem with the DSN option and DSN
|
|
||||||
format described in RFC 1891, RFC 1892, and RFC 1894. Unfortunately,
|
|
||||||
the DSN option is useless unless it is supported by every
|
|
||||||
intermediate MTA. The complexity of RFC 1891 means that it will be
|
|
||||||
many years, perhaps infinitely many, before DSNs are universally
|
|
||||||
supported. Furthermore, the complexity of RFC 1894 means that parsing
|
|
||||||
the subscriber address is difficult even on the occasions that the
|
|
||||||
address is available.
|
|
||||||
|
|
||||||
Variable envelope return paths (VERPs) completely eliminate this
|
|
||||||
problem _right now_. They automatically and reliably identify the
|
|
||||||
subscription address relevant to each bounce message. They provide
|
|
||||||
the address in a form that is trivial for automated bounce handlers
|
|
||||||
to parse. They require support from the local mailer, but they do not
|
|
||||||
require support from any other hosts.
|
|
||||||
|
|
||||||
|
|
||||||
2. Variable envelope return paths
|
|
||||||
|
|
||||||
Here is how VERPs work: each recipient of the message sees a
|
|
||||||
different envelope sender address. When a message to the
|
|
||||||
djb-sos@silverton.berkeley.edu mailing list is sent to
|
|
||||||
God@heaven.af.mil, for example, it has the following envelope sender:
|
|
||||||
|
|
||||||
djb-sos-owner-God=heaven.af.mil@silverton.berkeley.edu
|
|
||||||
|
|
||||||
If the message bounces, the bounce message will be sent back to
|
|
||||||
djb-sos-owner-God=heaven.af.mil@silverton.berkeley.edu.
|
|
||||||
|
|
||||||
If God is forwarding His mail, the bounce message will still go to
|
|
||||||
djb-sos-owner-God=heaven.af.mil@silverton.berkeley.edu. No matter how
|
|
||||||
uninformative the bounce message is, it will display God's
|
|
||||||
subscription address in its envelope.
|
|
||||||
|
|
||||||
Another benefit of VERPs is that God Himself can see what address He
|
|
||||||
used to subscribe.
|
|
||||||
|
|
||||||
Making VERPs work requires two pieces of local software support.
|
|
||||||
First: it must be easy to modify the outgoing sender address
|
|
||||||
separately for each envelope recipient. For example, with one mailer,
|
|
||||||
qmail, a user can simply touch ~/.qmail-list-owner and
|
|
||||||
~/.qmail-list-owner-default to apply VERPs to user-list.
|
|
||||||
|
|
||||||
Second, and more important: it must be easy to identify a collection
|
|
||||||
of addresses, such as djb-sos-owner-*, and send all mail for those
|
|
||||||
addresses to one place, while preserving the * information. Under
|
|
||||||
qmail, all user-list-owner-* mail will be sent to the user once he
|
|
||||||
touches ~/.qmail-list-owner-default. Sending the mail through an
|
|
||||||
automated bounce-handling program is just as easy.
|
|
||||||
|
|
||||||
With older mailers, applying VERPs would require setting up a new
|
|
||||||
user-list-owner-recipient alias for each new recipient. This
|
|
||||||
inconvenience has prevented VERPs from being widely exploited, even
|
|
||||||
though the idea is not new.
|
|
||||||
|
|
||||||
|
|
||||||
3. Per-message VERPs
|
|
||||||
|
|
||||||
VERPs are not restricted to distinguishing mailing list subscribers;
|
|
||||||
they can also be used to distinguish messages.
|
|
||||||
|
|
||||||
For example, a user can send one message with an envelope sender
|
|
||||||
address of user-dsn-1, the next message with user-dsn-2, and so on.
|
|
||||||
As long as the local mailer gives all user-dsn-* back to that user,
|
|
||||||
he can reliably match up incoming bounces with outgoing messages.
|
|
||||||
|
|
||||||
Per-message VERPs can be combined with per-recipient VERPs. Every
|
|
||||||
application of RFC 1891's ORCPT and ENVID can be handled with
|
|
||||||
VERPs---easily, reliably, and right now.
|
|
||||||
18
SECURITY
18
SECURITY
|
|
@ -5,6 +5,11 @@ discovered; sendmail's design means that any minor bug in 46000 lines of
|
||||||
code is a major security risk. Other popular mailers, such as Smail, and
|
code is a major security risk. Other popular mailers, such as Smail, and
|
||||||
even mailing-list managers, such as Majordomo, seem nearly as bad.
|
even mailing-list managers, such as Majordomo, seem nearly as bad.
|
||||||
|
|
||||||
|
Note added in 1998: I wrote the above paragraph in December 1995, when
|
||||||
|
the latest version of sendmail was 8.6.12 (with 41000 lines of code).
|
||||||
|
Fourteen security holes were discovered from sendmail 8.6.12 through
|
||||||
|
8.8.5. See http://pobox.com/~djb/docs/maildisasters/sendmail.html.
|
||||||
|
|
||||||
I started working on qmail because I was sick of this cycle of doom.
|
I started working on qmail because I was sick of this cycle of doom.
|
||||||
Here are some of the things I did to make sure that qmail will never let
|
Here are some of the things I did to make sure that qmail will never let
|
||||||
an intruder into your machine.
|
an intruder into your machine.
|
||||||
|
|
@ -38,7 +43,7 @@ timers, signals, and more. Even worse, the list of controlled items
|
||||||
varies from one vendor's UNIX to the next, so it is very difficult to
|
varies from one vendor's UNIX to the next, so it is very difficult to
|
||||||
write portable code that cleans up everything.
|
write portable code that cleans up everything.
|
||||||
|
|
||||||
Of the twelve most recent sendmail security holes, six worked only
|
Of the twenty most recent sendmail security holes, eleven worked only
|
||||||
because the entire sendmail system is setuid.
|
because the entire sendmail system is setuid.
|
||||||
|
|
||||||
Only one qmail program is setuid: qmail-queue. Its only purpose is to
|
Only one qmail program is setuid: qmail-queue. Its only purpose is to
|
||||||
|
|
@ -95,7 +100,7 @@ and the quoter both misinterpret the interface in the same way.
|
||||||
When the original data is controlled by a malicious user, many of these
|
When the original data is controlled by a malicious user, many of these
|
||||||
bugs translate into security holes. Some examples: the Linux login
|
bugs translate into security holes. Some examples: the Linux login
|
||||||
-froot security hole; the classic find | xargs rm security hole; the
|
-froot security hole; the classic find | xargs rm security hole; the
|
||||||
recent Majordomo security hole. Even a simple parser like getopt is
|
Majordomo injection security hole. Even a simple parser like getopt is
|
||||||
complicated enough for people to screw up the quoting.
|
complicated enough for people to screw up the quoting.
|
||||||
|
|
||||||
In qmail, all the internal file structures are incredibly simple: text0
|
In qmail, all the internal file structures are incredibly simple: text0
|
||||||
|
|
@ -107,11 +112,6 @@ All the complexity of parsing RFC 822 address lists and rewriting
|
||||||
headers is in the qmail-inject program, which runs without privileges
|
headers is in the qmail-inject program, which runs without privileges
|
||||||
and is essentially part of the UA.
|
and is essentially part of the UA.
|
||||||
|
|
||||||
The only nasty case is .qmail, qmail's answer to .forward. I tried to
|
|
||||||
make this as simple as possible, but unfortunately it still has to be
|
|
||||||
edited by users. As a result, the qlist mailing-list-management program
|
|
||||||
has to be careful to exclude subscriber addresses that contain newlines.
|
|
||||||
|
|
||||||
|
|
||||||
6. Keep it simple, stupid.
|
6. Keep it simple, stupid.
|
||||||
|
|
||||||
|
|
@ -127,5 +127,5 @@ I've mostly given up on the standard C library. Many of its facilities,
|
||||||
particularly stdio, seem designed to encourage bugs. A big chunk of
|
particularly stdio, seem designed to encourage bugs. A big chunk of
|
||||||
qmail is stolen from a basic C library that I've been developing for
|
qmail is stolen from a basic C library that I've been developing for
|
||||||
several years for a variety of applications. The stralloc concept and
|
several years for a variety of applications. The stralloc concept and
|
||||||
getline2() make it very easy to avoid buffer overruns, memory leaks,
|
getln() make it very easy to avoid buffer overruns, memory leaks, and
|
||||||
and artificial line length limits.
|
artificial line length limits.
|
||||||
|
|
|
||||||
76
SENDMAIL
Normal file
76
SENDMAIL
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
This document explains what you, as a user, will notice when the system
|
||||||
|
switches from sendmail to qmail.
|
||||||
|
|
||||||
|
This is a global document, part of the qmail package, not reflecting the
|
||||||
|
decisions made by your system administrator. For details on
|
||||||
|
|
||||||
|
* which local delivery agent qmail is configured to use,
|
||||||
|
* whether qmail is configured to use dot-forward,
|
||||||
|
* whether ezmlm is installed,
|
||||||
|
* whether fastforward is installed, and
|
||||||
|
* all other local configuration features,
|
||||||
|
|
||||||
|
see your local sendmail-qmail upgrade announcement (which your system
|
||||||
|
administrator may have placed into /var/qmail/doc/ANNOUNCE).
|
||||||
|
|
||||||
|
|
||||||
|
--- Mailbox location
|
||||||
|
|
||||||
|
If your system administrator has configured qmail to use binmail for
|
||||||
|
local deliveries, your mailbox will be in /var/spool/mail/you, just as
|
||||||
|
it was under sendmail.
|
||||||
|
|
||||||
|
If your system administrator has configured qmail to use qmail-local for
|
||||||
|
local deliveries, your mailbox will be moved to ~you/Mailbox. There is a
|
||||||
|
symbolic link from /var/spool/mail/you to ~you/Mailbox, so your mail
|
||||||
|
reader will find the mailbox at its new location.
|
||||||
|
|
||||||
|
|
||||||
|
--- Loop control
|
||||||
|
|
||||||
|
qmail-local automatically adds a Delivered-To field at the top of every
|
||||||
|
delivered message. It uses Delivered-To to prevent mail forwarding
|
||||||
|
loops, including cross-host mailing-list loops.
|
||||||
|
|
||||||
|
|
||||||
|
--- Outgoing messages
|
||||||
|
|
||||||
|
qmail lets you use environment variables to control the appearance of
|
||||||
|
your outgoing mail, supplementing the features offered by your MUA. For
|
||||||
|
example, qmail-inject will set up Mail-Followup-To for you automatically
|
||||||
|
if you tell it which mailing lists you are subscribed to. See
|
||||||
|
qmail-inject(8) for a complete list of features.
|
||||||
|
|
||||||
|
If you're at (say) sun.ee.movie.edu, qmail lets you type joe@mac for
|
||||||
|
joe@mac.ee.movie.edu, and joe@mac+ for joe@mac.movie.edu without the ee.
|
||||||
|
sendmail has a different interpretation of hostnames without dots.
|
||||||
|
|
||||||
|
|
||||||
|
--- Forwarding and mailing lists
|
||||||
|
|
||||||
|
qmail gives you the power to set up your own mailing lists without
|
||||||
|
pestering your system administrator.
|
||||||
|
|
||||||
|
Under qmail, you are in charge of all addresses of the form
|
||||||
|
you-anything. The delivery of you-anything is controlled by
|
||||||
|
~you/.qmail-anything, a file in your home directory.
|
||||||
|
|
||||||
|
For example, if you want to set up a bug-of-the-month-club mailing list,
|
||||||
|
you can put a list of addresses into ~you/.qmail-botmc. Any mail to
|
||||||
|
you-botmc will be forwarded to all of those addresses. Mail directly to
|
||||||
|
you is controlled by ~you/.qmail. You can even set up a catch-all,
|
||||||
|
~you/.qmail-default, to handle unknown you- addresses.
|
||||||
|
|
||||||
|
See dot-qmail(5) for the complete story. Beware that the syntax of
|
||||||
|
.qmail is different from the syntax of sendmail's .forward file.
|
||||||
|
|
||||||
|
If your system administrator has configured qmail to use the dot-forward
|
||||||
|
compatibility tool, you can put forwarding addresses (and programs) into
|
||||||
|
.forward the same way you did with sendmail.
|
||||||
|
|
||||||
|
If your system administrator has installed ezmlm, you can use ezmlm-make
|
||||||
|
to instantly set up a professional-quality mailing list, handling
|
||||||
|
subscriptions and archives automatically.
|
||||||
|
|
||||||
|
If your system administrator has installed fastforward, you can easily
|
||||||
|
manage a large database of forwarding addresses.
|
||||||
165
TARGETS
165
TARGETS
|
|
@ -8,58 +8,13 @@ compile
|
||||||
fork.h
|
fork.h
|
||||||
qmail-local.o
|
qmail-local.o
|
||||||
qmail.o
|
qmail.o
|
||||||
auto-str.o
|
|
||||||
make-makelib
|
|
||||||
makelib
|
|
||||||
substdio.o
|
|
||||||
substdi.o
|
|
||||||
substdo.o
|
|
||||||
subfderr.o
|
|
||||||
subfdout.o
|
|
||||||
subfdouts.o
|
|
||||||
subfdin.o
|
|
||||||
subfdins.o
|
|
||||||
substdio_copy.o
|
|
||||||
substdio.a
|
|
||||||
error.o
|
|
||||||
error_str.o
|
|
||||||
error_temp.o
|
|
||||||
error.a
|
|
||||||
str_len.o
|
|
||||||
str_diff.o
|
|
||||||
str_diffn.o
|
|
||||||
str_cpy.o
|
|
||||||
str_chr.o
|
|
||||||
str_rchr.o
|
|
||||||
str_start.o
|
|
||||||
byte_chr.o
|
|
||||||
byte_rchr.o
|
|
||||||
byte_diff.o
|
|
||||||
byte_copy.o
|
|
||||||
byte_cr.o
|
|
||||||
byte_zero.o
|
|
||||||
str.a
|
|
||||||
auto-str
|
|
||||||
auto_qmail.c
|
|
||||||
auto_qmail.o
|
|
||||||
auto-int8.o
|
|
||||||
fmt_str.o
|
|
||||||
fmt_strn.o
|
|
||||||
fmt_uint.o
|
|
||||||
fmt_uint0.o
|
|
||||||
fmt_ulong.o
|
|
||||||
scan_ulong.o
|
|
||||||
scan_8long.o
|
|
||||||
scan_nbblong.o
|
|
||||||
fs.a
|
|
||||||
auto-int8
|
|
||||||
auto_patrn.c
|
|
||||||
auto_patrn.o
|
|
||||||
quote.o
|
quote.o
|
||||||
now.o
|
now.o
|
||||||
gfrom.o
|
gfrom.o
|
||||||
myctime.o
|
myctime.o
|
||||||
slurpclose.o
|
slurpclose.o
|
||||||
|
make-makelib
|
||||||
|
makelib
|
||||||
case_diffb.o
|
case_diffb.o
|
||||||
case_diffs.o
|
case_diffs.o
|
||||||
case_lowerb.o
|
case_lowerb.o
|
||||||
|
|
@ -104,8 +59,8 @@ lock.a
|
||||||
fd_copy.o
|
fd_copy.o
|
||||||
fd_move.o
|
fd_move.o
|
||||||
fd.a
|
fd.a
|
||||||
wait_pid.o
|
|
||||||
haswaitp.h
|
haswaitp.h
|
||||||
|
wait_pid.o
|
||||||
wait_nohang.o
|
wait_nohang.o
|
||||||
wait.a
|
wait.a
|
||||||
env.o
|
env.o
|
||||||
|
|
@ -124,24 +79,66 @@ stralloc.a
|
||||||
alloc.o
|
alloc.o
|
||||||
alloc_re.o
|
alloc_re.o
|
||||||
alloc.a
|
alloc.a
|
||||||
|
strerr_sys.o
|
||||||
|
strerr_die.o
|
||||||
|
strerr.a
|
||||||
|
substdio.o
|
||||||
|
substdi.o
|
||||||
|
substdo.o
|
||||||
|
subfderr.o
|
||||||
|
subfdout.o
|
||||||
|
subfdouts.o
|
||||||
|
subfdin.o
|
||||||
|
subfdins.o
|
||||||
|
substdio_copy.o
|
||||||
|
substdio.a
|
||||||
|
error.o
|
||||||
|
error_str.o
|
||||||
|
error_temp.o
|
||||||
|
error.a
|
||||||
|
str_len.o
|
||||||
|
str_diff.o
|
||||||
|
str_diffn.o
|
||||||
|
str_cpy.o
|
||||||
|
str_chr.o
|
||||||
|
str_rchr.o
|
||||||
|
str_start.o
|
||||||
|
byte_chr.o
|
||||||
|
byte_rchr.o
|
||||||
|
byte_diff.o
|
||||||
|
byte_copy.o
|
||||||
|
byte_cr.o
|
||||||
|
byte_zero.o
|
||||||
|
str.a
|
||||||
|
fmt_str.o
|
||||||
|
fmt_strn.o
|
||||||
|
fmt_uint.o
|
||||||
|
fmt_uint0.o
|
||||||
|
fmt_ulong.o
|
||||||
|
scan_ulong.o
|
||||||
|
scan_8long.o
|
||||||
|
fs.a
|
||||||
datetime.o
|
datetime.o
|
||||||
datetime_un.o
|
datetime_un.o
|
||||||
datetime.a
|
datetime.a
|
||||||
|
auto-str.o
|
||||||
|
auto-str
|
||||||
|
auto_qmail.c
|
||||||
|
auto_qmail.o
|
||||||
|
auto-int8.o
|
||||||
|
auto-int8
|
||||||
|
auto_patrn.c
|
||||||
|
auto_patrn.o
|
||||||
|
socket.lib
|
||||||
qmail-local
|
qmail-local
|
||||||
uint32.h
|
uint32.h
|
||||||
qmail-lspawn.o
|
qmail-lspawn.o
|
||||||
auto-uid.o
|
select.h
|
||||||
auto-uid
|
chkspawn.o
|
||||||
auto-gid.o
|
|
||||||
auto-gid
|
|
||||||
auto_uids.c
|
|
||||||
auto_uids.o
|
|
||||||
auto-int.o
|
auto-int.o
|
||||||
auto-int
|
auto-int
|
||||||
auto_spawn.c
|
auto_spawn.c
|
||||||
auto_spawn.o
|
auto_spawn.o
|
||||||
select.h
|
|
||||||
chkspawn.o
|
|
||||||
chkspawn
|
chkspawn
|
||||||
spawn.o
|
spawn.o
|
||||||
chkshsgr.o
|
chkshsgr.o
|
||||||
|
|
@ -153,6 +150,12 @@ cdb_hash.o
|
||||||
cdb_unpack.o
|
cdb_unpack.o
|
||||||
cdb_seek.o
|
cdb_seek.o
|
||||||
cdb.a
|
cdb.a
|
||||||
|
auto-uid.o
|
||||||
|
auto-uid
|
||||||
|
auto-gid.o
|
||||||
|
auto-gid
|
||||||
|
auto_uids.c
|
||||||
|
auto_uids.o
|
||||||
qmail-lspawn
|
qmail-lspawn
|
||||||
qmail-getpw.o
|
qmail-getpw.o
|
||||||
auto_break.c
|
auto_break.c
|
||||||
|
|
@ -175,7 +178,6 @@ ipme.o
|
||||||
ndelay.o
|
ndelay.o
|
||||||
ndelay_off.o
|
ndelay_off.o
|
||||||
ndelay.a
|
ndelay.a
|
||||||
socket.lib
|
|
||||||
dns.lib
|
dns.lib
|
||||||
qmail-remote
|
qmail-remote
|
||||||
qmail-rspawn.o
|
qmail-rspawn.o
|
||||||
|
|
@ -183,9 +185,9 @@ tcpto_clean.o
|
||||||
qmail-rspawn
|
qmail-rspawn
|
||||||
direntry.h
|
direntry.h
|
||||||
qmail-clean.o
|
qmail-clean.o
|
||||||
|
fmtqfn.o
|
||||||
auto_split.c
|
auto_split.c
|
||||||
auto_split.o
|
auto_split.o
|
||||||
fmtqfn.o
|
|
||||||
qmail-clean
|
qmail-clean
|
||||||
qmail-send.o
|
qmail-send.o
|
||||||
qsutil.o
|
qsutil.o
|
||||||
|
|
@ -216,7 +218,6 @@ predate
|
||||||
datemail
|
datemail
|
||||||
mailsubj
|
mailsubj
|
||||||
qmail-upq
|
qmail-upq
|
||||||
qmail-config
|
|
||||||
qmail-showctl.o
|
qmail-showctl.o
|
||||||
qmail-showctl
|
qmail-showctl
|
||||||
qmail-newu.o
|
qmail-newu.o
|
||||||
|
|
@ -233,12 +234,21 @@ qmail-qread
|
||||||
qmail-qstat
|
qmail-qstat
|
||||||
qmail-tcpto.o
|
qmail-tcpto.o
|
||||||
qmail-tcpto
|
qmail-tcpto
|
||||||
|
qmail-tcpok.o
|
||||||
|
qmail-tcpok
|
||||||
qmail-pop3d.o
|
qmail-pop3d.o
|
||||||
|
commands.o
|
||||||
|
maildir.o
|
||||||
qmail-pop3d
|
qmail-pop3d
|
||||||
qmail-popup.o
|
qmail-popup.o
|
||||||
qmail-popup
|
qmail-popup
|
||||||
qmail-qmtpd.o
|
qmail-qmqpc.o
|
||||||
|
qmail-qmqpc
|
||||||
|
qmail-qmqpd.o
|
||||||
received.o
|
received.o
|
||||||
|
qmail-qmqpd
|
||||||
|
qmail-qmtpd.o
|
||||||
|
rcpthosts.o
|
||||||
qmail-qmtpd
|
qmail-qmtpd
|
||||||
qmail-smtpd.o
|
qmail-smtpd.o
|
||||||
qmail-smtpd
|
qmail-smtpd
|
||||||
|
|
@ -247,6 +257,10 @@ sendmail
|
||||||
tcp-env.o
|
tcp-env.o
|
||||||
remoteinfo.o
|
remoteinfo.o
|
||||||
tcp-env
|
tcp-env
|
||||||
|
qmail-newmrh.o
|
||||||
|
qmail-newmrh
|
||||||
|
config
|
||||||
|
config-fast
|
||||||
dnscname.o
|
dnscname.o
|
||||||
dnsdoe.o
|
dnsdoe.o
|
||||||
dnscname
|
dnscname
|
||||||
|
|
@ -262,9 +276,6 @@ hostname.o
|
||||||
hostname
|
hostname
|
||||||
ipmeprint.o
|
ipmeprint.o
|
||||||
ipmeprint
|
ipmeprint
|
||||||
qlist.o
|
|
||||||
qlist
|
|
||||||
qlist2
|
|
||||||
qreceipt.o
|
qreceipt.o
|
||||||
qreceipt
|
qreceipt
|
||||||
qsmhook.o
|
qsmhook.o
|
||||||
|
|
@ -280,10 +291,6 @@ condredirect
|
||||||
maildirmake.o
|
maildirmake.o
|
||||||
maildirmake
|
maildirmake
|
||||||
maildir2mbox.o
|
maildir2mbox.o
|
||||||
maildir.o
|
|
||||||
strerr_sys.o
|
|
||||||
strerr_die.o
|
|
||||||
strerr.a
|
|
||||||
maildir2mbox
|
maildir2mbox
|
||||||
maildirwatch.o
|
maildirwatch.o
|
||||||
maildirwatch
|
maildirwatch
|
||||||
|
|
@ -296,6 +303,16 @@ install.o
|
||||||
install
|
install
|
||||||
instcheck.o
|
instcheck.o
|
||||||
instcheck
|
instcheck
|
||||||
|
home
|
||||||
|
home+df
|
||||||
|
proc
|
||||||
|
proc+df
|
||||||
|
binm1
|
||||||
|
binm1+df
|
||||||
|
binm2
|
||||||
|
binm2+df
|
||||||
|
binm3
|
||||||
|
binm3+df
|
||||||
it
|
it
|
||||||
qmail-local.0
|
qmail-local.0
|
||||||
qmail-lspawn.0
|
qmail-lspawn.0
|
||||||
|
|
@ -306,24 +323,30 @@ qmail-rspawn.0
|
||||||
qmail-clean.0
|
qmail-clean.0
|
||||||
qmail-send.8
|
qmail-send.8
|
||||||
qmail-send.0
|
qmail-send.0
|
||||||
|
qmail-start.8
|
||||||
qmail-start.0
|
qmail-start.0
|
||||||
splogger.0
|
splogger.0
|
||||||
qmail-queue.0
|
qmail-queue.0
|
||||||
qmail-inject.0
|
qmail-inject.0
|
||||||
mailsubj.0
|
mailsubj.0
|
||||||
qmail-showctl.0
|
qmail-showctl.0
|
||||||
|
qmail-newu.8
|
||||||
qmail-newu.0
|
qmail-newu.0
|
||||||
qmail-pw2u.8
|
qmail-pw2u.8
|
||||||
qmail-pw2u.0
|
qmail-pw2u.0
|
||||||
qmail-qread.0
|
qmail-qread.0
|
||||||
qmail-qstat.0
|
qmail-qstat.0
|
||||||
qmail-tcpto.0
|
qmail-tcpto.0
|
||||||
|
qmail-tcpok.0
|
||||||
qmail-pop3d.0
|
qmail-pop3d.0
|
||||||
qmail-popup.0
|
qmail-popup.0
|
||||||
|
qmail-qmqpc.0
|
||||||
|
qmail-qmqpd.0
|
||||||
qmail-qmtpd.0
|
qmail-qmtpd.0
|
||||||
qmail-smtpd.0
|
qmail-smtpd.0
|
||||||
tcp-env.0
|
tcp-env.0
|
||||||
qlist.0
|
qmail-newmrh.8
|
||||||
|
qmail-newmrh.0
|
||||||
qreceipt.0
|
qreceipt.0
|
||||||
qbiff.0
|
qbiff.0
|
||||||
forward.0
|
forward.0
|
||||||
|
|
@ -333,13 +356,13 @@ maildirmake.0
|
||||||
maildir2mbox.0
|
maildir2mbox.0
|
||||||
maildirwatch.0
|
maildirwatch.0
|
||||||
qmail.0
|
qmail.0
|
||||||
qmail-upgrade.7
|
|
||||||
qmail-upgrade.0
|
|
||||||
qmail-limits.7
|
qmail-limits.7
|
||||||
qmail-limits.0
|
qmail-limits.0
|
||||||
qmail-log.0
|
qmail-log.0
|
||||||
|
qmail-control.5
|
||||||
qmail-control.0
|
qmail-control.0
|
||||||
qmail-header.0
|
qmail-header.0
|
||||||
|
qmail-users.5
|
||||||
qmail-users.0
|
qmail-users.0
|
||||||
dot-qmail.5
|
dot-qmail.5
|
||||||
dot-qmail.0
|
dot-qmail.0
|
||||||
|
|
@ -351,3 +374,5 @@ addresses.0
|
||||||
envelopes.0
|
envelopes.0
|
||||||
forgeries.0
|
forgeries.0
|
||||||
man
|
man
|
||||||
|
setup
|
||||||
|
check
|
||||||
|
|
|
||||||
522
THANKS
522
THANKS
|
|
@ -2,216 +2,334 @@ Thanks to lots of people for success and failure reports, code, ideas,
|
||||||
and documentation. See CHANGES for details of specific contributions.
|
and documentation. See CHANGES for details of specific contributions.
|
||||||
Sorry if I left anyone out.
|
Sorry if I left anyone out.
|
||||||
|
|
||||||
SA = Satoshi Adachi
|
A2B = Are Bryne
|
||||||
|
A2L = Ali Lomonaco
|
||||||
|
A2P = Andrea Paolini
|
||||||
|
AAF = Adam A. Frey
|
||||||
|
AB = Alan Briggs
|
||||||
|
ABC = Alan B. Clegg
|
||||||
|
AC = Arne Coucheron
|
||||||
|
ACB = Andy C. Brandt
|
||||||
|
AF = Andreas Faerber
|
||||||
|
AG = Armin Gruner
|
||||||
|
AGB = Andre Grosse Bley
|
||||||
|
AH = Amos Hayes
|
||||||
|
AI = Akihiro Iijima
|
||||||
|
AJ = Alan Jaffray
|
||||||
|
AJK = Antti-Juhani Kaijanaho
|
||||||
|
AKB = Allen K. Briggs
|
||||||
|
AL = Andreas Lamprecht
|
||||||
|
ALB = Allan L. Bazinet
|
||||||
|
ANR = Adriano Nagelschmidt Rodrigues
|
||||||
|
AP = Andrew Pam
|
||||||
|
AS = Akos Szalkai
|
||||||
|
AV = Alex Vostrikov
|
||||||
|
AWB = Andy W. Barclay
|
||||||
|
AY = Araki Yasuhiro
|
||||||
|
B1F = Bo Fussing
|
||||||
|
B2F = Brad Forschinger
|
||||||
|
B2H = Buck Huppmann
|
||||||
|
B2L = Brent Laminack
|
||||||
|
B2W = Bil Wendling
|
||||||
|
B3W = Boris Wedl
|
||||||
|
BB = Bruce Bodger
|
||||||
|
BC = Bob Collie
|
||||||
|
BCK = Benjamin C. Kite
|
||||||
|
BCM = Bill C. Miller
|
||||||
|
BDB = Boris D. Beletsky
|
||||||
|
BDM = Byron D. Miller
|
||||||
|
BEO = Bruce E. O'Neel
|
||||||
|
BET = Bennett E. Todd
|
||||||
|
BG = Bert Gijsbers
|
||||||
|
BH = Brad Howes
|
||||||
|
BJ = Brian Jackson
|
||||||
|
BJM = Barry J. Miller
|
||||||
|
BL = Brian Litzinger
|
||||||
|
BMF = Brian M. Fisk
|
||||||
|
BN = Bill Nugent
|
||||||
|
BP = Bruce Perens
|
||||||
|
BR = Brian J. Reichert
|
||||||
|
BS = Bjoern Stabell
|
||||||
|
BT = Brad Templeton
|
||||||
|
BTW = Brian T. Wightman
|
||||||
|
BW = Bill Weinman
|
||||||
|
BZ = Blaz Zupan
|
||||||
|
C2F = Chuck Foster
|
||||||
|
C2H = Christoph Heidermanns
|
||||||
|
C2S = Craig Shrimpton
|
||||||
|
CEJ = Colin Eric Johnson
|
||||||
|
CF = C. Ferree
|
||||||
|
CG = Chris Garrigues
|
||||||
|
CH = Chael Hall
|
||||||
|
CHR = Craig H. Rowland
|
||||||
|
CK = Christoph Kaesling
|
||||||
|
CL = Carsten Leonhardt
|
||||||
|
CLS = Christopher L. Seawood
|
||||||
|
CM = Charles Mattair
|
||||||
|
CMP = Chase M. Phillips
|
||||||
|
CR = Christian Riede
|
||||||
|
CS = Cloyce Spradling
|
||||||
|
CSH = Clayton S. Haapala
|
||||||
|
D1H = Dieter Heidner
|
||||||
|
D2H = Dan Hollis
|
||||||
|
D2K = Dax Kelson
|
||||||
|
D2S = Dan Senie
|
||||||
|
D3S = Don Samek
|
||||||
|
DA = Dave Arcuri
|
||||||
|
DAR = Daniel A. Reish
|
||||||
|
DB = David Buscher
|
||||||
|
DBK = Douglas B. Kerry
|
||||||
|
DC = Dan Cross
|
||||||
|
DCC = Daniel C. Cotey
|
||||||
|
DE = Daniel Egnor
|
||||||
|
DEH = Daniel E. Harris
|
||||||
|
DF = Dale Farnsworth
|
||||||
|
DG = David Guntner
|
||||||
|
DK = Dave Kopper
|
||||||
|
DL = Daniel Lawrence
|
||||||
|
DM = David Mazieres
|
||||||
|
DML = David M. Lew
|
||||||
|
DP = Dave Platt
|
||||||
|
DS = Dave Sill
|
||||||
|
DST = Daniel S. Thibadeau
|
||||||
|
DWS = David Wayne Summers
|
||||||
|
EC = Evan Champion
|
||||||
|
ECG = Eric C. Garrison
|
||||||
|
EG = Eivind Gjelseth
|
||||||
|
EK = Eric Krohn
|
||||||
|
EP = Emanuele Pucciarelli
|
||||||
|
ERH = Eric R. Hankins
|
||||||
|
ES = Eric Smith
|
||||||
|
ESM = Edward S. Marshall
|
||||||
|
ET = Eivind Tagseth
|
||||||
|
ETT = Emmanuel T. Tardieu
|
||||||
|
F2T = Frank Thieme
|
||||||
|
FE = Frank Ederveen
|
||||||
|
FN = Faried Nawaz
|
||||||
|
FPL = Frederik P. Lindberg
|
||||||
|
FT = Frank Tegtmeyer
|
||||||
|
FW = Frank Wagner
|
||||||
G1A = Graham Adams
|
G1A = Graham Adams
|
||||||
|
G2A = Greg Andrews
|
||||||
|
GAW = Greg A. Woods
|
||||||
|
GB = Glenn Barry
|
||||||
|
GH = Gene Hightower
|
||||||
|
GL = Giles Lean
|
||||||
|
GLM = Grant L. Miller
|
||||||
|
H2S = Harley Silver
|
||||||
|
HCJ = Helio Coelho Jr.
|
||||||
|
HDG = Hans de Graaff
|
||||||
|
HG = Howard Goldstein
|
||||||
|
HHO = Harald Hanche-Olsen
|
||||||
|
HJB = Herbert J. Bernstein
|
||||||
|
HM = Hirokazu Morikawa
|
||||||
|
HS = Harlan Stenn
|
||||||
|
HT = Henry Timmerman
|
||||||
|
HW = Hal Wine
|
||||||
|
HWM = Henry W. Miller
|
||||||
|
IH = Ingmar Hupp
|
||||||
|
IK = Ivan Kohler
|
||||||
|
IKW = Ian Keith Wynne
|
||||||
|
IS = Icarus Sparry
|
||||||
|
IW = Ian Westcott
|
||||||
|
J1B = John Banghart
|
||||||
|
J1K = Jost Krieger
|
||||||
|
J2B = Jos Backus
|
||||||
|
J2K = Johannes Kroeger
|
||||||
|
J2M = Joel Maslak
|
||||||
|
J2P = John Parker
|
||||||
|
J2W = Jim Whitby
|
||||||
|
JAB = Jeremy A. Bussard
|
||||||
|
JAK = Johan A. Kullstam
|
||||||
|
JB = Joshua Buysse
|
||||||
|
JBB = Jason B. Brown
|
||||||
|
JBF = John B. Fleming
|
||||||
|
JC = Jim Clausing
|
||||||
|
JCD = Jeffrey C. Dege
|
||||||
|
JD = Joe Doupnik
|
||||||
|
JDHB = Johannes D. H. Beekhuizen
|
||||||
|
JDJ = Joshua D. Juran
|
||||||
|
JF = Janos Farkas
|
||||||
|
JFK = James F. Kane III
|
||||||
|
JGM = John G. Myers
|
||||||
|
JJB = J. J. Bailey
|
||||||
|
JJMK = Jonathan J. M. Katz
|
||||||
|
JJR = Jaron J. Rubenstein
|
||||||
|
JK = Jari Kirma
|
||||||
|
JL = Jim Littlefield
|
||||||
|
JLB = Julie L. Baumler
|
||||||
|
JLH = Jason L. Haar
|
||||||
|
JLW = Jason L. Wright
|
||||||
|
JM = Jim Meehan
|
||||||
|
JMS = Jason M. Stokes
|
||||||
|
JMT = John M. Twilley
|
||||||
|
JP = John Palkovic
|
||||||
|
JPB = Joe Block
|
||||||
|
JPH = Justin P. Hannah
|
||||||
|
JPR = Jean-Pierre Radley
|
||||||
|
JRL = John R. Levine
|
||||||
|
JRY = Jamie R. Yukes
|
||||||
|
JS = Jesper Skriver
|
||||||
|
JTB = Jonathan T. Bowie
|
||||||
|
JW = John Whittaker
|
||||||
|
JWB = James W. Birdsall
|
||||||
|
K1J = Kyle Jones
|
||||||
|
K2J = Kevin Johnson
|
||||||
|
KA = Klaus Aigte
|
||||||
|
KB = Keith Burdis
|
||||||
|
KE = Kenny Elliott
|
||||||
|
KJJ = Kevin J. Johnson
|
||||||
|
KJS = Kevin J. Sawyer
|
||||||
|
KMD = Kevin M. Dulzo
|
||||||
|
KO = Keith Owens
|
||||||
|
KR = Kenji Rikitake
|
||||||
|
KT = Karsten Thygesen
|
||||||
|
KUT = Kai Uwe Tempel
|
||||||
|
KY = Kentaro Yoshitomi
|
||||||
|
L2L = Louis Larry
|
||||||
|
L3L = Luis Lopes
|
||||||
|
LB = Laurentiu Badea
|
||||||
|
LL = lilo
|
||||||
|
LW = Lionel Widdifield
|
||||||
|
M2C = Mark Crimmins
|
||||||
|
M2G = Michael R. Gile
|
||||||
|
M2H = Martin Hager
|
||||||
|
M2L = M. Lyons
|
||||||
|
M2R = Mark Riekenberg
|
||||||
|
M2S = Mikael Suokas
|
||||||
|
M3H = Michael Holzt
|
||||||
|
M3L = Michael Lazarou
|
||||||
|
M3S = Morten Skjelland
|
||||||
|
M4S = Michael Shields
|
||||||
|
MB = Martin Budsj?
|
||||||
|
MBS = Michael B. Scher
|
||||||
|
MC = Michael Cooley
|
||||||
|
MD = Mark Delany
|
||||||
|
MDI = Miguel de Icaza
|
||||||
|
ME = Marc Ewing
|
||||||
|
MEE = Mads E. Eilertsen
|
||||||
|
MF = Massimo Fusaro
|
||||||
|
MG = Michael Graff
|
||||||
|
MGM = Mitchell G. Morris
|
||||||
|
MH = Markus Hofmann
|
||||||
|
MJD = Mark-Jason Dominus
|
||||||
|
MJG = Manuel J. Galan
|
||||||
|
ML = Martin Lucina
|
||||||
|
MLH = May Liss Haarstad
|
||||||
|
MM = Martin Mersberger
|
||||||
|
MMM = Momchil M. Momchev
|
||||||
|
MMM2 = Marc M. Martinez
|
||||||
|
MP = Matt Paduano
|
||||||
|
MR = Mosfeq Rashid
|
||||||
|
MRG = Matthew R. Green
|
||||||
|
MS = Mark Spears
|
||||||
|
MSD = Mandell S. Degerness
|
||||||
|
MSS = Matthew S. Soffen
|
||||||
|
MT = Mark Thompson
|
||||||
|
MW = Mate Wierdl
|
||||||
|
MWE = Mark W. Eichin
|
||||||
NA = Norm Aleks
|
NA = Norm Aleks
|
||||||
NAA = Nicholas A. Amato
|
NAA = Nicholas A. Amato
|
||||||
G2A = Greg Andrews
|
|
||||||
TA = Tetsuo Aoki
|
|
||||||
DA = Dave Arcuri
|
|
||||||
JJB = J. J. Bailey
|
|
||||||
J2B = Jos Backus
|
|
||||||
SSB = Stik Bakken
|
|
||||||
J1B = John Banghart
|
|
||||||
GB = Glenn Barry
|
|
||||||
JLB = Julie L. Baumler
|
|
||||||
SLB = Steven L. Baur
|
|
||||||
ALB = Allan L. Bazinet
|
|
||||||
JDHB = Johannes D. H. Beekhuizen
|
|
||||||
BDB = Boris D. Beletsky
|
|
||||||
HJB = Herbert J. Bernstein
|
|
||||||
REB = Ronald E. Bickers
|
|
||||||
JPB = Joe Block
|
|
||||||
BB = Bruce Bodger
|
|
||||||
SB = Stephane Bortzmeyer
|
|
||||||
PB = Peter Bowyer
|
|
||||||
ACB = Andy C. Brandt
|
|
||||||
AB = Alan Briggs
|
|
||||||
AKB = Allen K. Briggs
|
|
||||||
JBB = Jason B. Brown
|
|
||||||
JAB = Jeremy A. Bussard
|
|
||||||
RJC = Robert J. Carter
|
|
||||||
EC = Evan Champion
|
|
||||||
JC = Jim Clausing
|
|
||||||
HCJ = Helio Coelho Jr.
|
|
||||||
BC = Bob Collie
|
|
||||||
SGC = Stephen G. Comings
|
|
||||||
MC = Michael Cooley
|
|
||||||
DCC = Daniel C. Cotey
|
|
||||||
AC = Arne Coucheron
|
|
||||||
M2C = Mark Crimmins
|
|
||||||
DC = Dan Cross
|
|
||||||
MD = Mark Delany
|
|
||||||
SVD = Stef Van Dessel
|
|
||||||
RD = Rahul Dhesi
|
|
||||||
MJD = Mark-Jason Dominus
|
|
||||||
JD = Joe Doupnik
|
|
||||||
FE = Frank Ederveen
|
|
||||||
DE = Daniel Egnor
|
|
||||||
MWE = Mark W. Eichin
|
|
||||||
MEE = Mads E. Eilertsen
|
|
||||||
KE = Kenny Elliott
|
|
||||||
TEE = Thomas E. Erskine
|
|
||||||
ME = Marc Ewing
|
|
||||||
JF = Janos Farkas
|
|
||||||
DF = Dale Farnsworth
|
|
||||||
YF = Yaroslav Faybishenko
|
|
||||||
CF = C. Ferree
|
|
||||||
JBF = John B. Fleming
|
|
||||||
C2F = Chuck Foster
|
|
||||||
RF = Rainer Fraedrich
|
|
||||||
MF = Massimo Fusaro
|
|
||||||
CG = Chris Garrigues
|
|
||||||
BG = Bert Gijsbers
|
|
||||||
M2G = Michael R. Gile
|
|
||||||
EG = Eivind Gjelseth
|
|
||||||
HG = Howard Goldstein
|
|
||||||
TG = Tim Goodwin
|
|
||||||
HDG = Hans de Graaff
|
|
||||||
MG = Michael Graff
|
|
||||||
PJG = Paul Graham
|
|
||||||
MRG = Matthew R. Green
|
|
||||||
SG = Steven Grimm
|
|
||||||
AG = Armin Gruner
|
|
||||||
CSH = Clayton S. Haapala
|
|
||||||
JLH = Jason L. Haar
|
|
||||||
MLH = May Liss Haarstad
|
|
||||||
CH = Chael Hall
|
|
||||||
JPH = Justin P. Hannah
|
|
||||||
RJH = Randy Harmon
|
|
||||||
PH = Paul Harrington
|
|
||||||
DEH = Daniel E. Harris
|
|
||||||
RFH = Robert F. Harrison
|
|
||||||
D1H = Dieter Heidner
|
|
||||||
GH = Gene Hightower
|
|
||||||
MH = Markus Hofmann
|
|
||||||
D2H = Dan Hollis
|
|
||||||
NH = Nick Holloway
|
NH = Nick Holloway
|
||||||
TH = Ton Hospel
|
NR = Norbert Roeding
|
||||||
BH = Brad Howes
|
NW = Nicholas Waples
|
||||||
TJH = Timothy J. Hunt
|
OK = Oezguer Kesim
|
||||||
B2H = Buck Huppmann
|
|
||||||
MDI = Miguel de Icaza
|
|
||||||
BJ = Brian Jackson
|
|
||||||
AJ = Alan Jaffray
|
|
||||||
CEJ = Colin Eric Johnson
|
|
||||||
K2J = Kevin Johnson
|
|
||||||
K1J = Kyle Jones
|
|
||||||
SJ = Sudish Joseph
|
|
||||||
W2K = Wolfram Kahl
|
|
||||||
JJMK = Jonathan J. M. Katz
|
|
||||||
CK = Christoph Kaesling
|
|
||||||
PK = Petri Kaukasoina
|
|
||||||
D2K = Dax Kelson
|
|
||||||
TK = Terry Kennedy
|
|
||||||
DBK = Douglas B. Kerry
|
|
||||||
WK = Werner Koch
|
|
||||||
DK = Dave Kopper
|
|
||||||
J1K = Jost Krieger
|
|
||||||
J2K = Johannes Kroeger
|
|
||||||
EK = Eric Krohn
|
|
||||||
B2L = Brent Laminack
|
|
||||||
AL = Andreas Lamprecht
|
|
||||||
L2L = Louis Larry
|
|
||||||
M3L = Michael Lazarou
|
|
||||||
CL = Carsten Leonhardt
|
|
||||||
JRL = John R. Levine
|
|
||||||
DML = David M. Lew
|
|
||||||
LL = lilo
|
|
||||||
FPL = Frederik P. Lindberg
|
|
||||||
JL = Jim Littlefield
|
|
||||||
BL = Brian Litzinger
|
|
||||||
RL = Robert Luce
|
|
||||||
ML = Martin Lucina
|
|
||||||
M2L = M. Lyons
|
|
||||||
TM = Toshinori Maeno
|
|
||||||
ESM = Edward S. Marshall
|
|
||||||
J2M = Joel Maslak
|
|
||||||
TLM = Timothy L. Mayo
|
|
||||||
DM = David Mazieres
|
|
||||||
RM = Rich McClellan
|
|
||||||
SM = Shawn McHorse
|
|
||||||
JM = Jim Meehan
|
|
||||||
HWM = Henry W. Miller
|
|
||||||
RDM = Raul Miller
|
|
||||||
MMM = Momchil M. Momchev
|
|
||||||
JGM = John G. Myers
|
|
||||||
FN = Faried Nawaz
|
|
||||||
RN = Russell Nelson
|
|
||||||
TN = Thomas Neumann
|
|
||||||
UO = Uwe Ohse
|
|
||||||
PCO = Peter C. Olsen
|
|
||||||
HHO = Harald Hanche-Olsen
|
|
||||||
BEO = Bruce E. O'Neel
|
|
||||||
JP = John Palkovic
|
|
||||||
AP = Andrew Pam
|
|
||||||
SP = Stephen Parker
|
|
||||||
TVP = Tom van Peer
|
|
||||||
BP = Bruce Perens
|
|
||||||
CMP = Chase M. Phillips
|
|
||||||
DP = Dave Platt
|
|
||||||
EP = Emanuele Pucciarelli
|
|
||||||
JPR = Jean-Pierre Radley
|
|
||||||
S1R = Satish Ramachandran
|
|
||||||
MR = Mosfeq Rashid
|
|
||||||
TRR = Tracy R. Reed
|
|
||||||
BR = Brian Reichert
|
|
||||||
S2R = Sean Reifschneider
|
|
||||||
DAR = Daniel A. Reish
|
|
||||||
CR = Christian Riede
|
|
||||||
KR = Kenji Rikitake
|
|
||||||
OR = Ollivier Robert
|
OR = Ollivier Robert
|
||||||
ANR = Adriano Nagelschmidt Rodrigues
|
|
||||||
JJR = Jaron J. Rubenstein
|
|
||||||
RS = Robert Sanders
|
|
||||||
KJS = Kevin J. Sawyer
|
|
||||||
MBS = Mike Scher
|
|
||||||
SAS = Steven A. Schrader
|
|
||||||
CLS = Christopher L. Seawood
|
|
||||||
OS = Oliver Seiler
|
OS = Oliver Seiler
|
||||||
D2S = Dan Senie
|
PB = Peter Bowyer
|
||||||
SS = Simon Shapiro
|
PCO = Peter C. Olsen
|
||||||
RGS = Richard G. Sharman
|
PGF = Paul Fox
|
||||||
DS = Dave Sill
|
PGR = Phil G. Rorex
|
||||||
H2S = Harley Silver
|
PH = Paul Harrington
|
||||||
M3S = Morten Skjelland
|
PJG = Paul Graham
|
||||||
JS = Jesper Skriver
|
PJH = Peter J. Hunter
|
||||||
ES = Eric Smith
|
PK = Petri Kaukasoina
|
||||||
IS = Icarus Sparry
|
PMH = Peter M. Haworth
|
||||||
CS = Cloyce Spradling
|
PO = Paul Overell
|
||||||
BS = Bjoern Stabell
|
|
||||||
HS = Harlan Stenn
|
|
||||||
JMS = Jason M. Stokes
|
|
||||||
DWS = David Wayne Summers
|
|
||||||
M2S = Mikael Suokas
|
|
||||||
PS = Paul Svensson
|
PS = Paul Svensson
|
||||||
ET = Eivind Tagseth
|
|
||||||
PT = Paul Taylor
|
PT = Paul Taylor
|
||||||
S2T = Steve Taylor
|
PTW = P. T. Withington
|
||||||
BT = Brad Templeton
|
|
||||||
DST = Daniel S. Thibadeau
|
|
||||||
MT = Mark Thompson
|
|
||||||
S3T = Steffen Thorsen
|
|
||||||
KT = Karsten Thygesen
|
|
||||||
BET = Bennett E. Todd
|
|
||||||
JMT = John M. Twilley
|
|
||||||
ST = Steve Tylock
|
|
||||||
TU = Tetsu Ushijima
|
|
||||||
VV = Vince Vielhaber
|
|
||||||
TV = Tommi Virtanen
|
|
||||||
FW = Frank Wagner
|
|
||||||
BW = Bill Weinman
|
|
||||||
IW = Ian Westcott
|
|
||||||
SJW = Stephen J. White
|
|
||||||
JW = John Whittaker
|
|
||||||
LW = Lionel Widdifield
|
|
||||||
MW = Mate Wierdl
|
|
||||||
BTW = Brian T. Wightman
|
|
||||||
PW = Peter Wilkinson
|
PW = Peter Wilkinson
|
||||||
HW = Hal Wine
|
R2N = Rivo Nurges
|
||||||
GAW = Greg A. Woods
|
RA = Russ Allbery
|
||||||
|
RAB = Randolph Allen Bentson
|
||||||
|
RAM = Robin A. McCollum
|
||||||
|
RB = Robert Bridgham
|
||||||
|
RC = Ryan Crum
|
||||||
|
RD = Rahul Dhesi
|
||||||
|
RDM = Raul D. Miller
|
||||||
|
REB = Ronald E. Bickers
|
||||||
|
RF = Rainer Fraedrich
|
||||||
|
RFH = Robert F. Harrison
|
||||||
|
RGS = Richard G. Sharman
|
||||||
|
RJC = Robert J. Carter
|
||||||
|
RJH = Randy Harmon
|
||||||
|
RJO = Richard J. Ohnemus
|
||||||
|
RK = Riho Kurg
|
||||||
|
RL = Robert Luce
|
||||||
|
RM = Rich McClellan
|
||||||
|
RN = Russell Nelson
|
||||||
|
RO = Roberto Oppedisano
|
||||||
|
RPS = Russell P. Sutherland
|
||||||
|
RS = Robert Sanders
|
||||||
|
RSK = Robert S. Krzaczek
|
||||||
|
S1R = Satish Ramachandran
|
||||||
|
S2P = Stefan Puscasu
|
||||||
|
S2R = Sean Reifschneider
|
||||||
|
S2S = Scott Schwartz
|
||||||
|
S2T = Steve Taylor
|
||||||
|
S3T = Steffen Thorsen
|
||||||
|
SA = Satoshi Adachi
|
||||||
|
SAE = Stefaan A. Eeckels
|
||||||
|
SAS = Steven A. Schrader
|
||||||
|
SB = Stephane Bortzmeyer
|
||||||
|
SC = Stefan Cars
|
||||||
SCW = Steven C. Work
|
SCW = Steven C. Work
|
||||||
JLW = Jason L. Wright
|
SG = Steven Grimm
|
||||||
|
SGC = Stephen G. Comings
|
||||||
|
SJ = Sudish Joseph
|
||||||
|
SJB = SJ Burns
|
||||||
|
SJW = Stephen J. White
|
||||||
|
SLB = Steven L. Baur
|
||||||
|
SM = Shawn McHorse
|
||||||
|
SP = Stephen Parker
|
||||||
|
SPM = Salvatore P. Miccicke
|
||||||
|
SS = Simon Shapiro
|
||||||
|
SSB = Stik Bakken
|
||||||
|
ST = Steve Tylock
|
||||||
|
SV = Sven Velt
|
||||||
|
SVD = Stef Van Dessel
|
||||||
|
T2K = Tomoya Konishi
|
||||||
|
T2M = Toni Mueller
|
||||||
|
T2U = Todd Underwood
|
||||||
|
TA = Tetsuo Aoki
|
||||||
|
TB = Tobias Brox
|
||||||
|
TD = Tom Demmer
|
||||||
|
TEE = Thomas E. Erskine
|
||||||
|
TG = Tim Goodwin
|
||||||
|
TH = Ton Hospel
|
||||||
|
TJH = Timothy J. Hunt
|
||||||
|
TK = Terry Kennedy
|
||||||
|
TL = Timothy Lorenc
|
||||||
|
TLF = Timo L. Felbinger
|
||||||
|
TLM = Timothy L. Mayo
|
||||||
|
TM = Toshinori Maeno
|
||||||
|
TN = Thomas Neumann
|
||||||
|
TRR = Tracy R. Reed
|
||||||
|
TT = Takaki Taniguchi
|
||||||
|
TU = Tetsu Ushijima
|
||||||
|
TV = Tommi Virtanen
|
||||||
|
TVP = Tom van Peer
|
||||||
|
UO = Uwe Ohse
|
||||||
|
VBM = Vladimir B. Machulsky
|
||||||
|
VR = Vincenzo Romano
|
||||||
|
VU = Viriya Upatising
|
||||||
|
VV = Vince Vielhaber
|
||||||
|
W2K = Wolfram Kahl
|
||||||
|
WEB = William E. Baxter
|
||||||
|
WK = Werner Koch
|
||||||
|
WS = Wilbur Sims
|
||||||
WW = Wei Wu
|
WW = Wei Wu
|
||||||
IKW = Ian Keith Wynne
|
YC = Yuji Chikahiro
|
||||||
BZ = Blaz Zupan
|
YF = Yaroslav Faybishenko
|
||||||
|
ZU = Zin Uda
|
||||||
|
|
|
||||||
149
THOUGHTS
149
THOUGHTS
|
|
@ -45,9 +45,8 @@ smaller resolver library into qmail. (Bonus: I'd avoid system-specific
|
||||||
problems with old resolvers.) The problem is that I'd then be writing a
|
problems with old resolvers.) The problem is that I'd then be writing a
|
||||||
fundamentally insecure library. I'd no longer be able to blame the BIND
|
fundamentally insecure library. I'd no longer be able to blame the BIND
|
||||||
authors and vendors for the fact that attackers can easily use DNS to
|
authors and vendors for the fact that attackers can easily use DNS to
|
||||||
steal mail. Possible solution: replace dns.c with something that passes
|
steal mail. Solution: insist that the resolver run on the same host; the
|
||||||
requests (reliably!) to a local daemon; call the original resolver
|
kernel can guarantee the security of low-numbered 127.0.0.1 UDP ports.
|
||||||
library from that daemon.
|
|
||||||
|
|
||||||
NFS is the primary enemy of security partitioning under UNIX. Here's the
|
NFS is the primary enemy of security partitioning under UNIX. Here's the
|
||||||
story. Sun knew from the start that NFS was completely insecure. It
|
story. Sun knew from the start that NFS was completely insecure. It
|
||||||
|
|
@ -72,10 +71,10 @@ is, as far as I can tell, always wrong.
|
||||||
|
|
||||||
2. Injecting mail locally (qmail-inject, sendmail-clone)
|
2. Injecting mail locally (qmail-inject, sendmail-clone)
|
||||||
|
|
||||||
RFC 822 section 3.4.9 prohibits certain visual effects in headers.
|
RFC 822 section 3.4.9 prohibits certain visual effects in headers, and
|
||||||
qmail-inject doesn't waste the time to enforce this absurd restriction.
|
the 822bis draft prohibits even more. qmail-inject could enforce these
|
||||||
If you will suffer from someone sending you ``flash mail,'' go find a
|
absurd restrictions, but why waste the time? If you will suffer from
|
||||||
better mail reader.
|
someone sending you ``flash mail,'' go find a better mail reader.
|
||||||
|
|
||||||
qmail-inject's ``Cc: recipient list not shown: ;'' successfully stops
|
qmail-inject's ``Cc: recipient list not shown: ;'' successfully stops
|
||||||
sendmail from adding Apparently-To. Unfortunately, old versions of
|
sendmail from adding Apparently-To. Unfortunately, old versions of
|
||||||
|
|
@ -101,44 +100,47 @@ It is possible to extract non-unique Message-IDs out of qmail-inject.
|
||||||
Here's how: stop qmail-inject before it gets to the third line of
|
Here's how: stop qmail-inject before it gets to the third line of
|
||||||
main(), then wait until the pids wrap around, then restart qmail-inject
|
main(), then wait until the pids wrap around, then restart qmail-inject
|
||||||
and blast the message through, then start another qmail-inject with the
|
and blast the message through, then start another qmail-inject with the
|
||||||
same pid in the same second. I'm not sure how to fix this. (Of course,
|
same pid in the same second. I'm not sure how to fix this without
|
||||||
the user could just type in his own non-unique Message-IDs.)
|
system-supplied sequence numbers. (Of course, the user could just type
|
||||||
|
in his own non-unique Message-IDs.)
|
||||||
|
|
||||||
The bat book says: ``Rules that hide hosts in a domain should be applied
|
The bat book says: ``Rules that hide hosts in a domain should be applied
|
||||||
only to sender addresses.'' Recipient masquerading works fine with
|
only to sender addresses.'' Recipient masquerading works fine with
|
||||||
qmail. None of sendmail's pitfalls apply, basically because qmail has a
|
qmail. None of sendmail's pitfalls apply, basically because qmail has a
|
||||||
straight paper path.
|
straight paper path.
|
||||||
|
|
||||||
I expect to receive some pressure to make up for the failings of MUA
|
I predicted that I would receive some pressure to make up for the
|
||||||
writers who don't understand the concept of reliability. (``Like, duh,
|
failings of MUA writers who don't understand the concept of reliability.
|
||||||
you mean I was supposed to check the sendmail exit code?'')
|
(``Like, duh, you mean I'm supposed to check the sendmail exit code?'')
|
||||||
|
I was right.
|
||||||
|
|
||||||
|
|
||||||
3. Receiving mail from the network (tcp-env, qmail-smtpd)
|
3. Receiving mail from the network (tcp-env, qmail-smtpd)
|
||||||
|
|
||||||
RFC 1123 requires VRFY support, but says that it's okay if an
|
qmail-smtpd doesn't allow privacy-invading commands like VRFY and EXPN.
|
||||||
implementation can be configured to not allow VRFY. qmail-smtpd doesn't
|
If you really want to publish such information, use a mechanism that
|
||||||
allow VRFY. If you desperately want your SMTP server (i.e., inetd) to
|
legitimate users actually know about, such as fingerd or httpd.
|
||||||
provide useful information for VRFY, just compile and install sendmail.
|
|
||||||
Were the RFC 1123 writers aware of the as-if principle of interface
|
RFC 1123 says that VRFY and EXPN are important to track down cross-host
|
||||||
specification? ... They say that VRFY and EXPN are important for
|
mailing list loops. With Delivered-To, mailing list loops do no damage,
|
||||||
tracking down cross-host mailing list loops. Catch up to the 1990s,
|
_and_ one of the list administrators gets a bounce message that shows
|
||||||
guys: with Delivered-To, mailing list loops do absolutely no damage,
|
exactly how the loop occurred. Solve the problem, not the symptom.
|
||||||
_and_ one of the list administrators gets a bounce that shows exactly
|
|
||||||
how the loop occurred. Solve the problem, not the symptom. ... There's a
|
|
||||||
vastly superior alternative to EXPN. Hint: finger postmaster@ai.mit.edu.
|
|
||||||
|
|
||||||
Should dns.c make special allowances for 127.0.0.1/localhost?
|
Should dns.c make special allowances for 127.0.0.1/localhost?
|
||||||
|
|
||||||
badmailfrom (like 8BITMIME) is a waste of code space.
|
badmailfrom (like 8BITMIME) is a waste of code space.
|
||||||
|
|
||||||
|
In theory a MAIL or RCPT argument can contain unquoted LFs. In practice
|
||||||
|
there are a huge number of clients that terminate commands with just LF,
|
||||||
|
even if they use CR properly inside DATA.
|
||||||
|
|
||||||
|
|
||||||
4. Adding messages to the queue (qmail-queue)
|
4. Adding messages to the queue (qmail-queue)
|
||||||
|
|
||||||
Should qmail-queue try to make sure enough disk space is free in
|
Should qmail-queue try to make sure enough disk space is free in
|
||||||
advance? When qmail-queue is invoked by qmail-local or (with ESMTP)
|
advance? When qmail-queue is invoked by qmail-local or (with ESMTP)
|
||||||
qmail-smtpd or qmail-qmtpd, it could be told a size in advance. I wish
|
qmail-smtpd or qmail-qmtpd or qmail-qmqpd, it could be told a size in
|
||||||
UNIX had an atomic allocate-disk-space routine...
|
advance. I wish UNIX had an atomic allocate-disk-space routine...
|
||||||
|
|
||||||
The qmail.h interface (reflecting the qmail-queue interface, which in
|
The qmail.h interface (reflecting the qmail-queue interface, which in
|
||||||
turn reflects the current queue file structure) is constitutionally
|
turn reflects the current queue file structure) is constitutionally
|
||||||
|
|
@ -152,11 +154,7 @@ Should qmail-queue not bother queueing a message with no recipients?
|
||||||
|
|
||||||
The queue directory must be local. Mounting it over NFS is extremely
|
The queue directory must be local. Mounting it over NFS is extremely
|
||||||
dangerous---not that this stops people from running sendmail that way!
|
dangerous---not that this stops people from running sendmail that way!
|
||||||
Perhaps it is worth putting together a diskless-host qmail package with
|
Diskless hosts should use mini-qmail instead.
|
||||||
just qmail-inject and an SMTP client in place of qmail-queue. Sending
|
|
||||||
mail to the server via SMTP is of course vastly better than trying to do
|
|
||||||
anything over NFS. If the NFS server is up but the mail server is down,
|
|
||||||
users will just have to wait.
|
|
||||||
|
|
||||||
Queue reliability demands that single-byte writes be atomic. This is
|
Queue reliability demands that single-byte writes be atomic. This is
|
||||||
true for a fixed-block filesystem such as UFS, and for a logging
|
true for a fixed-block filesystem such as UFS, and for a logging
|
||||||
|
|
@ -190,11 +188,8 @@ than one deliverable message at any given moment.
|
||||||
Exception: Even with all the concurrency tricks, qmail-send can end up
|
Exception: Even with all the concurrency tricks, qmail-send can end up
|
||||||
spending a few minutes on a mailing list with thousands of remote
|
spending a few minutes on a mailing list with thousands of remote
|
||||||
entries. A user might send a new message to a remote address in the
|
entries. A user might send a new message to a remote address in the
|
||||||
meantime. Perhaps qmail-send should limit its time per message to,
|
meantime. The simplest way to handle this would be to put big messages
|
||||||
say, thirty recipients. This will require some way to mark recipients
|
on a separate channel.
|
||||||
who were already done on this pass. Possible approach: Maintain two todo
|
|
||||||
lists (for both L and R). Always work on the earlier todo list. Move
|
|
||||||
deferrals to the other todo list.
|
|
||||||
|
|
||||||
qmail-send will never start a pass for a job that it already has. This
|
qmail-send will never start a pass for a job that it already has. This
|
||||||
means that, if one delivery takes longer than the retry interval, the
|
means that, if one delivery takes longer than the retry interval, the
|
||||||
|
|
@ -207,40 +202,26 @@ Some things that qmail-send does synchronously: queueing a bounce
|
||||||
message; doing a cleanup via qmail-clean; classifying and rewriting all
|
message; doing a cleanup via qmail-clean; classifying and rewriting all
|
||||||
the addresses in a new message. As usual, making these asynchronous
|
the addresses in a new message. As usual, making these asynchronous
|
||||||
would require some housekeeping, but could speed things up a bit.
|
would require some housekeeping, but could speed things up a bit.
|
||||||
(Making bounces asynchronous, without POSIX waitpid(), means that
|
(I'm willing to assume POSIX waitpid() for asynchronous bounces; putting
|
||||||
wait_pid() has to keep a buffer of previous wait()s. Ugh.)
|
an unbounded buffer into wait_pid() for the sake of NeXTSTEP 3 is not
|
||||||
|
worthwhile.)
|
||||||
|
|
||||||
fsync() is a bottleneck. To make this asynchronous would require gobs of
|
Disk I/O is a bottleneck; UFS is reliable but it isn't fast. A good
|
||||||
dedicated output processes whose only purpose in life is to watch data
|
logging filesystem offers much better performance, but logging
|
||||||
get written to the disk. Inconceivable! (``You keep using that word. I
|
filesystems aren't widely available. Solution: Keep a journal, separate
|
||||||
do not think that word means what you think it means.'')
|
from the queue, adequate to rebuild the queue (with at worst some
|
||||||
|
duplicate deliveries). Compress the journal. This would dramatically
|
||||||
|
reduce total disk I/O.
|
||||||
|
|
||||||
On the other hand, I could survive without fsync()ing the local and
|
Bounce aggregation is a dubious feature. Bounce records aren't
|
||||||
remote and info files as long as I don't unlink todo. This would require
|
crashproof; there can be a huge delay between a failure and a bounce;
|
||||||
redefining the queue states. I need to see how much speed can be gained.
|
the resulting bounce format is unnecessarily complicated. I'm tempted to
|
||||||
|
scrap the bounce directory and send one bounce for each failing
|
||||||
|
recipient, with appropriate modifications in the accompanying text.
|
||||||
|
|
||||||
Currently qmail-send sends at most one bounce message for each incoming
|
qmail-stop implementation: setuid to UID_SEND; kill -TERM -1. Or run
|
||||||
message. This means that the sender doesn't get flooded with copies of
|
qmail-start under an external service controller, such as supervise;
|
||||||
his own message. On the other hand, a single slow address can hold up
|
that's why it runs in the foreground.
|
||||||
bounces for a bunch of fast addresses. It would be easy to call
|
|
||||||
injectbounce() more often. What is the best strategy? This feels like
|
|
||||||
the TCP-buffering issue... don't want to pepper the other guy with
|
|
||||||
little packets, but do want to get the data across.
|
|
||||||
|
|
||||||
qmail-stop implementation: setuid to UID_SEND; kill -TERM -1. Given how
|
|
||||||
simple this is, I'm not inclined to set up some tricky locking solution
|
|
||||||
where qmail-send records its pid etc. But I just know that, if I provide
|
|
||||||
this qmail-stop program, someone will screw himself by making another
|
|
||||||
uid the same as UID_SEND, or making UID_SEND be root, or whatever.
|
|
||||||
Aargh. Maybe use another named pipe... New solution: Run qmail-start
|
|
||||||
under an external service controller---it runs in the foreground now.
|
|
||||||
|
|
||||||
Bounce messages could include more statistical information in the first
|
|
||||||
paragraph: when I received the message, how many recipients I was
|
|
||||||
supposed to handle, how many I successfully dealt with, how many I
|
|
||||||
already told you about, how many are still in the queue. Have to
|
|
||||||
emphasize that the number of recipients _here_ is perhaps less than the
|
|
||||||
number of recipients on the original message.
|
|
||||||
|
|
||||||
The readdir() interface hides I/O errors. Lower-level interfaces would
|
The readdir() interface hides I/O errors. Lower-level interfaces would
|
||||||
lead me into a thicket of portability problems. I'm really not sure what
|
lead me into a thicket of portability problems. I'm really not sure what
|
||||||
|
|
@ -270,22 +251,17 @@ messages to multiple recipients at a single host? For typical hosts,
|
||||||
multiple RCPTs per SMTP aren't an ``efficiency feature''; they're a
|
multiple RCPTs per SMTP aren't an ``efficiency feature''; they're a
|
||||||
_slowness_ feature. Separate SMTP transactions have much lower latency.
|
_slowness_ feature. Separate SMTP transactions have much lower latency.
|
||||||
|
|
||||||
The multiple-RCPT bandwidth gain _might_ be noticeable for a machine
|
I've heard three complaints about bandwidth use from masochists sending
|
||||||
that sends most messages to a smarthost. It would be easy to have
|
messages through a modem through a smarthost to thousands of users---
|
||||||
qmail-rspawn supply qmail-remote with all the addresses at once, as long
|
without sublists! They can get much better performance with QMQP.
|
||||||
as qmail-send says when it's about to block... Putting recipients into
|
|
||||||
the right order is clearly the UA's job. One multiple-RCPT pitfall is
|
|
||||||
that a remote host might not be able to deal with (say) 10 recipients,
|
|
||||||
even though RFC 821 says everyone has to be able to handle 100;
|
|
||||||
qmail-rspawn would have to notice this and back off. (Not that other
|
|
||||||
mailers do. Sometimes I'm amazed Internet mail works at all.)
|
|
||||||
|
|
||||||
In the opposite direction: It's tempting to remove the @host part of the
|
In the opposite direction: It's tempting to remove the @host part of the
|
||||||
qmail-remote recip argument. Or at least avoid double-dns_cname.
|
qmail-remote recip argument. Or at least avoid double-dns_cname.
|
||||||
|
|
||||||
There are lots of reasons that qmail-rspawn should take a more active
|
There are lots of reasons that qmail-rspawn should take a more active
|
||||||
role in qmail-remote's activities. It should call separate programs to
|
role in qmail-remote's activities. It should call separate programs to
|
||||||
do (1) MX lookups, (2) SMTP connections, (3) QMTP connections.
|
do (1) MX lookups, (2) SMTP connections, (3) QMTP connections. (But this
|
||||||
|
wouldn't be so important if the DNS library didn't burn so much memory.)
|
||||||
|
|
||||||
I bounce ambiguous MXs. (An ``ambiguous MX'' is a best-preference MX
|
I bounce ambiguous MXs. (An ``ambiguous MX'' is a best-preference MX
|
||||||
record sending me mail for a host that I don't recognize as local.)
|
record sending me mail for a host that I don't recognize as local.)
|
||||||
|
|
@ -310,6 +286,15 @@ time across any number of MXs; this idea is due to Mark Delany.
|
||||||
RFC 821 doesn't say what it means by ``text.'' qmail-remote assumes that
|
RFC 821 doesn't say what it means by ``text.'' qmail-remote assumes that
|
||||||
the server's reply text doesn't contain bare LFs.
|
the server's reply text doesn't contain bare LFs.
|
||||||
|
|
||||||
|
RFC 821 and RFC 1123 prohibit host names in MAIL FROM and RCPT TO from
|
||||||
|
being aliases. qmail-remote, like sendmail, rewrites aliases in RCPT;
|
||||||
|
people who don't list aliases in control/locals or sendmail's Cw are
|
||||||
|
implicitly relying on this conversion. It is course quite silly for an
|
||||||
|
internal DNS detail to have such an effect on mail delivery, but that's
|
||||||
|
how the Internet works. On the other hand, the compatibility arguments
|
||||||
|
do not apply to MAIL FROM. qmail-remote no longer bothers with CNAME
|
||||||
|
lookups for the envelope sender host.
|
||||||
|
|
||||||
|
|
||||||
7. Delivering mail locally (qmail-lspawn, qmail-local)
|
7. Delivering mail locally (qmail-lspawn, qmail-local)
|
||||||
|
|
||||||
|
|
@ -347,7 +332,7 @@ Configurable user database: Yup.
|
||||||
|
|
||||||
BIND support: Yup.
|
BIND support: Yup.
|
||||||
|
|
||||||
Keyed files: Yes, in qmsmac.
|
Keyed files: Yes, in fastforward.
|
||||||
|
|
||||||
931/1413/Ident/TAP: Yup.
|
931/1413/Ident/TAP: Yup.
|
||||||
|
|
||||||
|
|
@ -358,7 +343,9 @@ List-owner handling: Yup.
|
||||||
|
|
||||||
Dynamic header allocation: Yup.
|
Dynamic header allocation: Yup.
|
||||||
|
|
||||||
Minimum number of disk blocks: Yes, via tunefs -m.
|
Minimum number of disk blocks: Yes, via tunefs -m. (Or quotas; the right
|
||||||
|
setup has qmailq with a small quota, qmails with a larger quota, so that
|
||||||
|
qmail-send always has room to work.)
|
||||||
|
|
||||||
Checkpointing: Yes, but not configurable---qmail always checkpoints.
|
Checkpointing: Yes, but not configurable---qmail always checkpoints.
|
||||||
|
|
||||||
|
|
@ -420,12 +407,6 @@ I should clean up the bput/put choices.
|
||||||
Some of the stralloc_0()s indicate that certain lower-level routines
|
Some of the stralloc_0()s indicate that certain lower-level routines
|
||||||
should grok stralloc.
|
should grok stralloc.
|
||||||
|
|
||||||
RN suggests having qlist smash the case of the incoming host name.
|
|
||||||
|
|
||||||
K1J suggests that mailing list subscription managers should have
|
|
||||||
a three-way handshake, to prevent person A from subscribing person B to
|
|
||||||
a mailing list. qlist doesn't do this, but ezmlm does.
|
|
||||||
|
|
||||||
qmail assumes that all times are positive; that pid_t, time_t and ino_t
|
qmail assumes that all times are positive; that pid_t, time_t and ino_t
|
||||||
fit into unsigned long; that gid_t fits into int; that the character set
|
fit into unsigned long; that gid_t fits into int; that the character set
|
||||||
is ASCII; and that all pointers are interchangeable. Do I care?
|
is ASCII; and that all pointers are interchangeable. Do I care?
|
||||||
|
|
|
||||||
29
TODO
29
TODO
|
|
@ -1,9 +1,26 @@
|
||||||
do some serious coverage testing, preferably under Purify, without alloc slop
|
test qmail-qmqpc
|
||||||
replace INTERNALS and THOUGHTS with a real paper describing qmail
|
test qmail-qmqpd
|
||||||
reorganize qmail-inject to do most rw on characters, not tokens
|
|
||||||
allow concurrency over 255
|
consider stripping vdoms for VERPs; tnx PJH
|
||||||
handle IPv6
|
consider ~ in qmail-local for doing defaultdelivery (not recursively)
|
||||||
|
consider POP bulletins
|
||||||
turn qmail-upq into a more serious queue-moving utility
|
turn qmail-upq into a more serious queue-moving utility
|
||||||
|
consider fast-greeting option in qmail-smtpd
|
||||||
|
build a returnmail package
|
||||||
|
|
||||||
expand strerr coverage
|
expand strerr coverage
|
||||||
|
redo control interface
|
||||||
|
allow concurrency over 255
|
||||||
|
allow more channels at compile time
|
||||||
|
test for linux fifo close bug at compile time
|
||||||
|
|
||||||
|
eliminate qsmhook
|
||||||
|
finish OTBS conversion
|
||||||
|
use lib822 in qmail-inject
|
||||||
|
use lib822 in qreceipt
|
||||||
|
use lib822 in qbiff
|
||||||
|
use lib822 in maildirwatch
|
||||||
|
eliminate token822, headerbody, hfield
|
||||||
|
replace INTERNALS and THOUGHTS with a real paper describing qmail
|
||||||
|
handle IPv6
|
||||||
rewrite everything from scratch
|
rewrite everything from scratch
|
||||||
maybe allow root to clear tcpto on the fly
|
|
||||||
|
|
|
||||||
93
UPGRADE
93
UPGRADE
|
|
@ -3,12 +3,20 @@ information generally), the qmail system comes with NO WARRANTY. It's
|
||||||
much more secure and reliable than sendmail, but that's not saying much.
|
much more secure and reliable than sendmail, but that's not saying much.
|
||||||
|
|
||||||
|
|
||||||
Here's how to upgrade from qmail 1.00 to qmail 1.01. This procedure will
|
Here's how to upgrade from qmail 1.01 to qmail 1.02. This procedure will
|
||||||
overwrite the old qmail binaries. Furthermore, it may begin delivering
|
overwrite the old qmail binaries. Furthermore, it may begin delivering
|
||||||
messages from the queue before you have had a chance to test it.
|
messages from the queue before you have had a chance to test it.
|
||||||
|
|
||||||
|
|
||||||
WARNING: The qmail-start command line has changed.
|
WARNING: qlist has been split into a separate package. You can obtain it
|
||||||
|
from http://pobox.com/~djb/qlist.html if you have any users who need it.
|
||||||
|
|
||||||
|
WARNING: recipientmap is gone. The virtualdomains mechanism has been
|
||||||
|
expanded to support virtual users.
|
||||||
|
|
||||||
|
WARNING: qmail-start is now normally started from /var/qmail/rc. If you
|
||||||
|
have changed your qmail-start line, you will have to change
|
||||||
|
/var/qmail/rc accordingly in step 8.
|
||||||
|
|
||||||
|
|
||||||
Before starting, compare conf* to your old conf*, and make any necessary
|
Before starting, compare conf* to your old conf*, and make any necessary
|
||||||
|
|
@ -17,27 +25,37 @@ changes. Do not copy your old conf*; the baseline has changed.
|
||||||
|
|
||||||
How to install:
|
How to install:
|
||||||
|
|
||||||
1. Compile the programs:
|
1. Compile the programs and create the formatted man pages:
|
||||||
# make
|
# make it man
|
||||||
2. Create the formatted man pages, *.0:
|
|
||||||
# make man
|
2. Inform your users that mail will not be accepted for a few minutes.
|
||||||
3. Inform your users that mail will not be accepted for a few minutes.
|
|
||||||
4. Disable deliveries by killing your old qmail-send. Wait for it to
|
3. Disable deliveries by killing your old qmail-send. Wait for it to
|
||||||
print ``exiting'' in the log.
|
print ``exiting'' in the log.
|
||||||
5. Disable SMTP service by commenting out the smtp line in inetd.conf;
|
|
||||||
|
4. Disable SMTP service by commenting out the smtp line in inetd.conf;
|
||||||
kill -HUP your inetd. (If you are using tcpserver, simply kill -STOP
|
kill -HUP your inetd. (If you are using tcpserver, simply kill -STOP
|
||||||
your tcpserver.) Wait for current qmail-smtpd processes to die. (If
|
your tcpserver. If you are running a QMTP server, disable that too.)
|
||||||
you are running a QMTP server, disable that too.)
|
Wait for current qmail-smtpd processes to die.
|
||||||
6. Install the new binaries and man pages:
|
|
||||||
# rm /var/qmail/bin/* /var/qmail/man/*/*
|
5. Install the new binaries and man pages:
|
||||||
# make setup
|
# make setup
|
||||||
7. Run instcheck to make sure it doesn't print any warnings:
|
|
||||||
|
6. Run instcheck to make sure it doesn't print any warnings:
|
||||||
# make check
|
# make check
|
||||||
8. Reenable deliveries:
|
|
||||||
# env - PATH="/var/qmail/bin:$PATH" \
|
7. Copy /var/qmail/boot/home to /var/qmail/rc. (Use home+df instead if
|
||||||
qmail-start ./Mailbox splogger qmail &
|
you have installed dot-forward; use proc or proc+df if you are using
|
||||||
Make sure to include the ./ in ./Mailbox.
|
procmail by default for local deliveries.)
|
||||||
9. Insert ./Mailbox into the qmail-start line in your boot scripts.
|
|
||||||
|
8. Compare /var/qmail/rc to the qmail-start boot line in your boot
|
||||||
|
scripts. Edit /var/qmail/rc if necessary. Replace the qmail-start
|
||||||
|
boot line in your boot scripts with
|
||||||
|
csh -cf '/var/qmail/rc &'
|
||||||
|
|
||||||
|
9. Reenable deliveries:
|
||||||
|
# csh -cf '/var/qmail/rc &'
|
||||||
|
|
||||||
10. Reenable SMTP service by restoring the smtp line in inetd.conf; kill
|
10. Reenable SMTP service by restoring the smtp line in inetd.conf; kill
|
||||||
-HUP your inetd. (If you are using tcpserver, simply kill -CONT your
|
-HUP your inetd. (If you are using tcpserver, simply kill -CONT your
|
||||||
tcpserver. If you are running a QMTP server, reenable that too.)
|
tcpserver. If you are running a QMTP server, reenable that too.)
|
||||||
|
|
@ -46,48 +64,61 @@ How to install:
|
||||||
How to test (steps 11-17 can be done before step 10):
|
How to test (steps 11-17 can be done before step 10):
|
||||||
|
|
||||||
11. Look for a
|
11. Look for a
|
||||||
qmail: running
|
qmail: status: local 0/10 remote 0/20
|
||||||
line in syslog. (The big number is a splogger timestamp.)
|
line in syslog. (The big number is a splogger timestamp.)
|
||||||
|
|
||||||
12. Local-local test: Send yourself an empty message. (Replace ``me''
|
12. Local-local test: Send yourself an empty message. (Replace ``me''
|
||||||
with your username. Make sure to include the ``to:'' colon.)
|
with your username. Make sure to include the ``to:'' colon.)
|
||||||
% echo to: me | /var/qmail/bin/qmail-inject
|
% echo to: me | /var/qmail/bin/qmail-inject
|
||||||
The message will show up immediately in ~/Mailbox, and syslog will
|
The message will show up immediately in your mailbox, and syslog
|
||||||
show something like this:
|
will show something like this:
|
||||||
qmail: new msg 53
|
qmail: new msg 53
|
||||||
qmail: info msg 53: bytes 246 from <me@domain> qp 20345 uid 666
|
qmail: info msg 53: bytes 246 from <me@domain> qp 20345 uid 666
|
||||||
qmail: starting delivery 1: msg 53 to local me@domain
|
qmail: starting delivery 1: msg 53 to local me@domain
|
||||||
|
qmail: status: local 1/10 remote 0/20
|
||||||
qmail: delivery 1: success: did_1+0+0/
|
qmail: delivery 1: success: did_1+0+0/
|
||||||
|
qmail: status: local 0/10 remote 0/20
|
||||||
qmail: end msg 53
|
qmail: end msg 53
|
||||||
(53 is an inode number; 20345 is a process ID; your numbers will
|
(53 is an inode number; 20345 is a process ID; your numbers will
|
||||||
probably be different.)
|
probably be different.)
|
||||||
|
|
||||||
13. Local-error test: Send a message to a nonexistent local address.
|
13. Local-error test: Send a message to a nonexistent local address.
|
||||||
% echo to: nonexistent | /var/qmail/bin/qmail-inject
|
% echo to: nonexistent | /var/qmail/bin/qmail-inject
|
||||||
qmail: new msg 53
|
qmail: new msg 53
|
||||||
qmail: info msg 53: bytes 246 from <me@domain> qp 20351 uid 666
|
qmail: info msg 53: bytes 246 from <me@domain> qp 20351 uid 666
|
||||||
qmail: starting delivery 2: msg 53 to local nonexistent@domain
|
qmail: starting delivery 2: msg 53 to local nonexistent@domain
|
||||||
|
qmail: status: local 1/10 remote 0/20
|
||||||
qmail: delivery 2: failure: No_such_address.__#5.1.1_/
|
qmail: delivery 2: failure: No_such_address.__#5.1.1_/
|
||||||
|
qmail: status: local 0/10 remote 0/20
|
||||||
qmail: bounce msg 53 qp 20357
|
qmail: bounce msg 53 qp 20357
|
||||||
qmail: end msg 53
|
qmail: end msg 53
|
||||||
qmail: new msg 54
|
qmail: new msg 54
|
||||||
qmail: info msg 54: bytes 743 from <> qp 20357 uid 666
|
qmail: info msg 54: bytes 743 from <> qp 20357 uid 666
|
||||||
qmail: starting delivery 3: msg 54 to local me@domain
|
qmail: starting delivery 3: msg 54 to local me@domain
|
||||||
|
qmail: status: local 1/10 remote 0/20
|
||||||
qmail: delivery 3: success: did_1+0+0/
|
qmail: delivery 3: success: did_1+0+0/
|
||||||
|
qmail: status: local 0/10 remote 0/20
|
||||||
qmail: end msg 54
|
qmail: end msg 54
|
||||||
You will now have a bounce message in ~/Mailbox.
|
You will now have a bounce message in your mailbox.
|
||||||
|
|
||||||
14. Local-remote test: Send an empty message to your account on another
|
14. Local-remote test: Send an empty message to your account on another
|
||||||
machine.
|
machine.
|
||||||
% echo to: me@wherever | /var/qmail/bin/qmail-inject
|
% echo to: me@wherever | /var/qmail/bin/qmail-inject
|
||||||
qmail: new msg 53
|
qmail: new msg 53
|
||||||
qmail: info msg 53: bytes 246 from <me@domain> qp 20372 uid 666
|
qmail: info msg 53: bytes 246 from <me@domain> qp 20372 uid 666
|
||||||
qmail: starting delivery 4: msg 53 to remote me@wherever
|
qmail: starting delivery 4: msg 53 to remote me@wherever
|
||||||
|
qmail: status: local 0/10 remote 1/20
|
||||||
qmail: delivery 4: success: 1.2.3.4_accepted_message./...
|
qmail: delivery 4: success: 1.2.3.4_accepted_message./...
|
||||||
|
qmail: status: local 0/10 remote 0/20
|
||||||
qmail: end msg 53
|
qmail: end msg 53
|
||||||
There will be a pause between ``starting delivery'' and ``success'';
|
There will be a pause between ``starting delivery'' and ``success'';
|
||||||
SMTP is slow. Check that the message is in your mailbox on the other
|
SMTP is slow. Check that the message is in your mailbox on the other
|
||||||
machine.
|
machine.
|
||||||
|
|
||||||
15. Local-postmaster test: Send mail to postmaster, any capitalization.
|
15. Local-postmaster test: Send mail to postmaster, any capitalization.
|
||||||
% echo to: POSTmaster | /var/qmail/bin/qmail-inject
|
% echo to: POSTmaster | /var/qmail/bin/qmail-inject
|
||||||
Look for the message in ~alias/Mailbox.
|
Look for the message in the alias mailbox.
|
||||||
|
|
||||||
16. Double-bounce test: Send a message with a completely bad envelope.
|
16. Double-bounce test: Send a message with a completely bad envelope.
|
||||||
% /var/qmail/bin/qmail-inject -f nonexistent
|
% /var/qmail/bin/qmail-inject -f nonexistent
|
||||||
To: unknownuser
|
To: unknownuser
|
||||||
|
|
@ -96,7 +127,8 @@ How to test (steps 11-17 can be done before step 10):
|
||||||
This is a test. This is only a test.
|
This is a test. This is only a test.
|
||||||
%
|
%
|
||||||
(Use end-of-file, not dot, to end the message.) Look for the double
|
(Use end-of-file, not dot, to end the message.) Look for the double
|
||||||
bounce in ~alias/Mailbox.
|
bounce in the alias mailbox.
|
||||||
|
|
||||||
17. Group membership test:
|
17. Group membership test:
|
||||||
% cat > ~me/.qmail-groups
|
% cat > ~me/.qmail-groups
|
||||||
|groups >> MYGROUPS; exit 0
|
|groups >> MYGROUPS; exit 0
|
||||||
|
|
@ -104,6 +136,7 @@ How to test (steps 11-17 can be done before step 10):
|
||||||
% cat ~me/MYGROUPS
|
% cat ~me/MYGROUPS
|
||||||
MYGROUPS will show your normal gid and nothing else. (Under Solaris,
|
MYGROUPS will show your normal gid and nothing else. (Under Solaris,
|
||||||
make sure to use /usr/ucb/groups; /usr/bin/groups is broken.)
|
make sure to use /usr/ucb/groups; /usr/bin/groups is broken.)
|
||||||
|
|
||||||
18. SMTP server test: Forge some mail locally via SMTP.
|
18. SMTP server test: Forge some mail locally via SMTP.
|
||||||
% telnet 127.0.0.1 25
|
% telnet 127.0.0.1 25
|
||||||
Trying 127.0.0.1...
|
Trying 127.0.0.1...
|
||||||
|
|
@ -130,16 +163,20 @@ How to test (steps 11-17 can be done before step 10):
|
||||||
Connection closed by foreign host.
|
Connection closed by foreign host.
|
||||||
%
|
%
|
||||||
Look for the message in your mailbox.
|
Look for the message in your mailbox.
|
||||||
|
|
||||||
19. Remote-local test: Send yourself some mail from another machine.
|
19. Remote-local test: Send yourself some mail from another machine.
|
||||||
|
|
||||||
20. Remote-error test: I think you can figure this one out.
|
20. Remote-error test: I think you can figure this one out.
|
||||||
|
|
||||||
21. UA test: Try sending mail, first to a local account, then to a
|
21. UA test: Try sending mail, first to a local account, then to a
|
||||||
remote account, with your normal user agent.
|
remote account, with your normal user agent.
|
||||||
|
|
||||||
22. Remote-postmaster test: Send mail from another machine to
|
22. Remote-postmaster test: Send mail from another machine to
|
||||||
PoStMaStEr@domain. Look for the message in ~alias/Mailbox.
|
PoStMaStEr@domain. Look for the message in the alias mailbox.
|
||||||
|
|
||||||
|
|
||||||
That's it! To report success:
|
That's it! To report success:
|
||||||
% ( echo 'First M. Last'; cat `cat SYSDEPS` ) \
|
% ( echo 'First M. Last'; cat `cat SYSDEPS` ) \
|
||||||
| mail djb-qst@koobera.math.uic.edu
|
| mail djb-qst@cr.yp.to
|
||||||
Replace First M. Last with your name. If you have questions about qmail,
|
Replace First M. Last with your name. If you have questions about qmail,
|
||||||
contact qmail@pobox.com.
|
join the qmail mailing list; see http://pobox.com/~djb/qmail.html.
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
qmail 1.01
|
qmail 1.02
|
||||||
|
|
|
||||||
11
binm1+df.sh
Normal file
11
binm1+df.sh
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using dot-forward to support sendmail-style ~/.forward files.
|
||||||
|
# Using binmail to deliver messages to /var/spool/mail/$USER by default.
|
||||||
|
# Using BSD 4.4 binmail interface: /usr/libexec/mail.local -r
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start '|dot-forward .forward
|
||||||
|
|preline -f /usr/libexec/mail.local -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
|
||||||
|
splogger qmail
|
||||||
10
binm1.sh
Normal file
10
binm1.sh
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using binmail to deliver messages to /var/spool/mail/$USER by default.
|
||||||
|
# Using BSD 4.4 binmail interface: /usr/libexec/mail.local -r
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start \
|
||||||
|
'|preline -f /usr/libexec/mail.local -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
|
||||||
|
splogger qmail
|
||||||
11
binm2+df.sh
Normal file
11
binm2+df.sh
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using dot-forward to support sendmail-style ~/.forward files.
|
||||||
|
# Using binmail to deliver messages to /var/spool/mail/$USER by default.
|
||||||
|
# Using SVR4 binmail interface: /bin/mail -r
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start '|dot-forward .forward
|
||||||
|
|preline -f /bin/mail -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
|
||||||
|
splogger qmail
|
||||||
10
binm2.sh
Normal file
10
binm2.sh
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using binmail to deliver messages to /var/spool/mail/$USER by default.
|
||||||
|
# Using SVR4 binmail interface: /bin/mail -r
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start \
|
||||||
|
'|preline -f /bin/mail -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
|
||||||
|
splogger qmail
|
||||||
11
binm3+df.sh
Normal file
11
binm3+df.sh
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using dot-forward to support sendmail-style ~/.forward files.
|
||||||
|
# Using binmail to deliver messages to /var/spool/mail/$USER by default.
|
||||||
|
# Using V7 binmail interface: /bin/mail -f
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start '|dot-forward .forward
|
||||||
|
|preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
|
||||||
|
splogger qmail
|
||||||
10
binm3.sh
Normal file
10
binm3.sh
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using binmail to deliver messages to /var/spool/mail/$USER by default.
|
||||||
|
# Using V7 binmail interface: /bin/mail -f
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start \
|
||||||
|
'|preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
|
||||||
|
splogger qmail
|
||||||
40
commands.c
Normal file
40
commands.c
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include "commands.h"
|
||||||
|
#include "substdio.h"
|
||||||
|
#include "stralloc.h"
|
||||||
|
#include "str.h"
|
||||||
|
#include "case.h"
|
||||||
|
|
||||||
|
static stralloc cmd = {0};
|
||||||
|
|
||||||
|
int commands(ss,c)
|
||||||
|
substdio *ss;
|
||||||
|
struct commands *c;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *arg;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (!stralloc_copys(&cmd,"")) return -1;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (!stralloc_readyplus(&cmd,1)) return -1;
|
||||||
|
i = substdio_get(ss,cmd.s + cmd.len,1);
|
||||||
|
if (i != 1) return i;
|
||||||
|
if (cmd.s[cmd.len] == '\n') break;
|
||||||
|
++cmd.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.len > 0) if (cmd.s[cmd.len - 1] == '\r') --cmd.len;
|
||||||
|
|
||||||
|
cmd.s[cmd.len] = 0;
|
||||||
|
|
||||||
|
i = str_chr(cmd.s,' ');
|
||||||
|
arg = cmd.s + i;
|
||||||
|
while (*arg == ' ') ++arg;
|
||||||
|
cmd.s[i] = 0;
|
||||||
|
|
||||||
|
for (i = 0;c[i].text;++i) if (case_equals(c[i].text,cmd.s)) break;
|
||||||
|
c[i].fun(arg);
|
||||||
|
if (c[i].flush) c[i].flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
12
commands.h
Normal file
12
commands.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef COMMANDS_H
|
||||||
|
#define COMMANDS_H
|
||||||
|
|
||||||
|
struct commands {
|
||||||
|
char *text;
|
||||||
|
void (*fun)();
|
||||||
|
void (*flush)();
|
||||||
|
} ;
|
||||||
|
|
||||||
|
extern int commands();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -48,6 +48,13 @@ it is not safe for
|
||||||
.I program
|
.I program
|
||||||
to fork a child that
|
to fork a child that
|
||||||
reads the message in the background.
|
reads the message in the background.
|
||||||
|
|
||||||
|
.B WARNING:
|
||||||
|
If you create a
|
||||||
|
.B .qmail
|
||||||
|
file to enable
|
||||||
|
.BR condredirect ,
|
||||||
|
make sure to also add a line specifying delivery to your normal mailbox.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
dot-qmail(5),
|
dot-qmail(5),
|
||||||
qmail-command(8),
|
qmail-command(8),
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,11 @@
|
||||||
#include "wait.h"
|
#include "wait.h"
|
||||||
#include "seek.h"
|
#include "seek.h"
|
||||||
#include "qmail.h"
|
#include "qmail.h"
|
||||||
#include "stralloc.h"
|
#include "strerr.h"
|
||||||
#include "subfd.h"
|
|
||||||
#include "substdio.h"
|
#include "substdio.h"
|
||||||
|
#include "fmt.h"
|
||||||
|
|
||||||
void die_success() { _exit(0); }
|
#define FATAL "condredirect: fatal: "
|
||||||
void die_99() { _exit(99); }
|
|
||||||
void die_perm(s) char *s; { substdio_putsflush(subfderr,s); _exit(100); }
|
|
||||||
void die_temp(s) char *s; { substdio_putsflush(subfderr,s); _exit(111); }
|
|
||||||
void die_nomem() { die_temp("condredirect: fatal: out of memory\n"); }
|
|
||||||
|
|
||||||
struct qmail qqt;
|
struct qmail qqt;
|
||||||
|
|
||||||
|
|
@ -25,10 +21,12 @@ int mywrite(fd,buf,len) int fd; char *buf; int len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
substdio ssin;
|
|
||||||
substdio ssout;
|
|
||||||
char inbuf[SUBSTDIO_INSIZE];
|
char inbuf[SUBSTDIO_INSIZE];
|
||||||
char outbuf[16];
|
char outbuf[1];
|
||||||
|
substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
|
||||||
|
substdio ssout = SUBSTDIO_FDBUF(mywrite,-1,outbuf,sizeof outbuf);
|
||||||
|
|
||||||
|
char num[FMT_ULONG];
|
||||||
|
|
||||||
void main(argc,argv)
|
void main(argc,argv)
|
||||||
int argc;
|
int argc;
|
||||||
|
|
@ -38,50 +36,50 @@ char **argv;
|
||||||
char *dtline;
|
char *dtline;
|
||||||
int pid;
|
int pid;
|
||||||
int wstat;
|
int wstat;
|
||||||
|
char *qqx;
|
||||||
|
|
||||||
if (!argv[1] || !argv[2])
|
if (!argv[1] || !argv[2])
|
||||||
die_perm("condredirect: usage: condredirect newaddress program arg ...\n");
|
strerr_die1x(100,"condredirect: usage: condredirect newaddress program [ arg ... ]");
|
||||||
|
|
||||||
switch(pid = fork())
|
pid = fork();
|
||||||
{
|
if (pid == -1)
|
||||||
case -1: die_temp("condredirect: fatal: unable to fork\n");
|
strerr_die2sys(111,FATAL,"unable to fork: ");
|
||||||
case 0:
|
if (pid == 0) {
|
||||||
execvp(argv[2],argv + 2);
|
execvp(argv[2],argv + 2);
|
||||||
if (error_temp(errno)) _exit(111);
|
if (error_temp(errno)) _exit(111);
|
||||||
_exit(100);
|
_exit(100);
|
||||||
}
|
}
|
||||||
if (wait_pid(&wstat,pid) != pid)
|
if (wait_pid(&wstat,pid) == -1)
|
||||||
die_perm("condredirect: fatal: internal bug\n");
|
strerr_die2x(111,FATAL,"wait failed");
|
||||||
if (wait_crashed(wstat)) die_temp("condredirect: fatal: child crashed\n");
|
if (wait_crashed(wstat))
|
||||||
switch(wait_exitcode(wstat))
|
strerr_die2x(111,FATAL,"child crashed");
|
||||||
{
|
switch(wait_exitcode(wstat)) {
|
||||||
case 0: break;
|
case 0: break;
|
||||||
case 111: die_temp("condredirect: fatal: temporary child error\n");
|
case 111: strerr_die2x(111,FATAL,"temporary child error");
|
||||||
default: die_success();
|
default: _exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seek_begin(0) == -1) die_temp("condredirect: fatal: unable to rewind\n");
|
if (seek_begin(0) == -1)
|
||||||
|
strerr_die2sys(111,FATAL,"unable to rewind: ");
|
||||||
sig_pipeignore();
|
sig_pipeignore();
|
||||||
|
|
||||||
sender = env_get("SENDER");
|
sender = env_get("SENDER");
|
||||||
if (!sender) die_perm("condredirect: fatal: SENDER not set\n");
|
if (!sender) strerr_die2x(100,FATAL,"SENDER not set");
|
||||||
dtline = env_get("DTLINE");
|
dtline = env_get("DTLINE");
|
||||||
if (!dtline) die_perm("condredirect: fatal: DTLINE not set\n");
|
if (!dtline) strerr_die2x(100,FATAL,"DTLINE not set");
|
||||||
|
|
||||||
if (qmail_open(&qqt) == -1) die_temp("condredirect: fatal: unable to fork\n");
|
if (qmail_open(&qqt) == -1)
|
||||||
|
strerr_die2sys(111,FATAL,"unable to fork: ");
|
||||||
qmail_puts(&qqt,dtline);
|
qmail_puts(&qqt,dtline);
|
||||||
substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
|
|
||||||
substdio_fdbuf(&ssout,mywrite,-1,outbuf,sizeof(outbuf));
|
|
||||||
if (substdio_copy(&ssout,&ssin) != 0)
|
if (substdio_copy(&ssout,&ssin) != 0)
|
||||||
die_temp("condredirect: fatal: error while reading message\n");
|
strerr_die2sys(111,FATAL,"unable to read message: ");
|
||||||
substdio_flush(&ssout);
|
substdio_flush(&ssout);
|
||||||
|
|
||||||
|
num[fmt_ulong(num,qmail_qp(&qqt))] = 0;
|
||||||
|
|
||||||
qmail_from(&qqt,sender);
|
qmail_from(&qqt,sender);
|
||||||
qmail_to(&qqt,argv[1]);
|
qmail_to(&qqt,argv[1]);
|
||||||
switch(qmail_close(&qqt))
|
qqx = qmail_close(&qqt);
|
||||||
{
|
if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1);
|
||||||
case 0: die_99();
|
strerr_die2x(99,"condredirect: qp ",num);
|
||||||
case QMAIL_TOOLONG: die_perm("condredirect: fatal: permanent qmail-queue error\n");
|
|
||||||
default: die_temp("condredirect: fatal: temporary qmail-queue error\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,10 @@
|
||||||
|
|
||||||
This is the qmail home directory. It must be a local directory, not
|
This is the qmail home directory. It must be a local directory, not
|
||||||
shared among machines. This is where qmail queues all mail messages.
|
shared among machines. This is where qmail queues all mail messages.
|
||||||
|
|
||||||
|
The queue (except for bounce message contents) is crashproof, if the
|
||||||
|
filesystem guarantees that single-byte writes are atomic and that
|
||||||
|
directory operations are synchronous. These guarantees are provided by
|
||||||
|
fixed-block filesystems such as UFS and by journaling filesystems. Under
|
||||||
|
Linux, make sure that all mail-handling filesystems are mounted with
|
||||||
|
synchronous metadata.
|
||||||
|
|
|
||||||
30
config-fast.sh
Normal file
30
config-fast.sh
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
fqdn="$1"
|
||||||
|
echo Your fully qualified host name is "$fqdn".
|
||||||
|
|
||||||
|
echo Putting "$fqdn" into control/me...
|
||||||
|
echo "$fqdn" > QMAIL/control/me
|
||||||
|
chmod 644 QMAIL/control/me
|
||||||
|
|
||||||
|
( echo "$fqdn" | sed 's/^\([^\.]*\)\.\([^\.]*\)\./\2\./' | (
|
||||||
|
read ddom
|
||||||
|
echo Putting "$ddom" into control/defaultdomain...
|
||||||
|
echo "$ddom" > QMAIL/control/defaultdomain
|
||||||
|
chmod 644 QMAIL/control/defaultdomain
|
||||||
|
) )
|
||||||
|
|
||||||
|
( echo "$fqdn" | sed 's/^.*\.\([^\.]*\)\.\([^\.]*\)$/\1.\2/' | (
|
||||||
|
read pdom
|
||||||
|
echo Putting "$pdom" into control/plusdomain...
|
||||||
|
echo "$pdom" > QMAIL/control/plusdomain
|
||||||
|
chmod 644 QMAIL/control/plusdomain
|
||||||
|
) )
|
||||||
|
|
||||||
|
echo Putting "$fqdn" into control/locals...
|
||||||
|
echo "$fqdn" >> QMAIL/control/locals
|
||||||
|
chmod 644 QMAIL/control/locals
|
||||||
|
|
||||||
|
echo Putting "$fqdn" into control/rcpthosts...
|
||||||
|
echo "$fqdn" >> QMAIL/control/rcpthosts
|
||||||
|
chmod 644 QMAIL/control/rcpthosts
|
||||||
|
echo "Now qmail will refuse to accept SMTP messages except to $fqdn."
|
||||||
|
echo 'Make sure to change rcpthosts if you add hosts to locals or virtualdomains!'
|
||||||
27
constmap.c
27
constmap.c
|
|
@ -9,8 +9,7 @@ int len;
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
constmap_hash h;
|
constmap_hash h;
|
||||||
h = 5381;
|
h = 5381;
|
||||||
while (len > 0)
|
while (len > 0) {
|
||||||
{
|
|
||||||
ch = *s++ - 'A';
|
ch = *s++ - 'A';
|
||||||
if (ch <= 'Z' - 'A') ch += 'a' - 'A';
|
if (ch <= 'Z' - 'A') ch += 'a' - 'A';
|
||||||
h = ((h << 5) + h) ^ ch;
|
h = ((h << 5) + h) ^ ch;
|
||||||
|
|
@ -28,8 +27,7 @@ int len;
|
||||||
int pos;
|
int pos;
|
||||||
h = hash(s,len);
|
h = hash(s,len);
|
||||||
pos = cm->first[h & cm->mask];
|
pos = cm->first[h & cm->mask];
|
||||||
while (pos != -1)
|
while (pos != -1) {
|
||||||
{
|
|
||||||
if (h == cm->hash[pos])
|
if (h == cm->hash[pos])
|
||||||
if (len == cm->inputlen[pos])
|
if (len == cm->inputlen[pos])
|
||||||
if (!case_diffb(cm->input[pos],len,s))
|
if (!case_diffb(cm->input[pos],len,s))
|
||||||
|
|
@ -59,30 +57,23 @@ int flagcolon;
|
||||||
cm->mask = h - 1;
|
cm->mask = h - 1;
|
||||||
|
|
||||||
cm->first = (int *) alloc(sizeof(int) * h);
|
cm->first = (int *) alloc(sizeof(int) * h);
|
||||||
if (cm->first)
|
if (cm->first) {
|
||||||
{
|
|
||||||
cm->input = (char **) alloc(sizeof(char *) * cm->num);
|
cm->input = (char **) alloc(sizeof(char *) * cm->num);
|
||||||
if (cm->input)
|
if (cm->input) {
|
||||||
{
|
|
||||||
cm->inputlen = (int *) alloc(sizeof(int) * cm->num);
|
cm->inputlen = (int *) alloc(sizeof(int) * cm->num);
|
||||||
if (cm->inputlen)
|
if (cm->inputlen) {
|
||||||
{
|
|
||||||
cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num);
|
cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num);
|
||||||
if (cm->hash)
|
if (cm->hash) {
|
||||||
{
|
|
||||||
cm->next = (int *) alloc(sizeof(int) * cm->num);
|
cm->next = (int *) alloc(sizeof(int) * cm->num);
|
||||||
if (cm->next)
|
if (cm->next) {
|
||||||
{
|
|
||||||
for (h = 0;h <= cm->mask;++h)
|
for (h = 0;h <= cm->mask;++h)
|
||||||
cm->first[h] = -1;
|
cm->first[h] = -1;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
i = 0;
|
i = 0;
|
||||||
for (j = 0;j < len;++j)
|
for (j = 0;j < len;++j)
|
||||||
if (!s[j])
|
if (!s[j]) {
|
||||||
{
|
|
||||||
k = j - i;
|
k = j - i;
|
||||||
if (flagcolon)
|
if (flagcolon) {
|
||||||
{
|
|
||||||
for (k = i;k < j;++k)
|
for (k = i;k < j;++k)
|
||||||
if (s[k] == ':')
|
if (s[k] == ':')
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
|
|
||||||
typedef unsigned long constmap_hash;
|
typedef unsigned long constmap_hash;
|
||||||
|
|
||||||
struct constmap
|
struct constmap {
|
||||||
{
|
|
||||||
int num;
|
int num;
|
||||||
constmap_hash mask;
|
constmap_hash mask;
|
||||||
constmap_hash *hash;
|
constmap_hash *hash;
|
||||||
|
|
@ -12,8 +11,7 @@ struct constmap
|
||||||
int *next;
|
int *next;
|
||||||
char **input;
|
char **input;
|
||||||
int *inputlen;
|
int *inputlen;
|
||||||
}
|
} ;
|
||||||
;
|
|
||||||
|
|
||||||
extern int constmap_init();
|
extern int constmap_init();
|
||||||
extern void constmap_free();
|
extern void constmap_free();
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,8 @@ char *fn;
|
||||||
case 0: return 0;
|
case 0: return 0;
|
||||||
case -1: return -1;
|
case -1: return -1;
|
||||||
}
|
}
|
||||||
if (scan_nbblong(line.s,line.len,10,0,&u) == 0) return 0;
|
if (!stralloc_0(&line)) return -1;
|
||||||
|
if (!scan_ulong(line.s,&u)) return 0;
|
||||||
*i = u;
|
*i = u;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
dot-qmail.9
10
dot-qmail.9
|
|
@ -45,7 +45,7 @@ ignores the line.
|
||||||
A program line begins with a vertical bar:
|
A program line begins with a vertical bar:
|
||||||
|
|
||||||
.EX
|
.EX
|
||||||
|/usr/ucb/vacation djb
|
|preline /usr/ucb/vacation djb
|
||||||
.EE
|
.EE
|
||||||
|
|
||||||
.B qmail-local
|
.B qmail-local
|
||||||
|
|
@ -173,10 +173,10 @@ If
|
||||||
is completely empty (0 bytes long), or does not exist,
|
is completely empty (0 bytes long), or does not exist,
|
||||||
.B qmail-local
|
.B qmail-local
|
||||||
follows the
|
follows the
|
||||||
.I aliasempty
|
.I defaultdelivery
|
||||||
instructions set by your system administrator;
|
instructions set by your system administrator;
|
||||||
normally
|
normally
|
||||||
.I aliasempty
|
.I defaultdelivery
|
||||||
is
|
is
|
||||||
.BR ./Mailbox ,
|
.BR ./Mailbox ,
|
||||||
so
|
so
|
||||||
|
|
@ -224,7 +224,7 @@ It's a good idea to test your new
|
||||||
file as follows:
|
file as follows:
|
||||||
|
|
||||||
.EX
|
.EX
|
||||||
qmail-local -n $USER $HOME $USER '' '' '' ''
|
qmail-local -n $USER ~ $USER '' '' '' '' ./Mailbox
|
||||||
.EE
|
.EE
|
||||||
.SH "EXTENSION ADDRESSES"
|
.SH "EXTENSION ADDRESSES"
|
||||||
In the
|
In the
|
||||||
|
|
@ -274,7 +274,7 @@ If
|
||||||
is completely empty,
|
is completely empty,
|
||||||
.B qmail-local
|
.B qmail-local
|
||||||
follows the
|
follows the
|
||||||
.I aliasempty
|
.I defaultdelivery
|
||||||
instructions set by your system administrator.
|
instructions set by your system administrator.
|
||||||
|
|
||||||
If
|
If
|
||||||
|
|
|
||||||
44
forward.c
44
forward.c
|
|
@ -3,14 +3,13 @@
|
||||||
#include "exit.h"
|
#include "exit.h"
|
||||||
#include "env.h"
|
#include "env.h"
|
||||||
#include "qmail.h"
|
#include "qmail.h"
|
||||||
#include "stralloc.h"
|
#include "strerr.h"
|
||||||
#include "subfd.h"
|
|
||||||
#include "substdio.h"
|
#include "substdio.h"
|
||||||
|
#include "fmt.h"
|
||||||
|
|
||||||
void die_success() { _exit(0); }
|
#define FATAL "forward: fatal: "
|
||||||
void die_perm(s) char *s; { substdio_putsflush(subfderr,s); _exit(100); }
|
|
||||||
void die_temp(s) char *s; { substdio_putsflush(subfderr,s); _exit(111); }
|
void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); }
|
||||||
void die_nomem() { die_temp("forward: fatal: out of memory\n"); }
|
|
||||||
|
|
||||||
struct qmail qqt;
|
struct qmail qqt;
|
||||||
|
|
||||||
|
|
@ -20,10 +19,12 @@ int mywrite(fd,buf,len) int fd; char *buf; int len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
substdio ssin;
|
|
||||||
substdio ssout;
|
|
||||||
char inbuf[SUBSTDIO_INSIZE];
|
char inbuf[SUBSTDIO_INSIZE];
|
||||||
char outbuf[16];
|
char outbuf[1];
|
||||||
|
substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
|
||||||
|
substdio ssout = SUBSTDIO_FDBUF(mywrite,-1,outbuf,sizeof outbuf);
|
||||||
|
|
||||||
|
char num[FMT_ULONG];
|
||||||
|
|
||||||
void main(argc,argv)
|
void main(argc,argv)
|
||||||
int argc;
|
int argc;
|
||||||
|
|
@ -31,28 +32,29 @@ char **argv;
|
||||||
{
|
{
|
||||||
char *sender;
|
char *sender;
|
||||||
char *dtline;
|
char *dtline;
|
||||||
|
char *qqx;
|
||||||
|
|
||||||
sig_pipeignore();
|
sig_pipeignore();
|
||||||
|
|
||||||
sender = env_get("NEWSENDER");
|
sender = env_get("NEWSENDER");
|
||||||
if (!sender) die_perm("forward: fatal: NEWSENDER not set\n");
|
if (!sender)
|
||||||
|
strerr_die2x(100,FATAL,"NEWSENDER not set");
|
||||||
dtline = env_get("DTLINE");
|
dtline = env_get("DTLINE");
|
||||||
if (!dtline) die_perm("forward: fatal: DTLINE not set\n");
|
if (!dtline)
|
||||||
|
strerr_die2x(100,FATAL,"DTLINE not set");
|
||||||
|
|
||||||
if (qmail_open(&qqt) == -1) die_temp("forward: fatal: unable to fork\n");
|
if (qmail_open(&qqt) == -1)
|
||||||
|
strerr_die2sys(111,FATAL,"unable to fork: ");
|
||||||
qmail_puts(&qqt,dtline);
|
qmail_puts(&qqt,dtline);
|
||||||
substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
|
|
||||||
substdio_fdbuf(&ssout,mywrite,-1,outbuf,sizeof(outbuf));
|
|
||||||
if (substdio_copy(&ssout,&ssin) != 0)
|
if (substdio_copy(&ssout,&ssin) != 0)
|
||||||
die_temp("forward: fatal: error while reading message\n");
|
strerr_die2sys(111,FATAL,"unable to read message: ");
|
||||||
substdio_flush(&ssout);
|
substdio_flush(&ssout);
|
||||||
|
|
||||||
|
num[fmt_ulong(num,qmail_qp(&qqt))] = 0;
|
||||||
|
|
||||||
qmail_from(&qqt,sender);
|
qmail_from(&qqt,sender);
|
||||||
while (*++argv) qmail_to(&qqt,*argv);
|
while (*++argv) qmail_to(&qqt,*argv);
|
||||||
switch(qmail_close(&qqt))
|
qqx = qmail_close(&qqt);
|
||||||
{
|
if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1);
|
||||||
case 0: die_success();
|
strerr_die2x(0,"forward: qp ",num);
|
||||||
case QMAIL_TOOLONG: die_perm("forward: fatal: permanent qmail-queue error\n");
|
|
||||||
default: die_temp("forward: fatal: temporary qmail-queue error\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
hfield.c
1
hfield.c
|
|
@ -29,6 +29,7 @@ static char *(hname[]) = {
|
||||||
, "content-type"
|
, "content-type"
|
||||||
, "content-transfer-encoding"
|
, "content-transfer-encoding"
|
||||||
, "notice-requested-upon-delivery-to"
|
, "notice-requested-upon-delivery-to"
|
||||||
|
, "mail-followup-to"
|
||||||
, 0
|
, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
3
hfield.h
3
hfield.h
|
|
@ -32,6 +32,7 @@ extern int hfield_valid();
|
||||||
#define H_CONTENTTYPE 25
|
#define H_CONTENTTYPE 25
|
||||||
#define H_CONTENTTRANSFERENCODING 26
|
#define H_CONTENTTRANSFERENCODING 26
|
||||||
#define H_NOTICEREQUESTEDUPONDELIVERYTO 27
|
#define H_NOTICEREQUESTEDUPONDELIVERYTO 27
|
||||||
#define H_NUM 28
|
#define H_MAILFOLLOWUPTO 28
|
||||||
|
#define H_NUM 29
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
9
home+df.sh
Normal file
9
home+df.sh
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using dot-forward to support sendmail-style ~/.forward files.
|
||||||
|
# Using qmail-local to deliver messages to ~/Mailbox by default.
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start '|dot-forward .forward
|
||||||
|
./Mailbox' splogger qmail
|
||||||
7
home.sh
Normal file
7
home.sh
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using qmail-local to deliver messages to ~/Mailbox by default.
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start ./Mailbox splogger qmail
|
||||||
|
|
@ -209,7 +209,7 @@ or rename
|
||||||
as
|
as
|
||||||
.BR cur/\fIunique:info .
|
.BR cur/\fIunique:info .
|
||||||
See
|
See
|
||||||
.B http://pobox.com/~djb/maildir.html
|
.B http://pobox.com/~djb/proto/maildir.html
|
||||||
for the meaning of
|
for the meaning of
|
||||||
.IR info .
|
.IR info .
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
#include "subfd.h"
|
#include "strerr.h"
|
||||||
#include "substdio.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "exit.h"
|
#include "exit.h"
|
||||||
|
|
||||||
void die(s) char *s; { substdio_putsflush(subfderr,s); _exit(111); }
|
#define FATAL "maildirmake: fatal: "
|
||||||
|
|
||||||
void main(argc,argv)
|
void main(argc,argv)
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
{
|
{
|
||||||
umask(077);
|
umask(077);
|
||||||
if (!argv[1]) die("usage: maildirmake name\n");
|
if (!argv[1])
|
||||||
if (mkdir(argv[1],0700))
|
strerr_die1x(100,"maildirmake: usage: maildirmake name");
|
||||||
if (errno == error_exist) die("fatal: directory already exists\n");
|
if (mkdir(argv[1],0700) == -1)
|
||||||
else die("fatal: unable to mkdir\n");
|
strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],": ");
|
||||||
if (chdir(argv[1])) die("fatal: unable to chdir\n");
|
if (chdir(argv[1]) == -1)
|
||||||
if (mkdir("tmp",0700)) die("fatal: unable to make tmp/ subdir\n");
|
strerr_die4sys(111,FATAL,"unable to chdir to ",argv[1],": ");
|
||||||
if (mkdir("new",0700)) die("fatal: unable to make new/ subdir\n");
|
if (mkdir("tmp",0700) == -1)
|
||||||
if (mkdir("cur",0700)) die("fatal: unable to make cur/ subdir\n");
|
strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/tmp: ");
|
||||||
|
if (mkdir("new",0700) == -1)
|
||||||
|
strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/new: ");
|
||||||
|
if (mkdir("cur",0700) == -1)
|
||||||
|
strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/cur: ");
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
ndelay.c
6
ndelay.c
|
|
@ -2,8 +2,12 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "ndelay.h"
|
#include "ndelay.h"
|
||||||
|
|
||||||
|
#ifndef O_NONBLOCK
|
||||||
|
#define O_NONBLOCK O_NDELAY
|
||||||
|
#endif
|
||||||
|
|
||||||
int ndelay_on(fd)
|
int ndelay_on(fd)
|
||||||
int fd;
|
int fd;
|
||||||
{
|
{
|
||||||
return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NDELAY);
|
return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,12 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "ndelay.h"
|
#include "ndelay.h"
|
||||||
|
|
||||||
|
#ifndef O_NONBLOCK
|
||||||
|
#define O_NONBLOCK O_NDELAY
|
||||||
|
#endif
|
||||||
|
|
||||||
int ndelay_off(fd)
|
int ndelay_off(fd)
|
||||||
int fd;
|
int fd;
|
||||||
{
|
{
|
||||||
return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NDELAY);
|
return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
predate.c
39
predate.c
|
|
@ -5,11 +5,14 @@
|
||||||
#include "wait.h"
|
#include "wait.h"
|
||||||
#include "fd.h"
|
#include "fd.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
|
#include "strerr.h"
|
||||||
#include "substdio.h"
|
#include "substdio.h"
|
||||||
#include "subfd.h"
|
#include "subfd.h"
|
||||||
#include "readwrite.h"
|
#include "readwrite.h"
|
||||||
#include "exit.h"
|
#include "exit.h"
|
||||||
|
|
||||||
|
#define FATAL "predate: fatal: "
|
||||||
|
|
||||||
static char *montab[12] = {
|
static char *montab[12] = {
|
||||||
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
|
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
|
||||||
};
|
};
|
||||||
|
|
@ -34,30 +37,22 @@ char **argv;
|
||||||
|
|
||||||
sig_pipeignore();
|
sig_pipeignore();
|
||||||
|
|
||||||
if (!argv[1]) {
|
if (!argv[1])
|
||||||
substdio_putsflush(subfderr,"predate: usage: predate child\n");
|
strerr_die1x(100,"predate: usage: predate child");
|
||||||
_exit(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pipe(pi) == -1) {
|
if (pipe(pi) == -1)
|
||||||
substdio_putsflush(subfderr,"predate: fatal: unable to create pipe\n");
|
strerr_die2sys(111,FATAL,"unable to create pipe: ");
|
||||||
_exit(111);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(pid = fork()) {
|
switch(pid = fork()) {
|
||||||
case -1:
|
case -1:
|
||||||
substdio_putsflush(subfderr,"predate: fatal: unable to fork\n");
|
strerr_die2sys(111,FATAL,"unable to fork: ");
|
||||||
_exit(111);
|
|
||||||
case 0:
|
case 0:
|
||||||
close(pi[1]);
|
close(pi[1]);
|
||||||
if (fd_move(0,pi[0]) == -1) {
|
if (fd_move(0,pi[0]) == -1)
|
||||||
substdio_putsflush(subfderr,"predate: fatal: unable to set up fds\n");
|
strerr_die2sys(111,FATAL,"unable to set up fds: ");
|
||||||
_exit(111);
|
|
||||||
}
|
|
||||||
sig_pipedefault();
|
sig_pipedefault();
|
||||||
execvp(argv[1],argv + 1);
|
execvp(argv[1],argv + 1);
|
||||||
substdio_putsflush(subfderr,"predate: fatal: unable to exec\n");
|
strerr_die4sys(111,FATAL,"unable to run ",argv[1],": ");
|
||||||
_exit(111);
|
|
||||||
}
|
}
|
||||||
close(pi[0]);
|
close(pi[0]);
|
||||||
substdio_fdbuf(&ss,write,pi[1],outbuf,sizeof(outbuf));
|
substdio_fdbuf(&ss,write,pi[1],outbuf,sizeof(outbuf));
|
||||||
|
|
@ -113,13 +108,9 @@ char **argv;
|
||||||
substdio_flush(&ss);
|
substdio_flush(&ss);
|
||||||
close(pi[1]);
|
close(pi[1]);
|
||||||
|
|
||||||
if (wait_pid(&wstat,pid) == -1) {
|
if (wait_pid(&wstat,pid) == -1)
|
||||||
substdio_putsflush(subfderr,"predate: fatal: wait failed\n");
|
strerr_die2sys(111,FATAL,"wait failed: ");
|
||||||
_exit(111);
|
if (wait_crashed(wstat))
|
||||||
}
|
strerr_die2x(111,FATAL,"child crashed");
|
||||||
if (wait_crashed(wstat)) {
|
|
||||||
substdio_putsflush(subfderr,"predate: fatal: child crashed\n");
|
|
||||||
_exit(111);
|
|
||||||
}
|
|
||||||
_exit(wait_exitcode(wstat));
|
_exit(wait_exitcode(wstat));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
57
preline.c
57
preline.c
|
|
@ -1,7 +1,7 @@
|
||||||
#include "fd.h"
|
#include "fd.h"
|
||||||
#include "sgetopt.h"
|
#include "sgetopt.h"
|
||||||
#include "readwrite.h"
|
#include "readwrite.h"
|
||||||
#include "subfd.h"
|
#include "strerr.h"
|
||||||
#include "substdio.h"
|
#include "substdio.h"
|
||||||
#include "exit.h"
|
#include "exit.h"
|
||||||
#include "fork.h"
|
#include "fork.h"
|
||||||
|
|
@ -10,20 +10,21 @@
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); }
|
#define FATAL "preline: fatal: "
|
||||||
void die_usage() { die(100,"preline: fatal: incorrect usage\n"); }
|
|
||||||
void die_temp() { die(111,"preline: fatal: temporary problem\n"); }
|
void die_usage()
|
||||||
void die_read() { die(111,"preline: fatal: unable to read message\n"); }
|
{
|
||||||
void die_badcmd() { die(100,"preline: fatal: command not found\n"); }
|
strerr_die1x(100,"preline: usage: preline cmd [ arg ... ]");
|
||||||
|
}
|
||||||
|
|
||||||
int flagufline = 1; char *ufline;
|
int flagufline = 1; char *ufline;
|
||||||
int flagrpline = 1; char *rpline;
|
int flagrpline = 1; char *rpline;
|
||||||
int flagdtline = 1; char *dtline;
|
int flagdtline = 1; char *dtline;
|
||||||
|
|
||||||
substdio ssout;
|
|
||||||
char outbuf[SUBSTDIO_OUTSIZE];
|
char outbuf[SUBSTDIO_OUTSIZE];
|
||||||
substdio ssin;
|
|
||||||
char inbuf[SUBSTDIO_INSIZE];
|
char inbuf[SUBSTDIO_INSIZE];
|
||||||
|
substdio ssout = SUBSTDIO_FDBUF(write,1,outbuf,sizeof outbuf);
|
||||||
|
substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
|
||||||
|
|
||||||
void main(argc,argv)
|
void main(argc,argv)
|
||||||
int argc;
|
int argc;
|
||||||
|
|
@ -41,47 +42,49 @@ char **argv;
|
||||||
if (!(dtline = env_get("DTLINE"))) die_usage();
|
if (!(dtline = env_get("DTLINE"))) die_usage();
|
||||||
|
|
||||||
while ((opt = getopt(argc,argv,"frdFRD")) != opteof)
|
while ((opt = getopt(argc,argv,"frdFRD")) != opteof)
|
||||||
switch(opt)
|
switch(opt) {
|
||||||
{
|
|
||||||
case 'f': flagufline = 0; break;
|
case 'f': flagufline = 0; break;
|
||||||
case 'r': flagrpline = 0; break;
|
case 'r': flagrpline = 0; break;
|
||||||
case 'd': flagdtline = 0; break;
|
case 'd': flagdtline = 0; break;
|
||||||
case 'F': flagufline = 1; break;
|
case 'F': flagufline = 1; break;
|
||||||
case 'R': flagrpline = 1; break;
|
case 'R': flagrpline = 1; break;
|
||||||
case 'D': flagdtline = 1; break;
|
case 'D': flagdtline = 1; break;
|
||||||
default:
|
default: die_usage();
|
||||||
_exit(100);
|
|
||||||
}
|
}
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
if (!*argv) die_usage();
|
if (!*argv) die_usage();
|
||||||
|
|
||||||
if (pipe(pi) == -1) die_temp();
|
if (pipe(pi) == -1)
|
||||||
|
strerr_die2sys(111,FATAL,"unable to create pipe: ");
|
||||||
|
|
||||||
switch(pid = fork())
|
pid = fork();
|
||||||
{
|
if (pid == -1)
|
||||||
case -1:
|
strerr_die2sys(111,FATAL,"unable to fork: ");
|
||||||
die_temp();
|
|
||||||
case 0:
|
if (pid == 0) {
|
||||||
close(pi[1]);
|
close(pi[1]);
|
||||||
if (fd_move(0,pi[0])) die_temp();
|
if (fd_move(0,pi[0]) == -1)
|
||||||
|
strerr_die2sys(111,FATAL,"unable to set up fds: ");
|
||||||
sig_pipedefault();
|
sig_pipedefault();
|
||||||
execvp(*argv,argv);
|
execvp(*argv,argv);
|
||||||
if (error_temp(errno)) die_temp();
|
strerr_die4sys(error_temp(errno) ? 111 : 100,FATAL,"unable to run ",*argv,": ");
|
||||||
die_badcmd();
|
|
||||||
}
|
}
|
||||||
close(pi[0]);
|
close(pi[0]);
|
||||||
|
if (fd_move(1,pi[1]) == -1)
|
||||||
|
strerr_die2sys(111,FATAL,"unable to set up fds: ");
|
||||||
|
|
||||||
substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf));
|
|
||||||
substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
|
|
||||||
if (flagufline) substdio_bputs(&ssout,ufline);
|
if (flagufline) substdio_bputs(&ssout,ufline);
|
||||||
if (flagrpline) substdio_bputs(&ssout,rpline);
|
if (flagrpline) substdio_bputs(&ssout,rpline);
|
||||||
if (flagdtline) substdio_bputs(&ssout,dtline);
|
if (flagdtline) substdio_bputs(&ssout,dtline);
|
||||||
if (substdio_copy(&ssout,&ssin) == -2) die_read();
|
if (substdio_copy(&ssout,&ssin) != 0)
|
||||||
|
strerr_die2sys(111,FATAL,"unable to copy input: ");
|
||||||
substdio_flush(&ssout);
|
substdio_flush(&ssout);
|
||||||
close(pi[1]);
|
close(1);
|
||||||
|
|
||||||
if (wait_pid(&wstat,pid) == -1) die_temp();
|
if (wait_pid(&wstat,pid) == -1)
|
||||||
if (wait_crashed(wstat)) die_temp();
|
strerr_die2sys(111,FATAL,"wait failed: ");
|
||||||
|
if (wait_crashed(wstat))
|
||||||
|
strerr_die2x(111,FATAL,"child crashed");
|
||||||
_exit(wait_exitcode(wstat));
|
_exit(wait_exitcode(wstat));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
proc+df.sh
Normal file
9
proc+df.sh
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using dot-forward to support sendmail-style ~/.forward files.
|
||||||
|
# Using procmail to deliver messages to /var/spool/mail/$USER by default.
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start '|dot-forward .forward
|
||||||
|
|preline procmail' splogger qmail
|
||||||
7
proc.sh
Normal file
7
proc.sh
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Using splogger to send the log through syslog.
|
||||||
|
# Using procmail to deliver messages to /var/spool/mail/$USER by default.
|
||||||
|
|
||||||
|
exec env - PATH="QMAIL/bin:$PATH" \
|
||||||
|
qmail-start '|preline procmail' splogger qmail
|
||||||
112
qlist.1
112
qlist.1
|
|
@ -1,112 +0,0 @@
|
||||||
.TH qlist 1
|
|
||||||
.SH NAME
|
|
||||||
qlist \- handle mailing list subscription requests
|
|
||||||
.SH SYNOPSIS
|
|
||||||
in
|
|
||||||
.BR .qmail-\fIlist-request :
|
|
||||||
.br
|
|
||||||
.B |qlist
|
|
||||||
.I user-list@host
|
|
||||||
.I user-list-request@host
|
|
||||||
.br
|
|
||||||
.B .qmail-\fIlist
|
|
||||||
.B .qmail-\fIlist-request
|
|
||||||
.B .qtemp-\fIlist
|
|
||||||
.br
|
|
||||||
.I owner
|
|
||||||
[
|
|
||||||
.I moreinfo
|
|
||||||
]
|
|
||||||
.br
|
|
||||||
(all on one line)
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.B qlist
|
|
||||||
manages a
|
|
||||||
.B qmail
|
|
||||||
mailing list.
|
|
||||||
|
|
||||||
When
|
|
||||||
.B qlist
|
|
||||||
receives a message,
|
|
||||||
it looks through the body of the message for commands.
|
|
||||||
.B WARNING:
|
|
||||||
.B qlist
|
|
||||||
looks for a command only at the beginning of a line.
|
|
||||||
Exception:
|
|
||||||
.B qlist
|
|
||||||
also looks at
|
|
||||||
.B Subject
|
|
||||||
lines.
|
|
||||||
|
|
||||||
.B qlist
|
|
||||||
supports two commands.
|
|
||||||
.B SUBSCRIBE
|
|
||||||
adds a new subscription to the mailing list;
|
|
||||||
.B UNSUBSCRIBE
|
|
||||||
removes a subscription.
|
|
||||||
.B qlist
|
|
||||||
looks for the subscription address in the
|
|
||||||
.BR Reply-To ,
|
|
||||||
.BR From ,
|
|
||||||
or
|
|
||||||
.BR Return-Path
|
|
||||||
fields in the message.
|
|
||||||
|
|
||||||
.B qlist
|
|
||||||
inserts an acknowledgment of each action it took,
|
|
||||||
along with general help instructions, into the message.
|
|
||||||
It then forwards the message to the subscription address,
|
|
||||||
with a copy to
|
|
||||||
.IR owner .
|
|
||||||
|
|
||||||
.BR qlist 's
|
|
||||||
general help instructions identify
|
|
||||||
.I user-list@host
|
|
||||||
as the address of the mailing list,
|
|
||||||
.I user-list-request@host
|
|
||||||
as the address of
|
|
||||||
.B qlist
|
|
||||||
itself, and
|
|
||||||
.I owner
|
|
||||||
as the address
|
|
||||||
of the mailing list owner.
|
|
||||||
If
|
|
||||||
.I moreinfo
|
|
||||||
is supplied,
|
|
||||||
it is inserted into the middle of the instructions,
|
|
||||||
surrounded by blank lines.
|
|
||||||
|
|
||||||
.B qlist
|
|
||||||
maintains its address list in
|
|
||||||
.BR .qmail-\fIlist ,
|
|
||||||
so mail to
|
|
||||||
.I user-list
|
|
||||||
will be forwarded to each subscription address.
|
|
||||||
While
|
|
||||||
.B qlist
|
|
||||||
is editing
|
|
||||||
.BR .qmail-\fIlist ,
|
|
||||||
it locks
|
|
||||||
.BR .qmail-\fIlist-request .
|
|
||||||
It uses
|
|
||||||
.B .qtemp-\fIlist
|
|
||||||
as a temporary file.
|
|
||||||
|
|
||||||
Note that
|
|
||||||
.B qlist
|
|
||||||
only manipulates lines beginning with an ampersand;
|
|
||||||
if you manually add an address without an ampersand,
|
|
||||||
it cannot be removed by
|
|
||||||
.BR qlist .
|
|
||||||
|
|
||||||
.B qlist
|
|
||||||
automatically sets the execute bit on
|
|
||||||
.BR qmail-\fIlist ,
|
|
||||||
so
|
|
||||||
.B qmail-local
|
|
||||||
will ignore any program or file instructions in
|
|
||||||
.BR qmail-\fIlist .
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
dot-qmail(5),
|
|
||||||
envelopes(5),
|
|
||||||
qmail-queue(8)
|
|
||||||
333
qlist.c
333
qlist.c
|
|
@ -1,333 +0,0 @@
|
||||||
#include "sig.h"
|
|
||||||
#include "readwrite.h"
|
|
||||||
#include "substdio.h"
|
|
||||||
#include "stralloc.h"
|
|
||||||
#include "subfd.h"
|
|
||||||
#include "getln.h"
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "str.h"
|
|
||||||
#include "env.h"
|
|
||||||
#include "hfield.h"
|
|
||||||
#include "case.h"
|
|
||||||
#include "token822.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "gen_alloc.h"
|
|
||||||
#include "gen_allocdefs.h"
|
|
||||||
#include "headerbody.h"
|
|
||||||
#include "exit.h"
|
|
||||||
#include "open.h"
|
|
||||||
#include "lock.h"
|
|
||||||
#include "qmail.h"
|
|
||||||
|
|
||||||
#define ADDRLIMIT 100
|
|
||||||
|
|
||||||
void die() { _exit(100); }
|
|
||||||
void die_temp() { _exit(111); }
|
|
||||||
void die_nomem() {
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: out of memory\n"); die_temp(); }
|
|
||||||
void die_fork() {
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: unable to fork\n"); die_temp(); }
|
|
||||||
void die_nolock() {
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: unable to open lock file\n"); die_temp(); }
|
|
||||||
void die_boing() {
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: I don't reply to bounces\n"); die(); }
|
|
||||||
void die_badaddr() {
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: sorry, I'm not allowed to use that address\n"); die(); }
|
|
||||||
void die_qqperm() {
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: permanent qmail-queue error\n"); die(); }
|
|
||||||
void die_qqtemp() {
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: temporary qmail-queue error\n"); die_temp(); }
|
|
||||||
void die_usage() {
|
|
||||||
substdio_putsflush(subfderr,
|
|
||||||
"qlist: usage: qlist user-list@host user-list-request@host .qmail-list .qmail-list-request .qtemp-list owner [moreinfo]\n"); die(); }
|
|
||||||
void die_read() {
|
|
||||||
if (errno == error_nomem) die_nomem();
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: read error\n"); die_temp(); }
|
|
||||||
void doordie(sa,r) stralloc *sa; int r; {
|
|
||||||
if (r == 1) return; if (r == -1) die_nomem();
|
|
||||||
substdio_putsflush(subfderr,"qlist: fatal: unable to parse this: ");
|
|
||||||
substdio_putflush(subfderr,sa->s,sa->len); die(); }
|
|
||||||
|
|
||||||
int subjectaction = 0;
|
|
||||||
int numcommands;
|
|
||||||
|
|
||||||
int fdlock;
|
|
||||||
|
|
||||||
struct qmail qqt;
|
|
||||||
|
|
||||||
char *target;
|
|
||||||
char *listathost;
|
|
||||||
char *requestathost;
|
|
||||||
char *qmaillist;
|
|
||||||
char *qmailrequest;
|
|
||||||
char *qtemplist;
|
|
||||||
char *owner;
|
|
||||||
char *moreinfo;
|
|
||||||
|
|
||||||
char *dtline;
|
|
||||||
char *returnpath;
|
|
||||||
stralloc safrom = {0};
|
|
||||||
stralloc sart = {0};
|
|
||||||
|
|
||||||
int rwfrom(addr) token822_alloc *addr; { token822_reverse(addr);
|
|
||||||
if (token822_unquote(&safrom,addr) != 1) die_nomem();
|
|
||||||
token822_reverse(addr); return 1; }
|
|
||||||
int rwrt(addr) token822_alloc *addr; { token822_reverse(addr);
|
|
||||||
if (token822_unquote(&sart,addr) != 1) die_nomem();
|
|
||||||
token822_reverse(addr); return 1; }
|
|
||||||
|
|
||||||
GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
|
|
||||||
GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
|
|
||||||
static stralloc sauninit = {0}; saa savedh = {0};
|
|
||||||
void savedh_append(h) stralloc *h; {
|
|
||||||
if (!saa_readyplus(&savedh,1)) die_nomem(); savedh.sa[savedh.len] = sauninit;
|
|
||||||
if (!stralloc_copy(savedh.sa + savedh.len,h)) die_nomem(); ++savedh.len; }
|
|
||||||
void savedh_print() { int i; for (i = 0;i < savedh.len;++i)
|
|
||||||
qmail_put(&qqt,savedh.sa[i].s,savedh.sa[i].len); }
|
|
||||||
|
|
||||||
void finishheader()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (sart.s)
|
|
||||||
{ if (!stralloc_0(&sart)) die_nomem(); target = sart.s; }
|
|
||||||
else if (safrom.s)
|
|
||||||
{ if (!stralloc_0(&safrom)) die_nomem(); target = safrom.s; }
|
|
||||||
else
|
|
||||||
target = returnpath;
|
|
||||||
|
|
||||||
for (i = 0;target[i];++i)
|
|
||||||
if (target[i] == '\n')
|
|
||||||
die_badaddr();
|
|
||||||
if (i > ADDRLIMIT) die_badaddr();
|
|
||||||
if (str_equal(target,"")) die_boing();
|
|
||||||
if (str_equal(target,"#@[]")) die_boing();
|
|
||||||
|
|
||||||
if (qmail_open(&qqt) == -1) die_fork();
|
|
||||||
|
|
||||||
qmail_puts(&qqt,dtline);
|
|
||||||
savedh_print();
|
|
||||||
|
|
||||||
qmail_puts(&qqt,"\n***** Text inserted by ");
|
|
||||||
qmail_puts(&qqt,requestathost);
|
|
||||||
qmail_puts(&qqt,"\n\
|
|
||||||
*\n\
|
|
||||||
* Hi! This is the qlist program. I'm handling subscriptions for the\n\
|
|
||||||
* ");
|
|
||||||
qmail_puts(&qqt,listathost);
|
|
||||||
qmail_puts(&qqt," mailing list.\n\
|
|
||||||
*\n");
|
|
||||||
if (moreinfo)
|
|
||||||
{
|
|
||||||
qmail_puts(&qqt,"* ");
|
|
||||||
qmail_puts(&qqt,moreinfo);
|
|
||||||
qmail_puts(&qqt,"\n*\n");
|
|
||||||
}
|
|
||||||
qmail_puts(&qqt,"* My human owner is ");
|
|
||||||
qmail_puts(&qqt,owner);
|
|
||||||
qmail_puts(&qqt,".\n\
|
|
||||||
*\n\
|
|
||||||
* To the recipient: This message was sent to me on your behalf. (Your\n\
|
|
||||||
* address was listed in the Reply-To or From field.) For security,\n\
|
|
||||||
* I'm forwarding this message to you, along with my notes.\n\
|
|
||||||
*\n\
|
|
||||||
* Anyway, to subscribe, send me an empty message. To unsubscribe, send me\n\
|
|
||||||
* a message with the word UNSUBSCRIBE at the beginning of a line. Remember,\n\
|
|
||||||
* my address is ");
|
|
||||||
qmail_puts(&qqt,requestathost);
|
|
||||||
qmail_puts(&qqt,".\n\
|
|
||||||
*\n\
|
|
||||||
* Now I'll look for requests inside this message...\n\
|
|
||||||
*\n\
|
|
||||||
*****\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
substdio subin; char subinbuf[SUBSTDIO_INSIZE];
|
|
||||||
substdio subout; char suboutbuf[SUBSTDIO_OUTSIZE];
|
|
||||||
stralloc subline = {0};
|
|
||||||
void subscribe(flagadd)
|
|
||||||
int flagadd;
|
|
||||||
{
|
|
||||||
int fdin;
|
|
||||||
int fdout;
|
|
||||||
int match;
|
|
||||||
int flagwasthere;
|
|
||||||
|
|
||||||
++numcommands;
|
|
||||||
|
|
||||||
if (lock_ex(fdlock) == -1) goto bad;
|
|
||||||
fdin = open_read(qmaillist);
|
|
||||||
if (fdin == -1) goto badlock;
|
|
||||||
fdout = open_trunc(qtemplist);
|
|
||||||
if (fdout == -1) goto badinlock;
|
|
||||||
if (chmod(qtemplist,0700) == -1) goto badoutinlock;
|
|
||||||
|
|
||||||
flagwasthere = 0;
|
|
||||||
|
|
||||||
substdio_fdbuf(&subin,read,fdin,subinbuf,sizeof(subinbuf));
|
|
||||||
substdio_fdbuf(&subout,write,fdout,suboutbuf,sizeof(suboutbuf));
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (getln(&subin,&subline,&match,'\n') == -1) goto badoutinlock;
|
|
||||||
if (!match) break; /* goodbye partial lines */
|
|
||||||
if (subline.len == str_len(target) + 2)
|
|
||||||
if (!str_diffn(subline.s + 1,target,subline.len - 2))
|
|
||||||
if (subline.s[0] == '&')
|
|
||||||
{
|
|
||||||
flagwasthere = 1;
|
|
||||||
if (!flagadd)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (substdio_put(&subout,subline.s,subline.len) == -1) goto badoutinlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flagadd && !flagwasthere)
|
|
||||||
{
|
|
||||||
if (substdio_puts(&subout,"&") == -1) goto badoutinlock;
|
|
||||||
if (substdio_puts(&subout,target) == -1) goto badoutinlock;
|
|
||||||
if (substdio_puts(&subout,"\n") == -1) goto badoutinlock;
|
|
||||||
}
|
|
||||||
if (substdio_flush(&subout) == -1) goto badoutinlock;
|
|
||||||
|
|
||||||
close(fdout);
|
|
||||||
close(fdin);
|
|
||||||
if (rename(qtemplist,qmaillist) == -1) goto badlock;
|
|
||||||
if (chmod(qmaillist,0500) == -1) goto badlock;
|
|
||||||
|
|
||||||
lock_un(fdlock);
|
|
||||||
|
|
||||||
qmail_puts(&qqt,"***** Text inserted by ");
|
|
||||||
qmail_puts(&qqt,requestathost);
|
|
||||||
qmail_puts(&qqt,"\n*\n* ");
|
|
||||||
if (flagadd)
|
|
||||||
if (flagwasthere)
|
|
||||||
{
|
|
||||||
qmail_puts(&qqt,"Acknowledgment: ");
|
|
||||||
qmail_puts(&qqt,target);
|
|
||||||
qmail_puts(&qqt," was already a subscriber.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qmail_puts(&qqt,"Acknowledgment: ");
|
|
||||||
qmail_puts(&qqt,target);
|
|
||||||
qmail_puts(&qqt," is now a subscriber.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (flagwasthere)
|
|
||||||
{
|
|
||||||
qmail_puts(&qqt,"Acknowledgment: ");
|
|
||||||
qmail_puts(&qqt,target);
|
|
||||||
qmail_puts(&qqt," is no longer a subscriber.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qmail_puts(&qqt,"Hmmm, I don't see ");
|
|
||||||
qmail_puts(&qqt,target);
|
|
||||||
qmail_puts(&qqt," on the subscription list.\n* I'll let my owner know.\n");
|
|
||||||
}
|
|
||||||
qmail_puts(&qqt,"*\n*****\n");
|
|
||||||
return;
|
|
||||||
|
|
||||||
badoutinlock: close(fdout);
|
|
||||||
badinlock: close(fdin);
|
|
||||||
badlock: lock_un(fdlock);
|
|
||||||
bad:
|
|
||||||
qmail_puts(&qqt,"***** Text inserted by ");
|
|
||||||
qmail_puts(&qqt,requestathost);
|
|
||||||
qmail_puts(&qqt,"\n*\n\
|
|
||||||
* Oh no! Trouble making the new list. I'll let my owner know.\n\
|
|
||||||
*\n\
|
|
||||||
*****\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void dobody(h) stralloc *h;
|
|
||||||
{
|
|
||||||
qmail_put(&qqt,h->s,h->len);
|
|
||||||
if (case_starts(h->s,"subs")) subscribe(1);
|
|
||||||
if (case_starts(h->s,"unsu")) subscribe(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
stralloc hfbuf = {0};
|
|
||||||
token822_alloc hfin = {0};
|
|
||||||
token822_alloc hfrewrite = {0};
|
|
||||||
token822_alloc hfaddr = {0};
|
|
||||||
|
|
||||||
void doheaderfield(h)
|
|
||||||
stralloc *h;
|
|
||||||
{
|
|
||||||
char *x;
|
|
||||||
switch(hfield_known(h->s,h->len))
|
|
||||||
{
|
|
||||||
case H_CONTENTLENGTH: /* SVR4 silliness */
|
|
||||||
case H_CONTENTTYPE:
|
|
||||||
case H_CONTENTTRANSFERENCODING: /* A-bombs 4.2.1.5.2 is idiotic */
|
|
||||||
return;
|
|
||||||
case H_FROM:
|
|
||||||
doordie(h,token822_parse(&hfin,h,&hfbuf));
|
|
||||||
doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,rwfrom));
|
|
||||||
break;
|
|
||||||
case H_REPLYTO:
|
|
||||||
doordie(h,token822_parse(&hfin,h,&hfbuf));
|
|
||||||
doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,rwrt));
|
|
||||||
break;
|
|
||||||
case H_SUBJECT:
|
|
||||||
x = h->s + hfield_skipname(h->s,h->len);
|
|
||||||
if (!case_diffb(x,4,"subs")) subjectaction = 1;
|
|
||||||
if (!case_diffb(x,4,"unsu")) subjectaction = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
savedh_append(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(argc,argv)
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
|
||||||
sig_pipeignore();
|
|
||||||
|
|
||||||
if (!(listathost = argv[1])) die_usage();
|
|
||||||
if (!(requestathost = argv[2])) die_usage();
|
|
||||||
if (!(qmaillist = argv[3])) die_usage();
|
|
||||||
if (!(qmailrequest = argv[4])) die_usage();
|
|
||||||
if (!(qtemplist = argv[5])) die_usage();
|
|
||||||
if (!(owner = argv[6])) die_usage();
|
|
||||||
moreinfo = argv[7];
|
|
||||||
if (!(returnpath = env_get("NEWSENDER"))) die_usage();
|
|
||||||
if (!(dtline = env_get("DTLINE"))) die_usage();
|
|
||||||
|
|
||||||
fdlock = open_append(qmailrequest);
|
|
||||||
if (fdlock == -1) die_nolock();
|
|
||||||
|
|
||||||
numcommands = 0;
|
|
||||||
if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1) die_read();
|
|
||||||
if (!numcommands)
|
|
||||||
{
|
|
||||||
qmail_puts(&qqt,"***** Text inserted by ");
|
|
||||||
qmail_puts(&qqt,requestathost);
|
|
||||||
qmail_puts(&qqt,"\n*\n* ");
|
|
||||||
if (subjectaction)
|
|
||||||
{
|
|
||||||
qmail_puts(&qqt,"\
|
|
||||||
Hmmm, no commands? Let me check the Subject line...\n*\n*****\n");
|
|
||||||
subscribe(subjectaction == 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qmail_puts(&qqt,"\
|
|
||||||
I didn't see any commands. I presume this is a subscription request.\n\
|
|
||||||
*\n*****\n");
|
|
||||||
subscribe(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qmail_from(&qqt,returnpath);
|
|
||||||
qmail_to(&qqt,owner);
|
|
||||||
qmail_to(&qqt,target);
|
|
||||||
|
|
||||||
switch(qmail_close(&qqt))
|
|
||||||
{
|
|
||||||
case 0: _exit(0);
|
|
||||||
case QMAIL_TOOLONG: die_qqperm();
|
|
||||||
default: die_qqtemp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
exec QMAIL/bin/qlist "$USERBREAK$1@$2" "$USERBREAK$1-request@$2" .qmail-"$1" .qmail-"$1"-request .qtemp-"$1" "$USERBREAK$1-owner" ${3+"$3"}
|
|
||||||
|
|
@ -37,7 +37,7 @@ file, so it is not safe for
|
||||||
.I command
|
.I command
|
||||||
to fork a child that
|
to fork a child that
|
||||||
reads the message in the background while the parent exits.
|
reads the message in the background while the parent exits.
|
||||||
|
.SH "EXIT CODES"
|
||||||
.IR command 's
|
.IR command 's
|
||||||
exit codes are interpreted as follows:
|
exit codes are interpreted as follows:
|
||||||
0 means that the delivery was successful;
|
0 means that the delivery was successful;
|
||||||
|
|
@ -48,15 +48,21 @@ should ignore all further delivery instructions;
|
||||||
100 means that the delivery failed permanently (hard error);
|
100 means that the delivery failed permanently (hard error);
|
||||||
111 means that the delivery failed but should be tried again
|
111 means that the delivery failed but should be tried again
|
||||||
in a little while (soft error).
|
in a little while (soft error).
|
||||||
|
|
||||||
Currently 64, 65, 70, 76, 77, 78, and 112 are considered hard errors,
|
Currently 64, 65, 70, 76, 77, 78, and 112 are considered hard errors,
|
||||||
and all other codes are considered soft errors,
|
and all other codes are considered soft errors,
|
||||||
but
|
but
|
||||||
.I command
|
.I command
|
||||||
should avoid relying on this.
|
should avoid relying on this.
|
||||||
|
.SH "ENVIRONMENT VARIABLES"
|
||||||
.B qmail-local
|
.B qmail-local
|
||||||
supplies several useful environment variables to
|
supplies several useful environment variables to
|
||||||
.IR command .
|
.IR command .
|
||||||
|
.B WARNING:
|
||||||
|
These environment variables are not quoted.
|
||||||
|
They may contain special characters.
|
||||||
|
They are under the control of a possibly malicious remote user.
|
||||||
|
|
||||||
.B SENDER
|
.B SENDER
|
||||||
is the envelope sender address.
|
is the envelope sender address.
|
||||||
.B NEWSENDER
|
.B NEWSENDER
|
||||||
|
|
@ -82,9 +88,22 @@ is the
|
||||||
part.
|
part.
|
||||||
.B EXT
|
.B EXT
|
||||||
is the
|
is the
|
||||||
.B .qmail
|
address extension,
|
||||||
extension,
|
|
||||||
.IR ext .
|
.IR ext .
|
||||||
|
|
||||||
|
.B HOST2
|
||||||
|
is the portion of
|
||||||
|
.B HOST
|
||||||
|
preceding the last dot;
|
||||||
|
.B HOST3
|
||||||
|
is the portion of
|
||||||
|
.B HOST
|
||||||
|
preceding the second-to-last dot;
|
||||||
|
.B HOST4
|
||||||
|
is the portion of
|
||||||
|
.B HOST
|
||||||
|
preceding the third-to-last dot.
|
||||||
|
|
||||||
.B EXT2
|
.B EXT2
|
||||||
is the portion of
|
is the portion of
|
||||||
.B EXT
|
.B EXT
|
||||||
|
|
@ -95,6 +114,18 @@ following the second dash;
|
||||||
.B EXT4
|
.B EXT4
|
||||||
is the portion
|
is the portion
|
||||||
following the third dash.
|
following the third dash.
|
||||||
|
.B DEFAULT
|
||||||
|
is the portion
|
||||||
|
corresponding to the
|
||||||
|
.B default
|
||||||
|
part of the
|
||||||
|
.BR .qmail\- ...
|
||||||
|
file name;
|
||||||
|
.B DEFAULT
|
||||||
|
is not set if
|
||||||
|
the file name does not end with
|
||||||
|
.BR default .
|
||||||
|
|
||||||
.B DTLINE
|
.B DTLINE
|
||||||
and
|
and
|
||||||
.B RPLINE
|
.B RPLINE
|
||||||
|
|
@ -112,11 +143,6 @@ line that
|
||||||
adds to
|
adds to
|
||||||
.IR mbox -format
|
.IR mbox -format
|
||||||
files.
|
files.
|
||||||
|
|
||||||
.B WARNING:
|
|
||||||
These environment variables are not quoted.
|
|
||||||
They may contain special characters.
|
|
||||||
They are under the control of a possibly malicious remote user.
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
dot-qmail(5),
|
dot-qmail(5),
|
||||||
envelopes(5),
|
envelopes(5),
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ in
|
||||||
.IR badmailfrom ,
|
.IR badmailfrom ,
|
||||||
.IR locals ,
|
.IR locals ,
|
||||||
.IR percenthack ,
|
.IR percenthack ,
|
||||||
|
.IR qmqpservers ,
|
||||||
.IR rcpthosts ,
|
.IR rcpthosts ,
|
||||||
.IR smtproutes ,
|
.IR smtproutes ,
|
||||||
and
|
and
|
||||||
|
|
@ -46,6 +47,7 @@ control default used by
|
||||||
.I concurrencyremote \fR20 \fRqmail-send
|
.I concurrencyremote \fR20 \fRqmail-send
|
||||||
.I defaultdomain \fIme \fRqmail-inject
|
.I defaultdomain \fIme \fRqmail-inject
|
||||||
.I defaulthost \fIme \fRqmail-inject
|
.I defaulthost \fIme \fRqmail-inject
|
||||||
|
.I databytes \fR0 \fRqmail-smtpd
|
||||||
.I doublebouncehost \fIme \fRqmail-send
|
.I doublebouncehost \fIme \fRqmail-send
|
||||||
.I doublebounceto \fRpostmaster \fRqmail-send
|
.I doublebounceto \fRpostmaster \fRqmail-send
|
||||||
.I envnoathost \fIme \fRqmail-send
|
.I envnoathost \fIme \fRqmail-send
|
||||||
|
|
@ -53,11 +55,12 @@ control default used by
|
||||||
.I idhost \fIme \fRqmail-inject
|
.I idhost \fIme \fRqmail-inject
|
||||||
.I localiphost \fIme \fRqmail-smtpd
|
.I localiphost \fIme \fRqmail-smtpd
|
||||||
.I locals \fIme \fRqmail-send
|
.I locals \fIme \fRqmail-send
|
||||||
|
.I morercpthosts \fR(none) \fRqmail-smtpd
|
||||||
.I percenthack \fR(none) \fRqmail-send
|
.I percenthack \fR(none) \fRqmail-send
|
||||||
.I plusdomain \fIme \fRqmail-inject
|
.I plusdomain \fIme \fRqmail-inject
|
||||||
|
.I qmqpservers \fR(none) \fRqmail-qmqpc
|
||||||
.I queuelifetime \fR604800 \fRqmail-send
|
.I queuelifetime \fR604800 \fRqmail-send
|
||||||
.I rcpthosts \fR(none) \fRqmail-smtpd
|
.I rcpthosts \fR(none) \fRqmail-smtpd
|
||||||
.I recipientmap \fR(none) \fRqmail-send
|
|
||||||
.I smtpgreeting \fIme \fRqmail-smtpd
|
.I smtpgreeting \fIme \fRqmail-smtpd
|
||||||
.I smtproutes \fR(none) \fRqmail-remote
|
.I smtproutes \fR(none) \fRqmail-remote
|
||||||
.I timeoutconnect \fR60 \fRqmail-remote
|
.I timeoutconnect \fR60 \fRqmail-remote
|
||||||
|
|
@ -68,6 +71,7 @@ control default used by
|
||||||
.RE
|
.RE
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
qmail-inject(8),
|
qmail-inject(8),
|
||||||
|
qmail-qmqpc(8),
|
||||||
qmail-remote(8),
|
qmail-remote(8),
|
||||||
qmail-send(8),
|
qmail-send(8),
|
||||||
qmail-showctl(8),
|
qmail-showctl(8),
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,12 @@ The operating system's
|
||||||
.B getpwnam
|
.B getpwnam
|
||||||
function, which is at the heart of
|
function, which is at the heart of
|
||||||
.BR qmail-getpw ,
|
.BR qmail-getpw ,
|
||||||
is inherently unreliable.
|
is inherently unreliable:
|
||||||
|
it fails to distinguish between temporary errors and nonexistent users.
|
||||||
|
Future versions of
|
||||||
|
.B getpwnam
|
||||||
|
should return ETXTBSY to indicate temporary errors
|
||||||
|
and ESRCH to indicate nonexistent users.
|
||||||
.SH "RULES"
|
.SH "RULES"
|
||||||
.B qmail-getpw
|
.B qmail-getpw
|
||||||
considers an account in
|
considers an account in
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,9 @@ int userext()
|
||||||
byte_copy(username,extension - local,local);
|
byte_copy(username,extension - local,local);
|
||||||
username[extension - local] = 0;
|
username[extension - local] = 0;
|
||||||
case_lowers(username);
|
case_lowers(username);
|
||||||
|
errno = 0;
|
||||||
pw = getpwnam(username);
|
pw = getpwnam(username);
|
||||||
|
if (errno == error_txtbsy) _exit(QLX_SYS);
|
||||||
if (pw)
|
if (pw)
|
||||||
if (pw->pw_uid)
|
if (pw->pw_uid)
|
||||||
if (stat(pw->pw_dir,&st) == 0) {
|
if (stat(pw->pw_dir,&st) == 0) {
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,7 @@ does not create any
|
||||||
fields.
|
fields.
|
||||||
.SH "RESENT MESSAGES"
|
.SH "RESENT MESSAGES"
|
||||||
A message is
|
A message is
|
||||||
.I forwarded
|
.I resent
|
||||||
if it contains any of the following fields:
|
if it contains any of the following fields:
|
||||||
.BR Resent-Sender ,
|
.BR Resent-Sender ,
|
||||||
.BR Resent-From ,
|
.BR Resent-From ,
|
||||||
|
|
@ -250,7 +250,7 @@ if it contains any of the following fields:
|
||||||
.BR Resent-Date ,
|
.BR Resent-Date ,
|
||||||
.BR Resent-Message-ID .
|
.BR Resent-Message-ID .
|
||||||
|
|
||||||
If a message is forwarded,
|
If a message is resent,
|
||||||
.B qmail-inject
|
.B qmail-inject
|
||||||
changes its behavior as follows.
|
changes its behavior as follows.
|
||||||
|
|
||||||
|
|
|
||||||
56
qmail-hier.c
56
qmail-hier.c
|
|
@ -78,8 +78,42 @@ void main()
|
||||||
dir(auto_uido,"755","/man/man5");
|
dir(auto_uido,"755","/man/man5");
|
||||||
dir(auto_uido,"755","/man/man7");
|
dir(auto_uido,"755","/man/man7");
|
||||||
dir(auto_uido,"755","/man/man8");
|
dir(auto_uido,"755","/man/man8");
|
||||||
|
dir(auto_uido,"755","/doc");
|
||||||
|
dir(auto_uido,"755","/boot");
|
||||||
|
|
||||||
dir(auto_uida,"755","/alias");
|
copy(auto_uido,"755","/boot/","home");
|
||||||
|
copy(auto_uido,"755","/boot/","home+df");
|
||||||
|
copy(auto_uido,"755","/boot/","proc");
|
||||||
|
copy(auto_uido,"755","/boot/","proc+df");
|
||||||
|
copy(auto_uido,"755","/boot/","binm1");
|
||||||
|
copy(auto_uido,"755","/boot/","binm1+df");
|
||||||
|
copy(auto_uido,"755","/boot/","binm2");
|
||||||
|
copy(auto_uido,"755","/boot/","binm2+df");
|
||||||
|
copy(auto_uido,"755","/boot/","binm3");
|
||||||
|
copy(auto_uido,"755","/boot/","binm3+df");
|
||||||
|
|
||||||
|
copy(auto_uido,"644","/doc/","FAQ");
|
||||||
|
copy(auto_uido,"644","/doc/","UPGRADE");
|
||||||
|
copy(auto_uido,"644","/doc/","SENDMAIL");
|
||||||
|
copy(auto_uido,"644","/doc/","INSTALL");
|
||||||
|
copy(auto_uido,"644","/doc/","INSTALL.alias");
|
||||||
|
copy(auto_uido,"644","/doc/","INSTALL.boot");
|
||||||
|
copy(auto_uido,"644","/doc/","INSTALL.ctl");
|
||||||
|
copy(auto_uido,"644","/doc/","INSTALL.ids");
|
||||||
|
copy(auto_uido,"644","/doc/","INSTALL.maildir");
|
||||||
|
copy(auto_uido,"644","/doc/","INSTALL.mbox");
|
||||||
|
copy(auto_uido,"644","/doc/","INSTALL.vsm");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.local2alias");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.local2ext");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.local2local");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.local2rem");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.local2virt");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.nullclient");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.relaybad");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.relaygood");
|
||||||
|
copy(auto_uido,"644","/doc/","PIC.rem2local");
|
||||||
|
|
||||||
|
dir(auto_uida,"2755","/alias");
|
||||||
dir(auto_uidq,"750","/queue");
|
dir(auto_uidq,"750","/queue");
|
||||||
dir(auto_uidq,"700","/queue/pid");
|
dir(auto_uidq,"700","/queue/pid");
|
||||||
dir(auto_uidq,"700","/queue/intd");
|
dir(auto_uidq,"700","/queue/intd");
|
||||||
|
|
@ -115,6 +149,7 @@ void main()
|
||||||
copy(auto_uido,"711","/bin/","qmail-send");
|
copy(auto_uido,"711","/bin/","qmail-send");
|
||||||
copy(auto_uido,"711","/bin/","splogger");
|
copy(auto_uido,"711","/bin/","splogger");
|
||||||
copy(auto_uido,"700","/bin/","qmail-newu");
|
copy(auto_uido,"700","/bin/","qmail-newu");
|
||||||
|
copy(auto_uido,"700","/bin/","qmail-newmrh");
|
||||||
copy(auto_uido,"711","/bin/","qmail-pw2u");
|
copy(auto_uido,"711","/bin/","qmail-pw2u");
|
||||||
copy(auto_uido,"755","/bin/","qmail-inject");
|
copy(auto_uido,"755","/bin/","qmail-inject");
|
||||||
copy(auto_uido,"755","/bin/","predate");
|
copy(auto_uido,"755","/bin/","predate");
|
||||||
|
|
@ -124,14 +159,15 @@ void main()
|
||||||
copy(auto_uido,"755","/bin/","qmail-qread");
|
copy(auto_uido,"755","/bin/","qmail-qread");
|
||||||
copy(auto_uido,"755","/bin/","qmail-qstat");
|
copy(auto_uido,"755","/bin/","qmail-qstat");
|
||||||
copy(auto_uido,"755","/bin/","qmail-tcpto");
|
copy(auto_uido,"755","/bin/","qmail-tcpto");
|
||||||
|
copy(auto_uido,"755","/bin/","qmail-tcpok");
|
||||||
copy(auto_uido,"755","/bin/","qmail-pop3d");
|
copy(auto_uido,"755","/bin/","qmail-pop3d");
|
||||||
copy(auto_uido,"700","/bin/","qmail-popup");
|
copy(auto_uido,"711","/bin/","qmail-popup");
|
||||||
|
copy(auto_uido,"755","/bin/","qmail-qmqpc");
|
||||||
|
copy(auto_uido,"755","/bin/","qmail-qmqpd");
|
||||||
copy(auto_uido,"755","/bin/","qmail-qmtpd");
|
copy(auto_uido,"755","/bin/","qmail-qmtpd");
|
||||||
copy(auto_uido,"755","/bin/","qmail-smtpd");
|
copy(auto_uido,"755","/bin/","qmail-smtpd");
|
||||||
copy(auto_uido,"755","/bin/","sendmail");
|
copy(auto_uido,"755","/bin/","sendmail");
|
||||||
copy(auto_uido,"755","/bin/","tcp-env");
|
copy(auto_uido,"755","/bin/","tcp-env");
|
||||||
copy(auto_uido,"755","/bin/","qlist");
|
|
||||||
copy(auto_uido,"755","/bin/","qlist2");
|
|
||||||
copy(auto_uido,"755","/bin/","qreceipt");
|
copy(auto_uido,"755","/bin/","qreceipt");
|
||||||
copy(auto_uido,"755","/bin/","qsmhook");
|
copy(auto_uido,"755","/bin/","qsmhook");
|
||||||
copy(auto_uido,"755","/bin/","qbiff");
|
copy(auto_uido,"755","/bin/","qbiff");
|
||||||
|
|
@ -170,8 +206,6 @@ void main()
|
||||||
copy(auto_uido,"644","/man/cat7/","forgeries.0");
|
copy(auto_uido,"644","/man/cat7/","forgeries.0");
|
||||||
copy(auto_uido,"644","/man/man7/","qmail-limits.7");
|
copy(auto_uido,"644","/man/man7/","qmail-limits.7");
|
||||||
copy(auto_uido,"644","/man/cat7/","qmail-limits.0");
|
copy(auto_uido,"644","/man/cat7/","qmail-limits.0");
|
||||||
copy(auto_uido,"644","/man/man7/","qmail-upgrade.7");
|
|
||||||
copy(auto_uido,"644","/man/cat7/","qmail-upgrade.0");
|
|
||||||
copy(auto_uido,"644","/man/man7/","qmail.7");
|
copy(auto_uido,"644","/man/man7/","qmail.7");
|
||||||
copy(auto_uido,"644","/man/cat7/","qmail.0");
|
copy(auto_uido,"644","/man/cat7/","qmail.0");
|
||||||
|
|
||||||
|
|
@ -187,8 +221,6 @@ void main()
|
||||||
copy(auto_uido,"644","/man/cat1/","maildirwatch.0");
|
copy(auto_uido,"644","/man/cat1/","maildirwatch.0");
|
||||||
copy(auto_uido,"644","/man/man1/","mailsubj.1");
|
copy(auto_uido,"644","/man/man1/","mailsubj.1");
|
||||||
copy(auto_uido,"644","/man/cat1/","mailsubj.0");
|
copy(auto_uido,"644","/man/cat1/","mailsubj.0");
|
||||||
copy(auto_uido,"644","/man/man1/","qlist.1");
|
|
||||||
copy(auto_uido,"644","/man/cat1/","qlist.0");
|
|
||||||
copy(auto_uido,"644","/man/man1/","qreceipt.1");
|
copy(auto_uido,"644","/man/man1/","qreceipt.1");
|
||||||
copy(auto_uido,"644","/man/cat1/","qreceipt.0");
|
copy(auto_uido,"644","/man/cat1/","qreceipt.0");
|
||||||
copy(auto_uido,"644","/man/man1/","qbiff.1");
|
copy(auto_uido,"644","/man/man1/","qbiff.1");
|
||||||
|
|
@ -222,6 +254,8 @@ void main()
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-inject.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-inject.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-showctl.8");
|
copy(auto_uido,"644","/man/man8/","qmail-showctl.8");
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-showctl.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-showctl.0");
|
||||||
|
copy(auto_uido,"644","/man/man8/","qmail-newmrh.8");
|
||||||
|
copy(auto_uido,"644","/man/cat8/","qmail-newmrh.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-newu.8");
|
copy(auto_uido,"644","/man/man8/","qmail-newu.8");
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-newu.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-newu.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-pw2u.8");
|
copy(auto_uido,"644","/man/man8/","qmail-pw2u.8");
|
||||||
|
|
@ -230,12 +264,18 @@ void main()
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-qread.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-qread.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-qstat.8");
|
copy(auto_uido,"644","/man/man8/","qmail-qstat.8");
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-qstat.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-qstat.0");
|
||||||
|
copy(auto_uido,"644","/man/man8/","qmail-tcpok.8");
|
||||||
|
copy(auto_uido,"644","/man/cat8/","qmail-tcpok.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-tcpto.8");
|
copy(auto_uido,"644","/man/man8/","qmail-tcpto.8");
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-tcpto.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-tcpto.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-pop3d.8");
|
copy(auto_uido,"644","/man/man8/","qmail-pop3d.8");
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-pop3d.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-pop3d.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-popup.8");
|
copy(auto_uido,"644","/man/man8/","qmail-popup.8");
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-popup.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-popup.0");
|
||||||
|
copy(auto_uido,"644","/man/man8/","qmail-qmqpc.8");
|
||||||
|
copy(auto_uido,"644","/man/cat8/","qmail-qmqpc.0");
|
||||||
|
copy(auto_uido,"644","/man/man8/","qmail-qmqpd.8");
|
||||||
|
copy(auto_uido,"644","/man/cat8/","qmail-qmqpd.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-qmtpd.8");
|
copy(auto_uido,"644","/man/man8/","qmail-qmtpd.8");
|
||||||
copy(auto_uido,"644","/man/cat8/","qmail-qmtpd.0");
|
copy(auto_uido,"644","/man/cat8/","qmail-qmtpd.0");
|
||||||
copy(auto_uido,"644","/man/man8/","qmail-smtpd.8");
|
copy(auto_uido,"644","/man/man8/","qmail-smtpd.8");
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,21 @@ and
|
||||||
letters described below.
|
letters described below.
|
||||||
Bounces will be sent to this address.
|
Bounces will be sent to this address.
|
||||||
|
|
||||||
|
If
|
||||||
|
.B QMAILMFTFILE
|
||||||
|
is set,
|
||||||
|
.B qmail-inject
|
||||||
|
reads a list of mailing list addresses,
|
||||||
|
one per line,
|
||||||
|
from that file.
|
||||||
|
If To+Cc includes one of those addresses (without regard to case),
|
||||||
|
.B qmail-inject
|
||||||
|
adds a Mail-Followup-To field
|
||||||
|
with all the To+Cc addresses.
|
||||||
|
.B qmail-inject
|
||||||
|
does not add Mail-Followup-To
|
||||||
|
to a message that already has one.
|
||||||
|
|
||||||
The
|
The
|
||||||
.B QMAILINJECT
|
.B QMAILINJECT
|
||||||
environment variable
|
environment variable
|
||||||
|
|
|
||||||
144
qmail-inject.c
144
qmail-inject.c
|
|
@ -21,6 +21,7 @@
|
||||||
#include "headerbody.h"
|
#include "headerbody.h"
|
||||||
#include "auto_qmail.h"
|
#include "auto_qmail.h"
|
||||||
#include "newfield.h"
|
#include "newfield.h"
|
||||||
|
#include "constmap.h"
|
||||||
|
|
||||||
#define LINELEN 80
|
#define LINELEN 80
|
||||||
|
|
||||||
|
|
@ -63,14 +64,10 @@ void die_nomem() {
|
||||||
void die_invalid(sa) stralloc *sa; {
|
void die_invalid(sa) stralloc *sa; {
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: invalid header field: ");
|
substdio_putsflush(subfderr,"qmail-inject: fatal: invalid header field: ");
|
||||||
substdio_putflush(subfderr,sa->s,sa->len); perm(); }
|
substdio_putflush(subfderr,sa->s,sa->len); perm(); }
|
||||||
void die_exec() {
|
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: unable to exec qmail-queue\n"); temp(); }
|
|
||||||
void die_qqt() {
|
void die_qqt() {
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: unable to run qmail-queue\n"); temp(); }
|
substdio_putsflush(subfderr,"qmail-inject: fatal: unable to run qmail-queue\n"); temp(); }
|
||||||
void die_chdir() {
|
void die_chdir() {
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: internal bug\n"); temp(); }
|
substdio_putsflush(subfderr,"qmail-inject: fatal: internal bug\n"); temp(); }
|
||||||
void die_bug() {
|
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: internal bug\n"); temp(); }
|
|
||||||
void die_read() {
|
void die_read() {
|
||||||
if (errno == error_nomem) die_nomem();
|
if (errno == error_nomem) die_nomem();
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: read error\n"); temp(); }
|
substdio_putsflush(subfderr,"qmail-inject: fatal: read error\n"); temp(); }
|
||||||
|
|
@ -79,19 +76,6 @@ void doordie(sa,r) stralloc *sa; int r; {
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: unable to parse this line:\n");
|
substdio_putsflush(subfderr,"qmail-inject: fatal: unable to parse this line:\n");
|
||||||
substdio_putflush(subfderr,sa->s,sa->len); perm(); }
|
substdio_putflush(subfderr,sa->s,sa->len); perm(); }
|
||||||
|
|
||||||
void die_comm() {
|
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: qmail-queue lost communications link\n"); temp(); }
|
|
||||||
void die_qq() {
|
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: qmail-queue died\n"); temp(); }
|
|
||||||
void die_qqwrite() {
|
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: qmail-queue unable to write message to disk; disk full?\n"); temp(); }
|
|
||||||
void die_qqsig() {
|
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: qmail-queue was killed\n"); temp(); }
|
|
||||||
void die_qqtimeout() {
|
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: qmail-queue timed out\n"); temp(); }
|
|
||||||
void die_qqtoolong() {
|
|
||||||
substdio_putsflush(subfderr,"qmail-inject: fatal: qmail-queue unhappy with long addresses\n"); perm(); }
|
|
||||||
|
|
||||||
GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
|
GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
|
||||||
GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
|
GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
|
||||||
|
|
||||||
|
|
@ -99,12 +83,15 @@ static stralloc sauninit = {0};
|
||||||
|
|
||||||
saa savedh = {0};
|
saa savedh = {0};
|
||||||
saa hrlist = {0};
|
saa hrlist = {0};
|
||||||
|
saa tocclist = {0};
|
||||||
saa hrrlist = {0};
|
saa hrrlist = {0};
|
||||||
saa reciplist = {0};
|
saa reciplist = {0};
|
||||||
int flagresent;
|
int flagresent;
|
||||||
|
|
||||||
void exitnicely()
|
void exitnicely()
|
||||||
{
|
{
|
||||||
|
char *qqx;
|
||||||
|
|
||||||
if (!flagqueue) substdio_flush(subfdout);
|
if (!flagqueue) substdio_flush(subfdout);
|
||||||
|
|
||||||
if (flagqueue)
|
if (flagqueue)
|
||||||
|
|
@ -133,18 +120,21 @@ void exitnicely()
|
||||||
qmail_to(&qqt,hrlist.sa[i].s);
|
qmail_to(&qqt,hrlist.sa[i].s);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(qmail_close(&qqt))
|
qqx = qmail_close(&qqt);
|
||||||
{
|
if (*qqx)
|
||||||
case 0: break;
|
if (*qqx == 'D') {
|
||||||
case QMAIL_CRASHED: die_qqsig();
|
substdio_puts(subfderr,"qmail-inject: fatal: ");
|
||||||
case QMAIL_USAGE: case QMAIL_BUG: die_bug();
|
substdio_puts(subfderr,qqx + 1);
|
||||||
case QMAIL_EXECSOFT: die_exec();
|
substdio_puts(subfderr,"\n");
|
||||||
case QMAIL_NOMEM: die_nomem();
|
substdio_flush(subfderr);
|
||||||
case QMAIL_READ: die_comm();
|
perm();
|
||||||
case QMAIL_WRITE: die_qqwrite();
|
}
|
||||||
case QMAIL_TOOLONG: die_qqtoolong();
|
else {
|
||||||
case QMAIL_TIMEOUT: die_qqtimeout();
|
substdio_puts(subfderr,"qmail-inject: fatal: ");
|
||||||
default: die_qq();
|
substdio_puts(subfderr,qqx + 1);
|
||||||
|
substdio_puts(subfderr,"\n");
|
||||||
|
substdio_flush(subfderr);
|
||||||
|
temp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,11 +314,10 @@ token822_alloc *addr;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rwrecip(addr,xl)
|
void rwappend(addr,xl)
|
||||||
token822_alloc *addr;
|
token822_alloc *addr;
|
||||||
saa *xl;
|
saa *xl;
|
||||||
{
|
{
|
||||||
rwgeneric(addr);
|
|
||||||
token822_reverse(addr);
|
token822_reverse(addr);
|
||||||
if (!saa_readyplus(xl,1)) die_nomem();
|
if (!saa_readyplus(xl,1)) die_nomem();
|
||||||
xl->sa[xl->len] = sauninit;
|
xl->sa[xl->len] = sauninit;
|
||||||
|
|
@ -338,9 +327,11 @@ saa *xl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rwhrr(addr) token822_alloc *addr;
|
int rwhrr(addr) token822_alloc *addr;
|
||||||
{ rwrecip(addr,&hrrlist); return 1; }
|
{ rwgeneric(addr); rwappend(addr,&hrrlist); return 1; }
|
||||||
int rwhr(addr) token822_alloc *addr;
|
int rwhr(addr) token822_alloc *addr;
|
||||||
{ rwrecip(addr,&hrlist); return 1; }
|
{ rwgeneric(addr); rwappend(addr,&hrlist); return 1; }
|
||||||
|
int rwtocc(addr) token822_alloc *addr;
|
||||||
|
{ rwgeneric(addr); rwappend(addr,&hrlist); rwappend(addr,&tocclist); return 1; }
|
||||||
|
|
||||||
int htypeseen[H_NUM];
|
int htypeseen[H_NUM];
|
||||||
stralloc hfbuf = {0};
|
stralloc hfbuf = {0};
|
||||||
|
|
@ -352,9 +343,7 @@ void doheaderfield(h)
|
||||||
stralloc *h;
|
stralloc *h;
|
||||||
{
|
{
|
||||||
int htype;
|
int htype;
|
||||||
int flagrewrite;
|
int (*rw)() = 0;
|
||||||
int flagrecip;
|
|
||||||
int flagrr;
|
|
||||||
|
|
||||||
htype = hfield_known(h->s,h->len);
|
htype = hfield_known(h->s,h->len);
|
||||||
if (flagdeletefrom) if (htype == H_FROM) return;
|
if (flagdeletefrom) if (htype == H_FROM) return;
|
||||||
|
|
@ -367,26 +356,24 @@ stralloc *h;
|
||||||
if (!hfield_valid(h->s,h->len))
|
if (!hfield_valid(h->s,h->len))
|
||||||
die_invalid(h);
|
die_invalid(h);
|
||||||
|
|
||||||
flagrewrite = 0;
|
switch(htype) {
|
||||||
flagrecip = 0;
|
case H_TO: case H_CC:
|
||||||
flagrr = 0;
|
rw = rwtocc; break;
|
||||||
switch(htype)
|
case H_BCC: case H_APPARENTLYTO:
|
||||||
{
|
rw = rwhr; break;
|
||||||
case H_R_TO: case H_R_CC: case H_R_BCC:
|
case H_R_TO: case H_R_CC: case H_R_BCC:
|
||||||
flagrr = 1;
|
rw = rwhrr; break;
|
||||||
case H_TO: case H_CC: case H_BCC: case H_APPARENTLYTO:
|
case H_RETURNPATH:
|
||||||
flagrecip = 1;
|
rw = rwreturn; break;
|
||||||
case H_SENDER: case H_FROM: case H_REPLYTO:
|
case H_SENDER: case H_FROM: case H_REPLYTO:
|
||||||
case H_RETURNRECEIPTTO: case H_ERRORSTO: case H_RETURNPATH:
|
case H_RETURNRECEIPTTO: case H_ERRORSTO:
|
||||||
case H_R_SENDER: case H_R_FROM: case H_R_REPLYTO:
|
case H_R_SENDER: case H_R_FROM: case H_R_REPLYTO:
|
||||||
flagrewrite = 1;
|
rw = rwsender; break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flagrewrite)
|
if (rw) {
|
||||||
{
|
|
||||||
doordie(h,token822_parse(&hfin,h,&hfbuf));
|
doordie(h,token822_parse(&hfin,h,&hfbuf));
|
||||||
doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,(htype == H_RETURNPATH) ? rwreturn : (flagrecip ? (flagrr ? rwhrr : rwhr) : rwsender)));
|
doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,rw));
|
||||||
if (token822_unparse(h,&hfrewrite,LINELEN) != 1)
|
if (token822_unparse(h,&hfrewrite,LINELEN) != 1)
|
||||||
die_nomem();
|
die_nomem();
|
||||||
}
|
}
|
||||||
|
|
@ -421,7 +408,8 @@ char *s;
|
||||||
perm();
|
perm();
|
||||||
}
|
}
|
||||||
token822_reverse(&tr);
|
token822_reverse(&tr);
|
||||||
rwrecip(&tr,&reciplist);
|
rwgeneric(&tr);
|
||||||
|
rwappend(&tr,&reciplist);
|
||||||
}
|
}
|
||||||
|
|
||||||
stralloc defaultfrom = {0};
|
stralloc defaultfrom = {0};
|
||||||
|
|
@ -526,6 +514,53 @@ void dodefaultreturnpath()
|
||||||
if (token822_unparse(&defaultreturnpath,&hfrewrite,LINELEN) != 1) die_nomem();
|
if (token822_unparse(&defaultreturnpath,&hfrewrite,LINELEN) != 1) die_nomem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int flagmft = 0;
|
||||||
|
stralloc mft = {0};
|
||||||
|
struct constmap mapmft;
|
||||||
|
|
||||||
|
void mft_init()
|
||||||
|
{
|
||||||
|
char *x;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
x = env_get("QMAILMFTFILE");
|
||||||
|
if (!x) return;
|
||||||
|
|
||||||
|
r = control_readfile(&mft,x,0);
|
||||||
|
if (r == -1) die_read(); /*XXX*/
|
||||||
|
if (!r) return;
|
||||||
|
|
||||||
|
if (!constmap_init(&mapmft,mft.s,mft.len,0)) die_nomem();
|
||||||
|
flagmft = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void finishmft()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
static stralloc sa = {0};
|
||||||
|
static stralloc sa2 = {0};
|
||||||
|
|
||||||
|
if (!flagmft) return;
|
||||||
|
if (htypeseen[H_MAILFOLLOWUPTO]) return;
|
||||||
|
|
||||||
|
for (i = 0;i < tocclist.len;++i)
|
||||||
|
if (constmap(&mapmft,tocclist.sa[i].s,tocclist.sa[i].len))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i == tocclist.len) return;
|
||||||
|
|
||||||
|
puts("Mail-Followup-To: ");
|
||||||
|
i = tocclist.len;
|
||||||
|
while (i--) {
|
||||||
|
if (!stralloc_copy(&sa,&tocclist.sa[i])) die_nomem();
|
||||||
|
if (!stralloc_0(&sa)) die_nomem();
|
||||||
|
if (!quote2(&sa2,sa.s)) die_nomem();
|
||||||
|
put(sa2.s,sa2.len);
|
||||||
|
if (i) puts(",\n ");
|
||||||
|
}
|
||||||
|
puts("\n");
|
||||||
|
}
|
||||||
|
|
||||||
void finishheader()
|
void finishheader()
|
||||||
{
|
{
|
||||||
flagresent =
|
flagresent =
|
||||||
|
|
@ -596,6 +631,7 @@ void finishheader()
|
||||||
}
|
}
|
||||||
if (!htypeseen[H_TO] && !htypeseen[H_CC])
|
if (!htypeseen[H_TO] && !htypeseen[H_CC])
|
||||||
puts("Cc: recipient list not shown: ;\n");
|
puts("Cc: recipient list not shown: ;\n");
|
||||||
|
finishmft();
|
||||||
}
|
}
|
||||||
|
|
||||||
savedh_print();
|
savedh_print();
|
||||||
|
|
@ -606,6 +642,9 @@ void getcontrols()
|
||||||
static stralloc sa = {0};
|
static stralloc sa = {0};
|
||||||
char *x;
|
char *x;
|
||||||
|
|
||||||
|
mft_init();
|
||||||
|
|
||||||
|
if (chdir(auto_qmail) == -1) die_chdir();
|
||||||
if (control_init() == -1) die_read();
|
if (control_init() == -1) die_read();
|
||||||
|
|
||||||
if (control_rldef(&control_defaultdomain,"control/defaultdomain",1,"defaultdomain") != 1)
|
if (control_rldef(&control_defaultdomain,"control/defaultdomain",1,"defaultdomain") != 1)
|
||||||
|
|
@ -688,11 +727,10 @@ char **argv;
|
||||||
recipstrategy = RECIP_DEFAULT;
|
recipstrategy = RECIP_DEFAULT;
|
||||||
flagqueue = 1;
|
flagqueue = 1;
|
||||||
|
|
||||||
if (chdir(auto_qmail) == -1)
|
|
||||||
die_chdir();
|
|
||||||
getcontrols();
|
getcontrols();
|
||||||
|
|
||||||
if (!saa_readyplus(&hrlist,1)) die_nomem();
|
if (!saa_readyplus(&hrlist,1)) die_nomem();
|
||||||
|
if (!saa_readyplus(&tocclist,1)) die_nomem();
|
||||||
if (!saa_readyplus(&hrrlist,1)) die_nomem();
|
if (!saa_readyplus(&hrrlist,1)) die_nomem();
|
||||||
if (!saa_readyplus(&reciplist,1)) die_nomem();
|
if (!saa_readyplus(&reciplist,1)) die_nomem();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ qmail-local \- deliver or forward a mail message
|
||||||
.I ext
|
.I ext
|
||||||
.I domain
|
.I domain
|
||||||
.I sender
|
.I sender
|
||||||
.I aliasempty
|
.I defaultdelivery
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B qmail-local
|
.B qmail-local
|
||||||
reads a mail message
|
reads a mail message
|
||||||
|
|
@ -69,7 +69,7 @@ treats a nonexistent
|
||||||
the same way as an empty
|
the same way as an empty
|
||||||
.BR .qmail\fIext :
|
.BR .qmail\fIext :
|
||||||
namely, following the delivery instructions in
|
namely, following the delivery instructions in
|
||||||
.IR aliasempty .
|
.IR defaultdelivery .
|
||||||
|
|
||||||
The standard input for
|
The standard input for
|
||||||
.B qmail-local
|
.B qmail-local
|
||||||
|
|
|
||||||
262
qmail-local.c
262
qmail-local.c
|
|
@ -12,6 +12,7 @@
|
||||||
#include "seek.h"
|
#include "seek.h"
|
||||||
#include "substdio.h"
|
#include "substdio.h"
|
||||||
#include "getln.h"
|
#include "getln.h"
|
||||||
|
#include "strerr.h"
|
||||||
#include "subfd.h"
|
#include "subfd.h"
|
||||||
#include "sgetopt.h"
|
#include "sgetopt.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
|
|
@ -28,40 +29,17 @@
|
||||||
#include "gfrom.h"
|
#include "gfrom.h"
|
||||||
#include "auto_patrn.h"
|
#include "auto_patrn.h"
|
||||||
|
|
||||||
void err(s) char *s; { substdio_putsflush(subfderr,s); }
|
void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); }
|
||||||
void soft() { _exit(111); }
|
|
||||||
void hard() { _exit(100); }
|
|
||||||
|
|
||||||
void temp_childcrashed() { err("Aack, child crashed. (#4.3.0)\n"); soft(); }
|
void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); }
|
||||||
void temp_rewind() { err("Unable to rewind message. (#4.3.0)\n"); soft(); }
|
void temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); }
|
||||||
void temp_fork() { err("Unable to fork. (#4.3.0)\n"); soft(); }
|
void temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); }
|
||||||
void temp_read() { err("Error while reading message. (#4.3.0)\n"); soft(); }
|
void temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); }
|
||||||
void temp_write() { err("Error while writing message. (#4.3.0)\n"); soft(); }
|
void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); }
|
||||||
void temp_child() { err("Temporary error in forwarding message. (#4.3.0)\n"); soft(); }
|
void temp_slowlock()
|
||||||
void temp_maildirtimeout() { err("Timeout on maildir delivery. (#4.3.0)\n"); soft(); }
|
{ strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); }
|
||||||
void temp_maildir() { err("Temporary error on maildir delivery. (#4.3.0)\n"); soft(); }
|
void temp_qmail(fn) char *fn;
|
||||||
void temp_nomaildir() { err("Unable to chdir to maildir. (#4.2.1)\n"); soft(); }
|
{ strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); }
|
||||||
void temp_open(fn) char *fn; { err("Unable to open "); err(fn); err(". (#4.2.1)\n"); soft(); }
|
|
||||||
|
|
||||||
void temp_blankline() { err("Uh-oh: first line of .qmail file is blank. (#4.2.1)\n"); soft(); }
|
|
||||||
void temp_fofile() { err("Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)\n"); soft(); }
|
|
||||||
void temp_foprog() { err("Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)\n"); soft(); }
|
|
||||||
void temp_nomem() { err("Out of memory. (#4.3.0)\n"); soft(); }
|
|
||||||
void temp_chdir() { err("Unable to switch to home directory. (#4.3.0)\n"); soft(); }
|
|
||||||
void temp_homestat() { err("Unable to stat home directory. (#4.3.0)\n"); soft(); }
|
|
||||||
void temp_homesticky() { err("Home directory is sticky: user is editing his .qmail file. (#4.2.1)\n"); soft(); }
|
|
||||||
void temp_homewritable() { err("Uh-oh: home directory is writable. (#4.7.0)\n"); soft(); }
|
|
||||||
void temp_qmwritable() { err("Uh-oh: .qmail file is writable. (#4.7.0)\n"); soft(); }
|
|
||||||
void temp_nfsqmail() { err("Temporary error trying to open .qmail file. (#4.3.0)\n"); soft(); }
|
|
||||||
void temp_denyqmail() { err("Permission error trying to open .qmail file. (#4.3.0)\n"); soft(); }
|
|
||||||
void temp_slowlock() { err("File has been locked for 30 seconds straight. (#4.3.0)\n"); soft(); }
|
|
||||||
|
|
||||||
void bounce_childperm() { err("Permanent error in forwarding message. (#5.2.4)\n"); hard(); }
|
|
||||||
void bounce_loop() { err("This message is looping: it already has my Delivered-To line. (#5.4.6)\n"); hard(); }
|
|
||||||
void bounce_ext() { err("Sorry, no mailbox here by that name. (#5.1.1)\n"); hard(); }
|
|
||||||
void usage() { err("qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty\n"); hard(); }
|
|
||||||
|
|
||||||
void warn_homesticky() { err("Warning: home directory is sticky.\n"); }
|
|
||||||
|
|
||||||
int flagdoit;
|
int flagdoit;
|
||||||
int flag99;
|
int flag99;
|
||||||
|
|
@ -75,7 +53,7 @@ char *host;
|
||||||
char *sender;
|
char *sender;
|
||||||
char *aliasempty;
|
char *aliasempty;
|
||||||
|
|
||||||
stralloc dashext = {0};
|
stralloc safeext = {0};
|
||||||
stralloc ufline = {0};
|
stralloc ufline = {0};
|
||||||
stralloc rpline = {0};
|
stralloc rpline = {0};
|
||||||
stralloc envrecip = {0};
|
stralloc envrecip = {0};
|
||||||
|
|
@ -172,7 +150,7 @@ char *fn;
|
||||||
temp_fork();
|
temp_fork();
|
||||||
case 0:
|
case 0:
|
||||||
maildir_child(fn);
|
maildir_child(fn);
|
||||||
soft();
|
_exit(111);
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_pid(&wstat,child);
|
wait_pid(&wstat,child);
|
||||||
|
|
@ -181,15 +159,13 @@ char *fn;
|
||||||
switch(wait_exitcode(wstat))
|
switch(wait_exitcode(wstat))
|
||||||
{
|
{
|
||||||
case 0: break;
|
case 0: break;
|
||||||
case 2: temp_nomaildir();
|
case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
|
||||||
case 3: temp_maildirtimeout();
|
case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
|
||||||
case 4: temp_read();
|
case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
|
||||||
default: temp_maildir();
|
default: strerr_die1x(111,"Temporary error on maildir delivery. (#4.3.0)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void slowlock() { temp_slowlock(); }
|
|
||||||
|
|
||||||
void mailfile(fn)
|
void mailfile(fn)
|
||||||
char *fn;
|
char *fn;
|
||||||
{
|
{
|
||||||
|
|
@ -203,9 +179,10 @@ char *fn;
|
||||||
if (seek_begin(0) == -1) temp_rewind();
|
if (seek_begin(0) == -1) temp_rewind();
|
||||||
|
|
||||||
fd = open_append(fn);
|
fd = open_append(fn);
|
||||||
if (fd == -1) temp_open(fn);
|
if (fd == -1)
|
||||||
|
strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.2.1)");
|
||||||
|
|
||||||
sig_alarmcatch(slowlock);
|
sig_alarmcatch(temp_slowlock);
|
||||||
alarm(30);
|
alarm(30);
|
||||||
flaglocked = (lock_ex(fd) != -1);
|
flaglocked = (lock_ex(fd) != -1);
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
|
@ -222,7 +199,11 @@ char *fn;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (getln(&ss,&messline,&match,'\n') != 0)
|
if (getln(&ss,&messline,&match,'\n') != 0)
|
||||||
{ if (flaglocked) seek_trunc(fd,pos); close(fd); temp_read(); }
|
{
|
||||||
|
strerr_warn3("Unable to read message: ",error_str(errno),". (#4.3.0)",0);
|
||||||
|
if (flaglocked) seek_trunc(fd,pos); close(fd);
|
||||||
|
_exit(111);
|
||||||
|
}
|
||||||
if (!match && !messline.len) break;
|
if (!match && !messline.len) break;
|
||||||
if (gfrom(messline.s,messline.len))
|
if (gfrom(messline.s,messline.len))
|
||||||
if (substdio_bput(&ssout,">",1)) goto writeerrs;
|
if (substdio_bput(&ssout,">",1)) goto writeerrs;
|
||||||
|
|
@ -240,9 +221,10 @@ char *fn;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
writeerrs:
|
writeerrs:
|
||||||
|
strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0);
|
||||||
if (flaglocked) seek_trunc(fd,pos);
|
if (flaglocked) seek_trunc(fd,pos);
|
||||||
close(fd);
|
close(fd);
|
||||||
temp_write();
|
_exit(111);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mailprogram(prog)
|
void mailprogram(prog)
|
||||||
|
|
@ -259,15 +241,10 @@ char *prog;
|
||||||
case -1:
|
case -1:
|
||||||
temp_fork();
|
temp_fork();
|
||||||
case 0:
|
case 0:
|
||||||
args[0] = "sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;
|
args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;
|
||||||
sig_pipedefault();
|
sig_pipedefault();
|
||||||
execvp(*args,args);
|
execv(*args,args);
|
||||||
if (errno == error_txtbsy) { err("Text busy. (#4.3.0)\n"); soft(); }
|
strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)");
|
||||||
if (errno == error_nomem) { err("Out of memory. (#4.3.0)\n"); soft(); }
|
|
||||||
if (errno == error_io) { err("I/O error. (#4.3.0)\n"); soft(); }
|
|
||||||
if (error_temp(errno)) { err("Temporary error. (#4.3.0)\n"); soft(); }
|
|
||||||
err("Unable to execute "); err(*args); err(" (#5.2.4)\n");
|
|
||||||
hard();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_pid(&wstat,child);
|
wait_pid(&wstat,child);
|
||||||
|
|
@ -276,10 +253,10 @@ char *prog;
|
||||||
switch(wait_exitcode(wstat))
|
switch(wait_exitcode(wstat))
|
||||||
{
|
{
|
||||||
case 100:
|
case 100:
|
||||||
case 64: case 65: case 70: case 76: case 77: case 78: case 112: hard();
|
case 64: case 65: case 70: case 76: case 77: case 78: case 112: _exit(100);
|
||||||
case 0: break;
|
case 0: break;
|
||||||
case 99: flag99 = 1; break;
|
case 99: flag99 = 1; break;
|
||||||
default: soft();
|
default: _exit(111);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -289,6 +266,7 @@ void mailforward(recips)
|
||||||
char **recips;
|
char **recips;
|
||||||
{
|
{
|
||||||
struct qmail qqt;
|
struct qmail qqt;
|
||||||
|
char *qqx;
|
||||||
substdio ss;
|
substdio ss;
|
||||||
int match;
|
int match;
|
||||||
|
|
||||||
|
|
@ -306,13 +284,9 @@ char **recips;
|
||||||
while (match);
|
while (match);
|
||||||
qmail_from(&qqt,ueo.s);
|
qmail_from(&qqt,ueo.s);
|
||||||
while (*recips) qmail_to(&qqt,*recips++);
|
while (*recips) qmail_to(&qqt,*recips++);
|
||||||
switch(qmail_close(&qqt))
|
qqx = qmail_close(&qqt);
|
||||||
{
|
if (!*qqx) return;
|
||||||
case QMAIL_TOOLONG: bounce_childperm();
|
strerr_die3x(*qqx == 'D' ? 100 : 111,"Unable to forward message: ",qqx + 1,".");
|
||||||
case QMAIL_READ: temp_read();
|
|
||||||
case 0: return;
|
|
||||||
default: temp_child();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bouncexf()
|
void bouncexf()
|
||||||
|
|
@ -330,7 +304,7 @@ void bouncexf()
|
||||||
break;
|
break;
|
||||||
if (messline.len == dtline.len)
|
if (messline.len == dtline.len)
|
||||||
if (!str_diffn(messline.s,dtline.s,dtline.len))
|
if (!str_diffn(messline.s,dtline.s,dtline.len))
|
||||||
bounce_loop();
|
strerr_die1x(100,"This message is looping: it already has my Delivered-To line. (#5.4.6)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,10 +312,15 @@ void checkhome()
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (stat(".",&st) == -1) temp_homestat();
|
if (stat(".",&st) == -1)
|
||||||
if (st.st_mode & auto_patrn) temp_homewritable();
|
strerr_die3x(111,"Unable to stat home directory: ",error_str(errno),". (#4.3.0)");
|
||||||
|
if (st.st_mode & auto_patrn)
|
||||||
|
strerr_die1x(111,"Uh-oh: home directory is writable. (#4.7.0)");
|
||||||
if (st.st_mode & 01000)
|
if (st.st_mode & 01000)
|
||||||
if (flagdoit) temp_homesticky(); else warn_homesticky();
|
if (flagdoit)
|
||||||
|
strerr_die1x(111,"Home directory is sticky: user is editing his .qmail file. (#4.2.1)");
|
||||||
|
else
|
||||||
|
strerr_warn1("Warning: home directory is sticky.",0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int qmeox(dashowner)
|
int qmeox(dashowner)
|
||||||
|
|
@ -350,54 +329,86 @@ char *dashowner;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (!stralloc_copys(&qme,".qmail")) temp_nomem();
|
if (!stralloc_copys(&qme,".qmail")) temp_nomem();
|
||||||
if (!stralloc_cat(&qme,&dashext)) temp_nomem();
|
if (!stralloc_cats(&qme,dash)) temp_nomem();
|
||||||
|
if (!stralloc_cat(&qme,&safeext)) temp_nomem();
|
||||||
if (!stralloc_cats(&qme,dashowner)) temp_nomem();
|
if (!stralloc_cats(&qme,dashowner)) temp_nomem();
|
||||||
if (!stralloc_0(&qme)) temp_nomem();
|
if (!stralloc_0(&qme)) temp_nomem();
|
||||||
if (stat(qme.s,&st) == -1)
|
if (stat(qme.s,&st) == -1)
|
||||||
{
|
{
|
||||||
if (error_temp(errno)) temp_nfsqmail();
|
if (error_temp(errno)) temp_qmail(qme.s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qmeopen(cutable)
|
int qmeexists(fd,cutable)
|
||||||
|
int *fd;
|
||||||
int *cutable;
|
int *cutable;
|
||||||
{
|
{
|
||||||
int fd;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
|
if (!stralloc_0(&qme)) temp_nomem();
|
||||||
|
|
||||||
|
*fd = open_read(qme.s);
|
||||||
|
if (*fd == -1) {
|
||||||
|
if (error_temp(errno)) temp_qmail(qme.s);
|
||||||
|
if (errno == error_perm) temp_qmail(qme.s);
|
||||||
|
if (errno == error_acces) temp_qmail(qme.s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fstat(*fd,&st) == -1) temp_qmail(qme.s);
|
||||||
|
if ((st.st_mode & S_IFMT) == S_IFREG) {
|
||||||
|
if (st.st_mode & auto_patrn)
|
||||||
|
strerr_die1x(111,"Uh-oh: .qmail file is writable. (#4.7.0)");
|
||||||
|
*cutable = !!(st.st_mode & 0100);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
close(*fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "" "": "" */
|
||||||
|
/* "-/" "": "-/" "-/default" */
|
||||||
|
/* "-/" "a": "-/a" "-/default" */
|
||||||
|
/* "-/" "a-": "-/a-" "-/a-default" "-/default" */
|
||||||
|
/* "-/" "a-b": "-/a-b" "-/a-default" "-/default" */
|
||||||
|
/* "-/" "a-b-": "-/a-b-" "-/a-b-default" "-/a-default" "-/default" */
|
||||||
|
/* "-/" "a-b-c": "-/a-b-c" "-/a-b-default" "-/a-default" "-/default" */
|
||||||
|
|
||||||
|
void qmesearch(fd,cutable)
|
||||||
|
int *fd;
|
||||||
|
int *cutable;
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
i = dashext.len;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (!stralloc_copys(&qme,".qmail")) temp_nomem();
|
if (!stralloc_copys(&qme,".qmail")) temp_nomem();
|
||||||
if (!stralloc_catb(&qme,dashext.s,i)) temp_nomem();
|
if (!stralloc_cats(&qme,dash)) temp_nomem();
|
||||||
if (i < dashext.len) if (!stralloc_cats(&qme,"-default")) temp_nomem();
|
if (!stralloc_cat(&qme,&safeext)) temp_nomem();
|
||||||
if (!stralloc_0(&qme)) temp_nomem();
|
if (qmeexists(fd,cutable)) {
|
||||||
fd = open_read(qme.s);
|
if (safeext.len >= 7) {
|
||||||
if (fd == -1)
|
i = safeext.len - 7;
|
||||||
{
|
if (!byte_diff("default",7,safeext.s + i))
|
||||||
if (error_temp(errno)) temp_nfsqmail();
|
if (i <= str_len(ext)) /* paranoia */
|
||||||
if (errno == error_perm) temp_denyqmail();
|
if (!env_put2("DEFAULT",ext + i)) temp_nomem();
|
||||||
if (errno == error_acces) temp_denyqmail();
|
|
||||||
}
|
}
|
||||||
else
|
return;
|
||||||
{
|
|
||||||
if (fstat(fd,&st) == -1) temp_nfsqmail();
|
|
||||||
if ((st.st_mode & S_IFMT) == S_IFREG)
|
|
||||||
{
|
|
||||||
if (st.st_mode & auto_patrn) temp_qmwritable();
|
|
||||||
*cutable = !!(st.st_mode & 0100);
|
|
||||||
return fd;
|
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
|
for (i = safeext.len;i >= 0;--i)
|
||||||
|
if (!i || (safeext.s[i - 1] == '-')) {
|
||||||
|
if (!stralloc_copys(&qme,".qmail")) temp_nomem();
|
||||||
|
if (!stralloc_cats(&qme,dash)) temp_nomem();
|
||||||
|
if (!stralloc_catb(&qme,safeext.s,i)) temp_nomem();
|
||||||
|
if (!stralloc_cats(&qme,"default")) temp_nomem();
|
||||||
|
if (qmeexists(fd,cutable)) {
|
||||||
|
if (i <= str_len(ext)) /* paranoia */
|
||||||
|
if (!env_put2("DEFAULT",ext + i)) temp_nomem();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (!i) return -1;
|
|
||||||
do
|
|
||||||
if (dashext.s[--i] == '-') break;
|
|
||||||
while (i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long count_file = 0;
|
unsigned long count_file = 0;
|
||||||
|
|
@ -446,7 +457,7 @@ char **argv;
|
||||||
char **recips;
|
char **recips;
|
||||||
datetime_sec starttime;
|
datetime_sec starttime;
|
||||||
int flagforwardonly;
|
int flagforwardonly;
|
||||||
char *extx;
|
char *x;
|
||||||
|
|
||||||
umask(077);
|
umask(077);
|
||||||
sig_pipeignore();
|
sig_pipeignore();
|
||||||
|
|
@ -459,9 +470,8 @@ char **argv;
|
||||||
{
|
{
|
||||||
case 'n': flagdoit = 0; break;
|
case 'n': flagdoit = 0; break;
|
||||||
case 'N': flagdoit = 1; break;
|
case 'N': flagdoit = 1; break;
|
||||||
case '?':
|
|
||||||
default:
|
default:
|
||||||
hard();
|
usage();
|
||||||
}
|
}
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
@ -477,7 +487,8 @@ char **argv;
|
||||||
if (*argv) usage();
|
if (*argv) usage();
|
||||||
|
|
||||||
if (homedir[0] != '/') usage();
|
if (homedir[0] != '/') usage();
|
||||||
if (chdir(homedir) == -1) temp_chdir();
|
if (chdir(homedir) == -1)
|
||||||
|
strerr_die5x(111,"Unable to switch to ",homedir,": ",error_str(errno),". (#4.3.0)");
|
||||||
checkhome();
|
checkhome();
|
||||||
|
|
||||||
if (!env_put2("HOST",host)) temp_nomem();
|
if (!env_put2("HOST",host)) temp_nomem();
|
||||||
|
|
@ -542,25 +553,40 @@ char **argv;
|
||||||
if (!stralloc_0(&foo)) temp_nomem();
|
if (!stralloc_0(&foo)) temp_nomem();
|
||||||
if (!env_put2("UFLINE",foo.s)) temp_nomem();
|
if (!env_put2("UFLINE",foo.s)) temp_nomem();
|
||||||
|
|
||||||
if (!stralloc_copys(&dashext,dash)) temp_nomem();
|
x = ext;
|
||||||
if (!stralloc_cats(&dashext,ext)) temp_nomem();
|
if (!env_put2("EXT",x)) temp_nomem();
|
||||||
for (i = 0;i < dashext.len;++i)
|
x += str_chr(x,'-'); if (*x) ++x;
|
||||||
if (dashext.s[i] == '.')
|
if (!env_put2("EXT2",x)) temp_nomem();
|
||||||
dashext.s[i] = ':';
|
x += str_chr(x,'-'); if (*x) ++x;
|
||||||
case_lowerb(dashext.s,dashext.len);
|
if (!env_put2("EXT3",x)) temp_nomem();
|
||||||
|
x += str_chr(x,'-'); if (*x) ++x;
|
||||||
|
if (!env_put2("EXT4",x)) temp_nomem();
|
||||||
|
|
||||||
extx = ext;
|
if (!stralloc_copys(&safeext,ext)) temp_nomem();
|
||||||
if (!env_put2("EXT",extx)) temp_nomem();
|
case_lowerb(safeext.s,safeext.len);
|
||||||
extx += str_chr(extx,'-'); if (*extx) ++extx;
|
for (i = 0;i < safeext.len;++i)
|
||||||
if (!env_put2("EXT2",extx)) temp_nomem();
|
if (safeext.s[i] == '.')
|
||||||
extx += str_chr(extx,'-'); if (*extx) ++extx;
|
safeext.s[i] = ':';
|
||||||
if (!env_put2("EXT3",extx)) temp_nomem();
|
|
||||||
extx += str_chr(extx,'-'); if (*extx) ++extx;
|
i = str_len(host);
|
||||||
if (!env_put2("EXT4",extx)) temp_nomem();
|
i = byte_rchr(host,i,'.');
|
||||||
|
if (!stralloc_copyb(&foo,host,i)) temp_nomem();
|
||||||
|
if (!stralloc_0(&foo)) temp_nomem();
|
||||||
|
if (!env_put2("HOST2",foo.s)) temp_nomem();
|
||||||
|
i = byte_rchr(host,i,'.');
|
||||||
|
if (!stralloc_copyb(&foo,host,i)) temp_nomem();
|
||||||
|
if (!stralloc_0(&foo)) temp_nomem();
|
||||||
|
if (!env_put2("HOST3",foo.s)) temp_nomem();
|
||||||
|
i = byte_rchr(host,i,'.');
|
||||||
|
if (!stralloc_copyb(&foo,host,i)) temp_nomem();
|
||||||
|
if (!stralloc_0(&foo)) temp_nomem();
|
||||||
|
if (!env_put2("HOST4",foo.s)) temp_nomem();
|
||||||
|
|
||||||
flagforwardonly = 0;
|
flagforwardonly = 0;
|
||||||
fd = qmeopen(&flagforwardonly);
|
qmesearch(&fd,&flagforwardonly);
|
||||||
if (fd == -1) if (*dash) bounce_ext();
|
if (fd == -1)
|
||||||
|
if (*dash)
|
||||||
|
strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
|
||||||
|
|
||||||
if (!stralloc_copys(&ueo,sender)) temp_nomem();
|
if (!stralloc_copys(&ueo,sender)) temp_nomem();
|
||||||
if (str_diff(sender,""))
|
if (str_diff(sender,""))
|
||||||
|
|
@ -625,13 +651,13 @@ char **argv;
|
||||||
{
|
{
|
||||||
case 0: /* k == i */
|
case 0: /* k == i */
|
||||||
if (i) break;
|
if (i) break;
|
||||||
temp_blankline();
|
strerr_die1x(111,"Uh-oh: first line of .qmail file is blank. (#4.2.1)");
|
||||||
case '#':
|
case '#':
|
||||||
break;
|
break;
|
||||||
case '.':
|
case '.':
|
||||||
case '/':
|
case '/':
|
||||||
++count_file;
|
++count_file;
|
||||||
if (flagforwardonly) temp_fofile();
|
if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)");
|
||||||
if (cmds.s[k - 1] == '/')
|
if (cmds.s[k - 1] == '/')
|
||||||
if (flagdoit) maildir(cmds.s + i);
|
if (flagdoit) maildir(cmds.s + i);
|
||||||
else sayit("maildir ",cmds.s + i,k - i);
|
else sayit("maildir ",cmds.s + i,k - i);
|
||||||
|
|
@ -641,7 +667,7 @@ char **argv;
|
||||||
break;
|
break;
|
||||||
case '|':
|
case '|':
|
||||||
++count_program;
|
++count_program;
|
||||||
if (flagforwardonly) temp_foprog();
|
if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)");
|
||||||
if (flagdoit) mailprogram(cmds.s + i + 1);
|
if (flagdoit) mailprogram(cmds.s + i + 1);
|
||||||
else sayit("program ",cmds.s + i + 1,k - i - 1);
|
else sayit("program ",cmds.s + i + 1,k - i - 1);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
35
qmail-log.5
35
qmail-log.5
|
|
@ -5,31 +5,22 @@ qmail-log \- the qmail activity record
|
||||||
.B qmail-send
|
.B qmail-send
|
||||||
prints a series of lines describing its activities.
|
prints a series of lines describing its activities.
|
||||||
Each possible line is described below.
|
Each possible line is described below.
|
||||||
.SH "STARTING AND STOPPING"
|
.SH "STATUS"
|
||||||
.TP
|
.TP
|
||||||
.B running
|
.B status: local \fIl\fB/\fIL\fB remote \fIr\fB/\fIR\fB ...
|
||||||
.B qmail-send
|
.B qmail-send
|
||||||
is ready to deliver messages.
|
is waiting for
|
||||||
|
.I l
|
||||||
|
local deliveries
|
||||||
|
and
|
||||||
|
.I r
|
||||||
|
remote deliveries.
|
||||||
|
The concurrency limits are
|
||||||
|
.I L
|
||||||
|
and
|
||||||
|
.IR R .
|
||||||
.TP
|
.TP
|
||||||
.B local deliveries will be put on hold
|
.B status: exiting
|
||||||
The local concurrency limit is 0, so
|
|
||||||
.B qmail-send
|
|
||||||
will not perform any local deliveries.
|
|
||||||
.TP
|
|
||||||
.B remote deliveries will be put on hold
|
|
||||||
The remote concurrency limit is 0, so
|
|
||||||
.B qmail-send
|
|
||||||
will not perform any remote deliveries.
|
|
||||||
.TP
|
|
||||||
.B number of deliveries left before exiting: ...
|
|
||||||
.B qmail-send
|
|
||||||
wants to exit as soon as possible,
|
|
||||||
usually because it was sent a
|
|
||||||
TERM signal,
|
|
||||||
but it has to wait for some deliveries to finish.
|
|
||||||
It will not start any new deliveries.
|
|
||||||
.TP
|
|
||||||
.B exiting
|
|
||||||
.B qmail-send
|
.B qmail-send
|
||||||
is done.
|
is done.
|
||||||
.SH "FATAL PROBLEMS"
|
.SH "FATAL PROBLEMS"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
qmail-lspawn \- schedule local deliveries
|
qmail-lspawn \- schedule local deliveries
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B qmail-lspawn
|
.B qmail-lspawn
|
||||||
.I aliasempty
|
.I defaultdelivery
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B qmail-lspawn
|
.B qmail-lspawn
|
||||||
reads a series of local delivery commands from descriptor 0,
|
reads a series of local delivery commands from descriptor 0,
|
||||||
|
|
@ -12,7 +12,7 @@ invokes
|
||||||
to perform the deliveries,
|
to perform the deliveries,
|
||||||
and prints the results to descriptor 1.
|
and prints the results to descriptor 1.
|
||||||
It passes
|
It passes
|
||||||
.I aliasempty
|
.I defaultdelivery
|
||||||
to
|
to
|
||||||
.B qmail-local
|
.B qmail-local
|
||||||
as the default delivery instruction.
|
as the default delivery instruction.
|
||||||
|
|
|
||||||
41
qmail-newmrh.9
Normal file
41
qmail-newmrh.9
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
.TH qmail-newmrh 8
|
||||||
|
.SH NAME
|
||||||
|
qmail-newmrh \- prepare morercpthosts for qmail-smtpd
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B qmail-newmrh
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B qmail-newmrh
|
||||||
|
reads the instructions in
|
||||||
|
.B QMAILHOME/control/morercpthosts
|
||||||
|
and writes them into
|
||||||
|
.B QMAILHOME/control/morercpthosts.cdb
|
||||||
|
in a binary format suited
|
||||||
|
for quick access by
|
||||||
|
.BR qmail-smtpd .
|
||||||
|
|
||||||
|
If there is a problem with
|
||||||
|
.BR control/morercpthosts ,
|
||||||
|
.B qmail-newmrh
|
||||||
|
complains and leaves
|
||||||
|
.B control/morercpthosts.cdb
|
||||||
|
alone.
|
||||||
|
|
||||||
|
.B qmail-newmrh
|
||||||
|
ensures that
|
||||||
|
.B control/morercpthosts.cdb
|
||||||
|
is updated atomically,
|
||||||
|
so
|
||||||
|
.B qmail-smtpd
|
||||||
|
never has to wait for
|
||||||
|
.B qmail-newmrh
|
||||||
|
to finish.
|
||||||
|
However,
|
||||||
|
.B qmail-newmrh
|
||||||
|
makes no attempt to protect against two simultaneous updates of
|
||||||
|
.BR control/morercpthosts.cdb .
|
||||||
|
|
||||||
|
The binary
|
||||||
|
.B control/morercpthosts.cdb
|
||||||
|
format is portable across machines.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
qmail-smtpd(8)
|
||||||
70
qmail-newmrh.c
Normal file
70
qmail-newmrh.c
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include "strerr.h"
|
||||||
|
#include "stralloc.h"
|
||||||
|
#include "substdio.h"
|
||||||
|
#include "getln.h"
|
||||||
|
#include "exit.h"
|
||||||
|
#include "readwrite.h"
|
||||||
|
#include "open.h"
|
||||||
|
#include "auto_qmail.h"
|
||||||
|
#include "cdbmss.h"
|
||||||
|
|
||||||
|
#define FATAL "qmail-newmrh: fatal: "
|
||||||
|
|
||||||
|
void die_read()
|
||||||
|
{
|
||||||
|
strerr_die2sys(111,FATAL,"unable to read control/morercpthosts: ");
|
||||||
|
}
|
||||||
|
void die_write()
|
||||||
|
{
|
||||||
|
strerr_die2sys(111,FATAL,"unable to write to control/morercpthosts.tmp: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
char inbuf[1024];
|
||||||
|
substdio ssin;
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
int fdtemp;
|
||||||
|
|
||||||
|
struct cdbmss cdbmss;
|
||||||
|
stralloc line = {0};
|
||||||
|
int match;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
umask(033);
|
||||||
|
if (chdir(auto_qmail) == -1)
|
||||||
|
strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": ");
|
||||||
|
|
||||||
|
fd = open_read("control/morercpthosts");
|
||||||
|
if (fd == -1) die_read();
|
||||||
|
|
||||||
|
substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf);
|
||||||
|
|
||||||
|
fdtemp = open_trunc("control/morercpthosts.tmp");
|
||||||
|
if (fdtemp == -1) die_write();
|
||||||
|
|
||||||
|
if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (getln(&ssin,&line,&match,'\n') != 0) die_read();
|
||||||
|
case_lowerb(line.s,line.len);
|
||||||
|
while (line.len) {
|
||||||
|
if (line.s[line.len - 1] == ' ') { --line.len; continue; }
|
||||||
|
if (line.s[line.len - 1] == '\n') { --line.len; continue; }
|
||||||
|
if (line.s[line.len - 1] == '\t') { --line.len; continue; }
|
||||||
|
if (line.s[0] != '#')
|
||||||
|
if (cdbmss_add(&cdbmss,line.s,line.len,"",0) == -1)
|
||||||
|
die_write();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!match) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdbmss_finish(&cdbmss) == -1) die_write();
|
||||||
|
if (fsync(fdtemp) == -1) die_write();
|
||||||
|
if (close(fdtemp) == -1) die_write(); /* NFS stupidity */
|
||||||
|
if (rename("control/morercpthosts.tmp","control/morercpthosts.cdb") == -1)
|
||||||
|
strerr_die2sys(111,FATAL,"unable to move control/morercpthosts.tmp to control/morercpthosts.cdb");
|
||||||
|
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ which checks the password and sets up environment variables.
|
||||||
has a 20-minute idle timeout.
|
has a 20-minute idle timeout.
|
||||||
|
|
||||||
.B qmail-pop3d
|
.B qmail-pop3d
|
||||||
supports UIDL and TOP.
|
supports UIDL, TOP, and LAST.
|
||||||
|
|
||||||
.B qmail-pop3d
|
.B qmail-pop3d
|
||||||
appends an extra blank line to every message
|
appends an extra blank line to every message
|
||||||
|
|
|
||||||
344
qmail-pop3d.c
344
qmail-pop3d.c
|
|
@ -1,60 +1,69 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "direntry.h"
|
#include "commands.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "getln.h"
|
#include "getln.h"
|
||||||
#include "stralloc.h"
|
#include "stralloc.h"
|
||||||
#include "substdio.h"
|
#include "substdio.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "datetime.h"
|
|
||||||
#include "prot.h"
|
|
||||||
#include "open.h"
|
#include "open.h"
|
||||||
#include "prioq.h"
|
#include "prioq.h"
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "error.h"
|
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "exit.h"
|
#include "exit.h"
|
||||||
#include "now.h"
|
#include "maildir.h"
|
||||||
#include "readwrite.h"
|
#include "readwrite.h"
|
||||||
|
#include "timeoutread.h"
|
||||||
int timeout = 1200;
|
#include "timeoutwrite.h"
|
||||||
|
|
||||||
char ssoutbuf[1024];
|
|
||||||
substdio ssout = SUBSTDIO_FDBUF(write,1,ssoutbuf,sizeof(ssoutbuf));
|
|
||||||
|
|
||||||
int timeoutread(fd,buf,n) int fd; char *buf; int n;
|
|
||||||
{
|
|
||||||
int r; int saveerrno;
|
|
||||||
alarm(timeout);
|
|
||||||
r = read(fd,buf,n); saveerrno = errno;
|
|
||||||
alarm(0);
|
|
||||||
errno = saveerrno; return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
char ssinbuf[128];
|
|
||||||
substdio ssin = SUBSTDIO_FDBUF(timeoutread,0,ssinbuf,sizeof(ssinbuf));
|
|
||||||
|
|
||||||
|
|
||||||
void die() { _exit(0); }
|
void die() { _exit(0); }
|
||||||
|
|
||||||
|
int saferead(fd,buf,len) int fd; char *buf; int len;
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = timeoutread(1200,fd,buf,len);
|
||||||
|
if (r <= 0) die();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int safewrite(fd,buf,len) int fd; char *buf; int len;
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = timeoutwrite(1200,fd,buf,len);
|
||||||
|
if (r <= 0) die();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ssoutbuf[1024];
|
||||||
|
substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
|
||||||
|
|
||||||
|
char ssinbuf[128];
|
||||||
|
substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
|
||||||
|
|
||||||
|
void put(buf,len) char *buf; int len;
|
||||||
|
{
|
||||||
|
substdio_put(&ssout,buf,len);
|
||||||
|
}
|
||||||
void puts(s) char *s;
|
void puts(s) char *s;
|
||||||
{
|
{
|
||||||
if (substdio_puts(&ssout,s) == -1) die();
|
substdio_puts(&ssout,s);
|
||||||
}
|
}
|
||||||
void flush()
|
void flush()
|
||||||
{
|
{
|
||||||
if (substdio_flush(&ssout) == -1) die();
|
substdio_flush(&ssout);
|
||||||
}
|
}
|
||||||
void err(s) char *s;
|
void err(s) char *s;
|
||||||
{
|
{
|
||||||
puts("-ERR ");
|
puts("-ERR ");
|
||||||
puts(s);
|
puts(s);
|
||||||
puts("\r\n");
|
puts("\r\n");
|
||||||
if (substdio_flush(&ssout) == -1) die();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void die_nomem() { err("out of memory"); die(); }
|
void die_nomem() { err("out of memory"); die(); }
|
||||||
void die_prot() { err("protection problem"); die(); }
|
|
||||||
void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); }
|
void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); }
|
||||||
|
void die_scan() { err("unable to scan $HOME/Maildir"); die(); }
|
||||||
|
|
||||||
void err_syntax() { err("syntax error"); }
|
void err_syntax() { err("syntax error"); }
|
||||||
void err_unimpl() { err("unimplemented"); }
|
void err_unimpl() { err("unimplemented"); }
|
||||||
|
|
@ -65,26 +74,15 @@ void err_nosuch() { err("unable to open that message"); }
|
||||||
void err_nounlink() { err("unable to unlink all deleted messages"); }
|
void err_nounlink() { err("unable to unlink all deleted messages"); }
|
||||||
|
|
||||||
void okay() { puts("+OK \r\n"); flush(); }
|
void okay() { puts("+OK \r\n"); flush(); }
|
||||||
void pop3_last() { puts("+OK 0\r\n"); flush(); }
|
|
||||||
|
|
||||||
|
void printfn(fn) char *fn;
|
||||||
|
{
|
||||||
|
fn += 4;
|
||||||
|
put(fn,str_chr(fn,':'));
|
||||||
|
}
|
||||||
|
|
||||||
stralloc dataline = {0};
|
char strnum[FMT_ULONG];
|
||||||
|
stralloc line = {0};
|
||||||
stralloc filenames = {0};
|
|
||||||
prioq pq = {0};
|
|
||||||
stralloc newname = {0};
|
|
||||||
|
|
||||||
struct message
|
|
||||||
{
|
|
||||||
int flagdeleted;
|
|
||||||
unsigned long size;
|
|
||||||
char *fn;
|
|
||||||
}
|
|
||||||
*m;
|
|
||||||
int numm;
|
|
||||||
|
|
||||||
substdio ssmsg; char ssmsgbuf[1024];
|
|
||||||
|
|
||||||
|
|
||||||
void blast(ssfrom,limit)
|
void blast(ssfrom,limit)
|
||||||
substdio *ssfrom;
|
substdio *ssfrom;
|
||||||
|
|
@ -93,104 +91,50 @@ unsigned long limit;
|
||||||
int match;
|
int match;
|
||||||
int inheaders = 1;
|
int inheaders = 1;
|
||||||
|
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
if (getln(ssfrom,&line,&match,'\n') != 0) die();
|
||||||
if (getln(ssfrom,&dataline,&match,'\n') != 0) die();
|
if (!match && !line.len) break;
|
||||||
if (!match && !dataline.len) break;
|
if (match) --line.len; /* no way to pass this info over POP */
|
||||||
if (match) --dataline.len; /* no way to pass this info over POP */
|
|
||||||
if (limit) if (!inheaders) if (!--limit) break;
|
if (limit) if (!inheaders) if (!--limit) break;
|
||||||
if (!dataline.len)
|
if (!line.len)
|
||||||
inheaders = 0;
|
inheaders = 0;
|
||||||
else
|
else
|
||||||
if (dataline.s[0] == '.')
|
if (line.s[0] == '.')
|
||||||
substdio_put(&ssout,".",1);
|
put(".",1);
|
||||||
if (substdio_put(&ssout,dataline.s,dataline.len) == -1) die();
|
put(line.s,line.len);
|
||||||
if (substdio_put(&ssout,"\r\n",2) == -1) die();
|
put("\r\n",2);
|
||||||
if (!match) break;
|
if (!match) break;
|
||||||
}
|
}
|
||||||
if (substdio_put(&ssout,"\r\n.\r\n",5) == -1) die();
|
put("\r\n.\r\n",5);
|
||||||
if (substdio_flush(&ssout) == -1) die();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stralloc filenames = {0};
|
||||||
|
prioq pq = {0};
|
||||||
|
|
||||||
|
struct message {
|
||||||
|
int flagdeleted;
|
||||||
|
unsigned long size;
|
||||||
|
char *fn;
|
||||||
|
} *m;
|
||||||
|
int numm;
|
||||||
|
|
||||||
|
int last = 0;
|
||||||
|
|
||||||
void getlist()
|
void getlist()
|
||||||
{
|
{
|
||||||
unsigned long pos;
|
|
||||||
datetime_sec time;
|
|
||||||
DIR *dir;
|
|
||||||
direntry *d;
|
|
||||||
struct prioq_elt pe;
|
struct prioq_elt pe;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
numm = 0;
|
maildir_clean(&line);
|
||||||
|
if (maildir_scan(&pq,&filenames,1,1) == -1) die_scan();
|
||||||
time = now();
|
|
||||||
|
|
||||||
if (dir = opendir("tmp"))
|
|
||||||
{
|
|
||||||
while (d = readdir(dir))
|
|
||||||
{
|
|
||||||
if (str_equal(d->d_name,".")) continue;
|
|
||||||
if (str_equal(d->d_name,"..")) continue;
|
|
||||||
if (!stralloc_copys(&newname,"tmp/")) die_nomem();
|
|
||||||
if (!stralloc_cats(&newname,d->d_name)) die_nomem();
|
|
||||||
if (!stralloc_0(&newname)) die_nomem();
|
|
||||||
if (stat(newname.s,&st) == 0)
|
|
||||||
if (time > st.st_atime + 129600)
|
|
||||||
unlink(newname.s);
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stralloc_copys(&filenames,"")) die_nomem();
|
|
||||||
|
|
||||||
if (dir = opendir("new"))
|
|
||||||
{
|
|
||||||
while (d = readdir(dir))
|
|
||||||
{
|
|
||||||
if (str_equal(d->d_name,".")) continue;
|
|
||||||
if (str_equal(d->d_name,"..")) continue;
|
|
||||||
pos = filenames.len;
|
|
||||||
if (!stralloc_cats(&filenames,"new/")) die_nomem();
|
|
||||||
if (!stralloc_cats(&filenames,d->d_name)) die_nomem();
|
|
||||||
if (!stralloc_0(&filenames)) die_nomem();
|
|
||||||
if (stat(filenames.s + pos,&st) == 0)
|
|
||||||
{
|
|
||||||
pe.dt = st.st_mtime;
|
|
||||||
pe.id = pos;
|
|
||||||
if (!prioq_insert(&pq,&pe)) die_nomem();
|
|
||||||
++numm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir = opendir("cur"))
|
|
||||||
{
|
|
||||||
while (d = readdir(dir))
|
|
||||||
{
|
|
||||||
if (str_equal(d->d_name,".")) continue;
|
|
||||||
if (str_equal(d->d_name,"..")) continue;
|
|
||||||
pos = filenames.len;
|
|
||||||
if (!stralloc_cats(&filenames,"cur/")) die_nomem();
|
|
||||||
if (!stralloc_cats(&filenames,d->d_name)) die_nomem();
|
|
||||||
if (!stralloc_0(&filenames)) die_nomem();
|
|
||||||
if (stat(filenames.s + pos,&st) == 0)
|
|
||||||
{
|
|
||||||
pe.dt = st.st_mtime;
|
|
||||||
pe.id = pos;
|
|
||||||
if (!prioq_insert(&pq,&pe)) die_nomem();
|
|
||||||
++numm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
numm = pq.p ? pq.len : 0;
|
||||||
m = (struct message *) alloc(numm * sizeof(struct message));
|
m = (struct message *) alloc(numm * sizeof(struct message));
|
||||||
if (!m) die_nomem();
|
if (!m) die_nomem();
|
||||||
|
|
||||||
for (i = 0;i < numm;++i)
|
for (i = 0;i < numm;++i) {
|
||||||
{
|
|
||||||
if (!prioq_min(&pq,&pe)) { numm = i; break; }
|
if (!prioq_min(&pq,&pe)) { numm = i; break; }
|
||||||
prioq_delmin(&pq);
|
prioq_delmin(&pq);
|
||||||
m[i].fn = filenames.s + pe.id;
|
m[i].fn = filenames.s + pe.id;
|
||||||
|
|
@ -202,28 +146,6 @@ void getlist()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char foo[FMT_ULONG];
|
|
||||||
|
|
||||||
void printint(u) unsigned int u;
|
|
||||||
{
|
|
||||||
foo[fmt_uint(foo,u)] = 0;
|
|
||||||
puts(foo);
|
|
||||||
puts(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printlong(u) unsigned long u;
|
|
||||||
{
|
|
||||||
foo[fmt_uint(foo,u)] = 0;
|
|
||||||
puts(foo);
|
|
||||||
puts("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printfn(fn) char *fn;
|
|
||||||
{
|
|
||||||
puts(fn + 4);
|
|
||||||
puts("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop3_stat()
|
void pop3_stat()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -232,8 +154,10 @@ void pop3_stat()
|
||||||
total = 0;
|
total = 0;
|
||||||
for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
|
for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
|
||||||
puts("+OK ");
|
puts("+OK ");
|
||||||
printint(numm);
|
put(strnum,fmt_uint(strnum,numm));
|
||||||
printlong(total);
|
puts(" ");
|
||||||
|
put(strnum,fmt_ulong(strnum,total));
|
||||||
|
puts("\r\n");
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,15 +165,33 @@ void pop3_rset()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0;i < numm;++i) m[i].flagdeleted = 0;
|
for (i = 0;i < numm;++i) m[i].flagdeleted = 0;
|
||||||
|
last = 0;
|
||||||
okay();
|
okay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pop3_last()
|
||||||
|
{
|
||||||
|
puts("+OK ");
|
||||||
|
put(strnum,fmt_uint(strnum,last));
|
||||||
|
puts("\r\n");
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
void pop3_quit()
|
void pop3_quit()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0;i < numm;++i)
|
for (i = 0;i < numm;++i)
|
||||||
if (m[i].flagdeleted)
|
if (m[i].flagdeleted) {
|
||||||
if (unlink(m[i].fn) == -1) err_nounlink();
|
if (unlink(m[i].fn) == -1) err_nounlink();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (str_start(m[i].fn,"new/")) {
|
||||||
|
if (!stralloc_copys(&line,"cur/")) die_nomem();
|
||||||
|
if (!stralloc_cats(&line,m[i].fn + 4)) die_nomem();
|
||||||
|
if (!stralloc_cats(&line,":2,")) die_nomem();
|
||||||
|
if (!stralloc_0(&line)) die_nomem();
|
||||||
|
rename(m[i].fn,line.s); /* if it fails, bummer */
|
||||||
|
}
|
||||||
okay();
|
okay();
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +199,6 @@ void pop3_quit()
|
||||||
int msgno(arg) char *arg;
|
int msgno(arg) char *arg;
|
||||||
{
|
{
|
||||||
unsigned long u;
|
unsigned long u;
|
||||||
if (!arg) { err_syntax(); return -1; }
|
|
||||||
if (!scan_ulong(arg,&u)) { err_syntax(); return -1; }
|
if (!scan_ulong(arg,&u)) { err_syntax(); return -1; }
|
||||||
if (!u) { err_nozero(); return -1; }
|
if (!u) { err_nozero(); return -1; }
|
||||||
--u;
|
--u;
|
||||||
|
|
@ -269,35 +210,38 @@ int msgno(arg) char *arg;
|
||||||
void pop3_dele(arg) char *arg;
|
void pop3_dele(arg) char *arg;
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
i = msgno(arg);
|
i = msgno(arg);
|
||||||
if (i == -1) return;
|
if (i == -1) return;
|
||||||
m[i].flagdeleted = 1;
|
m[i].flagdeleted = 1;
|
||||||
|
if (i + 1 > last) last = i + 1;
|
||||||
okay();
|
okay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void list(i,flaguidl)
|
||||||
|
int i;
|
||||||
|
int flaguidl;
|
||||||
|
{
|
||||||
|
put(strnum,fmt_uint(strnum,i + 1));
|
||||||
|
puts(" ");
|
||||||
|
if (flaguidl) printfn(m[i].fn);
|
||||||
|
else put(strnum,fmt_ulong(strnum,m[i].size));
|
||||||
|
puts("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
void dolisting(arg,flaguidl) char *arg; int flaguidl;
|
void dolisting(arg,flaguidl) char *arg; int flaguidl;
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
if (*arg) {
|
||||||
if (arg)
|
|
||||||
{
|
|
||||||
i = msgno(arg);
|
i = msgno(arg);
|
||||||
if (i == -1) return;
|
if (i == -1) return;
|
||||||
puts("+OK ");
|
puts("+OK ");
|
||||||
printint(i + 1);
|
list(i,flaguidl);
|
||||||
if (flaguidl) printfn(m[i].fn); else printlong(m[i].size);
|
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
okay();
|
okay();
|
||||||
|
|
||||||
for (i = 0;i < numm;++i)
|
for (i = 0;i < numm;++i)
|
||||||
if (!m[i].flagdeleted)
|
if (!m[i].flagdeleted)
|
||||||
{
|
list(i,flaguidl);
|
||||||
printint(i + 1);
|
|
||||||
if (flaguidl) printfn(m[i].fn); else printlong(m[i].size);
|
|
||||||
}
|
|
||||||
puts(".\r\n");
|
puts(".\r\n");
|
||||||
}
|
}
|
||||||
flush();
|
flush();
|
||||||
|
|
@ -306,6 +250,8 @@ void dolisting(arg,flaguidl) char *arg; int flaguidl;
|
||||||
void pop3_uidl(arg) char *arg; { dolisting(arg,1); }
|
void pop3_uidl(arg) char *arg; { dolisting(arg,1); }
|
||||||
void pop3_list(arg) char *arg; { dolisting(arg,0); }
|
void pop3_list(arg) char *arg; { dolisting(arg,0); }
|
||||||
|
|
||||||
|
substdio ssmsg; char ssmsgbuf[1024];
|
||||||
|
|
||||||
void pop3_top(arg) char *arg;
|
void pop3_top(arg) char *arg;
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -327,53 +273,24 @@ void pop3_top(arg) char *arg;
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct { void (*fun)(); char *text; } pop3cmd[] = {
|
struct commands pop3commands[] = {
|
||||||
{ pop3_quit, "quit" }
|
{ "quit", pop3_quit, 0 }
|
||||||
, { pop3_stat, "stat" }
|
, { "stat", pop3_stat, 0 }
|
||||||
, { pop3_list, "list" }
|
, { "list", pop3_list, 0 }
|
||||||
, { pop3_uidl, "uidl" }
|
, { "uidl", pop3_uidl, 0 }
|
||||||
, { pop3_dele, "dele" }
|
, { "dele", pop3_dele, 0 }
|
||||||
, { pop3_top, "retr" }
|
, { "retr", pop3_top, 0 }
|
||||||
, { pop3_rset, "rset" }
|
, { "rset", pop3_rset, 0 }
|
||||||
, { pop3_last, "last" }
|
, { "last", pop3_last, 0 }
|
||||||
, { pop3_top, "top" }
|
, { "top", pop3_top, 0 }
|
||||||
, { okay, "noop" }
|
, { "noop", okay, 0 }
|
||||||
, { 0, 0 }
|
, { 0, err_unimpl, 0 }
|
||||||
};
|
} ;
|
||||||
|
|
||||||
void doit(cmd)
|
|
||||||
char *cmd;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
for (i = 0;pop3cmd[i].fun;++i)
|
|
||||||
{
|
|
||||||
for (j = 0;ch = pop3cmd[i].text[j];++j)
|
|
||||||
if ((cmd[j] != ch) && (cmd[j] != ch - 32))
|
|
||||||
break;
|
|
||||||
if (!ch)
|
|
||||||
if (!cmd[j] || (cmd[j] == ' '))
|
|
||||||
{
|
|
||||||
while (cmd[j] == ' ') ++j;
|
|
||||||
if (!cmd[j])
|
|
||||||
pop3cmd[i].fun((char *) 0);
|
|
||||||
else
|
|
||||||
pop3cmd[i].fun(cmd + j);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err_unimpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(argc,argv)
|
void main(argc,argv)
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
{
|
{
|
||||||
static stralloc cmd = {0};
|
|
||||||
int match;
|
|
||||||
|
|
||||||
sig_alarmcatch(die);
|
sig_alarmcatch(die);
|
||||||
sig_pipeignore();
|
sig_pipeignore();
|
||||||
|
|
||||||
|
|
@ -383,15 +300,6 @@ char **argv;
|
||||||
getlist();
|
getlist();
|
||||||
|
|
||||||
okay();
|
okay();
|
||||||
|
commands(&ssin,pop3commands);
|
||||||
for (;;)
|
die();
|
||||||
{
|
|
||||||
if (getln(&ssin,&cmd,&match,'\n') == -1) die();
|
|
||||||
if (!match) die();
|
|
||||||
if (cmd.len == 0) die();
|
|
||||||
if (cmd.s[--cmd.len] != '\n') die();
|
|
||||||
if ((cmd.len > 0) && (cmd.s[cmd.len - 1] == '\r')) --cmd.len;
|
|
||||||
cmd.s[cmd.len++] = 0;
|
|
||||||
doit(cmd.s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
154
qmail-popup.c
154
qmail-popup.c
|
|
@ -1,53 +1,59 @@
|
||||||
#include <sys/types.h>
|
#include "commands.h"
|
||||||
#include <sys/stat.h>
|
|
||||||
#include "fd.h"
|
#include "fd.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "getln.h"
|
|
||||||
#include "stralloc.h"
|
#include "stralloc.h"
|
||||||
#include "substdio.h"
|
#include "substdio.h"
|
||||||
#include "subfd.h"
|
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "datetime.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "wait.h"
|
#include "wait.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
|
#include "byte.h"
|
||||||
#include "now.h"
|
#include "now.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "exit.h"
|
#include "exit.h"
|
||||||
#include "readwrite.h"
|
#include "readwrite.h"
|
||||||
|
#include "timeoutread.h"
|
||||||
int timeout = 1200;
|
#include "timeoutwrite.h"
|
||||||
|
|
||||||
int timeoutread(fd,buf,n) int fd; char *buf; int n;
|
|
||||||
{
|
|
||||||
int r; int saveerrno;
|
|
||||||
alarm(timeout);
|
|
||||||
r = read(fd,buf,n); saveerrno = errno;
|
|
||||||
alarm(0);
|
|
||||||
errno = saveerrno; return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
char ssinbuf[128];
|
|
||||||
substdio ssin = SUBSTDIO_FDBUF(timeoutread,0,ssinbuf,sizeof(ssinbuf));
|
|
||||||
|
|
||||||
|
|
||||||
void die() { _exit(1); }
|
void die() { _exit(1); }
|
||||||
void out(s) char *s;
|
|
||||||
|
int saferead(fd,buf,len) int fd; char *buf; int len;
|
||||||
{
|
{
|
||||||
if (substdio_puts(subfdoutsmall,s) == -1) die();
|
int r;
|
||||||
|
r = timeoutread(1200,fd,buf,len);
|
||||||
|
if (r <= 0) die();
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
void outflush(s) char *s;
|
|
||||||
|
int safewrite(fd,buf,len) int fd; char *buf; int len;
|
||||||
{
|
{
|
||||||
out(s);
|
int r;
|
||||||
if (substdio_flush(subfdoutsmall) == -1) die();
|
r = timeoutwrite(1200,fd,buf,len);
|
||||||
|
if (r <= 0) die();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ssoutbuf[128];
|
||||||
|
substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
|
||||||
|
|
||||||
|
char ssinbuf[128];
|
||||||
|
substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
|
||||||
|
|
||||||
|
void puts(s) char *s;
|
||||||
|
{
|
||||||
|
substdio_puts(&ssout,s);
|
||||||
|
}
|
||||||
|
void flush()
|
||||||
|
{
|
||||||
|
substdio_flush(&ssout);
|
||||||
}
|
}
|
||||||
void err(s) char *s;
|
void err(s) char *s;
|
||||||
{
|
{
|
||||||
if (substdio_puts(subfdoutsmall,"-ERR ") == -1) die();
|
puts("-ERR ");
|
||||||
if (substdio_puts(subfdoutsmall,s) == -1) die();
|
puts(s);
|
||||||
if (substdio_puts(subfdoutsmall,"\r\n") == -1) die();
|
puts("\r\n");
|
||||||
if (substdio_flush(subfdoutsmall) == -1) die();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void die_usage() { err("usage: popup hostname subprogram"); die(); }
|
void die_usage() { err("usage: popup hostname subprogram"); die(); }
|
||||||
void die_nomem() { err("out of memory"); die(); }
|
void die_nomem() { err("out of memory"); die(); }
|
||||||
void die_pipe() { err("unable to open pipe"); die(); }
|
void die_pipe() { err("unable to open pipe"); die(); }
|
||||||
|
|
@ -60,7 +66,8 @@ void err_syntax() { err("syntax error"); }
|
||||||
void err_wantuser() { err("USER first"); }
|
void err_wantuser() { err("USER first"); }
|
||||||
void err_authoriz() { err("authorization first"); }
|
void err_authoriz() { err("authorization first"); }
|
||||||
|
|
||||||
void okay() { outflush("+OK \r\n"); }
|
void okay() { puts("+OK \r\n"); flush(); }
|
||||||
|
void pop3_quit() { okay(); die(); }
|
||||||
|
|
||||||
|
|
||||||
char unique[FMT_ULONG + FMT_ULONG + 3];
|
char unique[FMT_ULONG + FMT_ULONG + 3];
|
||||||
|
|
@ -80,14 +87,12 @@ char *pass;
|
||||||
int child;
|
int child;
|
||||||
int wstat;
|
int wstat;
|
||||||
int pi[2];
|
int pi[2];
|
||||||
int i;
|
|
||||||
|
|
||||||
if (fd_copy(2,1) == -1) die_pipe();
|
if (fd_copy(2,1) == -1) die_pipe();
|
||||||
close(3);
|
close(3);
|
||||||
if (pipe(pi) == -1) die_pipe();
|
if (pipe(pi) == -1) die_pipe();
|
||||||
if (pi[0] != 3) die_pipe();
|
if (pi[0] != 3) die_pipe();
|
||||||
switch(child = fork())
|
switch(child = fork()) {
|
||||||
{
|
|
||||||
case -1:
|
case -1:
|
||||||
die_fork();
|
die_fork();
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -97,7 +102,7 @@ char *pass;
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
close(pi[0]);
|
close(pi[0]);
|
||||||
substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof(upbuf));
|
substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf);
|
||||||
if (substdio_put(&ssup,user,userlen) == -1) die_write();
|
if (substdio_put(&ssup,user,userlen) == -1) die_write();
|
||||||
if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) die_write();
|
if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) die_write();
|
||||||
if (substdio_puts(&ssup,"<") == -1) die_write();
|
if (substdio_puts(&ssup,"<") == -1) die_write();
|
||||||
|
|
@ -106,8 +111,8 @@ char *pass;
|
||||||
if (substdio_put(&ssup,">",2) == -1) die_write();
|
if (substdio_put(&ssup,">",2) == -1) die_write();
|
||||||
if (substdio_flush(&ssup) == -1) die_write();
|
if (substdio_flush(&ssup) == -1) die_write();
|
||||||
close(pi[1]);
|
close(pi[1]);
|
||||||
for (i = 0;pass[i];++i) pass[i] = 0;
|
byte_zero(pass,str_len(pass));
|
||||||
for (i = 0;i < sizeof(upbuf);++i) upbuf[i] = 0;
|
byte_zero(upbuf,sizeof upbuf);
|
||||||
if (wait_pid(&wstat,child) == -1) die();
|
if (wait_pid(&wstat,child) == -1) die();
|
||||||
if (wait_crashed(wstat)) die_childcrashed();
|
if (wait_crashed(wstat)) die_childcrashed();
|
||||||
if (wait_exitcode(wstat)) die_badauth();
|
if (wait_exitcode(wstat)) die_badauth();
|
||||||
|
|
@ -122,15 +127,15 @@ void pop3_greet()
|
||||||
s += fmt_ulong(s,(unsigned long) now());
|
s += fmt_ulong(s,(unsigned long) now());
|
||||||
*s++ = '@';
|
*s++ = '@';
|
||||||
*s++ = 0;
|
*s++ = 0;
|
||||||
|
puts("+OK <");
|
||||||
out("+OK <");
|
puts(unique);
|
||||||
out(unique);
|
puts(hostname);
|
||||||
out(hostname);
|
puts(">\r\n");
|
||||||
outflush(">\r\n");
|
flush();
|
||||||
}
|
}
|
||||||
void pop3_user(arg) char *arg;
|
void pop3_user(arg) char *arg;
|
||||||
{
|
{
|
||||||
if (!arg) { err_syntax(); return; }
|
if (!*arg) { err_syntax(); return; }
|
||||||
okay();
|
okay();
|
||||||
seenuser = 1;
|
seenuser = 1;
|
||||||
if (!stralloc_copys(&username,arg)) die_nomem();
|
if (!stralloc_copys(&username,arg)) die_nomem();
|
||||||
|
|
@ -139,63 +144,31 @@ void pop3_user(arg) char *arg;
|
||||||
void pop3_pass(arg) char *arg;
|
void pop3_pass(arg) char *arg;
|
||||||
{
|
{
|
||||||
if (!seenuser) { err_wantuser(); return; }
|
if (!seenuser) { err_wantuser(); return; }
|
||||||
if (!arg) { err_syntax(); return; }
|
if (!*arg) { err_syntax(); return; }
|
||||||
doanddie(username.s,username.len,arg);
|
doanddie(username.s,username.len,arg);
|
||||||
}
|
}
|
||||||
void pop3_apop(arg) char *arg;
|
void pop3_apop(arg) char *arg;
|
||||||
{
|
{
|
||||||
char *space;
|
char *space;
|
||||||
if (!arg) { err_syntax(); return; }
|
|
||||||
space = arg + str_chr(arg,' ');
|
space = arg + str_chr(arg,' ');
|
||||||
if (!*space) { err_syntax(); return; }
|
if (!*space) { err_syntax(); return; }
|
||||||
*space++ = 0;
|
*space++ = 0;
|
||||||
doanddie(arg,space - arg,space);
|
doanddie(arg,space - arg,space);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop3_quit() { okay(); die(); }
|
struct commands pop3commands[] = {
|
||||||
|
{ "user", pop3_user, 0 }
|
||||||
static struct { void (*fun)(); char *text; } pop3cmd[] = {
|
, { "pass", pop3_pass, 0 }
|
||||||
{ pop3_user, "user" }
|
, { "apop", pop3_apop, 0 }
|
||||||
, { pop3_pass, "pass" }
|
, { "quit", pop3_quit, 0 }
|
||||||
, { pop3_apop, "apop" }
|
, { "noop", okay, 0 }
|
||||||
, { pop3_quit, "quit" }
|
, { 0, err_authoriz, 0 }
|
||||||
, { okay, "noop" }
|
} ;
|
||||||
, { 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
void doit(cmd)
|
|
||||||
char *cmd;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
for (i = 0;pop3cmd[i].fun;++i)
|
|
||||||
{
|
|
||||||
for (j = 0;ch = pop3cmd[i].text[j];++j)
|
|
||||||
if ((cmd[j] != ch) && (cmd[j] != ch - 32))
|
|
||||||
break;
|
|
||||||
if (!ch)
|
|
||||||
if (!cmd[j] || (cmd[j] == ' '))
|
|
||||||
{
|
|
||||||
while (cmd[j] == ' ') ++j;
|
|
||||||
if (!cmd[j])
|
|
||||||
pop3cmd[i].fun((char *) 0);
|
|
||||||
else
|
|
||||||
pop3cmd[i].fun(cmd + j);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err_authoriz();
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(argc,argv)
|
void main(argc,argv)
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
{
|
{
|
||||||
static stralloc cmd = {0};
|
|
||||||
int match;
|
|
||||||
|
|
||||||
sig_alarmcatch(die);
|
sig_alarmcatch(die);
|
||||||
sig_pipeignore();
|
sig_pipeignore();
|
||||||
|
|
||||||
|
|
@ -205,15 +178,6 @@ char **argv;
|
||||||
if (!*childargs) die_usage();
|
if (!*childargs) die_usage();
|
||||||
|
|
||||||
pop3_greet();
|
pop3_greet();
|
||||||
|
commands(&ssin,pop3commands);
|
||||||
for (;;)
|
die();
|
||||||
{
|
|
||||||
if (getln(&ssin,&cmd,&match,'\n') == -1) die();
|
|
||||||
if (!match) die();
|
|
||||||
if (cmd.len == 0) die();
|
|
||||||
if (cmd.s[--cmd.len] != '\n') die();
|
|
||||||
if ((cmd.len > 0) && (cmd.s[cmd.len - 1] == '\r')) --cmd.len;
|
|
||||||
cmd.s[cmd.len++] = 0;
|
|
||||||
doit(cmd.s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
qmail-pw2u.9
12
qmail-pw2u.9
|
|
@ -4,7 +4,7 @@ qmail-pw2u \- build address assignments from a passwd file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B qmail-pw2u
|
.B qmail-pw2u
|
||||||
[
|
[
|
||||||
.B \-ohHuUC
|
.B \-/ohHuUC
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
.B \-c\fIchar
|
.B \-c\fIchar
|
||||||
|
|
@ -160,7 +160,7 @@ Each line has the form
|
||||||
|
|
||||||
.I sub
|
.I sub
|
||||||
will be handled by
|
will be handled by
|
||||||
.IR home\fB/.qmail-\fIpre ,
|
.IR home\fB/.qmail\-\fIpre ,
|
||||||
where
|
where
|
||||||
.I home
|
.I home
|
||||||
is
|
is
|
||||||
|
|
@ -168,7 +168,7 @@ is
|
||||||
home directory;
|
home directory;
|
||||||
.I sub\fBBREAK\fIext
|
.I sub\fBBREAK\fIext
|
||||||
will be handled by
|
will be handled by
|
||||||
.IR home\fB/.qmail-\fIpre\fB-\fIext .
|
.IR home\fB/.qmail\-\fIpre\fB\-\fIext .
|
||||||
.TP
|
.TP
|
||||||
.B append
|
.B append
|
||||||
Extra assignments,
|
Extra assignments,
|
||||||
|
|
@ -228,6 +228,12 @@ in place of
|
||||||
.TP
|
.TP
|
||||||
.B \-C
|
.B \-C
|
||||||
Disable the user-extension mechanism.
|
Disable the user-extension mechanism.
|
||||||
|
.TP
|
||||||
|
.B \-/
|
||||||
|
Use
|
||||||
|
.IR home\fB/.qmail\-/ ...
|
||||||
|
instead of
|
||||||
|
.IR home\fB/.qmail\- ...
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
qmail-users(5),
|
qmail-users(5),
|
||||||
qmail-lspawn(8),
|
qmail-lspawn(8),
|
||||||
|
|
|
||||||
14
qmail-pw2u.c
14
qmail-pw2u.c
|
|
@ -67,6 +67,7 @@ void die_user(s,len) char *s; unsigned int len;
|
||||||
_exit(111);
|
_exit(111);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *dashcolon = "-:";
|
||||||
int flagalias = 0;
|
int flagalias = 0;
|
||||||
int flagnoupper = 1;
|
int flagnoupper = 1;
|
||||||
int homestrategy = 2;
|
int homestrategy = 2;
|
||||||
|
|
@ -154,7 +155,8 @@ void doaccount()
|
||||||
if (str_equal(user.s,auto_usera)) {
|
if (str_equal(user.s,auto_usera)) {
|
||||||
if (substdio_puts(subfdout,"+") == -1) die_write();
|
if (substdio_puts(subfdout,"+") == -1) die_write();
|
||||||
if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write();
|
if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write();
|
||||||
if (substdio_puts(subfdout,"-::\n") == -1) die_write();
|
if (substdio_puts(subfdout,dashcolon) == -1) die_write();
|
||||||
|
if (substdio_puts(subfdout,":\n") == -1) die_write();
|
||||||
flagalias = 1;
|
flagalias = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,7 +182,8 @@ void doaccount()
|
||||||
if (substdio_put(subfdout,mailnames,i) == -1) die_write();
|
if (substdio_put(subfdout,mailnames,i) == -1) die_write();
|
||||||
if (substdio_put(subfdout,auto_break,1) == -1) die_write();
|
if (substdio_put(subfdout,auto_break,1) == -1) die_write();
|
||||||
if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write();
|
if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write();
|
||||||
if (substdio_puts(subfdout,"-::\n") == -1) die_write();
|
if (substdio_puts(subfdout,dashcolon) == -1) die_write();
|
||||||
|
if (substdio_puts(subfdout,":\n") == -1) die_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
mailnames += i;
|
mailnames += i;
|
||||||
|
|
@ -206,7 +209,7 @@ void dosubuser()
|
||||||
if (substdio_puts(subfdout,"=") == -1) die_write();
|
if (substdio_puts(subfdout,"=") == -1) die_write();
|
||||||
if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write();
|
if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write();
|
||||||
if (substdio_puts(subfdout,uugh) == -1) die_write();
|
if (substdio_puts(subfdout,uugh) == -1) die_write();
|
||||||
if (substdio_puts(subfdout,"-:") == -1) die_write();
|
if (substdio_puts(subfdout,dashcolon) == -1) die_write();
|
||||||
if (substdio_put(subfdout,x,i) == -1) die_write();
|
if (substdio_put(subfdout,x,i) == -1) die_write();
|
||||||
if (substdio_puts(subfdout,":\n") == -1) die_write();
|
if (substdio_puts(subfdout,":\n") == -1) die_write();
|
||||||
|
|
||||||
|
|
@ -215,7 +218,7 @@ void dosubuser()
|
||||||
if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write();
|
if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write();
|
||||||
if (substdio_put(subfdout,auto_break,1) == -1) die_write();
|
if (substdio_put(subfdout,auto_break,1) == -1) die_write();
|
||||||
if (substdio_puts(subfdout,uugh) == -1) die_write();
|
if (substdio_puts(subfdout,uugh) == -1) die_write();
|
||||||
if (substdio_puts(subfdout,"-:") == -1) die_write();
|
if (substdio_puts(subfdout,dashcolon) == -1) die_write();
|
||||||
if (substdio_put(subfdout,x,i) == -1) die_write();
|
if (substdio_put(subfdout,x,i) == -1) die_write();
|
||||||
if (substdio_puts(subfdout,"-:\n") == -1) die_write();
|
if (substdio_puts(subfdout,"-:\n") == -1) die_write();
|
||||||
}
|
}
|
||||||
|
|
@ -232,8 +235,9 @@ char **argv;
|
||||||
int opt;
|
int opt;
|
||||||
int match;
|
int match;
|
||||||
|
|
||||||
while ((opt = getopt(argc,argv,"ohHuUc:C")) != opteof)
|
while ((opt = getopt(argc,argv,"/ohHuUc:C")) != opteof)
|
||||||
switch(opt) {
|
switch(opt) {
|
||||||
|
case '/': dashcolon = "-/:"; break;
|
||||||
case 'o': homestrategy = 2; break;
|
case 'o': homestrategy = 2; break;
|
||||||
case 'h': homestrategy = 1; break;
|
case 'h': homestrategy = 1; break;
|
||||||
case 'H': homestrategy = 0; break;
|
case 'H': homestrategy = 0; break;
|
||||||
|
|
|
||||||
35
qmail-qmqpc.8
Normal file
35
qmail-qmqpc.8
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
.TH qmail-qmqpc 8
|
||||||
|
.SH NAME
|
||||||
|
qmail-qmqpc \- queue a mail message via QMQP
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B qmail-qmqpc
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B qmail-qmqpc
|
||||||
|
offers the same interface as
|
||||||
|
.BR qmail-queue ,
|
||||||
|
but it gives the message to a QMQP server
|
||||||
|
instead of storing it locally.
|
||||||
|
|
||||||
|
In a
|
||||||
|
.B mini-qmail
|
||||||
|
installation,
|
||||||
|
.B qmail-queue
|
||||||
|
is replaced with a symbolic link to
|
||||||
|
.BR qmail-qmqpc .
|
||||||
|
|
||||||
|
.B qmail-qmqpc
|
||||||
|
is currently experimental;
|
||||||
|
use it at your own risk.
|
||||||
|
It will be fully supported in the next release of
|
||||||
|
.BR qmail .
|
||||||
|
.SH "CONTROL FILES"
|
||||||
|
.TP 5
|
||||||
|
.I qmqpservers
|
||||||
|
IP addresses of QMQP servers, one address per line.
|
||||||
|
.B qmail-qmqpc
|
||||||
|
will try each address in turn until it establishes a QMQP connection
|
||||||
|
or runs out of addresses.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
qmail-control(5),
|
||||||
|
qmail-queue(8),
|
||||||
|
qmail-qmqpd(8)
|
||||||
161
qmail-qmqpc.c
Normal file
161
qmail-qmqpc.c
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
/* EXPERIMENTAL! Use at your own risk. */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include "substdio.h"
|
||||||
|
#include "getln.h"
|
||||||
|
#include "readwrite.h"
|
||||||
|
#include "exit.h"
|
||||||
|
#include "stralloc.h"
|
||||||
|
#include "slurpclose.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "sig.h"
|
||||||
|
#include "ip.h"
|
||||||
|
#include "timeoutconn.h"
|
||||||
|
#include "timeoutread.h"
|
||||||
|
#include "timeoutwrite.h"
|
||||||
|
#include "auto_qmail.h"
|
||||||
|
#include "control.h"
|
||||||
|
#include "fmt.h"
|
||||||
|
|
||||||
|
#define PORT_QMQP 628
|
||||||
|
|
||||||
|
void die_success() { _exit(0); }
|
||||||
|
void die_perm() { _exit(31); }
|
||||||
|
void nomem() { _exit(51); }
|
||||||
|
void die_read() { if (errno == error_nomem) nomem(); _exit(54); }
|
||||||
|
void die_control() { _exit(55); }
|
||||||
|
void die_socket() { _exit(56); }
|
||||||
|
void die_home() { _exit(61); }
|
||||||
|
void die_temp() { _exit(71); }
|
||||||
|
void die_conn() { _exit(74); }
|
||||||
|
void die_format() { _exit(91); }
|
||||||
|
|
||||||
|
int lasterror = 55;
|
||||||
|
int qmqpfd;
|
||||||
|
|
||||||
|
int saferead(fd,buf,len) int fd; char *buf; int len;
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = timeoutread(60,qmqpfd,buf,len);
|
||||||
|
if (r <= 0) die_conn();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
int safewrite(fd,buf,len) int fd; char *buf; int len;
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = timeoutwrite(60,qmqpfd,buf,len);
|
||||||
|
if (r <= 0) die_conn();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
substdio to = SUBSTDIO_FDBUF(safewrite,-1,buf,sizeof buf);
|
||||||
|
substdio from = SUBSTDIO_FDBUF(saferead,-1,buf,sizeof buf);
|
||||||
|
substdio envelope = SUBSTDIO_FDBUF(read,1,buf,sizeof buf);
|
||||||
|
/* WARNING: can use only one of these at a time! */
|
||||||
|
|
||||||
|
stralloc beforemessage = {0};
|
||||||
|
stralloc message = {0};
|
||||||
|
stralloc aftermessage = {0};
|
||||||
|
|
||||||
|
char strnum[FMT_ULONG];
|
||||||
|
stralloc line = {0};
|
||||||
|
|
||||||
|
void getmess()
|
||||||
|
{
|
||||||
|
int match;
|
||||||
|
|
||||||
|
if (slurpclose(0,&message,1024) == -1) die_read();
|
||||||
|
|
||||||
|
strnum[fmt_ulong(strnum,(unsigned long) message.len)] = 0;
|
||||||
|
if (!stralloc_copys(&beforemessage,strnum)) nomem();
|
||||||
|
if (!stralloc_cats(&beforemessage,":")) nomem();
|
||||||
|
if (!stralloc_copys(&aftermessage,",")) nomem();
|
||||||
|
|
||||||
|
if (getln(&envelope,&line,&match,'\0') == -1) die_read();
|
||||||
|
if (!match) die_format();
|
||||||
|
if (line.len < 2) die_format();
|
||||||
|
if (line.s[0] != 'F') die_format();
|
||||||
|
|
||||||
|
strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0;
|
||||||
|
if (!stralloc_cats(&aftermessage,strnum)) nomem();
|
||||||
|
if (!stralloc_cats(&aftermessage,":")) nomem();
|
||||||
|
if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem();
|
||||||
|
if (!stralloc_cats(&aftermessage,",")) nomem();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (getln(&envelope,&line,&match,'\0') == -1) die_read();
|
||||||
|
if (!match) die_format();
|
||||||
|
if (line.len < 2) break;
|
||||||
|
if (line.s[0] != 'T') die_format();
|
||||||
|
|
||||||
|
strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0;
|
||||||
|
if (!stralloc_cats(&aftermessage,strnum)) nomem();
|
||||||
|
if (!stralloc_cats(&aftermessage,":")) nomem();
|
||||||
|
if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem();
|
||||||
|
if (!stralloc_cats(&aftermessage,",")) nomem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doit(server)
|
||||||
|
char *server;
|
||||||
|
{
|
||||||
|
struct ip_address ip;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
if (!ip_scan(server,&ip)) return;
|
||||||
|
|
||||||
|
qmqpfd = socket(AF_INET,SOCK_STREAM,0);
|
||||||
|
if (qmqpfd == -1) die_socket();
|
||||||
|
|
||||||
|
if (timeoutconn(qmqpfd,&ip,PORT_QMQP,10) != 0) {
|
||||||
|
lasterror = 73;
|
||||||
|
if (errno == error_timeout) lasterror = 72;
|
||||||
|
close(qmqpfd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strnum[fmt_ulong(strnum,(unsigned long) (beforemessage.len + message.len + aftermessage.len))] = 0;
|
||||||
|
substdio_puts(&to,strnum);
|
||||||
|
substdio_puts(&to,":");
|
||||||
|
substdio_put(&to,beforemessage.s,beforemessage.len);
|
||||||
|
substdio_put(&to,message.s,message.len);
|
||||||
|
substdio_put(&to,aftermessage.s,aftermessage.len);
|
||||||
|
substdio_puts(&to,",");
|
||||||
|
substdio_flush(&to);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
substdio_get(&from,&ch,1);
|
||||||
|
if (ch == 'K') die_success();
|
||||||
|
if (ch == 'Z') die_temp();
|
||||||
|
if (ch == 'D') die_perm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stralloc servers = {0};
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
sig_pipeignore();
|
||||||
|
|
||||||
|
if (chdir(auto_qmail) == -1) die_home();
|
||||||
|
if (control_init() == -1) die_control();
|
||||||
|
if (control_readfile(&servers,"control/qmqpservers",0) != 1) die_control();
|
||||||
|
|
||||||
|
getmess();
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for (j = 0;j < servers.len;++j)
|
||||||
|
if (!servers.s[j]) {
|
||||||
|
doit(servers.s + i);
|
||||||
|
i = j + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit(lasterror);
|
||||||
|
}
|
||||||
31
qmail-qmqpd.8
Normal file
31
qmail-qmqpd.8
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
.TH qmail-qmqpd 8
|
||||||
|
.SH NAME
|
||||||
|
qmail-qmqpd \- receive mail via QMQP
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B qmail-qmqpd
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B qmail-qmqpd
|
||||||
|
receives mail messages via the Quick Mail Queueing Protocol (QMQP)
|
||||||
|
and invokes
|
||||||
|
.B qmail-queue
|
||||||
|
to deposit them into the outgoing queue.
|
||||||
|
.B qmail-qmqpd
|
||||||
|
must be supplied several environment variables;
|
||||||
|
see
|
||||||
|
.BR tcp-environ(5) .
|
||||||
|
|
||||||
|
.B qmail-qmqpd
|
||||||
|
will relay messages to any destination.
|
||||||
|
It should be invoked only for connections from preauthorized users.
|
||||||
|
|
||||||
|
.B qmail-qmqpd
|
||||||
|
is currently experimental;
|
||||||
|
use it at your own risk.
|
||||||
|
It will be fully supported in the next release of
|
||||||
|
.BR qmail .
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
tcp-env(1),
|
||||||
|
tcpserver(1),
|
||||||
|
tcp-environ(5),
|
||||||
|
qmail-qmqpc(8),
|
||||||
|
qmail-queue(8)
|
||||||
178
qmail-qmqpd.c
Normal file
178
qmail-qmqpd.c
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
/* EXPERIMENTAL! Use at your own risk. */
|
||||||
|
|
||||||
|
#include "auto_qmail.h"
|
||||||
|
#include "qmail.h"
|
||||||
|
#include "received.h"
|
||||||
|
#include "sig.h"
|
||||||
|
#include "substdio.h"
|
||||||
|
#include "readwrite.h"
|
||||||
|
#include "exit.h"
|
||||||
|
#include "now.h"
|
||||||
|
#include "fmt.h"
|
||||||
|
#include "env.h"
|
||||||
|
|
||||||
|
void resources() { _exit(111); }
|
||||||
|
|
||||||
|
int safewrite(fd,buf,len) int fd; char *buf; int len;
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = write(fd,buf,len);
|
||||||
|
if (r <= 0) _exit(0);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
int saferead(fd,buf,len) int fd; char *buf; int len;
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = read(fd,buf,len);
|
||||||
|
if (r <= 0) _exit(0);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ssinbuf[512];
|
||||||
|
substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
|
||||||
|
char ssoutbuf[256];
|
||||||
|
substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
|
||||||
|
|
||||||
|
unsigned long bytesleft = 100;
|
||||||
|
|
||||||
|
void getbyte(ch)
|
||||||
|
char *ch;
|
||||||
|
{
|
||||||
|
if (!bytesleft--) _exit(100);
|
||||||
|
substdio_get(&ssin,ch,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long getlen()
|
||||||
|
{
|
||||||
|
unsigned long len = 0;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
getbyte(&ch);
|
||||||
|
if (ch == ':') return len;
|
||||||
|
if (len > 200000000) resources();
|
||||||
|
len = 10 * len + (ch - '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getcomma()
|
||||||
|
{
|
||||||
|
char ch;
|
||||||
|
getbyte(&ch);
|
||||||
|
if (ch != ',') _exit(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct qmail qq;
|
||||||
|
|
||||||
|
void identify()
|
||||||
|
{
|
||||||
|
char *remotehost;
|
||||||
|
char *remoteinfo;
|
||||||
|
char *remoteip;
|
||||||
|
char *local;
|
||||||
|
|
||||||
|
remotehost = env_get("TCPREMOTEHOST");
|
||||||
|
if (!remotehost) remotehost = "unknown";
|
||||||
|
remoteinfo = env_get("TCPREMOTEINFO");
|
||||||
|
remoteip = env_get("TCPREMOTEIP");
|
||||||
|
if (!remoteip) remoteip = "unknown";
|
||||||
|
local = env_get("TCPLOCALHOST");
|
||||||
|
if (!local) local = env_get("TCPLOCALIP");
|
||||||
|
if (!local) local = "unknown";
|
||||||
|
|
||||||
|
received(&qq,"QMQP",local,remoteip,remotehost,remoteinfo,(char *) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[1000];
|
||||||
|
char strnum[FMT_ULONG];
|
||||||
|
|
||||||
|
int getbuf()
|
||||||
|
{
|
||||||
|
unsigned long len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
len = getlen();
|
||||||
|
if (len >= 1000) {
|
||||||
|
for (i = 0;i < len;++i) getbyte(buf);
|
||||||
|
getcomma();
|
||||||
|
buf[0] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0;i < len;++i) getbyte(buf + i);
|
||||||
|
getcomma();
|
||||||
|
buf[len] = 0;
|
||||||
|
return byte_chr(buf,len,'\0') == len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flagok = 1;
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
unsigned long qp;
|
||||||
|
unsigned long len;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
sig_pipeignore();
|
||||||
|
sig_alarmcatch(resources);
|
||||||
|
alarm(3600);
|
||||||
|
|
||||||
|
bytesleft = getlen();
|
||||||
|
|
||||||
|
len = getlen();
|
||||||
|
|
||||||
|
if (chdir(auto_qmail) == -1) resources();
|
||||||
|
if (qmail_open(&qq) == -1) resources();
|
||||||
|
qp = qmail_qp(&qq);
|
||||||
|
identify();
|
||||||
|
|
||||||
|
while (len > 0) { /* XXX: could speed this up */
|
||||||
|
getbyte(&ch);
|
||||||
|
--len;
|
||||||
|
qmail_put(&qq,&ch,1);
|
||||||
|
}
|
||||||
|
getcomma();
|
||||||
|
|
||||||
|
if (getbuf())
|
||||||
|
qmail_from(&qq,buf);
|
||||||
|
else {
|
||||||
|
qmail_from(&qq,"");
|
||||||
|
qmail_fail(&qq);
|
||||||
|
flagok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (bytesleft)
|
||||||
|
if (getbuf())
|
||||||
|
qmail_to(&qq,buf);
|
||||||
|
else {
|
||||||
|
qmail_fail(&qq);
|
||||||
|
flagok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesleft = 1;
|
||||||
|
getcomma();
|
||||||
|
|
||||||
|
result = qmail_close(&qq);
|
||||||
|
|
||||||
|
if (!*result) {
|
||||||
|
len = fmt_str(buf,"Kok ");
|
||||||
|
len += fmt_ulong(buf + len,(unsigned long) now());
|
||||||
|
len += fmt_str(buf + len," qp ");
|
||||||
|
len += fmt_ulong(buf + len,qp);
|
||||||
|
buf[len] = 0;
|
||||||
|
result = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flagok)
|
||||||
|
result = "Dsorry, I can't accept addresses like that (#5.1.3)";
|
||||||
|
|
||||||
|
fmt_ulong(strnum,str_len(result));
|
||||||
|
|
||||||
|
substdio_puts(&ssout,strnum);
|
||||||
|
substdio_puts(&ssout,":");
|
||||||
|
substdio_puts(&ssout,result);
|
||||||
|
substdio_puts(&ssout,",");
|
||||||
|
substdio_flush(&ssout);
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
|
@ -16,9 +16,12 @@ see
|
||||||
|
|
||||||
.B qmail-qmtpd
|
.B qmail-qmtpd
|
||||||
supports the
|
supports the
|
||||||
.I rcpthosts
|
.IR rcpthosts ,
|
||||||
|
.IR morercpthosts ,
|
||||||
|
.BR RELAYCLIENT ,
|
||||||
|
.IR databytes ,
|
||||||
and
|
and
|
||||||
.B RELAYCLIENT
|
.B DATABYTES
|
||||||
mechanisms described in
|
mechanisms described in
|
||||||
.BR qmail-smtpd(8) .
|
.BR qmail-smtpd(8) .
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue