From 212b6f5da7c68d4577de2855da3c57ecf476dc96 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 28 Jun 1998 15:46:53 +0100 Subject: [PATCH] Upstream qmail 1.03 --- BIN.Makefile | 24 + BIN.README | 19 + BLURB2 | 6 +- BLURB3 | 17 +- BLURB4 | 4 +- CHANGES | 256 ++++++++ FAQ | 222 +++++-- FILES | 70 ++- INSTALL | 211 ++----- INSTALL.alias | 8 +- INSTALL.boot | 16 - INSTALL.ctl | 19 +- INSTALL.ids | 15 +- INSTALL.maildir | 59 ++ INSTALL.mbox | 131 ++-- INSTALL.qsmhook | 53 -- INSTALL.vsm | 50 ++ INTERNALS | 3 +- Makefile | 1344 ++++++++++++++++++++---------------------- PIC.local2alias | 37 ++ PIC.local2ext | 41 ++ PIC.local2local | 40 ++ PIC.local2rem | 38 ++ PIC.local2virt | 44 ++ PIC.nullclient | 38 ++ PIC.relaybad | 8 + PIC.relaygood | 33 ++ PIC.rem2local | 36 ++ README | 360 ++++++----- REMOVE.binmail | 16 + REMOVE.sendmail | 28 + RFCHCSC | 37 -- RFCLOOPS | 338 ----------- RFCMXPS | 122 ---- RFCNETSTR | 88 --- RFCNRUDT | 89 --- RFCQMTP | 229 ------- RFCQSBMF | 155 ----- RFCVERP | 88 --- SECURITY | 18 +- SENDMAIL | 76 +++ TARGETS | 178 +++--- TEST.deliver | 82 +++ TEST.receive | 41 ++ THANKS | 490 +++++++++------ THOUGHTS | 155 +++-- TODO | 26 +- UPGRADE | 167 ++---- VERSION | 2 +- binm1+df.sh | 11 + binm1.sh | 10 + binm2+df.sh | 11 + binm2.sh | 10 + binm3+df.sh | 11 + binm3.sh | 10 + bouncesaying.1 | 71 +++ bouncesaying.c | 41 ++ commands.c | 40 ++ commands.h | 12 + condredirect.1 | 9 + condredirect.c | 114 ++-- conf-patrn | 5 +- conf-qmail | 7 + config-fast.sh | 30 + qmail-config.sh => config.sh | 0 constmap.c | 161 +++-- constmap.h | 6 +- control.c | 3 +- dns.c | 24 +- dot-qmail.9 | 10 +- except.1 | 33 ++ except.c | 37 ++ forgeries.7 | 2 +- forward.c | 76 +-- hfield.c | 1 + hfield.h | 3 +- hier.c | 252 ++++++++ home+df.sh | 9 + home.sh | 7 + idedit.c | 147 +++++ install-big.c | 285 +++++++++ install.c | 283 +++++---- instcheck.c | 174 +++--- maildir.5 | 2 +- maildirmake.c | 30 +- ndelay.c | 6 +- ndelay_off.c | 6 +- predate.c | 39 +- preline.c | 121 ++-- proc+df.sh | 9 + proc.sh | 7 + qlist.1 | 112 ---- qlist.c | 333 ----------- qlist2.sh | 1 - qmail-command.8 | 44 +- qmail-control.9 | 6 +- qmail-getpw.9 | 7 +- qmail-getpw.c | 2 + qmail-header.5 | 7 +- qmail-hier.c | 248 -------- qmail-inject.8 | 15 + qmail-inject.c | 196 +++--- qmail-local.8 | 4 +- qmail-local.c | 274 +++++---- qmail-log.5 | 37 +- qmail-lspawn.8 | 4 +- qmail-newmrh.9 | 41 ++ qmail-newmrh.c | 70 +++ qmail-pop3d.8 | 2 +- qmail-pop3d.c | 500 +++++++--------- qmail-popup.c | 254 ++++---- qmail-pw2u.9 | 12 +- qmail-pw2u.c | 14 +- qmail-qmqpc.8 | 29 + qmail-qmqpc.c | 159 +++++ qmail-qmqpd.8 | 25 + qmail-qmqpd.c | 174 ++++++ qmail-qmtpd.8 | 7 +- qmail-qmtpd.c | 439 +++++++------- qmail-qstat.sh | 8 +- qmail-queue.8 | 109 +++- qmail-queue.c | 40 +- qmail-remote.8 | 3 +- qmail-remote.c | 613 +++++++++---------- qmail-send.9 | 40 +- qmail-send.c | 104 +--- qmail-showctl.c | 91 ++- qmail-smtpd.8 | 54 ++ qmail-smtpd.c | 706 +++++++++++----------- qmail-start.9 | 11 +- qmail-tcpok.8 | 24 + qmail-tcpok.c | 35 ++ qmail-tcpto.8 | 3 +- qmail-upgrade.9 | 201 ------- qmail.7 | 9 +- qmail.c | 52 +- qmail.h | 14 +- qreceipt.c | 12 +- quote.c | 3 +- rcpthosts.c | 60 ++ rcpthosts.h | 7 + remoteinfo.c | 16 +- scan_nbblong.c | 33 -- sendmail.c | 167 +++--- slurpclose.c | 2 + substdio.h | 6 + timeoutread.c | 7 +- timeoutread.h | 2 - timeoutwrite.c | 7 +- timeoutwrite.h | 2 - token822.c | 2 + wait_pid.c | 30 +- 152 files changed, 7006 insertions(+), 6235 deletions(-) create mode 100644 BIN.Makefile create mode 100644 BIN.README delete mode 100644 INSTALL.boot create mode 100644 INSTALL.maildir delete mode 100644 INSTALL.qsmhook create mode 100644 INSTALL.vsm create mode 100644 PIC.local2alias create mode 100644 PIC.local2ext create mode 100644 PIC.local2local create mode 100644 PIC.local2rem create mode 100644 PIC.local2virt create mode 100644 PIC.nullclient create mode 100644 PIC.relaybad create mode 100644 PIC.relaygood create mode 100644 PIC.rem2local create mode 100644 REMOVE.binmail create mode 100644 REMOVE.sendmail delete mode 100644 RFCHCSC delete mode 100644 RFCLOOPS delete mode 100644 RFCMXPS delete mode 100644 RFCNETSTR delete mode 100644 RFCNRUDT delete mode 100644 RFCQMTP delete mode 100644 RFCQSBMF delete mode 100644 RFCVERP create mode 100644 SENDMAIL create mode 100644 TEST.deliver create mode 100644 TEST.receive create mode 100644 binm1+df.sh create mode 100644 binm1.sh create mode 100644 binm2+df.sh create mode 100644 binm2.sh create mode 100644 binm3+df.sh create mode 100644 binm3.sh create mode 100644 bouncesaying.1 create mode 100644 bouncesaying.c create mode 100644 commands.c create mode 100644 commands.h create mode 100644 config-fast.sh rename qmail-config.sh => config.sh (100%) create mode 100644 except.1 create mode 100644 except.c create mode 100644 hier.c create mode 100644 home+df.sh create mode 100644 home.sh create mode 100644 idedit.c create mode 100644 install-big.c create mode 100644 proc+df.sh create mode 100644 proc.sh delete mode 100644 qlist.1 delete mode 100644 qlist.c delete mode 100644 qlist2.sh delete mode 100644 qmail-hier.c create mode 100644 qmail-newmrh.9 create mode 100644 qmail-newmrh.c create mode 100644 qmail-qmqpc.8 create mode 100644 qmail-qmqpc.c create mode 100644 qmail-qmqpd.8 create mode 100644 qmail-qmqpd.c create mode 100644 qmail-tcpok.8 create mode 100644 qmail-tcpok.c delete mode 100644 qmail-upgrade.9 create mode 100644 rcpthosts.c create mode 100644 rcpthosts.h delete mode 100644 scan_nbblong.c diff --git a/BIN.Makefile b/BIN.Makefile new file mode 100644 index 0000000..f46c537 --- /dev/null +++ b/BIN.Makefile @@ -0,0 +1,24 @@ +SHELL=/bin/sh + +# Files are edited in the installation directory, then copied. +# There are 40 arguments to idedit after the filename, +# showing the positions of each byte in the following ten ints: +# uida, uidd, uidl, uido, uidp, uidq, uidr, uids, gidq, gidn. +# Normal little-endian positions are n n+1 n+2 ... n+39 for some n. +# Normal big-endian positions are n+3 n+2 n+1 n n+7 ... n+36 for some n. + +setup: + mkdir /var/qmail + ./idedit install-big XXX + ./idedit qmail-lspawn XXX + ./idedit qmail-queue XXX + ./idedit qmail-rspawn XXX + ./idedit qmail-showctl XXX + ./idedit qmail-start XXX + ./install-big + cp /var/qmail/boot/binm1+df /var/qmail/rc + chmod 755 /var/qmail/rc + echo '|fastforward -d /etc/aliases.cdb' > /var/qmail/alias/.qmail-default + chmod 644 /var/qmail/alias/.qmail-default + hostname | grep -q '\.' + ./config-fast `hostname` diff --git a/BIN.README b/BIN.README new file mode 100644 index 0000000..6beeee1 --- /dev/null +++ b/BIN.README @@ -0,0 +1,19 @@ +Like any other piece of software (and information generally), qmail +comes with NO WARRANTY. + +Configuration: The qmail home directory is /var/qmail. (This must be a +local directory, not shared among machines. Under Linux, make sure that +all mail-handling filesystems are mounted with synchronous metadata.) +The user-ext delimiter is -. The silent concurrency limit is 120. The +queue subdirectory split is 23. + +To install: + # make setup + +To set up qmail to receive and deliver mail, follow the instructions in +/var/qmail/doc/fastforward/ALIASES, and then start at step 9 of +/var/qmail/doc/INSTALL. + +Compilation environment: Oops, the package creator forgot to edit this! +He's supposed to list his OS version, compiler version, hardware, and +name. diff --git a/BLURB2 b/BLURB2 index a63f21c..1a98d0e 100644 --- a/BLURB2 +++ b/BLURB2 @@ -16,11 +16,11 @@ out-of-the-box configuration. * 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 handles aliasing and forwarding with the same simple mechanism. For example, Postmaster is controlled by ~alias/.qmail-postmaster. This 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. diff --git a/BLURB3 b/BLURB3 index db3b699..5f8af6d 100644 --- a/BLURB3 +++ b/BLURB3 @@ -3,7 +3,7 @@ Here are some of qmail's features. Setup: * automatic adaptation to your UNIX variant---no configuration needed * 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 Security: @@ -16,11 +16,12 @@ Security: Message construction (qmail-inject): * RFC 822, RFC 1123 * 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 * host masquerading (control/defaulthost) -* user masquerading (MAILUSER, MAILHOST) -* sendmail hook for compatibility with current user agents +* user masquerading ($MAILUSER, $MAILHOST) +* automatic Mail-Followup-To creation ($QMAILMFTFILE) SMTP service (qmail-smtpd): * RFC 821, RFC 1123, RFC 1651, RFC 1652, RFC 1854 @@ -67,11 +68,13 @@ SMTP delivery (qmail-remote): Forwarding and mailing lists (qmail-local): * 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 * VERPs---automatic recipient identification for mailing list bounces * Delivered-To---automatic loop prevention, even across hosts -* automatic subscription management (qlist) +* automatic mailing list management (ezmlm, available separately) Local delivery (qmail-local): * user-controlled address hierarchy---fred controls fred-anything @@ -80,7 +83,7 @@ Local delivery (qmail-local): * user-controlled program delivery: procmail etc. (qmail-command) * optional new-mail notification (qbiff) * optional NRUDT return receipts (qreceipt) -* conditional filtering (condredirect) +* conditional filtering (condredirect, bouncesaying) POP3 service (qmail-popup, qmail-pop3d): * RFC 1939 diff --git a/BLURB4 b/BLURB4 index 35d2cd3..6c4eaac 100644 --- a/BLURB4 +++ b/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 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 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 @@ -14,7 +14,7 @@ accustamp and written to disk as usual.) 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 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 fast. Compare these figures to Zmailer's advertised rate for throwing recipients away without even delivering the message---only 0.48 million diff --git a/CHANGES b/CHANGES index 6abdaf3..6bfa516 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,259 @@ +19980615 version: qmail 1.03. +19980614 doc: eliminated BIN.setup in favor of a web page. +19980614 code: added other auto* to qmail-showctl output. +19980614 doc: added pointer to immhf.html in qmail-header.5. +19980614 doc: added note to TEST.receive about SMTP command format. +19980614 doc: added FAQ 5.6 on qmail-qmqpd. +19980614 code: removed unused variables in idedit.c. +19980613 code: changed conf-patrn to 002. +19980613 doc: moved SENDMAIL lower in INSTALL. +19980612 code: added install-big. +19980612 code: added BIN.Makefile. +19980612 doc: added BIN.README, BIN.setup. +19980612 code: switched to new install. +19980611 code: added idedit. +19980611 doc: added FAQ 1.3 on $QMAILMFTFILE. +19980611 doc: used bouncesaying in FAQ 5.5. +19980611 code: added except. +19980611 code: added bouncesaying. +19980611 code: allowed unbracketed IP addresses in dns_ipplus() and + dns_mxip(). +19980611 code: allowed spaces after colon in non-bracketed addresses in + qmail-smtpd. +19980611 doc: cleaned up UPGRADE. +19980528 bug: qmail-smtpd skips first character in rcpthosts() call. + tnx NND. impact: qmail-smtpd crashes on empty address; and it + allows relaying to ""@any.host. fix: use addr.s. +19980515 doc: expanded flock discussion in INSTALL.mbox. +19980515 doc: eliminated flock warning from INSTALL.maildir. +19980515 doc: split REMOVE.binmail out of INSTALL. +19980515 doc: split REMOVE.sendmail out of INSTALL. +19980515 doc: split TEST.deliver and TEST.receive out of INSTALL and + UPGRADE. +19980515 doc: integrated INSTALL.boot into INSTALL. +19980515 code: cleaned up final output in qmail-qmqpd.c. +19980514 doc: updated procmail notes in INSTALL.mbox. tnx JRM. +19980514 doc: changed FAQ 4.4 to point to INSTALL.mbox for procmail. + tnx JRM. +19980514 code: separated HELO and EHLO; single-line response for HELO. + tnx to various people. +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. 19970414 doc: tightened up qmail-upgrade.7. 19970414 code: rewrote rewrite(). diff --git a/FAQ b/FAQ index 214cc1b..8540dbd 100644 --- a/FAQ +++ b/FAQ @@ -1,6 +1,7 @@ 1. Controlling the appearance of outgoing messages 1.1. How do I set up host masquerading? 1.2. How do I set up user masquerading? +1.3. How do I set up Mail-Followup-To automatically? 2. Routing outgoing messages 2.1. How do I send local messages to another host? @@ -21,6 +22,10 @@ 4.4. How do I use procmail with qmail? 4.5. How do I use elm's filter with qmail? 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.1. How do I run qmail-smtpd under tcpserver? @@ -28,10 +33,11 @@ 5.3. How do I set up qmail-pop3d? 5.4. How do I allow selected clients to use this host as a relay? 5.5. How do I fix up messages from broken SMTP clients? +5.6. How do I set up qmail-qmqpd? 6. Configuring MUAs to work with qmail 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.4. How do I stop Sun's dtcm from hanging? @@ -41,6 +47,8 @@ 7.3. How do I rejuvenate a message? 7.4. How do I organize a big network? 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.1. How do I tell qmail to do more deliveries at once? @@ -69,6 +77,14 @@ override From lines supplied by your MUA, add QMAILINJECT=f to your environment. +1.3. How do I set up Mail-Followup-To automatically? When I send a +message to the sos@heaven.af.mil mailing list, I'd like to include +``Mail-Followup-To: sos@heaven.af.mil''. + +Answer: Add QMAILMFTFILE=$HOME/.lists to your environment, and put +sos@heaven.af.mil into ~/.lists. + + 2. Routing outgoing messages @@ -102,11 +118,11 @@ Answer: Put 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 -to use -d instead of -df. Also, you may need to insert a space between --a and "$SENDER" for bounces to work properly.) If qmail-send is +(all on one line) into ~alias/.qmail-uucp-default. (For some UUCP +software you will need to use -d instead of -df.) If qmail-send is running, give it a HUP. @@ -120,9 +136,9 @@ showed that a message was deferred for this reason. Why is qmail doing CNAME lookups, anyway? 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 -the relevant DNS server is down, qmail defers the message. It will try -again soon. +has to do a CNAME lookup in DNS for every recipient host. If the +relevant DNS server is down, qmail defers the message. It will try again +soon. @@ -135,7 +151,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? 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 @@ -147,7 +164,8 @@ Answer: Put nowhere.mil:bob 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 bob-whatever. Bob can set up ~bob/.qmail-default to catch all the @@ -165,7 +183,8 @@ Answer: Put two lines into control/virtualdomains: everywhere.org:bob-everywhere 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 can even set up .qmail-nowhere-default and .qmail-everywhere-default. @@ -191,21 +210,22 @@ forwarded to a bunch of people. 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. 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 -handled automatically, put - - | qlist2 sos my.host.name +you rather than the original sender. -into ~me/.qmail-sos-request. Anyone who wants to subscribe can simply -send a message to me-sos-request@my.host.name. +Alternative: ezmlm (http://pobox.com/~djb/ezmlm.html) is a modern +mailing list manager, supporting automatic subscriptions, confirmations, +archives, fully automatic bounce handling (including warnings to +subscribers saying which messages they've missed), and more. 4.3. How do I use majordomo with qmail? -Answer: You need to patch majordomo so that it creates qmail-style -lists. See ftp://koobera.math.uic.edu/pub/software/majordomo+qmail.gz. -Exception: qmsmac understands sendmail-style :include: files, so you -shouldn't patch majordomo if you're using qmsmac. +Answer: See ftp://ftp.eyrie.org/pub/software/majordomo/mjqmail and +http://www.qmail.org for various methods. majordomo 2.0 is expected to +support qmail directly. + +Beware that majordomo's lists are not crashproof. + 4.4. How do I use procmail with qmail? @@ -216,8 +236,8 @@ Answer: Put into ~/.qmail. You'll have to use a full path for procmail unless procmail is in the system's startup PATH. Note that procmail will try to -deliver to /usr/spool/mail/$USER by default; to change this, change -SYSTEM_MBOX in procmail's config.h. +deliver to /var/spool/mail/$USER by default; to change this, see +INSTALL.mbox. 4.5. How do I use elm's filter with qmail? @@ -237,6 +257,48 @@ Answer: Use .qmail-p:d:q:bach. Dots are converted to colons, and 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 @@ -281,20 +343,23 @@ If you have tcpserver installed, skip the inetd step, and set up tcpserver -u 7770 -g 2108 0 qmtp /var/qmail/bin/qmail-qmtpd & replacing 7770 and 2108 with the qmaild uid and nofiles gid. See -question 5.1 for more details. +question 5.1 for more details on tcpserver. -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 (http://pobox.com/~djb/checkpwd.html). Second, make sure you have a 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 - qmail-popup YOURHOST /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir + pop3 stream tcp nowait root + /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 host's fully qualified domain name. Fourth, set up Maildir delivery for @@ -307,7 +372,7 @@ lines) /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir & replacing YOURHOST with your host's fully qualified domain name. See -question 5.1 for more details. +question 5.1 for more details on tcpserver. Security note: pop3d should be used only within a secure network; otherwise an eavesdropper can steal passwords. @@ -315,8 +380,7 @@ otherwise an eavesdropper can steal passwords. 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 -control/rcpthosts. I know I could entirely disable this feature by -removing control/rcpthosts, but I want to be more selective. +control/rcpthosts. Answer: Three steps. First, install tcp-wrappers, available separately, including hosts_options. Second, change your qmail-smtpd line in @@ -336,29 +400,29 @@ ignores control/rcpthosts when RELAYCLIENT is set. (It also appends RELAYCLIENT to each envelope recipient address. See question 5.5 for an application.) -Alternative procedure, if you are using tcpserver: Install tcpcontrol -(http://pobox.com/~djb/tcpcontrol.html). Create /etc/tcp.smtp containing +Alternative procedure, if you are using tcpserver 0.80 or above: Create +/etc/tcp.smtp containing 1.2.3.6:allow,RELAYCLIENT="" 127.:allow,RELAYCLIENT="" 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 - 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? Answer: Three steps. First, put - | [ "@$HOST" = "@fixme" ] || ( echo Permission denied; exit 100 ) - | qmail-inject -f "$SENDER" -- "$EXT2" + | bouncesaying 'Permission denied' [ "@$HOST" != "@fixme" ] + | qmail-inject -f "$SENDER" -- "$DEFAULT" into ~alias/.qmail-fixup-default. Second, put @@ -371,12 +435,34 @@ string ``@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 -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.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. + + +5.6. How do I set up qmail-qmqpd? I'd like to allow fast queueing of +outgoing mail from authorized clients. + +Answer: Make sure you have installed tcpserver 0.80 or above. Create +/etc/qmqp.tcp in tcprules format to allow connections from authorized +hosts. For example, if queueing is allowed from 1.2.3.*: + + 1.2.3.:allow + :deny + +Convert /etc/qmqp.tcp to /etc/qmqp.cdb: + + tcprules /etc/qmqp.cdb /etc/qmqp.tmp < /etc/qmqp.tcp + +Finally, set up + + tcpserver -x /etc/qmqp.cdb -u 7770 -g 2108 0 628 /var/qmail/bin/qmail-qmqpd & + +replacing 7770 and 2108 with the qmaild uid and nofiles gid. See +question 5.1 for more details on tcpserver. @@ -395,8 +481,7 @@ into your .mailrc or your system-wide Mail.rc. Beware that BSD mail is neither secure nor reliable. -6.2. How do I stop pine from crashing? When I ask any version of pine -past 3.91 to send mail, it crashes. +6.2. How do I make pine work with qmail? Answer: Put @@ -432,14 +517,25 @@ sendmail, it was always tricky to kill sendmail without risking the loss of current deliveries; what should I do with qmail-send? 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 -qmail-start the same way as it's run from your system boot scripts. +cleanly. Wait for ``exiting'' to show up in the log. To restart qmail, +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 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 @@ -521,6 +617,42 @@ battery backups. RAID boxes let you replace dead disks without losing 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 diff --git a/FILES b/FILES index b581fac..bbf25c2 100644 --- a/FILES +++ b/FILES @@ -6,31 +6,40 @@ README FAQ INSTALL INSTALL.alias -INSTALL.boot INSTALL.ctl INSTALL.ids +INSTALL.maildir INSTALL.mbox -INSTALL.qsmhook +INSTALL.vsm +REMOVE.sendmail +REMOVE.binmail +TEST.deliver +TEST.receive UPGRADE THOUGHTS TODO THANKS CHANGES -RFCHCSC -RFCLOOPS -RFCMXPS -RFCNETSTR -RFCNRUDT -RFCQMTP -RFCQSBMF -RFCVERP SECURITY INTERNALS +SENDMAIL +PIC.local2alias +PIC.local2ext +PIC.local2local +PIC.local2rem +PIC.local2virt +PIC.nullclient +PIC.relaybad +PIC.relaygood +PIC.rem2local FILES VERSION SYSDEPS TARGETS Makefile +BIN.README +BIN.Makefile +idedit.c conf-break auto_break.h conf-spawn @@ -46,6 +55,8 @@ auto_uids.h auto_usera.h extra.h addresses.5 +except.1 +bouncesaying.1 condredirect.1 dot-qmail.9 envelopes.5 @@ -58,7 +69,6 @@ mailsubj.1 mbox.5 preline.1 qbiff.1 -qlist.1 qmail-clean.8 qmail-command.8 qmail-control.9 @@ -69,10 +79,13 @@ qmail-limits.9 qmail-local.8 qmail-log.5 qmail-lspawn.8 +qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 qmail-popup.8 qmail-pw2u.9 +qmail-qmqpc.8 +qmail-qmqpd.8 qmail-qmtpd.8 qmail-qread.8 qmail-qstat.8 @@ -83,24 +96,27 @@ qmail-send.9 qmail-showctl.8 qmail-smtpd.8 qmail-start.9 +qmail-tcpok.8 qmail-tcpto.8 -qmail-upgrade.9 qmail-users.9 qmail.7 qreceipt.1 splogger.8 tcp-env.1 +config.sh +config-fast.sh qmail-clean.c -qmail-config.sh qmail-getpw.c -qmail-hier.c qmail-inject.c qmail-local.c qmail-lspawn.c +qmail-newmrh.c qmail-newu.c qmail-pop3d.c qmail-popup.c qmail-pw2u.c +qmail-qmqpc.c +qmail-qmqpd.c qmail-qmtpd.c qmail-qread.c qmail-qstat.sh @@ -111,6 +127,7 @@ qmail-send.c qmail-showctl.c qmail-smtpd.c qmail-start.c +qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c @@ -122,13 +139,14 @@ hostname.c ipmeprint.c tcp-env.c sendmail.c -qlist.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c +except.c +bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c @@ -137,13 +155,14 @@ splogger.c qail.sh elq.sh pinq.sh -qlist2.sh qmail-upq.sh datemail.sh mailsubj.sh qlx.h -constmap.h -constmap.c +rcpthosts.h +rcpthosts.c +commands.h +commands.c dnsdoe.h dnsdoe.c fmtqfn.h @@ -171,6 +190,16 @@ trynpbg1.c trysyslog.c conf-cc 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 make-compile.sh make-load.sh @@ -182,8 +211,10 @@ auto-int.c auto-int8.c auto-gid.c auto-uid.c +hier.c install.c instcheck.c +install-big.c alloc.3 alloc.h alloc.c @@ -348,7 +379,6 @@ fmt_ulong.c scan.h scan_ulong.c scan_8long.c -scan_nbblong.c slurpclose.h slurpclose.c quote.h @@ -399,3 +429,5 @@ maildir.5 maildir.h maildir.c tcp-environ.5 +constmap.h +constmap.c diff --git a/INSTALL b/INSTALL index 314e94a..e3b0f09 100644 --- a/INSTALL +++ b/INSTALL @@ -12,170 +12,73 @@ directory, edit conf-qmail now. names, edit conf-users and conf-groups now. -Installation steps that won't interfere with sendmail: +To create /var/qmail and configure qmail (won't interfere with sendmail): 1. Create the qmail home directory: # mkdir /var/qmail + 2. Read INSTALL.ids. You must set up the qmail group and the qmail users before compiling the programs. - 3. Compile the programs: - # make - 4. Create the formatted man pages, *.0: - # make man - 5. Create the qmail directory tree: - # make setup - 6. Run instcheck to make sure it doesn't print any warnings: - # make check - 7. Read INSTALL.ctl and FAQ. Minimal survival command: - # ./qmail-config - 8. Read INSTALL.alias. Minimal survival command: + + 3. Compile the programs and create the qmail directory tree: + # make setup check + + 4. Read INSTALL.ctl and FAQ. Minimal survival command: + # ./config + + 5. Read INSTALL.alias. Minimal survival command: # (cd ~alias; touch .qmail-postmaster .qmail-mailer-daemon .qmail-root) # chmod 644 ~alias/.qmail* - 9. Read INSTALL.mbox. -10. Read qmail-upgrade.0. This is what your users will need to know - about the switch from sendmail to qmail. - - -Pre-upgrade tests: - -11. Enable deliveries of messages injected into qmail: - # env - PATH="/var/qmail/bin:$PATH" \ - qmail-start ./Mailbox splogger qmail & - Make sure to include the ./ in ./Mailbox. -12. Look for a - qmail: running - line in syslog. qmail-send always prints either ``cannot start'' or - ``running''. (The big number is a splogger timestamp.) -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 - as root; qmail-rspawn, running as qmailr; and qmail-clean, running - as qmailq. You will also see the splogger process. -14. Local-local test: Send yourself an empty message. (Replace ``me'' - with your username. Make sure to include the ``to:'' colon.) - % echo to: me | /var/qmail/bin/qmail-inject - The message will show up immediately in ~/Mailbox, and syslog will - show something like this: - qmail: new msg 53 - qmail: info msg 53: bytes 246 from qp 20345 uid 666 - qmail: starting delivery 1: msg 53 to local me@domain - qmail: delivery 1: success: did_1+0+0/ - qmail: end msg 53 - (53 is an inode number; 20345 is a process ID; your numbers will - probably be different.) -15. Local-error test: Send a message to a nonexistent local address. - % echo to: nonexistent | /var/qmail/bin/qmail-inject - qmail: new msg 53 - qmail: info msg 53: bytes 246 from qp 20351 uid 666 - qmail: starting delivery 2: msg 53 to local nonexistent@domain - qmail: delivery 2: failure: No_such_address.__#5.1.1_/ - qmail: bounce msg 53 qp 20357 - qmail: end msg 53 - qmail: new msg 54 - qmail: info msg 54: bytes 743 from <> qp 20357 uid 666 - qmail: starting delivery 3: msg 54 to local me@domain - qmail: delivery 3: success: did_1+0+0/ - qmail: end msg 54 - You will now have a bounce message in ~/Mailbox. -16. Local-remote test: Send an empty message to your account on another - machine. - % echo to: me@wherever | /var/qmail/bin/qmail-inject - qmail: new msg 53 - qmail: info msg 53: bytes 246 from qp 20372 uid 666 - qmail: starting delivery 4: msg 53 to remote me@wherever - qmail: delivery 4: success: 1.2.3.4_accepted_message./... - qmail: end msg 53 - There will be a pause between ``starting delivery'' and ``success''; - SMTP is slow. Check that the message is in your mailbox on the other - machine. -17. Local-postmaster test: Send mail to postmaster, any capitalization. - % echo to: POSTmaster | /var/qmail/bin/qmail-inject - Look for the message in ~alias/Mailbox. -18. Double-bounce test: Send a message with a completely bad envelope. - % /var/qmail/bin/qmail-inject -f nonexistent - To: unknownuser - Subject: testing - - This is a test. This is only a test. - % - (Use end-of-file, not dot, to end the message.) Look for the double - bounce in ~alias/Mailbox. -19. Group membership test: - % cat > ~me/.qmail-groups - |groups >> MYGROUPS; exit 0 - % /var/qmail/bin/qmail-inject me-groups < /dev/null - % cat ~me/MYGROUPS - MYGROUPS will show your normal gid and nothing else. (Under Solaris, - make sure to use /usr/ucb/groups; /usr/bin/groups is broken.) - - -Upgrading from sendmail to qmail: - -20. Read INSTALL.boot. You must replace the sendmail invocation in your - boot scripts with an appropriate qmail invocation. -21. Kill the sendmail daemon. You should first kill -STOP the daemon; if - any children are running, you should kill -CONT, wait, kill -STOP - again, and repeat ad nauseam. If there aren't any children, kill - -TERM and then kill -CONT. -22. Replace sendmail with a link to qmail's ``sendmail'' wrapper: - # mv /usr/lib/sendmail /usr/lib/sendmail.bak + + 6. Read INSTALL.mbox and INSTALL.vsm. + + 7. Read INSTALL.maildir. + + 8. Copy /var/qmail/boot/home (or proc) to /var/qmail/rc. + + +To test qmail deliveries (won't interfere with sendmail): + + 9. Enable deliveries of messages injected into qmail: + # csh -cf '/var/qmail/rc &' + +10. Read TEST.deliver. + + +To upgrade from sendmail to qmail: + +11. Read SENDMAIL. This is what your users will want to know about the + switch from sendmail to qmail. + +12. Read REMOVE.sendmail. You must remove sendmail before installing + qmail. + +13. Read REMOVE.binmail. + +14. Add + csh -cf '/var/qmail/rc &' + to your boot scripts, so that the qmail daemons are restarted + whenever your system reboots. Make sure you include the &. + +15. Make qmail's ``sendmail'' wrapper available to MUAs: # ln -s /var/qmail/bin/sendmail /usr/lib/sendmail -23. Set up qmail-smtpd in /etc/inetd.conf (all on one line): + # ln -s /var/qmail/bin/sendmail /usr/sbin/sendmail + /usr/sbin might not exist on your system. + +16. Set up qmail-smtpd in /etc/inetd.conf (all on one line): smtp stream tcp nowait qmaild /var/qmail/bin/tcp-env - tcp-env /var/qmail/bin/qmail-smtpd - Also comment out comsat in /etc/inetd.conf. -24. Reboot. (Or kill -HUP your inetd and make sure the qmail daemons + tcp-env /var/qmail/bin/qmail-smtpd + +17. Reboot. (Or kill -HUP your inetd and make sure the qmail daemons are running.) -25. Try to flush the sendmail queue: - # /usr/lib/sendmail.bak -q - You can safely run sendmail.bak -q (or even sendmail.bak -q15m) - while qmail is running. Do this until the sendmail queue is empty. - This may take several days. -26. Disable all the sendmail and binmail programs in your system. The - safest approach is to chmod 0 everything. Some locations to check: - /usr/sbin/sendmail, /usr/lib/sendmail.bak, /usr/lib/sendmail.mx, - /bin/mail, /usr/libexec/mail.local. -27. Make sure that ``mail'' still invokes a reasonable mailer. Under - SVR4 you may want to link mail to mailx. - - -Post-upgrade tests (can be done immediately after step 24): - -28. SMTP server test: Forge some mail locally via SMTP. - % telnet 127.0.0.1 25 - Trying 127.0.0.1... - Connected to 127.0.0.1. - Escape character is '^]'. - 220 domain ESMTP - helo dude - 250-domain - 250-PIPELINING - 250 8BITMIME - mail - 250 ok - rcpt - 250 ok - data - 354 go ahead - Subject: testing - - This is a test. - . - 250 ok 812345679 qp 12345 - quit - 221 domain - Connection closed by foreign host. - % - Look for the message in your mailbox. -29. Remote-local test: Send yourself some mail from another machine. -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 - remote account, with your normal user agent. -32. Remote-postmaster test: Send mail from another machine to - PoStMaStEr@domain. Look for the message in ~alias/Mailbox. + +18. Read TEST.receive. + That's it! To report success: - % ( echo 'First M. Last'; cat `cat SYSDEPS` ) \ - | mail djb-qst@koobera.math.uic.edu -Replace First M. Last with your name. If you have questions about qmail, -contact qmail@pobox.com. + % ( echo 'First M. Last'; cat `cat SYSDEPS` ) | mail djb-qst@cr.yp.to +Replace First M. Last with your name. + +If you have questions about qmail, join the qmail mailing list; see +http://pobox.com/~djb/qmail.html. diff --git a/INSTALL.alias b/INSTALL.alias index 5721da1..672365a 100644 --- a/INSTALL.alias +++ b/INSTALL.alias @@ -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 user, alias. Delivery instructions for foo go into ~alias/.qmail-foo; 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 -big /etc/aliases and you'd like to keep it, install the qmsmac package, -available separately. /etc/aliases should already include the aliases -discussed below---Postmaster, MAILER-DAEMON, and root. +big /etc/aliases and you'd like to keep it, install the fastforward +package, available separately. /etc/aliases should already include the +aliases discussed below---Postmaster, MAILER-DAEMON, and root. 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 diff --git a/INSTALL.boot b/INSTALL.boot deleted file mode 100644 index 0010288..0000000 --- a/INSTALL.boot +++ /dev/null @@ -1,16 +0,0 @@ -The qmail daemons have to be restarted whenever your system reboots. -Meanwhile, sendmail doesn't have to be started any more. Here's what you -should do. - -Find sendmail in your boot scripts. It's usually in either /etc/rc or -/etc/init.d/sendmail. It looks like - - sendmail -bd -q15m - --q15m means it should run the queue every 15 minutes; you may see a -different number. Comment out this line, and replace it with - - env - PATH="/var/qmail/bin:$PATH" \ - csh -cf 'qmail-start ./Mailbox splogger qmail &' - -That's it. (Make sure you include the ./ and the &.) diff --git a/INSTALL.ctl b/INSTALL.ctl index f493fcf..00ce689 100644 --- a/INSTALL.ctl +++ b/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 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 -way to do this is to run the qmail-config script: +There's one big exception. You MUST tell qmail your hostname. Just run +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 -control/me. It also selects good defaults for a few other controls. +config-fast puts your.full.host.name into control/me. It also puts it +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 design decision. qmail does all its local functions---header rewriting, diff --git a/INSTALL.ids b/INSTALL.ids index e0e4ee2..a50e10d 100644 --- a/INSTALL.ids +++ b/INSTALL.ids @@ -1,6 +1,7 @@ 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 # 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 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: # addgroup nofiles diff --git a/INSTALL.maildir b/INSTALL.maildir new file mode 100644 index 0000000..72373aa --- /dev/null +++ b/INSTALL.maildir @@ -0,0 +1,59 @@ +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. + + +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. diff --git a/INSTALL.mbox b/INSTALL.mbox index a62a181..93ca16c 100644 --- a/INSTALL.mbox +++ b/INSTALL.mbox @@ -2,111 +2,52 @@ The qmail package includes a local delivery agent, qmail-local, which provides user-controlled mailing lists, cross-host alias loop detection, and many other important qmail features. -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 -mail by default into ~user/Mailbox (in mbox format). +There's one important difference between qmail-local and binmail: +qmail-local delivers mail by default into ~user/Mailbox, rather than +/var/spool/mail/user. It uses mbox format, with lockf locking on systems +that don't have flock (HP/UX, Solaris), and flock locking otherwise. -This file explains what you should do to deal with this change. It also -points out some reasons that you might want to make an even bigger -change, switching from mbox format to a new format, maildir. +This file explains how to switch your system to ~user/Mailbox. You +aren't required to do this; for further discussion of /var/spool/mail, +and an explanation of how to continue using binmail for local +deliveries, see INSTALL.vsm. -If you desperately don't want to change anything, see INSTALL.qsmhook. +The basic procedure for switching to ~user/Mailbox is simple: + * Move each /var/spool/mail/user to ~user/Mailbox. For safety, do + this in single-user mode. -Contents: -1. Throw away /usr/spool/mail! -2. The trouble with mbox -3. Sun's Network F_ail_u_re System + * As root, set up a symbolic link from /var/spool/mail/user to + ~user/Mailbox for each user. /var/spool/mail should be mode 1777, + so users will not be able to accidentally remove these links. +A few mail programs are unable to handle symbolic links, so you will +have to configure them to look at ~user/Mailbox directly: -1. Throw away /usr/spool/mail! + * procmail: Change SYSTEM_MBOX in config.h and recompile; or, with + recent versions, define MAILSPOOLHOME in src/authenticate.c. -/usr/spool/mail, often called /var/spool/mail or /var/mail, is a -security disaster. A user's mailbox belongs in his home directory, not a -shared directory. Even if you don't install qmail, you should destroy -/usr/spool/mail. This takes four steps: +An alternative to symbolic links is hlfsd. Consult the documentation for +hlfsd if it is included in your operating system. - A. Convince your local mailer to deliver to ~user/Mailbox. If you're - using something like procmail, this is easy---just change SYSTEM_MBOX - in config.h. If you're installing qmail, you don't have to do - anything. Otherwise, take a look at hlfsd from - ftp.cs.columbia.edu/pub/amd. +If /var/spool/mail is large, you can gain extra speed by configuring +all your mail software to look at ~user/Mailbox directly: - B. Move each /usr/spool/mail/user to ~user/Mailbox. For safety, do - this in single-user mode---you don't want to risk corrupting - 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. + * Most MUAs: Put ``setenv MAIL $HOME/Mailbox'' in your system-wide + .cshrc and ``MAIL=$HOME/Mailbox; export MAIL'' in your system-wide + .profile. - C. Put ``setenv MAIL $HOME/Mailbox'' in your system-wide .cshrc, - ``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. + * elm: Change "mailbox" to "Mailbox" around line 388 of newmbox.c and + recompile. (elm looks at $MAIL, but without this change elm will + fail if two users try to read mail simultaneously.) - D. Announce the change. + * pine: Put ``inbox-path=Mailbox'' in your system-wide pine.conf. + (For pine versions more recent than 3.91, see also FAQ 6.2.) -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. -After you get rid of /usr/spool/mail, you can also disable 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. + * qpopper 2.2: Change /.mail to /Mailbox in pop_dropcopy.c and + recompile with -DHOMEDIRMAIL in CFLAGS. - -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. +Some vendors, in a misguided attempt to solve the security problems of +/var/spool/mail, have made all their mail software setgid mail. After +you move the mailboxes, you can---and, for security, should---remove +those setgid-mail bits. diff --git a/INSTALL.qsmhook b/INSTALL.qsmhook deleted file mode 100644 index 952fcd2..0000000 --- a/INSTALL.qsmhook +++ /dev/null @@ -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 diff --git a/INSTALL.vsm b/INSTALL.vsm new file mode 100644 index 0000000..cf6a6cc --- /dev/null +++ b/INSTALL.vsm @@ -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. diff --git a/INTERNALS b/INTERNALS index ee80517..e668ae8 100644 --- a/INTERNALS +++ b/INTERNALS @@ -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 as DONE. If the delivery attempt meets with permanent failure, 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 a new bounce message, created from bounce/457 and mess/457; (2) deletes diff --git a/Makefile b/Makefile index 96a352c..9230887 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +# Don't edit Makefile! Use conf-* for configuration. + SHELL=/bin/sh default: it @@ -11,11 +13,11 @@ makelib alloc.o alloc_re.o ./makelib alloc.a alloc.o alloc_re.o alloc.o: \ -compile alloc.c alloc.h alloc.c error.h alloc.c +compile alloc.c alloc.h error.h ./compile alloc.c alloc_re.o: \ -compile alloc_re.c alloc.h alloc_re.c byte.h alloc_re.c +compile alloc_re.c alloc.h byte.h ./compile alloc_re.c auto-ccld.sh: \ @@ -30,9 +32,8 @@ load auto-gid.o substdio.a error.a str.a fs.a ./load auto-gid substdio.a error.a str.a fs.a auto-gid.o: \ -compile auto-gid.c auto-gid.c auto-gid.c subfd.h substdio.h subfd.h \ -auto-gid.c substdio.h substdio.h auto-gid.c readwrite.h auto-gid.c \ -exit.h auto-gid.c scan.h auto-gid.c fmt.h auto-gid.c +compile auto-gid.c subfd.h substdio.h substdio.h readwrite.h exit.h \ +scan.h fmt.h ./compile auto-gid.c auto-int: \ @@ -40,8 +41,7 @@ load auto-int.o substdio.a error.a str.a fs.a ./load auto-int substdio.a error.a str.a fs.a auto-int.o: \ -compile auto-int.c substdio.h auto-int.c readwrite.h auto-int.c \ -exit.h auto-int.c scan.h auto-int.c fmt.h auto-int.c +compile auto-int.c substdio.h readwrite.h exit.h scan.h fmt.h ./compile auto-int.c auto-int8: \ @@ -49,8 +49,7 @@ load auto-int8.o substdio.a error.a str.a fs.a ./load auto-int8 substdio.a error.a str.a fs.a auto-int8.o: \ -compile auto-int8.c substdio.h auto-int8.c readwrite.h auto-int8.c \ -exit.h auto-int8.c scan.h auto-int8.c fmt.h auto-int8.c +compile auto-int8.c substdio.h readwrite.h exit.h scan.h fmt.h ./compile auto-int8.c auto-str: \ @@ -58,8 +57,7 @@ load auto-str.o substdio.a error.a str.a ./load auto-str substdio.a error.a str.a auto-str.o: \ -compile auto-str.c substdio.h auto-str.c readwrite.h auto-str.c \ -exit.h auto-str.c +compile auto-str.c substdio.h readwrite.h exit.h ./compile auto-str.c auto-uid: \ @@ -67,9 +65,8 @@ load auto-uid.o substdio.a error.a str.a fs.a ./load auto-uid substdio.a error.a str.a fs.a auto-uid.o: \ -compile auto-uid.c auto-uid.c auto-uid.c subfd.h substdio.h subfd.h \ -auto-uid.c substdio.h substdio.h auto-uid.c readwrite.h auto-uid.c \ -exit.h auto-uid.c scan.h auto-uid.c fmt.h auto-uid.c +compile auto-uid.c subfd.h substdio.h substdio.h readwrite.h exit.h \ +scan.h fmt.h ./compile auto-uid.c auto_break.c: \ @@ -125,7 +122,7 @@ auto-uid auto-gid conf-users conf-groups &&./auto-uid auto_uids `head -8 conf-users | tail -1` \ &&./auto-gid auto_gidq `head -1 conf-groups` \ &&./auto-gid auto_gidn `head -2 conf-groups | tail -1` \ - ) > auto_uids.c + ) > auto_uids.c.tmp && mv auto_uids.c.tmp auto_uids.c auto_uids.o: \ compile auto_uids.c @@ -139,28 +136,83 @@ auto_usera.o: \ compile auto_usera.c ./compile auto_usera.c +binm1: \ +binm1.sh conf-qmail + cat binm1.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > binm1 + chmod 755 binm1 + +binm1+df: \ +binm1+df.sh conf-qmail + cat binm1+df.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > binm1+df + chmod 755 binm1+df + +binm2: \ +binm2.sh conf-qmail + cat binm2.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > binm2 + chmod 755 binm2 + +binm2+df: \ +binm2+df.sh conf-qmail + cat binm2+df.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > binm2+df + chmod 755 binm2+df + +binm3: \ +binm3.sh conf-qmail + cat binm3.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > binm3 + chmod 755 binm3 + +binm3+df: \ +binm3+df.sh conf-qmail + cat binm3+df.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > binm3+df + chmod 755 binm3+df + +bouncesaying: \ +load bouncesaying.o strerr.a error.a substdio.a str.a wait.a + ./load bouncesaying strerr.a error.a substdio.a str.a \ + wait.a + +bouncesaying.0: \ +bouncesaying.1 + nroff -man bouncesaying.1 > bouncesaying.0 + +bouncesaying.o: \ +compile bouncesaying.c fork.h strerr.h error.h wait.h sig.h exit.h + ./compile bouncesaying.c + byte_chr.o: \ -compile byte_chr.c byte.h byte_chr.c +compile byte_chr.c byte.h ./compile byte_chr.c byte_copy.o: \ -compile byte_copy.c byte.h byte_copy.c +compile byte_copy.c byte.h ./compile byte_copy.c byte_cr.o: \ -compile byte_cr.c byte.h byte_cr.c +compile byte_cr.c byte.h ./compile byte_cr.c byte_diff.o: \ -compile byte_diff.c byte.h byte_diff.c +compile byte_diff.c byte.h ./compile byte_diff.c byte_rchr.o: \ -compile byte_rchr.c byte.h byte_rchr.c +compile byte_rchr.c byte.h ./compile byte_rchr.c byte_zero.o: \ -compile byte_zero.c byte.h byte_zero.c +compile byte_zero.c byte.h ./compile byte_zero.c case.a: \ @@ -170,23 +222,23 @@ case_starts.o case_lowers.o case_starts.o case_diffb.o: \ -compile case_diffb.c case.h case_diffb.c +compile case_diffb.c case.h ./compile case_diffb.c case_diffs.o: \ -compile case_diffs.c case.h case_diffs.c +compile case_diffs.c case.h ./compile case_diffs.c case_lowerb.o: \ -compile case_lowerb.c case.h case_lowerb.c +compile case_lowerb.c case.h ./compile case_lowerb.c case_lowers.o: \ -compile case_lowers.c case.h case_lowers.c +compile case_lowers.c case.h ./compile case_lowers.c case_starts.o: \ -compile case_starts.c case.h case_starts.c +compile case_starts.c case.h ./compile case_starts.c cdb.a: \ @@ -194,16 +246,15 @@ makelib cdb_hash.o cdb_unpack.o cdb_seek.o ./makelib cdb.a cdb_hash.o cdb_unpack.o cdb_seek.o cdb_hash.o: \ -compile cdb_hash.c cdb.h uint32.h cdb.h cdb_hash.c +compile cdb_hash.c cdb.h uint32.h ./compile cdb_hash.c cdb_seek.o: \ -compile cdb_seek.c cdb_seek.c cdb_seek.c cdb.h uint32.h cdb.h \ -cdb_seek.c +compile cdb_seek.c cdb.h uint32.h ./compile cdb_seek.c cdb_unpack.o: \ -compile cdb_unpack.c cdb.h uint32.h cdb.h cdb_unpack.c +compile cdb_unpack.c cdb.h uint32.h ./compile cdb_unpack.c cdbmake.a: \ @@ -212,33 +263,32 @@ makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o cdbmake_add.o cdbmake_add.o: \ -compile cdbmake_add.c cdbmake.h uint32.h cdbmake.h cdbmake_add.c +compile cdbmake_add.c cdbmake.h uint32.h ./compile cdbmake_add.c cdbmake_hash.o: \ -compile cdbmake_hash.c cdbmake.h uint32.h cdbmake.h cdbmake_hash.c +compile cdbmake_hash.c cdbmake.h uint32.h ./compile cdbmake_hash.c cdbmake_pack.o: \ -compile cdbmake_pack.c cdbmake.h uint32.h cdbmake.h cdbmake_pack.c +compile cdbmake_pack.c cdbmake.h uint32.h ./compile cdbmake_pack.c cdbmss.o: \ -compile cdbmss.c readwrite.h cdbmss.c seek.h cdbmss.c alloc.h \ -cdbmss.c cdbmss.h cdbmake.h uint32.h cdbmake.h cdbmss.h substdio.h \ -cdbmss.h cdbmss.c +compile cdbmss.c readwrite.h seek.h alloc.h cdbmss.h cdbmake.h \ +uint32.h substdio.h ./compile cdbmss.c check: \ -it man conf-qmail - ./qmail-hier | ./instcheck `head -1 conf-qmail` +it man + ./instcheck chkshsgr: \ load chkshsgr.o ./load chkshsgr chkshsgr.o: \ -compile chkshsgr.c exit.h chkshsgr.c +compile chkshsgr.c exit.h ./compile chkshsgr.c chkspawn: \ @@ -246,10 +296,8 @@ load chkspawn.o substdio.a error.a str.a fs.a auto_spawn.o ./load chkspawn substdio.a error.a str.a fs.a auto_spawn.o chkspawn.o: \ -compile chkspawn.c substdio.h chkspawn.c subfd.h substdio.h \ -substdio.h subfd.h chkspawn.c fmt.h chkspawn.c select.h select.h \ -select.h select.h chkspawn.c exit.h chkspawn.c auto_spawn.h \ -chkspawn.c +compile chkspawn.c substdio.h subfd.h substdio.h fmt.h select.h \ +exit.h auto_spawn.h ./compile chkspawn.c clean: \ @@ -257,9 +305,14 @@ TARGETS rm -f `cat TARGETS` coe.o: \ -compile coe.c coe.c coe.h coe.c +compile coe.c coe.h ./compile coe.c +commands.o: \ +compile commands.c commands.h substdio.h stralloc.h gen_alloc.h str.h \ +case.h + ./compile commands.c + compile: \ make-compile warn-auto.sh systype ( cat warn-auto.sh; ./make-compile "`cat systype`" ) > \ @@ -267,39 +320,49 @@ make-compile warn-auto.sh systype chmod 755 compile condredirect: \ -load condredirect.o qmail.o fd.a sig.a wait.a seek.a env.a alloc.a \ -substdio.a error.a str.a auto_qmail.o - ./load condredirect qmail.o fd.a sig.a wait.a seek.a env.a \ - alloc.a substdio.a error.a str.a auto_qmail.o +load condredirect.o qmail.o strerr.a fd.a sig.a wait.a seek.a env.a \ +substdio.a error.a str.a fs.a auto_qmail.o + ./load condredirect qmail.o strerr.a fd.a sig.a wait.a \ + seek.a env.a substdio.a error.a str.a fs.a auto_qmail.o condredirect.0: \ condredirect.1 nroff -man condredirect.1 > condredirect.0 condredirect.o: \ -compile condredirect.c sig.h condredirect.c readwrite.h \ -condredirect.c exit.h condredirect.c env.h condredirect.c error.h \ -condredirect.c fork.h condredirect.c wait.h condredirect.c seek.h \ -condredirect.c qmail.h substdio.h qmail.h condredirect.c stralloc.h \ -gen_alloc.h stralloc.h condredirect.c subfd.h substdio.h substdio.h \ -subfd.h condredirect.c substdio.h substdio.h condredirect.c +compile condredirect.c sig.h readwrite.h exit.h env.h error.h fork.h \ +wait.h seek.h qmail.h substdio.h strerr.h substdio.h fmt.h ./compile condredirect.c +config: \ +warn-auto.sh config.sh conf-qmail conf-break conf-split + cat warn-auto.sh config.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}BREAK}"`head -1 conf-break`"}g \ + | sed s}SPLIT}"`head -1 conf-split`"}g \ + > config + chmod 755 config + +config-fast: \ +warn-auto.sh config-fast.sh conf-qmail conf-break conf-split + cat warn-auto.sh config-fast.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}BREAK}"`head -1 conf-break`"}g \ + | sed s}SPLIT}"`head -1 conf-split`"}g \ + > config-fast + chmod 755 config-fast + constmap.o: \ -compile constmap.c constmap.h constmap.c alloc.h constmap.c case.h \ -constmap.c +compile constmap.c constmap.h alloc.h case.h ./compile constmap.c control.o: \ -compile control.c readwrite.h control.c open.h control.c getln.h \ -control.c stralloc.h gen_alloc.h stralloc.h control.c substdio.h \ -control.c error.h control.c control.h control.c alloc.h control.c \ -scan.h control.c +compile control.c readwrite.h open.h getln.h stralloc.h gen_alloc.h \ +substdio.h error.h control.h alloc.h scan.h ./compile control.c date822fmt.o: \ -compile date822fmt.c datetime.h date822fmt.c fmt.h date822fmt.c \ -date822fmt.h date822fmt.c +compile date822fmt.c datetime.h fmt.h date822fmt.h ./compile date822fmt.c datemail: \ @@ -316,11 +379,11 @@ makelib datetime.o datetime_un.o ./makelib datetime.a datetime.o datetime_un.o datetime.o: \ -compile datetime.c datetime.h datetime.c +compile datetime.c datetime.h ./compile datetime.c datetime_un.o: \ -compile datetime_un.c datetime.h datetime_un.c +compile datetime_un.c datetime.h ./compile datetime_un.c direntry.h: \ @@ -339,10 +402,8 @@ alloc.a error.a fs.a str.a rm -f tryrsolv.o tryrsolv dns.o: \ -compile dns.c dns.c dns.c dns.c dns.c dns.c dns.c dns.c ip.h dns.c \ -ipalloc.h ip.h ip.h ipalloc.h gen_alloc.h ipalloc.h dns.c fmt.h dns.c \ -alloc.h dns.c str.h dns.c stralloc.h gen_alloc.h stralloc.h dns.c \ -dns.h dns.c case.h dns.c +compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \ +stralloc.h gen_alloc.h dns.h case.h ./compile dns.c dnscname: \ @@ -353,15 +414,12 @@ substdio.a error.a str.a fs.a dns.lib socket.lib socket.lib` dnscname.o: \ -compile dnscname.c substdio.h dnscname.c subfd.h substdio.h \ -substdio.h subfd.h dnscname.c stralloc.h gen_alloc.h stralloc.h \ -dnscname.c dns.h dnscname.c dnsdoe.h dnscname.c readwrite.h \ -dnscname.c exit.h dnscname.c +compile dnscname.c substdio.h subfd.h substdio.h stralloc.h \ +gen_alloc.h dns.h dnsdoe.h readwrite.h exit.h ./compile dnscname.c dnsdoe.o: \ -compile dnsdoe.c substdio.h dnsdoe.c subfd.h substdio.h substdio.h \ -subfd.h dnsdoe.c exit.h dnsdoe.c dns.h dnsdoe.c dnsdoe.h dnsdoe.c +compile dnsdoe.c substdio.h subfd.h substdio.h exit.h dns.h dnsdoe.h ./compile dnsdoe.c dnsfq: \ @@ -372,10 +430,8 @@ substdio.a error.a str.a fs.a dns.lib socket.lib socket.lib` dnsfq.o: \ -compile dnsfq.c substdio.h dnsfq.c subfd.h substdio.h substdio.h \ -subfd.h dnsfq.c stralloc.h gen_alloc.h stralloc.h dnsfq.c dns.h \ -dnsfq.c dnsdoe.h dnsfq.c ip.h dnsfq.c ipalloc.h ip.h ip.h ipalloc.h \ -gen_alloc.h ipalloc.h dnsfq.c exit.h dnsfq.c +compile dnsfq.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \ +dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h ./compile dnsfq.c dnsip: \ @@ -386,10 +442,8 @@ substdio.a error.a str.a fs.a dns.lib socket.lib socket.lib` dnsip.o: \ -compile dnsip.c substdio.h dnsip.c subfd.h substdio.h substdio.h \ -subfd.h dnsip.c stralloc.h gen_alloc.h stralloc.h dnsip.c dns.h \ -dnsip.c dnsdoe.h dnsip.c ip.h dnsip.c ipalloc.h ip.h ip.h ipalloc.h \ -gen_alloc.h ipalloc.h dnsip.c exit.h dnsip.c +compile dnsip.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \ +dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h ./compile dnsip.c dnsmxip: \ @@ -400,11 +454,9 @@ substdio.a error.a str.a fs.a dns.lib socket.lib dns.lib` `cat socket.lib` dnsmxip.o: \ -compile dnsmxip.c substdio.h dnsmxip.c subfd.h substdio.h substdio.h \ -subfd.h dnsmxip.c stralloc.h gen_alloc.h stralloc.h dnsmxip.c fmt.h \ -dnsmxip.c dns.h dnsmxip.c dnsdoe.h dnsmxip.c ip.h dnsmxip.c ipalloc.h \ -ip.h ip.h ipalloc.h gen_alloc.h ipalloc.h dnsmxip.c now.h datetime.h \ -now.h dnsmxip.c exit.h dnsmxip.c +compile dnsmxip.c substdio.h subfd.h substdio.h stralloc.h \ +gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h \ +now.h datetime.h exit.h ./compile dnsmxip.c dnsptr: \ @@ -415,10 +467,8 @@ substdio.a error.a str.a fs.a dns.lib socket.lib socket.lib` dnsptr.o: \ -compile dnsptr.c substdio.h dnsptr.c subfd.h substdio.h substdio.h \ -subfd.h dnsptr.c stralloc.h gen_alloc.h stralloc.h dnsptr.c str.h \ -dnsptr.c scan.h dnsptr.c dns.h dnsptr.c dnsdoe.h dnsptr.c ip.h \ -dnsptr.c exit.h dnsptr.c +compile dnsptr.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \ +str.h scan.h dns.h dnsdoe.h ip.h exit.h ./compile dnsptr.c dot-qmail.0: \ @@ -447,7 +497,7 @@ makelib env.o envread.o ./makelib env.a env.o envread.o env.o: \ -compile env.c str.h env.c alloc.h env.c env.h env.c +compile env.c str.h alloc.h env.h ./compile env.c envelopes.0: \ @@ -455,7 +505,7 @@ envelopes.5 nroff -man envelopes.5 > envelopes.0 envread.o: \ -compile envread.c env.h envread.c str.h envread.c +compile envread.c env.h str.h ./compile envread.c error.a: \ @@ -463,31 +513,43 @@ makelib error.o error_str.o error_temp.o ./makelib error.a error.o error_str.o error_temp.o error.o: \ -compile error.c error.c error.h error.c +compile error.c error.h ./compile error.c error_str.o: \ -compile error_str.c error_str.c error.h error_str.c +compile error_str.c error.h ./compile error_str.c error_temp.o: \ -compile error_temp.c error_temp.c error.h error_temp.c +compile error_temp.c error.h ./compile error_temp.c +except: \ +load except.o strerr.a error.a substdio.a str.a wait.a + ./load except strerr.a error.a substdio.a str.a wait.a + +except.0: \ +except.1 + nroff -man except.1 > except.0 + +except.o: \ +compile except.c fork.h strerr.h wait.h error.h exit.h + ./compile except.c + fd.a: \ makelib fd_copy.o fd_move.o ./makelib fd.a fd_copy.o fd_move.o fd_copy.o: \ -compile fd_copy.c fd_copy.c fd.h fd_copy.c +compile fd_copy.c fd.h ./compile fd_copy.c fd_move.o: \ -compile fd_move.c fd.h fd_move.c +compile fd_move.c fd.h ./compile fd_move.c fifo.o: \ -compile fifo.c fifo.c fifo.c hasmkffo.h fifo.c fifo.h fifo.c +compile fifo.c hasmkffo.h fifo.h ./compile fifo.c find-systype: \ @@ -496,28 +558,27 @@ find-systype.sh auto-ccld.sh chmod 755 find-systype fmt_str.o: \ -compile fmt_str.c fmt.h fmt_str.c +compile fmt_str.c fmt.h ./compile fmt_str.c fmt_strn.o: \ -compile fmt_strn.c fmt.h fmt_strn.c +compile fmt_strn.c fmt.h ./compile fmt_strn.c fmt_uint.o: \ -compile fmt_uint.c fmt.h fmt_uint.c +compile fmt_uint.c fmt.h ./compile fmt_uint.c fmt_uint0.o: \ -compile fmt_uint0.c fmt.h fmt_uint0.c +compile fmt_uint0.c fmt.h ./compile fmt_uint0.c fmt_ulong.o: \ -compile fmt_ulong.c fmt.h fmt_ulong.c +compile fmt_ulong.c fmt.h ./compile fmt_ulong.c fmtqfn.o: \ -compile fmtqfn.c fmtqfn.h fmtqfn.c fmt.h fmtqfn.c auto_split.h \ -fmtqfn.c +compile fmtqfn.c fmtqfn.h fmt.h auto_split.h ./compile fmtqfn.c forgeries.0: \ @@ -532,40 +593,36 @@ compile load tryvfork.c fork.h1 fork.h2 rm -f tryvfork.o tryvfork forward: \ -load forward.o stralloc.a alloc.a qmail.o fd.a wait.a sig.a env.a \ -substdio.a error.a str.a auto_qmail.o - ./load forward stralloc.a alloc.a qmail.o fd.a wait.a \ - sig.a env.a substdio.a error.a str.a auto_qmail.o +load forward.o qmail.o strerr.a alloc.a fd.a wait.a sig.a env.a \ +substdio.a error.a str.a fs.a auto_qmail.o + ./load forward qmail.o strerr.a alloc.a fd.a wait.a sig.a \ + env.a substdio.a error.a str.a fs.a auto_qmail.o forward.0: \ forward.1 nroff -man forward.1 > forward.0 forward.o: \ -compile forward.c sig.h forward.c readwrite.h forward.c exit.h \ -forward.c env.h forward.c qmail.h substdio.h qmail.h forward.c \ -stralloc.h gen_alloc.h stralloc.h forward.c subfd.h substdio.h \ -substdio.h subfd.h forward.c substdio.h substdio.h forward.c +compile forward.c sig.h readwrite.h exit.h env.h qmail.h substdio.h \ +strerr.h substdio.h fmt.h ./compile forward.c fs.a: \ makelib fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o fmt_ulong.o \ -scan_ulong.o scan_8long.o scan_nbblong.o +scan_ulong.o scan_8long.o ./makelib fs.a fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o \ - fmt_ulong.o scan_ulong.o scan_8long.o scan_nbblong.o + fmt_ulong.o scan_ulong.o scan_8long.o getln.a: \ makelib getln.o getln2.o ./makelib getln.a getln.o getln2.o getln.o: \ -compile getln.c substdio.h getln.c byte.h getln.c stralloc.h \ -gen_alloc.h stralloc.h getln.c getln.h getln.c +compile getln.c substdio.h byte.h stralloc.h gen_alloc.h getln.h ./compile getln.c getln2.o: \ -compile getln2.c substdio.h getln2.c stralloc.h gen_alloc.h \ -stralloc.h getln2.c byte.h getln2.c getln.h getln2.c +compile getln2.c substdio.h stralloc.h gen_alloc.h byte.h getln.h ./compile getln2.c getopt.a: \ @@ -573,7 +630,7 @@ makelib subgetopt.o sgetopt.o ./makelib getopt.a subgetopt.o sgetopt.o gfrom.o: \ -compile gfrom.c str.h gfrom.c gfrom.h gfrom.c +compile gfrom.c str.h gfrom.h ./compile gfrom.c hasflock.h: \ @@ -636,68 +693,97 @@ trywaitp.c compile load rm -f trywaitp.o trywaitp headerbody.o: \ -compile headerbody.c stralloc.h gen_alloc.h stralloc.h headerbody.c \ -substdio.h headerbody.c getln.h headerbody.c hfield.h headerbody.c \ -headerbody.h headerbody.c +compile headerbody.c stralloc.h gen_alloc.h substdio.h getln.h \ +hfield.h headerbody.h ./compile headerbody.c hfield.o: \ -compile hfield.c hfield.h hfield.c +compile hfield.c hfield.h ./compile hfield.c +hier.o: \ +compile hier.c auto_qmail.h auto_split.h auto_uids.h fmt.h fifo.h + ./compile hier.c + +home: \ +home.sh conf-qmail + cat home.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > home + chmod 755 home + +home+df: \ +home+df.sh conf-qmail + cat home+df.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > home+df + chmod 755 home+df + hostname: \ load hostname.o substdio.a error.a str.a dns.lib socket.lib ./load hostname substdio.a error.a str.a `cat dns.lib` \ `cat socket.lib` hostname.o: \ -compile hostname.c substdio.h hostname.c subfd.h substdio.h \ -substdio.h subfd.h hostname.c readwrite.h hostname.c exit.h \ -hostname.c +compile hostname.c substdio.h subfd.h substdio.h readwrite.h exit.h ./compile hostname.c +idedit: \ +load idedit.o strerr.a substdio.a error.a str.a fs.a wait.a open.a \ +seek.a + ./load idedit strerr.a substdio.a error.a str.a fs.a \ + wait.a open.a seek.a + +idedit.o: \ +compile idedit.c readwrite.h exit.h scan.h fmt.h strerr.h open.h \ +seek.h fork.h + ./compile idedit.c + install: \ -load install.o fifo.o getln.a strerr.a substdio.a stralloc.a alloc.a \ -open.a error.a str.a fs.a - ./load install fifo.o getln.a strerr.a substdio.a \ - stralloc.a alloc.a open.a error.a str.a fs.a +load install.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \ +strerr.a substdio.a open.a error.a str.a fs.a + ./load install fifo.o hier.o auto_qmail.o auto_split.o \ + auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a + +install-big: \ +load install-big.o fifo.o install.o auto_qmail.o auto_split.o \ +auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a + ./load install-big fifo.o install.o auto_qmail.o \ + auto_split.o auto_uids.o strerr.a substdio.a open.a error.a \ + str.a fs.a + +install-big.o: \ +compile install-big.c auto_qmail.h auto_split.h auto_uids.h fmt.h \ +fifo.h + ./compile install-big.c install.o: \ -compile install.c substdio.h install.c stralloc.h gen_alloc.h \ -stralloc.h install.c getln.h install.c readwrite.h install.c exit.h \ -install.c open.h install.c error.h install.c strerr.h install.c \ -byte.h install.c fifo.h install.c +compile install.c substdio.h strerr.h error.h open.h readwrite.h \ +exit.h ./compile install.c instcheck: \ -load instcheck.o getln.a strerr.a substdio.a stralloc.a alloc.a \ -error.a str.a fs.a - ./load instcheck getln.a strerr.a substdio.a stralloc.a \ - alloc.a error.a str.a fs.a +load instcheck.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \ +strerr.a substdio.a error.a str.a fs.a + ./load instcheck fifo.o hier.o auto_qmail.o auto_split.o \ + auto_uids.o strerr.a substdio.a error.a str.a fs.a instcheck.o: \ -compile instcheck.c instcheck.c instcheck.c substdio.h instcheck.c \ -stralloc.h gen_alloc.h stralloc.h instcheck.c getln.h instcheck.c \ -readwrite.h instcheck.c exit.h instcheck.c error.h instcheck.c \ -strerr.h instcheck.c byte.h instcheck.c +compile instcheck.c strerr.h error.h readwrite.h exit.h ./compile instcheck.c ip.o: \ -compile ip.c fmt.h ip.c scan.h ip.c ip.h ip.c +compile ip.c fmt.h scan.h ip.h ./compile ip.c ipalloc.o: \ -compile ipalloc.c alloc.h ipalloc.c gen_allocdefs.h gen_allocdefs.h \ -gen_allocdefs.h ipalloc.c ip.h ipalloc.c ipalloc.h ip.h ip.h \ -ipalloc.h gen_alloc.h ipalloc.h ipalloc.c +compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h ip.h \ +gen_alloc.h ./compile ipalloc.c ipme.o: \ -compile ipme.c ipme.c ipme.c ipme.c ipme.c ipme.c ipme.c ipme.c \ -hassalen.h ipme.c byte.h ipme.c ip.h ipme.c ipalloc.h ip.h ip.h \ -ipalloc.h gen_alloc.h ipalloc.h ipme.c stralloc.h gen_alloc.h \ -stralloc.h ipme.c ipme.h ip.h ip.h ipme.h ipalloc.h ipalloc.h ipme.h \ -ipme.c ipme.c +compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \ +stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h ./compile ipme.c ipmeprint: \ @@ -707,21 +793,22 @@ error.a str.a fs.a socket.lib substdio.a error.a str.a fs.a `cat socket.lib` ipmeprint.o: \ -compile ipmeprint.c subfd.h substdio.h subfd.h ipmeprint.c substdio.h \ -substdio.h ipmeprint.c ip.h ipmeprint.c ipme.h ip.h ip.h ipme.h \ -ipalloc.h ip.h ip.h ipalloc.h gen_alloc.h ipalloc.h ipme.h \ -ipmeprint.c exit.h ipmeprint.c +compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \ +ipalloc.h ip.h gen_alloc.h exit.h ./compile ipmeprint.c it: \ qmail-local qmail-lspawn qmail-getpw qmail-remote qmail-rspawn \ qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \ -predate datemail mailsubj qmail-upq qmail-config qmail-showctl \ -qmail-newu qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-pop3d \ -qmail-popup qmail-qmtpd qmail-smtpd sendmail tcp-env dnscname dnsptr \ -dnsip dnsmxip dnsfq hostname ipmeprint qlist qlist2 qreceipt qsmhook \ -qbiff forward preline condredirect maildirmake maildir2mbox \ -maildirwatch qail elq pinq qmail-hier install instcheck +predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \ +qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \ +qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \ +qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \ +dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ +forward preline condredirect bouncesaying except maildirmake \ +maildir2mbox maildirwatch qail elq pinq idedit install-big install \ +instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \ +binm3 binm3+df load: \ make-load warn-auto.sh systype @@ -733,18 +820,15 @@ makelib lock_ex.o lock_exnb.o lock_un.o ./makelib lock.a lock_ex.o lock_exnb.o lock_un.o lock_ex.o: \ -compile lock_ex.c lock_ex.c lock_ex.c lock_ex.c hasflock.h lock_ex.c \ -lock.h lock_ex.c +compile lock_ex.c hasflock.h lock.h ./compile lock_ex.c lock_exnb.o: \ -compile lock_exnb.c lock_exnb.c lock_exnb.c lock_exnb.c hasflock.h \ -lock_exnb.c lock.h lock_exnb.c +compile lock_exnb.c hasflock.h lock.h ./compile lock_exnb.c lock_un.o: \ -compile lock_un.c lock_un.c lock_un.c lock_un.c hasflock.h lock_un.c \ -lock.h lock_un.c +compile lock_un.c hasflock.h lock.h ./compile lock_un.c maildir.0: \ @@ -752,11 +836,9 @@ maildir.5 nroff -man maildir.5 > maildir.0 maildir.o: \ -compile maildir.c maildir.c maildir.c prioq.h datetime.h prioq.h \ -gen_alloc.h prioq.h maildir.c env.h maildir.c stralloc.h gen_alloc.h \ -stralloc.h maildir.c direntry.h direntry.h direntry.h maildir.c \ -datetime.h datetime.h maildir.c now.h datetime.h datetime.h now.h \ -maildir.c str.h maildir.c maildir.h strerr.h maildir.h maildir.c +compile maildir.c prioq.h datetime.h gen_alloc.h env.h stralloc.h \ +gen_alloc.h direntry.h datetime.h now.h datetime.h str.h maildir.h \ +strerr.h ./compile maildir.c maildir2mbox: \ @@ -772,28 +854,22 @@ maildir2mbox.1 nroff -man maildir2mbox.1 > maildir2mbox.0 maildir2mbox.o: \ -compile maildir2mbox.c readwrite.h maildir2mbox.c prioq.h datetime.h \ -prioq.h gen_alloc.h prioq.h maildir2mbox.c env.h maildir2mbox.c \ -stralloc.h gen_alloc.h stralloc.h maildir2mbox.c subfd.h substdio.h \ -subfd.h maildir2mbox.c substdio.h substdio.h maildir2mbox.c getln.h \ -maildir2mbox.c error.h maildir2mbox.c open.h maildir2mbox.c lock.h \ -maildir2mbox.c gfrom.h maildir2mbox.c str.h maildir2mbox.c exit.h \ -maildir2mbox.c myctime.h maildir2mbox.c maildir.h strerr.h maildir.h \ -maildir2mbox.c +compile maildir2mbox.c readwrite.h prioq.h datetime.h gen_alloc.h \ +env.h stralloc.h gen_alloc.h subfd.h substdio.h substdio.h getln.h \ +error.h open.h lock.h gfrom.h str.h exit.h myctime.h maildir.h \ +strerr.h ./compile maildir2mbox.c maildirmake: \ -load maildirmake.o substdio.a error.a str.a - ./load maildirmake substdio.a error.a str.a +load maildirmake.o strerr.a substdio.a error.a str.a + ./load maildirmake strerr.a substdio.a error.a str.a maildirmake.0: \ maildirmake.1 nroff -man maildirmake.1 > maildirmake.0 maildirmake.o: \ -compile maildirmake.c subfd.h substdio.h subfd.h maildirmake.c \ -substdio.h substdio.h maildirmake.c error.h maildirmake.c exit.h \ -maildirmake.c +compile maildirmake.c strerr.h exit.h ./compile maildirmake.c maildirwatch: \ @@ -809,13 +885,9 @@ maildirwatch.1 nroff -man maildirwatch.1 > maildirwatch.0 maildirwatch.o: \ -compile maildirwatch.c getln.h maildirwatch.c substdio.h \ -maildirwatch.c subfd.h substdio.h substdio.h subfd.h maildirwatch.c \ -prioq.h datetime.h prioq.h gen_alloc.h prioq.h maildirwatch.c \ -stralloc.h gen_alloc.h stralloc.h maildirwatch.c str.h maildirwatch.c \ -exit.h maildirwatch.c hfield.h maildirwatch.c readwrite.h \ -maildirwatch.c open.h maildirwatch.c headerbody.h maildirwatch.c \ -maildir.h strerr.h maildir.h maildirwatch.c +compile maildirwatch.c getln.h substdio.h subfd.h substdio.h prioq.h \ +datetime.h gen_alloc.h stralloc.h gen_alloc.h str.h exit.h hfield.h \ +readwrite.h open.h headerbody.h maildir.h strerr.h ./compile maildirwatch.c mailsubj: \ @@ -856,11 +928,12 @@ man: \ qmail-local.0 qmail-lspawn.0 qmail-getpw.0 qmail-remote.0 \ qmail-rspawn.0 qmail-clean.0 qmail-send.0 qmail-start.0 splogger.0 \ qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.0 \ -qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-pop3d.0 \ -qmail-popup.0 qmail-qmtpd.0 qmail-smtpd.0 tcp-env.0 qlist.0 \ -qreceipt.0 qbiff.0 forward.0 preline.0 condredirect.0 maildirmake.0 \ -maildir2mbox.0 maildirwatch.0 qmail.0 qmail-upgrade.0 qmail-limits.0 \ -qmail-log.0 qmail-control.0 qmail-header.0 qmail-users.0 dot-qmail.0 \ +qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \ +qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \ +qmail-smtpd.0 tcp-env.0 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 \ +preline.0 condredirect.0 bouncesaying.0 except.0 maildirmake.0 \ +maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.0 qmail-log.0 \ +qmail-control.0 qmail-header.0 qmail-users.0 dot-qmail.0 \ qmail-command.0 tcp-environ.0 maildir.0 mbox.0 addresses.0 \ envelopes.0 forgeries.0 @@ -869,8 +942,7 @@ mbox.5 nroff -man mbox.5 > mbox.0 myctime.o: \ -compile myctime.c datetime.h myctime.c fmt.h myctime.c myctime.h \ -myctime.c +compile myctime.c datetime.h fmt.h myctime.h ./compile myctime.c ndelay.a: \ @@ -878,22 +950,20 @@ makelib ndelay.o ndelay_off.o ./makelib ndelay.a ndelay.o ndelay_off.o ndelay.o: \ -compile ndelay.c ndelay.c ndelay.c ndelay.h ndelay.c +compile ndelay.c ndelay.h ./compile ndelay.c ndelay_off.o: \ -compile ndelay_off.c ndelay_off.c ndelay_off.c ndelay.h ndelay_off.c +compile ndelay_off.c ndelay.h ./compile ndelay_off.c newfield.o: \ -compile newfield.c fmt.h newfield.c datetime.h newfield.c stralloc.h \ -gen_alloc.h stralloc.h newfield.c date822fmt.h newfield.c newfield.h \ -stralloc.h stralloc.h newfield.h newfield.c +compile newfield.c fmt.h datetime.h stralloc.h gen_alloc.h \ +date822fmt.h newfield.h stralloc.h ./compile newfield.c now.o: \ -compile now.c now.c datetime.h now.c now.h datetime.h datetime.h \ -now.h now.c +compile now.c datetime.h now.h datetime.h ./compile now.c open.a: \ @@ -903,24 +973,23 @@ open_write.o open_trunc.o open_write.o open_append.o: \ -compile open_append.c open_append.c open_append.c open.h \ -open_append.c +compile open_append.c open.h ./compile open_append.c open_excl.o: \ -compile open_excl.c open_excl.c open_excl.c open.h open_excl.c +compile open_excl.c open.h ./compile open_excl.c open_read.o: \ -compile open_read.c open_read.c open_read.c open.h open_read.c +compile open_read.c open.h ./compile open_read.c open_trunc.o: \ -compile open_trunc.c open_trunc.c open_trunc.c open.h open_trunc.c +compile open_trunc.c open.h ./compile open_trunc.c open_write.o: \ -compile open_write.c open_write.c open_write.c open.h open_write.c +compile open_write.c open.h ./compile open_write.c pinq: \ @@ -933,43 +1002,52 @@ warn-auto.sh pinq.sh conf-qmail conf-break conf-split chmod 755 pinq predate: \ -load predate.o datetime.a sig.a fd.a wait.a substdio.a error.a str.a \ -fs.a - ./load predate datetime.a sig.a fd.a wait.a substdio.a \ - error.a str.a fs.a +load predate.o datetime.a strerr.a sig.a fd.a wait.a substdio.a \ +error.a str.a fs.a + ./load predate datetime.a strerr.a sig.a fd.a wait.a \ + substdio.a error.a str.a fs.a predate.o: \ -compile predate.c predate.c predate.c datetime.h predate.c fork.h \ -predate.c wait.h predate.c fd.h predate.c fmt.h predate.c substdio.h \ -predate.c subfd.h substdio.h substdio.h subfd.h predate.c readwrite.h \ -predate.c exit.h predate.c +compile predate.c datetime.h fork.h wait.h fd.h fmt.h strerr.h \ +substdio.h subfd.h substdio.h readwrite.h exit.h ./compile predate.c preline: \ -load preline.o fd.a wait.a sig.a env.a getopt.a substdio.a error.a \ -str.a - ./load preline fd.a wait.a sig.a env.a getopt.a substdio.a \ - error.a str.a +load preline.o strerr.a fd.a wait.a sig.a env.a getopt.a substdio.a \ +error.a str.a + ./load preline strerr.a fd.a wait.a sig.a env.a getopt.a \ + substdio.a error.a str.a preline.0: \ preline.1 nroff -man preline.1 > preline.0 preline.o: \ -compile preline.c fd.h preline.c sgetopt.h subgetopt.h sgetopt.h \ -preline.c readwrite.h preline.c subfd.h substdio.h subfd.h preline.c \ -substdio.h substdio.h preline.c exit.h preline.c fork.h preline.c \ -wait.h preline.c env.h preline.c sig.h preline.c error.h preline.c +compile preline.c fd.h sgetopt.h subgetopt.h readwrite.h strerr.h \ +substdio.h exit.h fork.h wait.h env.h sig.h error.h ./compile preline.c prioq.o: \ -compile prioq.c alloc.h prioq.c gen_allocdefs.h gen_allocdefs.h \ -gen_allocdefs.h prioq.c prioq.h datetime.h prioq.h gen_alloc.h \ -prioq.h prioq.c +compile prioq.c alloc.h gen_allocdefs.h prioq.h datetime.h \ +gen_alloc.h ./compile prioq.c +proc: \ +proc.sh conf-qmail + cat proc.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > proc + chmod 755 proc + +proc+df: \ +proc+df.sh conf-qmail + cat proc+df.sh \ + | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + > proc+df + chmod 755 proc+df + prot.o: \ -compile prot.c hasshsgr.h prot.c prot.h prot.c +compile prot.c hasshsgr.h prot.h ./compile prot.c qail: \ @@ -992,45 +1070,10 @@ qbiff.1 nroff -man qbiff.1 > qbiff.0 qbiff.o: \ -compile qbiff.c qbiff.c qbiff.c qbiff.c readwrite.h qbiff.c \ -stralloc.h gen_alloc.h stralloc.h qbiff.c substdio.h qbiff.c subfd.h \ -substdio.h substdio.h subfd.h qbiff.c open.h qbiff.c byte.h qbiff.c \ -str.h qbiff.c headerbody.h qbiff.c hfield.h qbiff.c env.h qbiff.c \ -exit.h qbiff.c +compile qbiff.c readwrite.h stralloc.h gen_alloc.h substdio.h subfd.h \ +substdio.h open.h byte.h str.h headerbody.h hfield.h env.h exit.h ./compile qbiff.c -qlist: \ -load qlist.o headerbody.o hfield.o token822.o qmail.o getln.a env.a \ -case.a sig.a fd.a wait.a open.a lock.a stralloc.a alloc.a substdio.a \ -error.a str.a auto_qmail.o - ./load qlist headerbody.o hfield.o token822.o qmail.o \ - getln.a env.a case.a sig.a fd.a wait.a open.a lock.a \ - stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o - -qlist.0: \ -qlist.1 - nroff -man qlist.1 > qlist.0 - -qlist.o: \ -compile qlist.c sig.h qlist.c readwrite.h qlist.c substdio.h qlist.c \ -stralloc.h gen_alloc.h stralloc.h qlist.c subfd.h substdio.h \ -substdio.h subfd.h qlist.c getln.h qlist.c alloc.h qlist.c str.h \ -qlist.c env.h qlist.c hfield.h qlist.c case.h qlist.c token822.h \ -gen_alloc.h token822.h qlist.c error.h qlist.c gen_alloc.h qlist.c \ -gen_allocdefs.h gen_allocdefs.h gen_allocdefs.h qlist.c headerbody.h \ -qlist.c exit.h qlist.c open.h qlist.c lock.h qlist.c qmail.h \ -substdio.h substdio.h qmail.h qlist.c qlist.c - ./compile qlist.c - -qlist2: \ -warn-auto.sh qlist2.sh conf-qmail conf-break conf-split - cat warn-auto.sh qlist2.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ - > qlist2 - chmod 755 qlist2 - qmail-clean: \ load qmail-clean.o fmtqfn.o now.o getln.a sig.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a auto_qmail.o auto_split.o @@ -1043,29 +1086,15 @@ qmail-clean.8 nroff -man qmail-clean.8 > qmail-clean.0 qmail-clean.o: \ -compile qmail-clean.c qmail-clean.c qmail-clean.c readwrite.h \ -qmail-clean.c sig.h qmail-clean.c now.h datetime.h now.h \ -qmail-clean.c str.h qmail-clean.c direntry.h direntry.h direntry.h \ -qmail-clean.c getln.h qmail-clean.c stralloc.h gen_alloc.h stralloc.h \ -qmail-clean.c substdio.h qmail-clean.c subfd.h substdio.h substdio.h \ -subfd.h qmail-clean.c byte.h qmail-clean.c scan.h qmail-clean.c fmt.h \ -qmail-clean.c error.h qmail-clean.c exit.h qmail-clean.c fmtqfn.h \ -qmail-clean.c auto_qmail.h qmail-clean.c +compile qmail-clean.c readwrite.h sig.h now.h datetime.h str.h \ +direntry.h getln.h stralloc.h gen_alloc.h substdio.h subfd.h \ +substdio.h byte.h scan.h fmt.h error.h exit.h fmtqfn.h auto_qmail.h ./compile qmail-clean.c qmail-command.0: \ qmail-command.8 nroff -man qmail-command.8 > qmail-command.0 -qmail-config: \ -warn-auto.sh qmail-config.sh conf-qmail conf-break conf-split - cat warn-auto.sh qmail-config.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ - > qmail-config - chmod 755 qmail-config - qmail-control.0: \ qmail-control.5 nroff -man qmail-control.5 > qmail-control.0 @@ -1097,59 +1126,36 @@ qmail-getpw.9 conf-break conf-spawn > qmail-getpw.8 qmail-getpw.o: \ -compile qmail-getpw.c qmail-getpw.c qmail-getpw.c qmail-getpw.c \ -readwrite.h qmail-getpw.c substdio.h qmail-getpw.c subfd.h substdio.h \ -substdio.h subfd.h qmail-getpw.c error.h qmail-getpw.c exit.h \ -qmail-getpw.c byte.h qmail-getpw.c str.h qmail-getpw.c case.h \ -qmail-getpw.c fmt.h qmail-getpw.c auto_usera.h qmail-getpw.c \ -auto_break.h qmail-getpw.c qlx.h qmail-getpw.c +compile qmail-getpw.c readwrite.h substdio.h subfd.h substdio.h \ +error.h exit.h byte.h str.h case.h fmt.h auto_usera.h auto_break.h \ +qlx.h ./compile qmail-getpw.c qmail-header.0: \ qmail-header.5 nroff -man qmail-header.5 > qmail-header.0 -qmail-hier: \ -load qmail-hier.o substdio.a error.a str.a fs.a auto_split.o \ -auto_uids.o - ./load qmail-hier substdio.a error.a str.a fs.a \ - auto_split.o auto_uids.o - -qmail-hier.o: \ -compile qmail-hier.c subfd.h substdio.h subfd.h qmail-hier.c \ -substdio.h substdio.h qmail-hier.c auto_split.h qmail-hier.c \ -auto_uids.h qmail-hier.c fmt.h qmail-hier.c - ./compile qmail-hier.c - qmail-inject: \ load qmail-inject.o headerbody.o hfield.o newfield.o quote.o now.o \ -control.o date822fmt.o qmail.o fd.a wait.a open.a getln.a sig.a \ -getopt.a datetime.a token822.o env.a stralloc.a alloc.a substdio.a \ -error.a str.a fs.a auto_qmail.o +control.o date822fmt.o constmap.o qmail.o case.a fd.a wait.a open.a \ +getln.a sig.a getopt.a datetime.a token822.o env.a stralloc.a alloc.a \ +substdio.a error.a str.a fs.a auto_qmail.o ./load qmail-inject headerbody.o hfield.o newfield.o \ - quote.o now.o control.o date822fmt.o qmail.o fd.a wait.a \ - open.a getln.a sig.a getopt.a datetime.a token822.o env.a \ - stralloc.a alloc.a substdio.a error.a str.a fs.a \ - auto_qmail.o + quote.o now.o control.o date822fmt.o constmap.o qmail.o \ + case.a fd.a wait.a open.a getln.a sig.a getopt.a datetime.a \ + token822.o env.a stralloc.a alloc.a substdio.a error.a \ + str.a fs.a auto_qmail.o qmail-inject.0: \ qmail-inject.8 nroff -man qmail-inject.8 > qmail-inject.0 qmail-inject.o: \ -compile qmail-inject.c sig.h qmail-inject.c substdio.h qmail-inject.c \ -stralloc.h gen_alloc.h stralloc.h qmail-inject.c subfd.h substdio.h \ -substdio.h subfd.h qmail-inject.c sgetopt.h subgetopt.h sgetopt.h \ -qmail-inject.c getln.h qmail-inject.c alloc.h qmail-inject.c str.h \ -qmail-inject.c fmt.h qmail-inject.c hfield.h qmail-inject.c \ -token822.h gen_alloc.h token822.h qmail-inject.c control.h \ -qmail-inject.c env.h qmail-inject.c gen_alloc.h qmail-inject.c \ -gen_allocdefs.h gen_allocdefs.h gen_allocdefs.h qmail-inject.c \ -error.h qmail-inject.c qmail.h substdio.h substdio.h qmail.h \ -qmail-inject.c now.h datetime.h now.h qmail-inject.c exit.h \ -qmail-inject.c quote.h qmail-inject.c headerbody.h qmail-inject.c \ -auto_qmail.h qmail-inject.c newfield.h stralloc.h stralloc.h \ -newfield.h qmail-inject.c +compile qmail-inject.c sig.h substdio.h stralloc.h gen_alloc.h \ +subfd.h substdio.h sgetopt.h subgetopt.h getln.h alloc.h str.h fmt.h \ +hfield.h token822.h gen_alloc.h control.h env.h gen_alloc.h \ +gen_allocdefs.h error.h qmail.h substdio.h now.h datetime.h exit.h \ +quote.h headerbody.h auto_qmail.h newfield.h stralloc.h constmap.h ./compile qmail-inject.c qmail-limits.0: \ @@ -1167,31 +1173,24 @@ qmail-limits.9 conf-break conf-spawn qmail-local: \ load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \ slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \ -wait.a env.a stralloc.a alloc.a substdio.a error.a str.a fs.a \ -datetime.a auto_qmail.o auto_patrn.o socket.lib +wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ +fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib ./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \ slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \ - lock.a fd.a wait.a env.a stralloc.a alloc.a substdio.a \ - error.a str.a fs.a datetime.a auto_qmail.o auto_patrn.o \ - `cat socket.lib` + lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \ + substdio.a error.a str.a fs.a datetime.a auto_qmail.o \ + auto_patrn.o `cat socket.lib` qmail-local.0: \ qmail-local.8 nroff -man qmail-local.8 > qmail-local.0 qmail-local.o: \ -compile qmail-local.c qmail-local.c qmail-local.c readwrite.h \ -qmail-local.c sig.h qmail-local.c env.h qmail-local.c byte.h \ -qmail-local.c exit.h qmail-local.c fork.h qmail-local.c open.h \ -qmail-local.c wait.h qmail-local.c lock.h qmail-local.c seek.h \ -qmail-local.c substdio.h qmail-local.c getln.h qmail-local.c subfd.h \ -substdio.h substdio.h subfd.h qmail-local.c sgetopt.h subgetopt.h \ -sgetopt.h qmail-local.c alloc.h qmail-local.c error.h qmail-local.c \ -stralloc.h gen_alloc.h stralloc.h qmail-local.c fmt.h qmail-local.c \ -str.h qmail-local.c now.h datetime.h now.h qmail-local.c case.h \ -qmail-local.c quote.h qmail-local.c qmail.h substdio.h substdio.h \ -qmail.h qmail-local.c slurpclose.h qmail-local.c myctime.h \ -qmail-local.c gfrom.h qmail-local.c auto_patrn.h qmail-local.c +compile qmail-local.c readwrite.h sig.h env.h byte.h exit.h fork.h \ +open.h wait.h lock.h seek.h substdio.h getln.h strerr.h subfd.h \ +substdio.h sgetopt.h subgetopt.h alloc.h error.h stralloc.h \ +gen_alloc.h fmt.h str.h now.h datetime.h case.h quote.h qmail.h \ +substdio.h slurpclose.h myctime.h gfrom.h auto_patrn.h ./compile qmail-local.c qmail-log.0: \ @@ -1212,15 +1211,36 @@ qmail-lspawn.8 nroff -man qmail-lspawn.8 > qmail-lspawn.0 qmail-lspawn.o: \ -compile qmail-lspawn.c fd.h qmail-lspawn.c wait.h qmail-lspawn.c \ -prot.h qmail-lspawn.c substdio.h qmail-lspawn.c stralloc.h \ -gen_alloc.h stralloc.h qmail-lspawn.c scan.h qmail-lspawn.c exit.h \ -qmail-lspawn.c fork.h qmail-lspawn.c error.h qmail-lspawn.c cdb.h \ -uint32.h cdb.h qmail-lspawn.c case.h qmail-lspawn.c slurpclose.h \ -qmail-lspawn.c auto_qmail.h qmail-lspawn.c auto_uids.h qmail-lspawn.c \ -qlx.h qmail-lspawn.c +compile qmail-lspawn.c fd.h wait.h prot.h substdio.h stralloc.h \ +gen_alloc.h scan.h exit.h fork.h error.h cdb.h uint32.h case.h \ +slurpclose.h auto_qmail.h auto_uids.h qlx.h ./compile qmail-lspawn.c +qmail-newmrh: \ +load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \ +stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o + ./load qmail-newmrh cdbmss.o getln.a open.a cdbmake.a \ + seek.a case.a stralloc.a alloc.a strerr.a substdio.a \ + error.a str.a auto_qmail.o + +qmail-newmrh.0: \ +qmail-newmrh.8 + nroff -man qmail-newmrh.8 > qmail-newmrh.0 + +qmail-newmrh.8: \ +qmail-newmrh.9 conf-break conf-spawn + cat qmail-newmrh.9 \ + | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ + | sed s}BREAK}"`head -1 conf-break`"}g \ + | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + > qmail-newmrh.8 + +qmail-newmrh.o: \ +compile qmail-newmrh.c strerr.h stralloc.h gen_alloc.h substdio.h \ +getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \ +uint32.h substdio.h + ./compile qmail-newmrh.c + qmail-newu: \ load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \ stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o @@ -1241,54 +1261,47 @@ qmail-newu.9 conf-break conf-spawn > qmail-newu.8 qmail-newu.o: \ -compile qmail-newu.c stralloc.h gen_alloc.h stralloc.h qmail-newu.c \ -subfd.h substdio.h subfd.h qmail-newu.c getln.h qmail-newu.c \ -substdio.h substdio.h qmail-newu.c cdbmss.h cdbmake.h uint32.h \ -cdbmake.h cdbmss.h substdio.h substdio.h cdbmss.h qmail-newu.c exit.h \ -qmail-newu.c readwrite.h qmail-newu.c open.h qmail-newu.c error.h \ -qmail-newu.c case.h qmail-newu.c auto_qmail.h qmail-newu.c +compile qmail-newu.c stralloc.h gen_alloc.h subfd.h substdio.h \ +getln.h substdio.h cdbmss.h cdbmake.h uint32.h substdio.h exit.h \ +readwrite.h open.h error.h case.h auto_qmail.h ./compile qmail-newu.c qmail-pop3d: \ -load qmail-pop3d.o prioq.o now.o sig.a open.a getln.a stralloc.a \ -alloc.a substdio.a error.a str.a fs.a - ./load qmail-pop3d prioq.o now.o sig.a open.a getln.a \ - stralloc.a alloc.a substdio.a error.a str.a fs.a +load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \ +maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \ +stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib + ./load qmail-pop3d commands.o case.a timeoutread.o \ + timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \ + open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \ + fs.a `cat socket.lib` qmail-pop3d.0: \ qmail-pop3d.8 nroff -man qmail-pop3d.8 > qmail-pop3d.0 qmail-pop3d.o: \ -compile qmail-pop3d.c qmail-pop3d.c qmail-pop3d.c direntry.h \ -direntry.h direntry.h qmail-pop3d.c sig.h qmail-pop3d.c getln.h \ -qmail-pop3d.c stralloc.h gen_alloc.h stralloc.h qmail-pop3d.c \ -substdio.h qmail-pop3d.c alloc.h qmail-pop3d.c datetime.h \ -qmail-pop3d.c prot.h qmail-pop3d.c open.h qmail-pop3d.c prioq.h \ -datetime.h datetime.h prioq.h gen_alloc.h prioq.h qmail-pop3d.c \ -scan.h qmail-pop3d.c fmt.h qmail-pop3d.c error.h qmail-pop3d.c str.h \ -qmail-pop3d.c exit.h qmail-pop3d.c now.h datetime.h datetime.h now.h \ -qmail-pop3d.c readwrite.h qmail-pop3d.c +compile qmail-pop3d.c commands.h sig.h getln.h stralloc.h gen_alloc.h \ +substdio.h alloc.h open.h prioq.h datetime.h gen_alloc.h scan.h fmt.h \ +str.h exit.h maildir.h strerr.h readwrite.h timeoutread.h \ +timeoutwrite.h ./compile qmail-pop3d.c qmail-popup: \ -load qmail-popup.o now.o fd.a sig.a wait.a getln.a stralloc.a alloc.a \ -substdio.a error.a str.a fs.a - ./load qmail-popup now.o fd.a sig.a wait.a getln.a \ - stralloc.a alloc.a substdio.a error.a str.a fs.a +load qmail-popup.o commands.o timeoutread.o timeoutwrite.o now.o \ +case.a fd.a sig.a wait.a stralloc.a alloc.a substdio.a error.a str.a \ +fs.a socket.lib + ./load qmail-popup commands.o timeoutread.o timeoutwrite.o \ + now.o case.a fd.a sig.a wait.a stralloc.a alloc.a \ + substdio.a error.a str.a fs.a `cat socket.lib` qmail-popup.0: \ qmail-popup.8 nroff -man qmail-popup.8 > qmail-popup.0 qmail-popup.o: \ -compile qmail-popup.c qmail-popup.c qmail-popup.c fd.h qmail-popup.c \ -sig.h qmail-popup.c getln.h qmail-popup.c stralloc.h gen_alloc.h \ -stralloc.h qmail-popup.c substdio.h qmail-popup.c subfd.h substdio.h \ -substdio.h subfd.h qmail-popup.c alloc.h qmail-popup.c datetime.h \ -qmail-popup.c error.h qmail-popup.c wait.h qmail-popup.c str.h \ -qmail-popup.c now.h datetime.h datetime.h now.h qmail-popup.c fmt.h \ -qmail-popup.c exit.h qmail-popup.c readwrite.h qmail-popup.c +compile qmail-popup.c commands.h fd.h sig.h stralloc.h gen_alloc.h \ +substdio.h alloc.h wait.h str.h byte.h now.h datetime.h fmt.h exit.h \ +readwrite.h timeoutread.h timeoutwrite.h ./compile qmail-popup.c qmail-pw2u: \ @@ -1312,38 +1325,65 @@ qmail-pw2u.9 conf-break conf-spawn > qmail-pw2u.8 qmail-pw2u.o: \ -compile qmail-pw2u.c qmail-pw2u.c qmail-pw2u.c substdio.h \ -qmail-pw2u.c readwrite.h qmail-pw2u.c subfd.h substdio.h substdio.h \ -subfd.h qmail-pw2u.c sgetopt.h subgetopt.h sgetopt.h qmail-pw2u.c \ -control.h qmail-pw2u.c constmap.h qmail-pw2u.c stralloc.h gen_alloc.h \ -stralloc.h qmail-pw2u.c fmt.h qmail-pw2u.c str.h qmail-pw2u.c scan.h \ -qmail-pw2u.c open.h qmail-pw2u.c error.h qmail-pw2u.c getln.h \ -qmail-pw2u.c auto_break.h qmail-pw2u.c auto_qmail.h qmail-pw2u.c \ -auto_usera.h qmail-pw2u.c +compile qmail-pw2u.c substdio.h readwrite.h subfd.h substdio.h \ +sgetopt.h subgetopt.h control.h constmap.h stralloc.h gen_alloc.h \ +fmt.h str.h scan.h open.h error.h getln.h auto_break.h auto_qmail.h \ +auto_usera.h ./compile qmail-pw2u.c +qmail-qmqpc: \ +load qmail-qmqpc.o slurpclose.o timeoutread.o timeoutwrite.o \ +timeoutconn.o ip.o control.o auto_qmail.o sig.a ndelay.a open.a \ +getln.a substdio.a stralloc.a alloc.a error.a str.a fs.a socket.lib + ./load qmail-qmqpc slurpclose.o timeoutread.o \ + timeoutwrite.o timeoutconn.o ip.o control.o auto_qmail.o \ + sig.a ndelay.a open.a getln.a substdio.a stralloc.a alloc.a \ + error.a str.a fs.a `cat socket.lib` + +qmail-qmqpc.0: \ +qmail-qmqpc.8 + nroff -man qmail-qmqpc.8 > qmail-qmqpc.0 + +qmail-qmqpc.o: \ +compile qmail-qmqpc.c substdio.h getln.h readwrite.h exit.h \ +stralloc.h gen_alloc.h slurpclose.h error.h sig.h ip.h timeoutconn.h \ +timeoutread.h timeoutwrite.h auto_qmail.h control.h fmt.h + ./compile qmail-qmqpc.c + +qmail-qmqpd: \ +load qmail-qmqpd.o received.o now.o date822fmt.o qmail.o auto_qmail.o \ +env.a substdio.a sig.a error.a wait.a fd.a str.a datetime.a fs.a + ./load qmail-qmqpd received.o now.o date822fmt.o qmail.o \ + auto_qmail.o env.a substdio.a sig.a error.a wait.a fd.a \ + str.a datetime.a fs.a + +qmail-qmqpd.0: \ +qmail-qmqpd.8 + nroff -man qmail-qmqpd.8 > qmail-qmqpd.0 + +qmail-qmqpd.o: \ +compile qmail-qmqpd.c auto_qmail.h qmail.h substdio.h received.h \ +sig.h substdio.h readwrite.h exit.h now.h datetime.h fmt.h env.h + ./compile qmail-qmqpd.c + qmail-qmtpd: \ -load qmail-qmtpd.o control.o constmap.o received.o date822fmt.o now.o \ -qmail.o fd.a wait.a datetime.a open.a getln.a sig.a case.a env.a \ -stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o - ./load qmail-qmtpd control.o constmap.o received.o \ - date822fmt.o now.o qmail.o fd.a wait.a datetime.a open.a \ - getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a \ - error.a str.a fs.a auto_qmail.o +load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \ +date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \ +getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \ +str.a fs.a auto_qmail.o + ./load qmail-qmtpd rcpthosts.o control.o constmap.o \ + received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ + datetime.a open.a getln.a sig.a case.a env.a stralloc.a \ + alloc.a substdio.a error.a str.a fs.a auto_qmail.o qmail-qmtpd.0: \ qmail-qmtpd.8 nroff -man qmail-qmtpd.8 > qmail-qmtpd.0 qmail-qmtpd.o: \ -compile qmail-qmtpd.c stralloc.h gen_alloc.h stralloc.h qmail-qmtpd.c \ -substdio.h qmail-qmtpd.c subfd.h substdio.h substdio.h subfd.h \ -qmail-qmtpd.c qmail.h substdio.h substdio.h qmail.h qmail-qmtpd.c \ -now.h datetime.h now.h qmail-qmtpd.c str.h qmail-qmtpd.c fmt.h \ -qmail-qmtpd.c env.h qmail-qmtpd.c sig.h qmail-qmtpd.c auto_qmail.h \ -qmail-qmtpd.c now.h qmail-qmtpd.c datetime.h datetime.h qmail-qmtpd.c \ -date822fmt.h qmail-qmtpd.c readwrite.h qmail-qmtpd.c control.h \ -qmail-qmtpd.c constmap.h qmail-qmtpd.c received.h qmail-qmtpd.c +compile qmail-qmtpd.c stralloc.h gen_alloc.h substdio.h qmail.h \ +substdio.h now.h datetime.h str.h fmt.h env.h sig.h rcpthosts.h \ +auto_qmail.h readwrite.h control.h received.h ./compile qmail-qmtpd.c qmail-qread: \ @@ -1359,14 +1399,10 @@ qmail-qread.8 nroff -man qmail-qread.8 > qmail-qread.0 qmail-qread.o: \ -compile qmail-qread.c qmail-qread.c qmail-qread.c stralloc.h \ -gen_alloc.h stralloc.h qmail-qread.c substdio.h qmail-qread.c subfd.h \ -substdio.h substdio.h subfd.h qmail-qread.c fmt.h qmail-qread.c str.h \ -qmail-qread.c getln.h qmail-qread.c fmtqfn.h qmail-qread.c \ -readsubdir.h direntry.h direntry.h direntry.h readsubdir.h \ -qmail-qread.c auto_qmail.h qmail-qread.c open.h qmail-qread.c \ -datetime.h qmail-qread.c date822fmt.h qmail-qread.c readwrite.h \ -qmail-qread.c error.h qmail-qread.c exit.h qmail-qread.c +compile qmail-qread.c stralloc.h gen_alloc.h substdio.h subfd.h \ +substdio.h fmt.h str.h getln.h fmtqfn.h readsubdir.h direntry.h \ +auto_qmail.h open.h datetime.h date822fmt.h readwrite.h error.h \ +exit.h ./compile qmail-qread.c qmail-qstat: \ @@ -1396,13 +1432,9 @@ qmail-queue.8 nroff -man qmail-queue.8 > qmail-queue.0 qmail-queue.o: \ -compile qmail-queue.c qmail-queue.c qmail-queue.c readwrite.h \ -qmail-queue.c sig.h qmail-queue.c exit.h qmail-queue.c open.h \ -qmail-queue.c seek.h qmail-queue.c fmt.h qmail-queue.c alloc.h \ -qmail-queue.c substdio.h qmail-queue.c datetime.h qmail-queue.c now.h \ -datetime.h datetime.h now.h qmail-queue.c triggerpull.h qmail-queue.c \ -extra.h qmail-queue.c auto_qmail.h qmail-queue.c auto_uids.h \ -qmail-queue.c date822fmt.h qmail-queue.c fmtqfn.h qmail-queue.c +compile qmail-queue.c readwrite.h sig.h exit.h open.h seek.h fmt.h \ +alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \ +auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h ./compile qmail-queue.c qmail-remote: \ @@ -1421,21 +1453,11 @@ qmail-remote.8 nroff -man qmail-remote.8 > qmail-remote.0 qmail-remote.o: \ -compile qmail-remote.c qmail-remote.c qmail-remote.c qmail-remote.c \ -qmail-remote.c sig.h qmail-remote.c getln.h qmail-remote.c stralloc.h \ -gen_alloc.h stralloc.h qmail-remote.c substdio.h qmail-remote.c \ -subfd.h substdio.h substdio.h subfd.h qmail-remote.c scan.h \ -qmail-remote.c case.h qmail-remote.c error.h qmail-remote.c \ -auto_qmail.h qmail-remote.c control.h qmail-remote.c dns.h \ -qmail-remote.c alloc.h qmail-remote.c quote.h qmail-remote.c ip.h \ -qmail-remote.c ipalloc.h ip.h ip.h ipalloc.h gen_alloc.h ipalloc.h \ -qmail-remote.c ipme.h ip.h ip.h ipme.h ipalloc.h ipalloc.h ipme.h \ -qmail-remote.c gen_alloc.h qmail-remote.c gen_allocdefs.h \ -gen_allocdefs.h gen_allocdefs.h qmail-remote.c str.h qmail-remote.c \ -now.h datetime.h now.h qmail-remote.c exit.h qmail-remote.c \ -constmap.h qmail-remote.c tcpto.h qmail-remote.c timeoutconn.h \ -qmail-remote.c timeoutread.h qmail-remote.c timeoutwrite.h \ -qmail-remote.c +compile qmail-remote.c sig.h stralloc.h gen_alloc.h substdio.h \ +subfd.h substdio.h scan.h case.h error.h auto_qmail.h control.h dns.h \ +alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \ +gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \ +tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h ./compile qmail-remote.c qmail-rspawn: \ @@ -1452,9 +1474,8 @@ qmail-rspawn.8 nroff -man qmail-rspawn.8 > qmail-rspawn.0 qmail-rspawn.o: \ -compile qmail-rspawn.c fd.h qmail-rspawn.c wait.h qmail-rspawn.c \ -substdio.h qmail-rspawn.c exit.h qmail-rspawn.c fork.h qmail-rspawn.c \ -error.h qmail-rspawn.c tcpto.h qmail-rspawn.c +compile qmail-rspawn.c fd.h wait.h substdio.h exit.h fork.h error.h \ +tcpto.h ./compile qmail-rspawn.c qmail-send: \ @@ -1482,68 +1503,57 @@ qmail-send.9 conf-break conf-spawn > qmail-send.8 qmail-send.o: \ -compile qmail-send.c qmail-send.c qmail-send.c readwrite.h \ -qmail-send.c sig.h qmail-send.c direntry.h direntry.h direntry.h \ -qmail-send.c control.h qmail-send.c select.h select.h select.h \ -select.h qmail-send.c open.h qmail-send.c seek.h qmail-send.c exit.h \ -qmail-send.c lock.h qmail-send.c ndelay.h qmail-send.c now.h \ -datetime.h now.h qmail-send.c getln.h qmail-send.c substdio.h \ -qmail-send.c alloc.h qmail-send.c error.h qmail-send.c stralloc.h \ -gen_alloc.h stralloc.h qmail-send.c str.h qmail-send.c byte.h \ -qmail-send.c fmt.h qmail-send.c scan.h qmail-send.c case.h \ -qmail-send.c auto_qmail.h qmail-send.c trigger.h qmail-send.c \ -newfield.h stralloc.h stralloc.h newfield.h qmail-send.c quote.h \ -qmail-send.c qmail.h substdio.h substdio.h qmail.h qmail-send.c \ -qsutil.h qmail-send.c prioq.h datetime.h datetime.h prioq.h \ -gen_alloc.h prioq.h qmail-send.c constmap.h qmail-send.c fmtqfn.h \ -qmail-send.c readsubdir.h direntry.h readsubdir.h qmail-send.c +compile qmail-send.c readwrite.h sig.h direntry.h control.h select.h \ +open.h seek.h exit.h lock.h ndelay.h now.h datetime.h getln.h \ +substdio.h alloc.h error.h stralloc.h gen_alloc.h str.h byte.h fmt.h \ +scan.h case.h auto_qmail.h trigger.h newfield.h stralloc.h quote.h \ +qmail.h substdio.h qsutil.h prioq.h datetime.h gen_alloc.h constmap.h \ +fmtqfn.h readsubdir.h direntry.h ./compile qmail-send.c qmail-showctl: \ -load qmail-showctl.o control.o open.a getln.a stralloc.a alloc.a \ -substdio.a error.a str.a fs.a auto_qmail.o - ./load qmail-showctl control.o open.a getln.a stralloc.a \ - alloc.a substdio.a error.a str.a fs.a auto_qmail.o +load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \ +alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_break.o \ +auto_patrn.o auto_spawn.o auto_split.o + ./load qmail-showctl auto_uids.o control.o open.a getln.a \ + stralloc.a alloc.a substdio.a error.a str.a fs.a \ + auto_qmail.o auto_break.o auto_patrn.o auto_spawn.o \ + auto_split.o qmail-showctl.0: \ qmail-showctl.8 nroff -man qmail-showctl.8 > qmail-showctl.0 qmail-showctl.o: \ -compile qmail-showctl.c substdio.h qmail-showctl.c subfd.h substdio.h \ -substdio.h subfd.h qmail-showctl.c exit.h qmail-showctl.c fmt.h \ -qmail-showctl.c str.h qmail-showctl.c control.h qmail-showctl.c \ -constmap.h qmail-showctl.c stralloc.h gen_alloc.h stralloc.h \ -qmail-showctl.c direntry.h direntry.h direntry.h qmail-showctl.c \ -auto_qmail.h qmail-showctl.c +compile qmail-showctl.c substdio.h subfd.h substdio.h exit.h fmt.h \ +str.h control.h constmap.h stralloc.h gen_alloc.h direntry.h \ +auto_uids.h auto_qmail.h auto_break.h auto_patrn.h auto_spawn.h \ +auto_split.h ./compile qmail-showctl.c qmail-smtpd: \ -load qmail-smtpd.o ip.o ipme.o ipalloc.o control.o constmap.o \ -received.o date822fmt.o now.o qmail.o fd.a wait.a datetime.a open.a \ -getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \ -str.a fs.a auto_qmail.o socket.lib - ./load qmail-smtpd ip.o ipme.o ipalloc.o control.o \ - constmap.o received.o date822fmt.o now.o qmail.o fd.a \ - wait.a datetime.a open.a getln.a sig.a case.a env.a \ - stralloc.a alloc.a substdio.a error.a str.a fs.a \ - auto_qmail.o `cat socket.lib` +load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \ +timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \ +date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \ +open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \ +fs.a auto_qmail.o socket.lib + ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ + timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \ + received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ + datetime.a getln.a open.a sig.a case.a env.a stralloc.a \ + alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ + socket.lib` qmail-smtpd.0: \ qmail-smtpd.8 nroff -man qmail-smtpd.8 > qmail-smtpd.0 qmail-smtpd.o: \ -compile qmail-smtpd.c sig.h qmail-smtpd.c readwrite.h qmail-smtpd.c \ -getln.h qmail-smtpd.c stralloc.h gen_alloc.h stralloc.h qmail-smtpd.c \ -substdio.h qmail-smtpd.c alloc.h qmail-smtpd.c auto_qmail.h \ -qmail-smtpd.c control.h qmail-smtpd.c received.h qmail-smtpd.c \ -constmap.h qmail-smtpd.c error.h qmail-smtpd.c ipme.h ip.h ipme.h \ -ipalloc.h ip.h ip.h ipalloc.h gen_alloc.h ipalloc.h ipme.h \ -qmail-smtpd.c ip.h ip.h qmail-smtpd.c qmail.h substdio.h substdio.h \ -qmail.h qmail-smtpd.c str.h qmail-smtpd.c fmt.h qmail-smtpd.c byte.h \ -qmail-smtpd.c case.h qmail-smtpd.c env.h qmail-smtpd.c now.h \ -datetime.h now.h qmail-smtpd.c exit.h qmail-smtpd.c +compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \ +substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ +error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \ +substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ +exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h ./compile qmail-smtpd.c qmail-start: \ @@ -1563,10 +1573,24 @@ qmail-start.9 conf-break conf-spawn > qmail-start.8 qmail-start.o: \ -compile qmail-start.c fd.h qmail-start.c prot.h qmail-start.c exit.h \ -qmail-start.c fork.h qmail-start.c auto_uids.h qmail-start.c +compile qmail-start.c fd.h prot.h exit.h fork.h auto_uids.h ./compile qmail-start.c +qmail-tcpok: \ +load qmail-tcpok.o open.a lock.a strerr.a substdio.a error.a str.a \ +auto_qmail.o + ./load qmail-tcpok open.a lock.a strerr.a substdio.a \ + error.a str.a auto_qmail.o + +qmail-tcpok.0: \ +qmail-tcpok.8 + nroff -man qmail-tcpok.8 > qmail-tcpok.0 + +qmail-tcpok.o: \ +compile qmail-tcpok.c strerr.h substdio.h lock.h open.h readwrite.h \ +auto_qmail.h exit.h + ./compile qmail-tcpok.c + qmail-tcpto: \ load qmail-tcpto.o ip.o now.o open.a lock.a substdio.a error.a str.a \ fs.a auto_qmail.o @@ -1578,25 +1602,10 @@ qmail-tcpto.8 nroff -man qmail-tcpto.8 > qmail-tcpto.0 qmail-tcpto.o: \ -compile qmail-tcpto.c substdio.h qmail-tcpto.c subfd.h substdio.h \ -substdio.h subfd.h qmail-tcpto.c auto_qmail.h qmail-tcpto.c fmt.h \ -qmail-tcpto.c ip.h qmail-tcpto.c lock.h qmail-tcpto.c error.h \ -qmail-tcpto.c exit.h qmail-tcpto.c datetime.h qmail-tcpto.c now.h \ -datetime.h datetime.h now.h qmail-tcpto.c +compile qmail-tcpto.c substdio.h subfd.h substdio.h auto_qmail.h \ +fmt.h ip.h lock.h error.h exit.h datetime.h now.h datetime.h ./compile qmail-tcpto.c -qmail-upgrade.0: \ -qmail-upgrade.7 - nroff -man qmail-upgrade.7 > qmail-upgrade.0 - -qmail-upgrade.7: \ -qmail-upgrade.9 conf-break conf-spawn - cat qmail-upgrade.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ - > qmail-upgrade.7 - qmail-upq: \ warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split cat warn-auto.sh qmail-upq.sh \ @@ -1623,9 +1632,8 @@ qmail.7 nroff -man qmail.7 > qmail.0 qmail.o: \ -compile qmail.c substdio.h qmail.c readwrite.h qmail.c wait.h qmail.c \ -exit.h qmail.c fork.h qmail.c fd.h qmail.c qmail.h substdio.h \ -substdio.h qmail.h qmail.c auto_qmail.h qmail.c +compile qmail.c substdio.h readwrite.h wait.h exit.h fork.h fd.h \ +qmail.h substdio.h auto_qmail.h ./compile qmail.c qreceipt: \ @@ -1641,14 +1649,10 @@ qreceipt.1 nroff -man qreceipt.1 > qreceipt.0 qreceipt.o: \ -compile qreceipt.c sig.h qreceipt.c env.h qreceipt.c substdio.h \ -qreceipt.c stralloc.h gen_alloc.h stralloc.h qreceipt.c subfd.h \ -substdio.h substdio.h subfd.h qreceipt.c getln.h qreceipt.c alloc.h \ -qreceipt.c str.h qreceipt.c hfield.h qreceipt.c token822.h \ -gen_alloc.h token822.h qreceipt.c error.h qreceipt.c gen_alloc.h \ -qreceipt.c gen_allocdefs.h gen_allocdefs.h gen_allocdefs.h qreceipt.c \ -headerbody.h qreceipt.c exit.h qreceipt.c open.h qreceipt.c quote.h \ -qreceipt.c qmail.h substdio.h substdio.h qmail.h qreceipt.c +compile qreceipt.c sig.h env.h substdio.h stralloc.h gen_alloc.h \ +subfd.h substdio.h getln.h alloc.h str.h hfield.h token822.h \ +gen_alloc.h error.h gen_alloc.h gen_allocdefs.h headerbody.h exit.h \ +open.h quote.h qmail.h substdio.h ./compile qreceipt.c qsmhook: \ @@ -1658,54 +1662,46 @@ alloc.a substdio.a error.a str.a stralloc.a alloc.a substdio.a error.a str.a qsmhook.o: \ -compile qsmhook.c fd.h qsmhook.c stralloc.h gen_alloc.h stralloc.h \ -qsmhook.c readwrite.h qsmhook.c sgetopt.h subgetopt.h sgetopt.h \ -qsmhook.c wait.h qsmhook.c env.h qsmhook.c byte.h qsmhook.c str.h \ -qsmhook.c alloc.h qsmhook.c exit.h qsmhook.c fork.h qsmhook.c case.h \ -qsmhook.c subfd.h substdio.h subfd.h qsmhook.c error.h qsmhook.c \ -substdio.h substdio.h qsmhook.c sig.h qsmhook.c +compile qsmhook.c fd.h stralloc.h gen_alloc.h readwrite.h sgetopt.h \ +subgetopt.h wait.h env.h byte.h str.h alloc.h exit.h fork.h case.h \ +subfd.h substdio.h error.h substdio.h sig.h ./compile qsmhook.c qsutil.o: \ -compile qsutil.c stralloc.h gen_alloc.h stralloc.h qsutil.c \ -readwrite.h qsutil.c substdio.h qsutil.c qsutil.h qsutil.c +compile qsutil.c stralloc.h gen_alloc.h readwrite.h substdio.h \ +qsutil.h ./compile qsutil.c quote.o: \ -compile quote.c stralloc.h gen_alloc.h stralloc.h quote.c str.h \ -quote.c quote.h quote.c +compile quote.c stralloc.h gen_alloc.h str.h quote.h ./compile quote.c +rcpthosts.o: \ +compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \ +constmap.h stralloc.h gen_alloc.h rcpthosts.h + ./compile rcpthosts.c + readsubdir.o: \ -compile readsubdir.c readsubdir.h direntry.h direntry.h direntry.h \ -readsubdir.h readsubdir.c fmt.h readsubdir.c scan.h readsubdir.c \ -str.h readsubdir.c auto_split.h readsubdir.c +compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \ +auto_split.h ./compile readsubdir.c received.o: \ -compile received.c fmt.h received.c qmail.h substdio.h qmail.h \ -received.c now.h datetime.h now.h received.c datetime.h datetime.h \ -received.c date822fmt.h received.c received.h received.c +compile received.c fmt.h qmail.h substdio.h now.h datetime.h \ +datetime.h date822fmt.h received.h ./compile received.c remoteinfo.o: \ -compile remoteinfo.c remoteinfo.c remoteinfo.c remoteinfo.c \ -remoteinfo.c byte.h remoteinfo.c substdio.h remoteinfo.c ip.h \ -remoteinfo.c fmt.h remoteinfo.c timeoutconn.h remoteinfo.c \ -timeoutread.h remoteinfo.c timeoutwrite.h remoteinfo.c remoteinfo.h \ -remoteinfo.c +compile remoteinfo.c byte.h substdio.h ip.h fmt.h timeoutconn.h \ +timeoutread.h timeoutwrite.h remoteinfo.h ./compile remoteinfo.c scan_8long.o: \ -compile scan_8long.c scan.h scan_8long.c +compile scan_8long.c scan.h ./compile scan_8long.c -scan_nbblong.o: \ -compile scan_nbblong.c scan.h scan_nbblong.c - ./compile scan_nbblong.c - scan_ulong.o: \ -compile scan_ulong.c scan.h scan_ulong.c +compile scan_ulong.c scan.h ./compile scan_ulong.c seek.a: \ @@ -1714,19 +1710,19 @@ makelib seek_cur.o seek_end.o seek_set.o seek_trunc.o seek_trunc.o seek_cur.o: \ -compile seek_cur.c seek_cur.c seek.h seek_cur.c +compile seek_cur.c seek.h ./compile seek_cur.c seek_end.o: \ -compile seek_end.c seek_end.c seek.h seek_end.c +compile seek_end.c seek.h ./compile seek_end.c seek_set.o: \ -compile seek_set.c seek_set.c seek.h seek_set.c +compile seek_set.c seek.h ./compile seek_set.c seek_trunc.o: \ -compile seek_trunc.c seek_trunc.c seek.h seek_trunc.c +compile seek_trunc.c seek.h ./compile seek_trunc.c select.h: \ @@ -1742,57 +1738,62 @@ auto_qmail.o str.a auto_qmail.o sendmail.o: \ -compile sendmail.c sgetopt.h subgetopt.h sgetopt.h sendmail.c \ -substdio.h sendmail.c subfd.h substdio.h substdio.h subfd.h \ -sendmail.c alloc.h sendmail.c auto_qmail.h sendmail.c exit.h \ -sendmail.c env.h sendmail.c str.h sendmail.c +compile sendmail.c sgetopt.h subgetopt.h substdio.h subfd.h \ +substdio.h alloc.h auto_qmail.h exit.h env.h str.h ./compile sendmail.c setup: \ -it man conf-qmail - ./qmail-hier | ./install `head -1 conf-qmail` +it man + ./install sgetopt.o: \ -compile sgetopt.c substdio.h sgetopt.c subfd.h substdio.h substdio.h \ -subfd.h sgetopt.c sgetopt.h sgetopt.h subgetopt.h sgetopt.h sgetopt.c \ -subgetopt.h subgetopt.h sgetopt.c +compile sgetopt.c substdio.h subfd.h substdio.h sgetopt.h subgetopt.h \ +subgetopt.h ./compile sgetopt.c shar: \ FILES BLURB BLURB2 BLURB3 BLURB4 README FAQ INSTALL INSTALL.alias \ -INSTALL.boot INSTALL.ctl INSTALL.ids INSTALL.mbox INSTALL.qsmhook \ -UPGRADE THOUGHTS TODO THANKS CHANGES RFCHCSC RFCLOOPS RFCMXPS \ -RFCNETSTR RFCNRUDT RFCQMTP RFCQSBMF RFCVERP SECURITY INTERNALS FILES \ -VERSION SYSDEPS TARGETS Makefile conf-break auto_break.h conf-spawn \ +INSTALL.ctl INSTALL.ids INSTALL.maildir INSTALL.mbox INSTALL.vsm \ +REMOVE.sendmail REMOVE.binmail TEST.deliver TEST.receive UPGRADE \ +THOUGHTS TODO THANKS CHANGES SECURITY INTERNALS SENDMAIL \ +PIC.local2alias PIC.local2ext PIC.local2local PIC.local2rem \ +PIC.local2virt PIC.nullclient PIC.relaybad PIC.relaygood \ +PIC.rem2local FILES VERSION SYSDEPS TARGETS Makefile BIN.README \ +BIN.Makefile BIN.setup idedit.c conf-break auto_break.h conf-spawn \ auto_spawn.h chkspawn.c conf-split auto_split.h conf-patrn \ auto_patrn.h conf-users conf-groups auto_uids.h auto_usera.h extra.h \ -addresses.5 condredirect.1 dot-qmail.9 envelopes.5 forgeries.7 \ -forward.1 maildir2mbox.1 maildirmake.1 maildirwatch.1 mailsubj.1 \ -mbox.5 preline.1 qbiff.1 qlist.1 qmail-clean.8 qmail-command.8 \ -qmail-control.5 qmail-getpw.9 qmail-header.5 qmail-inject.8 \ -qmail-limits.9 qmail-local.8 qmail-log.5 qmail-lspawn.8 qmail-newu.8 \ -qmail-pop3d.8 qmail-popup.8 qmail-pw2u.9 qmail-qmtpd.8 qmail-qread.8 \ -qmail-qstat.8 qmail-queue.8 qmail-remote.8 qmail-rspawn.8 \ -qmail-send.9 qmail-showctl.8 qmail-smtpd.8 qmail-start.8 \ -qmail-tcpto.8 qmail-upgrade.9 qmail-users.5 qmail.7 qreceipt.1 \ -splogger.8 tcp-env.1 qmail-clean.c qmail-config.sh qmail-getpw.c \ -qmail-hier.c qmail-inject.c qmail-local.c qmail-lspawn.c qmail-newu.c \ -qmail-pop3d.c qmail-popup.c qmail-pw2u.c qmail-qmtpd.c qmail-qread.c \ -qmail-qstat.sh qmail-queue.c qmail-remote.c qmail-rspawn.c \ -qmail-send.c qmail-showctl.c qmail-smtpd.c qmail-start.c \ -qmail-tcpto.c spawn.c dnscname.c dnsfq.c dnsip.c dnsmxip.c dnsptr.c \ -hostname.c ipmeprint.c tcp-env.c sendmail.c qlist.c qreceipt.c \ -qsmhook.c qbiff.c forward.c preline.c predate.c condredirect.c \ -maildirmake.c maildir2mbox.c maildirwatch.c splogger.c qail.sh elq.sh \ -pinq.sh qlist2.sh qmail-upq.sh datemail.sh mailsubj.sh qlx.h \ -constmap.h constmap.c dnsdoe.h dnsdoe.c fmtqfn.h fmtqfn.c gfrom.h \ -gfrom.c myctime.h myctime.c newfield.h newfield.c qsutil.h qsutil.c \ +addresses.5 except.1 bouncesaying.1 condredirect.1 dot-qmail.9 \ +envelopes.5 forgeries.7 forward.1 maildir2mbox.1 maildirmake.1 \ +maildirwatch.1 mailsubj.1 mbox.5 preline.1 qbiff.1 qmail-clean.8 \ +qmail-command.8 qmail-control.9 qmail-getpw.9 qmail-header.5 \ +qmail-inject.8 qmail-limits.9 qmail-local.8 qmail-log.5 \ +qmail-lspawn.8 qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 \ +qmail-popup.8 qmail-pw2u.9 qmail-qmqpc.8 qmail-qmqpd.8 qmail-qmtpd.8 \ +qmail-qread.8 qmail-qstat.8 qmail-queue.8 qmail-remote.8 \ +qmail-rspawn.8 qmail-send.9 qmail-showctl.8 qmail-smtpd.8 \ +qmail-start.9 qmail-tcpok.8 qmail-tcpto.8 qmail-users.9 qmail.7 \ +qreceipt.1 splogger.8 tcp-env.1 config.sh config-fast.sh \ +qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c \ +qmail-lspawn.c qmail-newmrh.c qmail-newu.c qmail-pop3d.c \ +qmail-popup.c qmail-pw2u.c qmail-qmqpc.c qmail-qmqpd.c qmail-qmtpd.c \ +qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \ +qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \ +qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \ +dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \ +sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c \ +except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c \ +maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh \ +datemail.sh mailsubj.sh qlx.h rcpthosts.h rcpthosts.c commands.h \ +commands.c dnsdoe.h dnsdoe.c fmtqfn.h fmtqfn.c gfrom.h gfrom.c \ +myctime.h myctime.c newfield.h newfield.c qsutil.h qsutil.c \ readsubdir.h readsubdir.c received.h received.c tcpto.h tcpto.c \ tcpto_clean.c trigger.h trigger.c triggerpull.h triggerpull.c \ -trynpbg1.c trysyslog.c conf-cc conf-ld find-systype.sh \ -make-compile.sh make-load.sh make-makelib.sh trycpp.c warn-auto.sh \ -auto-str.c auto-int.c auto-int8.c auto-gid.c auto-uid.c install.c \ -instcheck.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \ +trynpbg1.c trysyslog.c conf-cc 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 make-compile.sh make-load.sh \ +make-makelib.sh trycpp.c warn-auto.sh auto-str.c auto-int.c \ +auto-int8.c auto-gid.c auto-uid.c hier.c install.c instcheck.c \ +install-big.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \ case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c \ cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h \ cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c coe.3 \ @@ -1819,14 +1820,14 @@ getln.h getln.c getln2.3 getln2.c sgetopt.3 sgetopt.h sgetopt.c \ subgetopt.3 subgetopt.h subgetopt.c error.3 error_str.3 error_temp.3 \ error.h error.c error_str.c error_temp.c fmt.h fmt_str.c fmt_strn.c \ fmt_uint.c fmt_uint0.c fmt_ulong.c scan.h scan_ulong.c scan_8long.c \ -scan_nbblong.c slurpclose.h slurpclose.c quote.h quote.c hfield.h \ -hfield.c headerbody.h headerbody.c token822.h token822.c control.h \ -control.c datetime.3 datetime.h datetime.c datetime_un.c prioq.h \ -prioq.c date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c \ -ip.h ip.c ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h \ -ndelay.c ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c \ -prot.h prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c \ -trysalen.c maildir.5 maildir.h maildir.c tcp-environ.5 +slurpclose.h slurpclose.c quote.h quote.c hfield.h hfield.c \ +headerbody.h headerbody.c token822.h token822.c control.h control.c \ +datetime.3 datetime.h datetime.c datetime_un.c prioq.h prioq.c \ +date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c ip.h ip.c \ +ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \ +ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \ +prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \ +maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c shar -m `cat FILES` > shar chmod 400 shar @@ -1838,51 +1839,48 @@ sig_child.o sig_hup.o sig_term.o sig_bug.o sig_misc.o sig_bug.o sig_misc.o sig_alarm.o: \ -compile sig_alarm.c sig_alarm.c sig.h sig_alarm.c +compile sig_alarm.c sig.h ./compile sig_alarm.c sig_block.o: \ -compile sig_block.c sig_block.c sig.h sig_block.c hassgprm.h \ -sig_block.c +compile sig_block.c sig.h hassgprm.h ./compile sig_block.c sig_bug.o: \ -compile sig_bug.c sig_bug.c sig.h sig_bug.c +compile sig_bug.c sig.h ./compile sig_bug.c sig_catch.o: \ -compile sig_catch.c sig_catch.c sig.h sig_catch.c hassgact.h \ -sig_catch.c +compile sig_catch.c sig.h hassgact.h ./compile sig_catch.c sig_child.o: \ -compile sig_child.c sig_child.c sig.h sig_child.c +compile sig_child.c sig.h ./compile sig_child.c sig_hup.o: \ -compile sig_hup.c sig_hup.c sig.h sig_hup.c +compile sig_hup.c sig.h ./compile sig_hup.c sig_misc.o: \ -compile sig_misc.c sig_misc.c sig.h sig_misc.c +compile sig_misc.c sig.h ./compile sig_misc.c sig_pause.o: \ -compile sig_pause.c sig_pause.c sig.h sig_pause.c hassgprm.h \ -sig_pause.c +compile sig_pause.c sig.h hassgprm.h ./compile sig_pause.c sig_pipe.o: \ -compile sig_pipe.c sig_pipe.c sig.h sig_pipe.c +compile sig_pipe.c sig.h ./compile sig_pipe.c sig_term.o: \ -compile sig_term.c sig_term.c sig.h sig_term.c +compile sig_term.c sig.h ./compile sig_term.c slurpclose.o: \ -compile slurpclose.c stralloc.h gen_alloc.h stralloc.h slurpclose.c \ -readwrite.h slurpclose.c slurpclose.h slurpclose.c +compile slurpclose.c stralloc.h gen_alloc.h readwrite.h slurpclose.h \ +error.h ./compile slurpclose.c socket.lib: \ @@ -1893,28 +1891,24 @@ trylsock.c compile load rm -f trylsock.o trylsock spawn.o: \ -compile chkspawn spawn.c spawn.c spawn.c sig.h spawn.c wait.h spawn.c \ -substdio.h spawn.c byte.h spawn.c str.h spawn.c stralloc.h \ -gen_alloc.h stralloc.h spawn.c select.h select.h select.h select.h \ -spawn.c exit.h spawn.c coe.h spawn.c open.h spawn.c error.h spawn.c \ -auto_qmail.h spawn.c auto_uids.h spawn.c auto_spawn.h spawn.c +compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \ +stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \ +auto_qmail.h auto_uids.h auto_spawn.h ./chkspawn ./compile spawn.c splogger: \ -load splogger.o substdio.a error.a str.a fs.a syslog.lib +load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib ./load splogger substdio.a error.a str.a fs.a `cat \ - syslog.lib` + syslog.lib` `cat socket.lib` splogger.0: \ splogger.8 nroff -man splogger.8 > splogger.0 splogger.o: \ -compile splogger.c splogger.c splogger.c splogger.c error.h \ -splogger.c substdio.h splogger.c subfd.h substdio.h substdio.h \ -subfd.h splogger.c exit.h splogger.c str.h splogger.c scan.h \ -splogger.c fmt.h splogger.c +compile splogger.c error.h substdio.h subfd.h substdio.h exit.h str.h \ +scan.h fmt.h ./compile splogger.c str.a: \ @@ -1926,31 +1920,31 @@ byte_cr.o byte_zero.o byte_diff.o byte_copy.o byte_cr.o byte_zero.o str_chr.o: \ -compile str_chr.c str.h str_chr.c +compile str_chr.c str.h ./compile str_chr.c str_cpy.o: \ -compile str_cpy.c str.h str_cpy.c +compile str_cpy.c str.h ./compile str_cpy.c str_diff.o: \ -compile str_diff.c str.h str_diff.c +compile str_diff.c str.h ./compile str_diff.c str_diffn.o: \ -compile str_diffn.c str.h str_diffn.c +compile str_diffn.c str.h ./compile str_diffn.c str_len.o: \ -compile str_len.c str.h str_len.c +compile str_len.c str.h ./compile str_len.c str_rchr.o: \ -compile str_rchr.c str.h str_rchr.c +compile str_rchr.c str.h ./compile str_rchr.c str_start.o: \ -compile str_start.c str.h str_start.c +compile str_start.c str.h ./compile str_start.c stralloc.a: \ @@ -1963,50 +1957,41 @@ stralloc_catb.o stralloc_arts.o stralloc_arts.o stralloc_arts.o: \ -compile stralloc_arts.c byte.h stralloc_arts.c str.h stralloc_arts.c \ -stralloc.h gen_alloc.h stralloc.h stralloc_arts.c +compile stralloc_arts.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_arts.c stralloc_cat.o: \ -compile stralloc_cat.c byte.h stralloc_cat.c stralloc.h gen_alloc.h \ -stralloc.h stralloc_cat.c +compile stralloc_cat.c byte.h stralloc.h gen_alloc.h ./compile stralloc_cat.c stralloc_catb.o: \ -compile stralloc_catb.c stralloc.h gen_alloc.h stralloc.h \ -stralloc_catb.c byte.h stralloc_catb.c +compile stralloc_catb.c stralloc.h gen_alloc.h byte.h ./compile stralloc_catb.c stralloc_cats.o: \ -compile stralloc_cats.c byte.h stralloc_cats.c str.h stralloc_cats.c \ -stralloc.h gen_alloc.h stralloc.h stralloc_cats.c +compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_cats.c stralloc_copy.o: \ -compile stralloc_copy.c byte.h stralloc_copy.c stralloc.h gen_alloc.h \ -stralloc.h stralloc_copy.c +compile stralloc_copy.c byte.h stralloc.h gen_alloc.h ./compile stralloc_copy.c stralloc_eady.o: \ -compile stralloc_eady.c alloc.h stralloc_eady.c stralloc.h \ -gen_alloc.h stralloc.h stralloc_eady.c gen_allocdefs.h \ -gen_allocdefs.h gen_allocdefs.h stralloc_eady.c +compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \ +gen_allocdefs.h ./compile stralloc_eady.c stralloc_opyb.o: \ -compile stralloc_opyb.c stralloc.h gen_alloc.h stralloc.h \ -stralloc_opyb.c byte.h stralloc_opyb.c +compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h ./compile stralloc_opyb.c stralloc_opys.o: \ -compile stralloc_opys.c byte.h stralloc_opys.c str.h stralloc_opys.c \ -stralloc.h gen_alloc.h stralloc.h stralloc_opys.c +compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_opys.c stralloc_pend.o: \ -compile stralloc_pend.c alloc.h stralloc_pend.c stralloc.h \ -gen_alloc.h stralloc.h stralloc_pend.c gen_allocdefs.h \ -gen_allocdefs.h gen_allocdefs.h stralloc_pend.c +compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \ +gen_allocdefs.h ./compile stralloc_pend.c strerr.a: \ @@ -2014,47 +1999,39 @@ makelib strerr_sys.o strerr_die.o ./makelib strerr.a strerr_sys.o strerr_die.o strerr_die.o: \ -compile strerr_die.c substdio.h strerr_die.c subfd.h substdio.h \ -substdio.h subfd.h strerr_die.c exit.h strerr_die.c strerr.h \ -strerr_die.c +compile strerr_die.c substdio.h subfd.h substdio.h exit.h strerr.h ./compile strerr_die.c strerr_sys.o: \ -compile strerr_sys.c error.h strerr_sys.c strerr.h strerr_sys.c +compile strerr_sys.c error.h strerr.h ./compile strerr_sys.c subfderr.o: \ -compile subfderr.c readwrite.h subfderr.c substdio.h subfderr.c \ -subfd.h substdio.h substdio.h subfd.h subfderr.c +compile subfderr.c readwrite.h substdio.h subfd.h substdio.h ./compile subfderr.c subfdin.o: \ -compile subfdin.c readwrite.h subfdin.c substdio.h subfdin.c subfd.h \ -substdio.h substdio.h subfd.h subfdin.c +compile subfdin.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdin.c subfdins.o: \ -compile subfdins.c readwrite.h subfdins.c substdio.h subfdins.c \ -subfd.h substdio.h substdio.h subfd.h subfdins.c +compile subfdins.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdins.c subfdout.o: \ -compile subfdout.c readwrite.h subfdout.c substdio.h subfdout.c \ -subfd.h substdio.h substdio.h subfd.h subfdout.c +compile subfdout.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdout.c subfdouts.o: \ -compile subfdouts.c readwrite.h subfdouts.c substdio.h subfdouts.c \ -subfd.h substdio.h substdio.h subfd.h subfdouts.c +compile subfdouts.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdouts.c subgetopt.o: \ -compile subgetopt.c subgetopt.h subgetopt.h subgetopt.c +compile subgetopt.c subgetopt.h ./compile subgetopt.c substdi.o: \ -compile substdi.c substdio.h substdi.c byte.h substdi.c error.h \ -substdi.c +compile substdi.c substdio.h byte.h error.h ./compile substdi.c substdio.a: \ @@ -2065,16 +2042,15 @@ subfdouts.o subfdin.o subfdins.o substdio_copy.o substdio_copy.o substdio.o: \ -compile substdio.c substdio.h substdio.c +compile substdio.c substdio.h ./compile substdio.c substdio_copy.o: \ -compile substdio_copy.c substdio.h substdio_copy.c +compile substdio_copy.c substdio.h ./compile substdio_copy.c substdo.o: \ -compile substdo.c substdio.h substdo.c str.h substdo.c byte.h \ -substdo.c error.h substdo.c +compile substdo.c substdio.h str.h byte.h error.h ./compile substdo.c syslog.lib: \ @@ -2102,11 +2078,8 @@ tcp-env.1 nroff -man tcp-env.1 > tcp-env.0 tcp-env.o: \ -compile tcp-env.c tcp-env.c tcp-env.c tcp-env.c tcp-env.c sig.h \ -tcp-env.c stralloc.h gen_alloc.h stralloc.h tcp-env.c str.h tcp-env.c \ -env.h tcp-env.c fmt.h tcp-env.c scan.h tcp-env.c subgetopt.h \ -tcp-env.c ip.h tcp-env.c dns.h tcp-env.c byte.h tcp-env.c \ -remoteinfo.h tcp-env.c exit.h tcp-env.c case.h tcp-env.c +compile tcp-env.c sig.h stralloc.h gen_alloc.h str.h env.h fmt.h \ +scan.h subgetopt.h ip.h dns.h byte.h remoteinfo.h exit.h case.h ./compile tcp-env.c tcp-environ.0: \ @@ -2114,50 +2087,38 @@ tcp-environ.5 nroff -man tcp-environ.5 > tcp-environ.0 tcpto.o: \ -compile tcpto.c tcpto.h tcpto.c open.h tcpto.c lock.h tcpto.c seek.h \ -tcpto.c now.h datetime.h now.h tcpto.c ip.h tcpto.c byte.h tcpto.c \ -datetime.h datetime.h tcpto.c readwrite.h tcpto.c +compile tcpto.c tcpto.h open.h lock.h seek.h now.h datetime.h ip.h \ +byte.h datetime.h readwrite.h ./compile tcpto.c tcpto_clean.o: \ -compile tcpto_clean.c tcpto.h tcpto_clean.c open.h tcpto_clean.c \ -substdio.h tcpto_clean.c readwrite.h tcpto_clean.c +compile tcpto_clean.c tcpto.h open.h substdio.h readwrite.h ./compile tcpto_clean.c timeoutconn.o: \ -compile timeoutconn.c timeoutconn.c timeoutconn.c timeoutconn.c \ -timeoutconn.c ndelay.h timeoutconn.c select.h select.h select.h \ -select.h timeoutconn.c error.h timeoutconn.c readwrite.h \ -timeoutconn.c ip.h timeoutconn.c byte.h timeoutconn.c timeoutconn.h \ -timeoutconn.c +compile timeoutconn.c ndelay.h select.h error.h readwrite.h ip.h \ +byte.h timeoutconn.h ./compile timeoutconn.c timeoutread.o: \ -compile timeoutread.c timeoutread.h timeoutread.c select.h select.h \ -select.h select.h timeoutread.c error.h timeoutread.c readwrite.h \ -timeoutread.c +compile timeoutread.c timeoutread.h select.h error.h readwrite.h ./compile timeoutread.c timeoutwrite.o: \ -compile timeoutwrite.c timeoutwrite.h timeoutwrite.c select.h \ -select.h select.h select.h timeoutwrite.c error.h timeoutwrite.c \ -readwrite.h timeoutwrite.c +compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h ./compile timeoutwrite.c token822.o: \ -compile token822.c stralloc.h gen_alloc.h stralloc.h token822.c \ -alloc.h token822.c str.h token822.c token822.h gen_alloc.h token822.h \ -token822.c gen_allocdefs.h gen_allocdefs.h gen_allocdefs.h token822.c +compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \ +gen_alloc.h gen_allocdefs.h ./compile token822.c trigger.o: \ -compile trigger.c select.h select.h select.h select.h trigger.c \ -open.h trigger.c trigger.h trigger.c hasnpbg1.h trigger.c +compile trigger.c select.h open.h trigger.h hasnpbg1.h ./compile trigger.c triggerpull.o: \ -compile triggerpull.c ndelay.h triggerpull.c open.h triggerpull.c \ -triggerpull.h triggerpull.c +compile triggerpull.c ndelay.h open.h triggerpull.h ./compile triggerpull.c uint32.h: \ @@ -2172,10 +2133,9 @@ makelib wait_pid.o wait_nohang.o ./makelib wait.a wait_pid.o wait_nohang.o wait_nohang.o: \ -compile wait_nohang.c wait_nohang.c wait_nohang.c haswaitp.h \ -wait_nohang.c +compile wait_nohang.c haswaitp.h ./compile wait_nohang.c wait_pid.o: \ -compile wait_pid.c wait_pid.c wait_pid.c error.h wait_pid.c +compile wait_pid.c error.h haswaitp.h ./compile wait_pid.c diff --git a/PIC.local2alias b/PIC.local2alias new file mode 100644 index 0000000..75cff56 --- /dev/null +++ b/PIC.local2alias @@ -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. diff --git a/PIC.local2ext b/PIC.local2ext new file mode 100644 index 0000000..a8bf644 --- /dev/null +++ b/PIC.local2ext @@ -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. diff --git a/PIC.local2local b/PIC.local2local new file mode 100644 index 0000000..3a067e0 --- /dev/null +++ b/PIC.local2local @@ -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. diff --git a/PIC.local2rem b/PIC.local2rem new file mode 100644 index 0000000..6857af5 --- /dev/null +++ b/PIC.local2rem @@ -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: + RCPT TO: diff --git a/PIC.local2virt b/PIC.local2virt new file mode 100644 index 0000000..60f80c8 --- /dev/null +++ b/PIC.local2virt @@ -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. diff --git a/PIC.nullclient b/PIC.nullclient new file mode 100644 index 0000000..a90d7cb --- /dev/null +++ b/PIC.nullclient @@ -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: + RCPT TO: diff --git a/PIC.relaybad b/PIC.relaybad new file mode 100644 index 0000000..513f74f --- /dev/null +++ b/PIC.relaybad @@ -0,0 +1,8 @@ +qmail-smtpd Receive message by SMTP from another host: + + MAIL FROM: + RCPT TO: + + Is $RELAYCLIENT set? No. + Is irs.gov in rcpthosts? No. + Reject RCPT. diff --git a/PIC.relaygood b/PIC.relaygood new file mode 100644 index 0000000..0d62fa9 --- /dev/null +++ b/PIC.relaygood @@ -0,0 +1,33 @@ +qmail-smtpd Receive message by SMTP from another host: + + | MAIL FROM: + | RCPT TO: + | + | 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: + RCPT TO: diff --git a/PIC.rem2local b/PIC.rem2local new file mode 100644 index 0000000..62fe61a --- /dev/null +++ b/PIC.rem2local @@ -0,0 +1,36 @@ +qmail-smtpd Receive message by SMTP from another host: + + | MAIL FROM: + | RCPT TO: + | + | 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. diff --git a/README b/README index 929e25a..5208eaf 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ -qmail 1.01 -19970413 -Copyright 1997 +qmail 1.03 +19980615 +Copyright 1998 D. J. Bernstein, qmail@pobox.com qmail is a secure, reliable, efficient, simple message transfer agent. @@ -8,192 +8,262 @@ It is meant as a replacement for the entire sendmail-binmail system on typical Internet-connected UNIX hosts. See BLURB, BLURB2, BLURB3, and BLURB4 for more detailed advertisements. -INSTALL says how to set up and test qmail. If you're upgrading from -1.00, read UPGRADE instead. +INSTALL says how to set up and test qmail. If you're upgrading from a +previous version, 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 and a pointer to the qmail mailing list. -Other documentation here: RFC* explain solutions to several Internet -mail problems; all of these except RFCMXPS are implemented in qmail. -CHANGES and THANKS show how qmail has changed since it was first -released. SECURITY, INTERNALS, THOUGHTS, and TODO record many of the -qmail design decisions. +Other documentation: http://pobox.com/~djb/proto.html shows solutions to +several Internet mail problems; many of these solutions are implemented +in qmail. CHANGES and THANKS show how qmail has changed since it was +first released. SECURITY, INTERNALS, THOUGHTS, and TODO record many of +the qmail design decisions. 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 -was the final gamma version. 1.00 had exactly the same code as 0.96. To -see your systype, make systype; cat systype. +qmail have been reported to work. 0.96 was the final gamma version; 1.00 +had exactly the same code as 0.96. To see your systype, make systype; +cat systype. 1.00: a.ux-3.0-svr2-:-:-:mc68030-:- (tnx RF) -0.96: aix-3-2-:-:-:000011216700-:- (tnx JLB) -0.91: aix-3-2-:-:-:000109257500-:- -0.96: aix-4-1-:-:-:000088581000-:- (tnx HJB) -0.95: aix-4-1-:-:-:00061176a600-:- (tnx JS) -1.00: aix-4-1-:-:-:00910033a000-:- (tnx K2J) -0.91: aix-4-2-:-:-:006030934c00-:- -1.00: bsd.os-2.0.1-:i386-:-:i486-:- (tnx KR) -0.93: bsd.os-2.0.1-:i386-:-:pentium-:- +1.01: aix-3-2-:-:-:000000406300-:- (tnx DG) +1.01: aix-3-2-:-:-:000011216700-:- (tnx JLB) +1.01: aix-4-1-:-:-:000041574c00-:- (tnx M2H) +1.01: aix-4-1-:-:-:000088581000-:- (tnx HJB) +1.01: aix-4-1-:-:-:002b51134c00-:- (tnx MP) +1.00: aix-4-1-:-:-:00910033a000-:- (tnx KJJ) +1.01: aix-4-2-:-:-:000055247900-:- (tnx JLB) +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) 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.93: dgux-5.4r3.10-generic-:-:-:aviion-:- (tnx HWM) -0.91: freebsd-2.0.5-release-:i386-:-:-:- (tnx TG) -0.92: freebsd-2.1-stable-:i386-:-:pentium.815\100-:- -0.90: freebsd-2.1.0-release-:i386-:-:cy486dlc-:- (tnx G2A) -1.00: freebsd-2.1.0-release-:i386-:-:i486-dx2-:- (tnx JLB) -1.00: freebsd-2.1.0-release-:i386-:-:i486-dx-:- (tnx chrisj=???) -0.96: freebsd-2.1.0-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MBS) -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.01: freebsd-2.1.0-release-:i386-:-:i486-dx-:- (tnx VV) +1.01: freebsd-2.1.0-release-:i386-:-:i486.dx2-:- (tnx JLB) +1.00: freebsd-2.1.0-release-:i386-:-:i486dx-:- (tnx chrisj=???) +1.01: freebsd-2.1.0-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MBS) +1.01: freebsd-2.1.5-release-:i386-:-:i486-dx-:- (tnx B1F) +0.96: freebsd-2.1.5-release-:i386-:-:i486dx-:- (tnx FN) +1.01: freebsd-2.1.5-release-:i386-:-:unknown.-:- (tnx BMF) 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-:-:i486-dx-:- (tnx HCJ) -0.95: freebsd-2.1.6-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx M2L) +1.01: freebsd-2.1.6-release-:i386-:-:cy486dlc-:- (tnx M3H) 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) -0.95: freebsd-2.2-beta_a-:i386-:-:i486-dx2-:- (tnx DA) -0.91: freebsd-2.2-current-:i386-:-:i486-dx-:- (tnx DC) +1.01: freebsd-2.1.7-release-:i386-:-:pentium.815\100-:- (tnx B1F) +1.01: freebsd-2.2-970422-releng-:i386-:-:-:- (tnx TM) 1.00: freebsd-2.2-release-:i386-:-:-:- (tnx MT) -1.00: freebsd-2.2.1-release-:i386-:-:-:- (tnx TM) -1.00: freebsd-2.2.1-release-:i386-:-:i486-dx2-:- (tnx BR) -1.00: freebsd-2.2.1-release-:i386-:-:pentium-:- (tnx IW) -0.92: freebsd-3.0-current-:i386-:-:pentium-:- (tnx J2M) +1.01: freebsd-2.2-stable-:i386-:-:cyrix.5x86-:- (tnx A2B) +1.01: freebsd-2.2-stable-:i386-:-:pentium-:- (tnx gary@systemics=???) +1.01: freebsd-2.2.1-release-:i386-:-:-:- (tnx M2R) +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) -0.91: hp-ux-b.10.01-a-:-:-:9000.712-:- (tnx S2R) -0.94: hp-ux-b.10.01-a-:-:-:9000.715-:- (tnx BG) -0.91: hp-ux-b.10.01-a-:-:-:9000.801-:- (tnx S2T) -0.93: irix-5.3-02091401-:-:-:ip22-:- (tnx PW) -0.91: irix-5.3-11091811-:sgi-:-:ip19-:- (tnx BS) -0.96: irix-5.3-11091812-:-:-:ip22-:- (tnx JL) -1.00: irix-6.2-03131015-:-:-:ip22-:- (tnx SAS) -0.92: linux-1.2.13-:i386-:-:i386-:- (tnx RN) -1.00: linux-1.2.13-:i386-:-:i486-:- (tnx RF) -0.96: linux-1.2.13-:i386-:-:pentium-:- (tnx MEE) -0.91: linux-1.3.90-:alpha-:-:alpha-:- (tnx ES) -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.01: hp-ux-b.10.20-a-:-:-:9000.755-:- (tnx BCK) +1.01: irix-5.3-11091812-:-:-:ip22-:- (tnx JL) +1.01: irix-6.2-03131015-:-:-:ip22-:- (tnx DS) +1.01: irix64-6.2-03131016-:-:-:ip19-:- (tnx AH) +1.01: irix64-6.2-06101031-:-:-:ip28-:- (tnx DB) +1.01: linux-1.2.13-:i386-:-:i486-:- (tnx RF) +1.01: linux-1.2.13-:i386-:-:pentium-:- (tnx MEE) +1.01: linux-1.99.4-:i386-:-:pentium-:- (tnx C2H) +1.01: linux-2.0.0-:i386-:-:i486-:- (tnx kragen@gentle=???) +1.01: linux-2.0.0-:i386-:-:pentium-:- (tnx MJD) +1.01: linux-2.0.6-:i386-:-:pentium-:- 1.00: linux-2.0.6-:i386-:-:ppro-:- (tnx MR) -0.96: linux-2.0.7-:i386-:-:i486-:- (tnx TLM) -0.90: linux-2.0.7-:i386-:-:pentium-:- (tnx K2J) -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) +1.01: linux-2.0.7-:i386-:-:i486-:- (tnx TLM) +1.01: linux-2.0.9-:i386-:-:i486-:- (tnx VBM) 0.96: linux-2.0.13-:i386-:-:pentium-:- (tnx BW) -0.90: linux-2.0.14-:i386-:-:pentium-:- (tnx PS) -0.91: linux-2.0.15-:i386-:-:pentium-:- (tnx CL) -0.90: linux-2.0.16-:i386-:-:i486-:- (tnx AP) -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.01: linux-2.0.15-:i386-:-:i486-:- (tnx JCD) +1.01: linux-2.0.18-:i386-:-:i486-:- (tnx tk@avalon=???) +1.01: linux-2.0.18-:i386-:-:pentium-:- (tnx root@webtvchat=???) 1.00: linux-2.0.22-:i386-:-:pentium-:- (tnx MDI) 1.00: linux-2.0.23-:i386-:-:i486-:- (tnx B2L) -0.93: linux-2.0.23-:i386-:-:pentium-:- (tnx IW) -0.93: linux-2.0.24-:i386-:-:i486-:- (tnx root@cerberus=???) +1.01: linux-2.0.24-:i386-:-:i486-:- (tnx GLM) 1.00: linux-2.0.24-:i386-:-:pentium-:- (tnx VV) 0.96: linux-2.0.25-:i386-:-:i486-:- (tnx BDB) -1.00: linux-2.0.25-:i386-:-:pentium-:- (tnx AP) -0.93: linux-2.0.25-:i386-:-:ppro-:- (tnx CS) -0.93: linux-2.0.26-:i386-:-:i486-:- (tnx blynch=???) -0.96: linux-2.0.26-:i386-:-:pentium-:- (tnx ESM) -0.93: linux-2.0.26-:i386-:-:ppro-:- (tnx modus@enews=???) +1.01: linux-2.0.25-:i386-:-:pentium-:- (tnx KA) +0.93: linux-2.0.26-:i386-:-:i486-:- (tnx blynch@texas=???) +1.01: linux-2.0.26-:i386-:-:pentium-:- (tnx robbie@opus=???) 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-:-:pentium-:- (tnx root@bullwinkle=???) -1.00: linux-2.0.27-:i386-:-:ppro-:- (tnx DE) -1.00: linux-2.0.28-:i386-:-:i486-:- (tnx H2S) +1.00: linux-2.0.27-:i386-:-:i386-:- (tnx ECG) +1.01: linux-2.0.27-:i386-:-:i486-:- (tnx BN) +1.01: linux-2.0.27-:i386-:-:pentium-:- (tnx EK) +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-:-:ppro-:- (tnx KJS) -1.00: linux-2.0.29-:i386-:-:i486-:- (tnx PK) -1.00: linux-2.0.29-:i386-:-:pentium-:- (tnx CL) +1.01: linux-2.0.28-:i386-:-:ppro-:- (tnx S3T) +1.01: linux-2.0.28-osfmach3-:-:-:ppc-:- (tnx CG) +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) -0.92: linux-2.1.1-:i386-:-:i486-:- (tnx nick@sga2=???) -0.92: linux-2.1.7-:i386-:-:ppro-:- (tnx JL) -0.92: linux-2.1.9-:i386-:-:pentium-:- (tnx AC) -0.92: linux-2.1.10-:i386-:-:ppro-:- (tnx S3T) +1.01: linux-2.0.30-:-:-:sparc-:- (tnx J2P) +1.01: linux-2.0.30-:alpha-:-:alpha-:- (tnx WS) +1.01: linux-2.0.30-:i386-:-:i386-:- (tnx OK) +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.93: linux-2.1.13-:i386-:-:ppro-:- (tnx JL) 0.96: linux-2.1.14-:i386-:-:pentium-:- (tnx SCW) 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-:-:pentium-:- (tnx UO) 1.00: linux-2.1.26-:i386-:-:i486-:- (tnx DK) 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.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.91: netbsd-1.2-:mac68k-:-:apple.macintosh.se/30..(68030)-:- (tnx hauke=???) -0.92: netbsd-1.2b-:i386-:-:-:- (tnx MG) -0.93: netbsd-1.2b-:i386-:-:pentium.(genuineintel.586-class.cpu)-:- (tnx MG) +1.01: netbsd-1.2.1-:mac68k-:-:apple.macintosh.se/30..(68030)-:- (tnx HM) +1.01: netbsd-1.2.1-:sparc-:-:fmi,mb86904.@.110.mhz,.on-chip.fpu-:- (tnx ZU) 0.96: netbsd-1.2c-:pmax-:-:-:- (tnx JLW) -0.92: nextstep-3.3-:hppa-:-:7100lc-:- -0.92: nextstep-3.3-:i386-:-:pentium-:- -0.91: openbsd-1.2-:openbsd.m68k-:-:mac68k-:- (tnx AKB) -0.95: openbsd-2.0-:openbsd.i386-:-:i386-:- (tnx JPH) -0.96: openbsd-2.0-:openbsd.m68k-:-:mac68k-:- (tnx AKB) +1.01: netbsd-1.3-:hp300-:-:hp.9000/433.(33mhz.mc68040.cpu+mmu+fpu,.4k.on-chip.physical.i/d.caches)-:- (tnx TB) +1.01: netbsd-1.3.1-:sun3-:-:sun.3/60-:- (tnx MBS) +1.01: netbsd-1.3_alpha-:i386-:-:intel.pentium.(p54c).(586-class)-:- (tnx GL) +1.01: nextstep-3.1-:mc680x0-:-:68040-:- (tnx JRY) +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-mr_potatoe_head#2-:openbsd.i386-:-:i386-:- (JJMK) -0.96: openbsd-2.0-puma#1-:openbsd.m68k-:-:mac68k-:- (tnx AB) -0.92: osf1-v3.0-347-:-:-:alpha-:- (tnx B2H) -0.92: osf1-v4.0-386-:-:-:alpha-:- (tnx WW) -0.96: sco_sv-3.2-2-:-:-:i386-:- (tnx DEH) -0.96: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4c-:sun4c- (tnx MBS) -0.91: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4m-:sun4m- (tnx IS) -0.92: sunos-4.1.3_u1-2-:sparc-:sun4-:sun4c-:sun4c- (tnx ANR) -0.93: sunos-4.1.3_u1-4-:sparc-:sun4-:sun4m-:sun4m- (tnx J2B) +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 AKB) +1.01: openbsd-2.1-asgard#1-:openbsd.i386-:-:i386-:- (tnx ETT) +1.01: openbsd-2.1-generic#71-:openbsd.sparc-:-:sparc-:- (tnx MMM2) +1.01: openbsd-2.1-katana#2-:openbsd.i386-:-:i386-:- (tnx CHR) +1.01: openbsd-2.1-puma#0-:openbsd.m68k-:-:mac68k-:- (tnx AKB) +1.01: openbsd-2.2-ele#2-:openbsd.i386-:-:i386-:- (tnx RC) +1.01: openbsd-2.2-generic#424-:openbsd.i386-:-:i386-:- (tnx ETT) +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) -0.91: sunos-4.1.3_u1-9-:sparc-:sun4-:sun4m-:sun4m- (tnx TA) -0.91: sunos-4.1.4-2-:sparc-:sun4-:sun4c-:sun4c- (tnx ST) -0.95: sunos-4.1.4-2-:sparc-:sun4-:sun4m-:sun4m- (tnx TG) -0.95: sunos-4.1c-4.1.3-:sparc-:sun4-:sun4-:s4000- (tnx DBK) -0.91: sunos-5.4-generic-:sparc-:sun4-:sun4m-:sun4m- +1.01: sunos-4.1.3_u1-6-:sparc-:sun4-:sun4m-:sun4m- (tnx RD) +1.01: sunos-4.1.4-1-:unknown-:sun4-:sun4m-:sun4m- (tnx M3S) +1.01: sunos-4.1.4-2-:sparc-:sun4-:sun4m-:sun4m- +1.01: sunos-5.3-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx JDJ) +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.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) -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.5-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx M2G) -0.93: sunos-5.5-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx CG) -1.00: sunos-5.5-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx SG) -1.00: sunos-5.5-generic_103093-02-:sparc-:sun4-:sun4m-:sun4m- (tnx RF) -0.91: sunos-5.5-generic_103093-03-:sparc-:sun4-:sun4d-:sun4d- (tnx M3S) +1.01: sunos-5.5-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx seong=???) +1.01: sunos-5.5-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx SPM) +1.01: sunos-5.5-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx RDM) +1.01: sunos-5.5-generic-:sparc-:sun4-:sun4u-:sun4u- (tnx YC) +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.91: sunos-5.5-generic_103093-03-:sparc-:sun4-:sun4u-:sun4u- (tnx olav=???) -0.92: sunos-5.5-generic_103093-05-:sparc-:sun4-:sun4m-:sun4m- (tnx KE) -0.93: sunos-5.5-generic_103093-06-:sparc-:sun4-:sun4d-:sun4d- (tnx KT) -1.00: sunos-5.5-generic_103093-06-:sparc-:sun4-:sun4m-:sun4m- (tnx TEE) -0.94: sunos-5.5-generic_103094-01-:i386-:i86pc-:i86pc-:i86pc- (tnx MD) -0.91: sunos-5.5-generic_103094-03-:i386-:i86pc-:i86pc-:i86pc- (tnx ding=???) -1.00: sunos-5.5.1-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx DML) -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) +1.01: sunos-5.5-generic_103093-06-:sparc-:sun4-:sun4m-:sun4m- (tnx ERH) +1.01: sunos-5.5-generic_103093-10-:sparc-:sun4-:sun4d-:sun4d- (tnx KT) +1.01: sunos-5.5-generic_103094-05-:i386-:i86pc-:i86pc-:i86pc- (tnx M2G) +1.01: sunos-5.5.1-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx cro=???) +1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx CG) +1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx MBS) +1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4u-:sun4u- 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-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) +1.01: ultrix-4.4-0-:-:-:risc-:- (tnx RSK) +1.01: unix_sv-4.2mp-2.1.2-:i386-:-:i386-:- (tnx J2W) diff --git a/REMOVE.binmail b/REMOVE.binmail new file mode 100644 index 0000000..9532ac9 --- /dev/null +++ b/REMOVE.binmail @@ -0,0 +1,16 @@ +Here's how to remove binmail from your system. Don't do this if you have +configured qmail to use binmail for local delivery. + + +1. Find the binmail binary on your system: /usr/libexec/mail.local if + that exists, otherwise /bin/mail. + +2. Remove permissions from the binmail binary: + # chmod 0 /usr/libexec/mail.local + +3. If the binmail binary was /bin/mail, make sure that ``mail'' still + invokes a usable mailer. Under SVR4 you may want to link mail to + mailx. + +4. Comment out the comsat line in /etc/inetd.conf, and kill -HUP your + inetd. diff --git a/REMOVE.sendmail b/REMOVE.sendmail new file mode 100644 index 0000000..5be6e78 --- /dev/null +++ b/REMOVE.sendmail @@ -0,0 +1,28 @@ +Here's how to remove sendmail from your system. + +1. Find sendmail in your boot scripts. It's usually in either /etc/rc or + /etc/init.d/sendmail. It looks like + sendmail -bd -q15m + -q15m means that it should run the queue every 15 minutes; you may + see a different number. Comment out this line. + +2. Kill the sendmail daemon. You should first kill -STOP the daemon; if + any children are running, you should kill -CONT, wait, kill -STOP + again, and repeat ad nauseam. If there aren't any children, kill + -TERM and then kill -CONT. + +3. Check whether you have any messages in the sendmail queue, + /var/spool/mqueue. If you do, you will have to try flushing them with + sendmail.bak -q. If necessary, wait a while and run sendmail.bak -q + again. Repeat until the queue is empty. This may take several days. + +4. Remove the setuid bit on the sendmail binary, to prevent local users + from gaining extra privileges through sendmail's security holes. The + binary may be at several different locations: + # chmod 0 /usr/lib/sendmail + # chmod 0 /usr/sbin/sendmail + # chmod 0 /usr/lib/sendmail.mx + +5. Move the sendmail binary out of the way: + # mv /usr/lib/sendmail /usr/lib/sendmail.bak + # mv /usr/sbin/sendmail /usr/sbin/sendmail.bak diff --git a/RFCHCSC b/RFCHCSC deleted file mode 100644 index fba3184..0000000 --- a/RFCHCSC +++ /dev/null @@ -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: - - : - 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: - - : - 127.3.4.5 does not like recipient. - Remote host said: 550 ... User unknown (#5.1.1) - - -3. Security considerations - - Don't take drastic action upon seeing "(#"; it might not be HCMSSC. diff --git a/RFCLOOPS b/RFCLOOPS deleted file mode 100644 index 0c4c91a..0000000 --- a/RFCLOOPS +++ /dev/null @@ -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, is neither <> nor <#@[]> normal messages - 1 hop, is neither <> nor <#@[]> - 2 hops, is neither <> nor <#@[]> - etc. - 0 hops, is <> bounces - 1 hop, is <> - 2 hops, is <> - etc. - 0 hops, is <#@[]> double bounces - 1 hop, is <#@[]> - 2 hops, 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 - Date: 2 Jan 1996 03:38:25 GMT - From: DELIVERY NOTICE SYSTEM - 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). diff --git a/RFCMXPS b/RFCMXPS deleted file mode 100644 index d0d3a70..0000000 --- a/RFCMXPS +++ /dev/null @@ -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. diff --git a/RFCNETSTR b/RFCNETSTR deleted file mode 100644 index 6c02506..0000000 --- a/RFCNETSTR +++ /dev/null @@ -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. diff --git a/RFCNRUDT b/RFCNRUDT deleted file mode 100644 index 4f3196a..0000000 --- a/RFCNRUDT +++ /dev/null @@ -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" - Message-Id: <19960101214334.8529.qmail@silverton.berkeley.edu> - Notice-Requested-Upon-Delivery-To: God , - 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 - 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. diff --git a/RFCQMTP b/RFCQMTP deleted file mode 100644 index 6c48e98..0000000 --- a/RFCQMTP +++ /dev/null @@ -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:" <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. diff --git a/RFCQSBMF b/RFCQSBMF deleted file mode 100644 index de132a7..0000000 --- a/RFCQSBMF +++ /dev/null @@ -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. - - : - Sorry, I couldn't find any host by that name. - - --- Below this line is a copy of the message. - - Return-Path: - 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. diff --git a/RFCVERP b/RFCVERP deleted file mode 100644 index 6299a44..0000000 --- a/RFCVERP +++ /dev/null @@ -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. diff --git a/SECURITY b/SECURITY index 218830d..098f124 100644 --- a/SECURITY +++ b/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 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. Here are some of the things I did to make sure that qmail will never let 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 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. 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 bugs translate into security holes. Some examples: the Linux login -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. 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 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. @@ -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 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 -getline2() make it very easy to avoid buffer overruns, memory leaks, -and artificial line length limits. +getln() make it very easy to avoid buffer overruns, memory leaks, and +artificial line length limits. diff --git a/SENDMAIL b/SENDMAIL new file mode 100644 index 0000000..9280c24 --- /dev/null +++ b/SENDMAIL @@ -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. diff --git a/TARGETS b/TARGETS index 12054c0..facdad7 100644 --- a/TARGETS +++ b/TARGETS @@ -8,58 +8,13 @@ compile fork.h qmail-local.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 now.o gfrom.o myctime.o slurpclose.o +make-makelib +makelib case_diffb.o case_diffs.o case_lowerb.o @@ -104,8 +59,8 @@ lock.a fd_copy.o fd_move.o fd.a -wait_pid.o haswaitp.h +wait_pid.o wait_nohang.o wait.a env.o @@ -124,24 +79,66 @@ stralloc.a alloc.o alloc_re.o 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_un.o 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 uint32.h qmail-lspawn.o -auto-uid.o -auto-uid -auto-gid.o -auto-gid -auto_uids.c -auto_uids.o +select.h +chkspawn.o auto-int.o auto-int auto_spawn.c auto_spawn.o -select.h -chkspawn.o chkspawn spawn.o chkshsgr.o @@ -153,6 +150,12 @@ cdb_hash.o cdb_unpack.o cdb_seek.o cdb.a +auto-uid.o +auto-uid +auto-gid.o +auto-gid +auto_uids.c +auto_uids.o qmail-lspawn qmail-getpw.o auto_break.c @@ -175,7 +178,6 @@ ipme.o ndelay.o ndelay_off.o ndelay.a -socket.lib dns.lib qmail-remote qmail-rspawn.o @@ -183,9 +185,9 @@ tcpto_clean.o qmail-rspawn direntry.h qmail-clean.o +fmtqfn.o auto_split.c auto_split.o -fmtqfn.o qmail-clean qmail-send.o qsutil.o @@ -216,7 +218,6 @@ predate datemail mailsubj qmail-upq -qmail-config qmail-showctl.o qmail-showctl qmail-newu.o @@ -233,12 +234,21 @@ qmail-qread qmail-qstat qmail-tcpto.o qmail-tcpto +qmail-tcpok.o +qmail-tcpok qmail-pop3d.o +commands.o +maildir.o qmail-pop3d qmail-popup.o qmail-popup -qmail-qmtpd.o +qmail-qmqpc.o +qmail-qmqpc +qmail-qmqpd.o received.o +qmail-qmqpd +qmail-qmtpd.o +rcpthosts.o qmail-qmtpd qmail-smtpd.o qmail-smtpd @@ -247,6 +257,10 @@ sendmail tcp-env.o remoteinfo.o tcp-env +qmail-newmrh.o +qmail-newmrh +config +config-fast dnscname.o dnsdoe.o dnscname @@ -262,9 +276,6 @@ hostname.o hostname ipmeprint.o ipmeprint -qlist.o -qlist -qlist2 qreceipt.o qreceipt qsmhook.o @@ -277,25 +288,38 @@ preline.o preline condredirect.o condredirect +bouncesaying.o +bouncesaying +except.o +except maildirmake.o maildirmake maildir2mbox.o -maildir.o -strerr_sys.o -strerr_die.o -strerr.a maildir2mbox maildirwatch.o maildirwatch qail elq pinq -qmail-hier.o -qmail-hier +idedit.o +idedit +install-big.o install.o +install-big +hier.o install instcheck.o instcheck +home +home+df +proc +proc+df +binm1 +binm1+df +binm2 +binm2+df +binm3 +binm3+df it qmail-local.0 qmail-lspawn.0 @@ -306,40 +330,48 @@ qmail-rspawn.0 qmail-clean.0 qmail-send.8 qmail-send.0 +qmail-start.8 qmail-start.0 splogger.0 qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 +qmail-newu.8 qmail-newu.0 qmail-pw2u.8 qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 +qmail-tcpok.0 qmail-pop3d.0 qmail-popup.0 +qmail-qmqpc.0 +qmail-qmqpd.0 qmail-qmtpd.0 qmail-smtpd.0 tcp-env.0 -qlist.0 +qmail-newmrh.8 +qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 preline.0 condredirect.0 +bouncesaying.0 +except.0 maildirmake.0 maildir2mbox.0 maildirwatch.0 qmail.0 -qmail-upgrade.7 -qmail-upgrade.0 qmail-limits.7 qmail-limits.0 qmail-log.0 +qmail-control.5 qmail-control.0 qmail-header.0 +qmail-users.5 qmail-users.0 dot-qmail.5 dot-qmail.0 @@ -351,3 +383,5 @@ addresses.0 envelopes.0 forgeries.0 man +setup +check diff --git a/TEST.deliver b/TEST.deliver new file mode 100644 index 0000000..4fc4c32 --- /dev/null +++ b/TEST.deliver @@ -0,0 +1,82 @@ +You can do several tests of qmail delivery without setting up qmail to +accept messages through SMTP or through /usr/lib/sendmail: + +1. After you start qmail, look for a + qmail: status: local 0/10 remote 0/20 + line in syslog. qmail-send always prints either ``cannot start'' or + ``status''. (The big number is a splogger timestamp.) + +2. 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 + as root; qmail-rspawn, running as qmailr; and qmail-clean, running + as qmailq. You will also see splogger, running as qmaill. + +3. Local-local test: Send yourself an empty message. (Replace ``me'' + with your username. Make sure to include the ``to:'' colon.) + % echo to: me | /var/qmail/bin/qmail-inject + The message will show up immediately in your mailbox, and syslog + will show something like this: + qmail: new msg 53 + qmail: info msg 53: bytes 246 from qp 20345 uid 666 + 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: status: local 0/10 remote 0/20 + qmail: end msg 53 + (53 is an inode number; 20345 is a process ID; your numbers will + probably be different.) + +4. Local-error test: Send a message to a nonexistent local address. + % echo to: nonexistent | /var/qmail/bin/qmail-inject + qmail: new msg 53 + qmail: info msg 53: bytes 246 from qp 20351 uid 666 + 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: status: local 0/10 remote 0/20 + qmail: bounce msg 53 qp 20357 + qmail: end msg 53 + qmail: new msg 54 + qmail: info msg 54: bytes 743 from <> qp 20357 uid 666 + 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: status: local 0/10 remote 0/20 + qmail: end msg 54 + You will now have a bounce message in your mailbox. + +5. Local-remote test: Send an empty message to your account on another + machine. + % echo to: me@wherever | /var/qmail/bin/qmail-inject + qmail: new msg 53 + qmail: info msg 53: bytes 246 from qp 20372 uid 666 + 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: status: local 0/10 remote 0/20 + qmail: end msg 53 + There will be a pause between ``starting delivery'' and ``success''; + SMTP is slow. Check that the message is in your mailbox on the other + machine. + +6. Local-postmaster test: Send mail to postmaster, any capitalization. + % echo to: POSTmaster | /var/qmail/bin/qmail-inject + Look for the message in the alias mailbox, normally ~alias/Mailbox. + +7. Double-bounce test: Send a message with a completely bad envelope. + % /var/qmail/bin/qmail-inject -f nonexistent + To: unknownuser + Subject: testing + + This is a test. This is only a test. + % + (Use end-of-file, not dot, to end the message.) Look for the double + bounce in the alias mailbox. + +8. Group membership test: + % cat > ~me/.qmail-groups + |groups >> MYGROUPS; exit 0 + % /var/qmail/bin/qmail-inject me-groups < /dev/null + % cat ~me/MYGROUPS + MYGROUPS will show your normal gid and nothing else. (Under Solaris, + make sure to use /usr/ucb/groups; /usr/bin/groups is broken.) diff --git a/TEST.receive b/TEST.receive new file mode 100644 index 0000000..7644845 --- /dev/null +++ b/TEST.receive @@ -0,0 +1,41 @@ +You can do several tests of messages entering the qmail system: + +1. SMTP server test: Forge some mail locally via SMTP. Replace ``me'' + with your username and ``domain'' with your host's name. + % telnet 127.0.0.1 25 + Trying 127.0.0.1... + Connected to 127.0.0.1. + Escape character is '^]'. + 220 domain ESMTP + helo dude + 250 domain + mail + 250 ok + rcpt + 250 ok + data + 354 go ahead + Subject: testing + + This is a test. + . + 250 ok 812345679 qp 12345 + quit + 221 domain + Connection closed by foreign host. + % + Look for the message in your mailbox. (Note for programmers: Most + SMTP servers need more text after MAIL and RCPT. See RFC 821.) + +2. Remote-local test: Send yourself some mail from another machine. + Look for the message in your mailbox. + +3. Remote-error test: Send some mail from another machine to + nonexistent@domain. Look for a bounce message in the remote mailbox. + +4. UA test: Try sending mail, first to a local account, then to a + remote account, with your normal user agent. + +5. Remote-postmaster test: Send mail from another machine to + PoStMaStEr@domain. Look for the message in the alias mailbox, + normally ~alias/Mailbox. diff --git a/THANKS b/THANKS index c3d5ba0..b1ad88e 100644 --- a/THANKS +++ b/THANKS @@ -2,216 +2,336 @@ Thanks to lots of people for success and failure reports, code, ideas, and documentation. See CHANGES for details of specific contributions. Sorry if I left anyone out. -SA = Satoshi Adachi -G1A = Graham Adams -NA = Norm Aleks -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 +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 -JBB = Jason B. Brown -JAB = Jeremy A. Bussard -RJC = Robert J. Carter -EC = Evan Champion -JC = Jim Clausing -HCJ = Helio Coelho Jr. +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 -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 +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 -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 -TH = Ton Hospel BH = Brad Howes -TJH = Timothy J. Hunt -B2H = Buck Huppmann -MDI = Miguel de Icaza BJ = Brian Jackson -AJ = Alan Jaffray +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 -K2J = Kevin Johnson -K1J = Kyle Jones -SJ = Sudish Joseph -W2K = Wolfram Kahl -JJMK = Jonathan J. M. Katz +CF = C. Ferree +CG = Chris Garrigues +CH = Chael Hall +CHR = Craig H. Rowland CK = Christoph Kaesling -PK = Petri Kaukasoina +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 -TK = Terry Kennedy +D2S = Dan Senie +D3S = Don Samek +DA = Dave Arcuri +DAR = Daniel A. Reish +DB = David Buscher DBK = Douglas B. Kerry -WK = Werner Koch +DC = Dan Cross +DCC = Daniel C. Cotey +DE = Daniel Egnor +DEH = Daniel E. Harris +DF = Dale Farnsworth +DG = David Guntner 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 +DL = Daniel Lawrence +DM = David Mazieres 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 +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 -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 +ET = Eivind Tagseth +ETT = Emmanuel T. Tardieu +F2T = Frank Thieme +FE = Frank Ederveen FN = Faried Nawaz -RN = Russell Nelson -TN = Thomas Neumann -UO = Uwe Ohse -PCO = Peter C. Olsen +FPL = Frederik P. Lindberg +FT = Frank Tegtmeyer +FW = Frank Wagner +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 -BEO = Bruce E. O'Neel +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 -AP = Andrew Pam -SP = Stephen Parker -TVP = Tom van Peer -BP = Bruce Perens -CMP = Chase M. Phillips -DP = Dave Platt -EP = Emanuele Pucciarelli +JPB = Joe Block +JPH = Justin P. Hannah 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 +JRL = John R. Levine +JRM = Jason R. Mastaler +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 +NAA = Nicholas A. Amato +NH = Nick Holloway +NND = N. Dudorov +NR = Norbert Roeding +NW = Nicholas Waples +OK = Oezguer Kesim 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 -D2S = Dan Senie -SS = Simon Shapiro -RGS = Richard G. Sharman -DS = Dave Sill -H2S = Harley Silver -M3S = Morten Skjelland -JS = Jesper Skriver -ES = Eric Smith -IS = Icarus Sparry -CS = Cloyce Spradling -BS = Bjoern Stabell -HS = Harlan Stenn -JMS = Jason M. Stokes -DWS = David Wayne Summers -M2S = Mikael Suokas +PB = Peter Bowyer +PCO = Peter C. Olsen +PGF = Paul Fox +PGR = Phil G. Rorex +PH = Paul Harrington +PJG = Paul Graham +PJH = Peter J. Hunter +PK = Petri Kaukasoina +PMH = Peter M. Haworth +PO = Paul Overell PS = Paul Svensson -ET = Eivind Tagseth PT = Paul Taylor +PTW = P. T. Withington +PW = Peter Wilkinson +R2N = Rivo Nurges +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 -BT = Brad Templeton -DST = Daniel S. Thibadeau -MT = Mark Thompson S3T = Steffen Thorsen -KT = Karsten Thygesen -BET = Bennett E. Todd -JMT = John M. Twilley +SA = Satoshi Adachi +SAE = Stefaan A. Eeckels +SAS = Steven A. Schrader +SB = Stephane Bortzmeyer +SC = Stefan Cars +SCW = Steven C. Work +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 -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 -HW = Hal Wine -GAW = Greg A. Woods -SCW = Steven C. Work -JLW = Jason L. Wright +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 -IKW = Ian Keith Wynne -BZ = Blaz Zupan +YC = Yuji Chikahiro +YF = Yaroslav Faybishenko +ZU = Zin Uda diff --git a/THOUGHTS b/THOUGHTS index 6587084..d6910da 100644 --- a/THOUGHTS +++ b/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 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 -steal mail. Possible solution: replace dns.c with something that passes -requests (reliably!) to a local daemon; call the original resolver -library from that daemon. +steal mail. Solution: insist that the resolver run on the same host; the +kernel can guarantee the security of low-numbered 127.0.0.1 UDP ports. 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 @@ -72,10 +71,10 @@ is, as far as I can tell, always wrong. 2. Injecting mail locally (qmail-inject, sendmail-clone) -RFC 822 section 3.4.9 prohibits certain visual effects in headers. -qmail-inject doesn't waste the time to enforce this absurd restriction. -If you will suffer from someone sending you ``flash mail,'' go find a -better mail reader. +RFC 822 section 3.4.9 prohibits certain visual effects in headers, and +the 822bis draft prohibits even more. qmail-inject could enforce these +absurd restrictions, but why waste the time? If you will suffer from +someone sending you ``flash mail,'' go find a better mail reader. qmail-inject's ``Cc: recipient list not shown: ;'' successfully stops 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 main(), then wait until the pids wrap around, then restart qmail-inject 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, -the user could just type in his own non-unique Message-IDs.) +same pid in the same second. I'm not sure how to fix this without +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 only to sender addresses.'' Recipient masquerading works fine with qmail. None of sendmail's pitfalls apply, basically because qmail has a straight paper path. -I expect to receive some pressure to make up for the failings of MUA -writers who don't understand the concept of reliability. (``Like, duh, -you mean I was supposed to check the sendmail exit code?'') +I predicted that I would receive some pressure to make up for the +failings of MUA writers who don't understand the concept of reliability. +(``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) -RFC 1123 requires VRFY support, but says that it's okay if an -implementation can be configured to not allow VRFY. qmail-smtpd doesn't -allow VRFY. If you desperately want your SMTP server (i.e., inetd) to -provide useful information for VRFY, just compile and install sendmail. -Were the RFC 1123 writers aware of the as-if principle of interface -specification? ... They say that VRFY and EXPN are important for -tracking down cross-host mailing list loops. Catch up to the 1990s, -guys: with Delivered-To, mailing list loops do absolutely no damage, -_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. +qmail-smtpd doesn't allow privacy-invading commands like VRFY and EXPN. +If you really want to publish such information, use a mechanism that +legitimate users actually know about, such as fingerd or httpd. + +RFC 1123 says that VRFY and EXPN are important to track down cross-host +mailing list loops. With Delivered-To, mailing list loops do no damage, +_and_ one of the list administrators gets a bounce message that shows +exactly how the loop occurred. Solve the problem, not the symptom. Should dns.c make special allowances for 127.0.0.1/localhost? 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) 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) -qmail-smtpd or qmail-qmtpd, it could be told a size in advance. I wish -UNIX had an atomic allocate-disk-space routine... +qmail-smtpd or qmail-qmtpd or qmail-qmqpd, it could be told a size in +advance. I wish UNIX had an atomic allocate-disk-space routine... The qmail.h interface (reflecting the qmail-queue interface, which in 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 dangerous---not that this stops people from running sendmail that way! -Perhaps it is worth putting together a diskless-host qmail package with -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. +Diskless hosts should use mini-qmail instead. Queue reliability demands that single-byte writes be atomic. This is 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 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 -meantime. Perhaps qmail-send should limit its time per message to, -say, thirty recipients. This will require some way to mark recipients -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. +meantime. The simplest way to handle this would be to put big messages +on a separate channel. 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 @@ -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 the addresses in a new message. As usual, making these asynchronous would require some housekeeping, but could speed things up a bit. -(Making bounces asynchronous, without POSIX waitpid(), means that -wait_pid() has to keep a buffer of previous wait()s. Ugh.) - -fsync() is a bottleneck. To make this asynchronous would require gobs of -dedicated output processes whose only purpose in life is to watch data -get written to the disk. Inconceivable! (``You keep using that word. I -do not think that word means what you think it means.'') - -On the other hand, I could survive without fsync()ing the local and -remote and info files as long as I don't unlink todo. This would require -redefining the queue states. I need to see how much speed can be gained. - -Currently qmail-send sends at most one bounce message for each incoming -message. This means that the sender doesn't get flooded with copies of -his own message. On the other hand, a single slow address can hold up -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. +(I'm willing to assume POSIX waitpid() for asynchronous bounces; putting +an unbounded buffer into wait_pid() for the sake of NeXTSTEP 3 is not +worthwhile.) + +Disk I/O is a bottleneck; UFS is reliable but it isn't fast. A good +logging filesystem offers much better performance, but logging +filesystems aren't widely available. Solution: Keep a journal, separate +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. + +Bounce aggregation is a dubious feature. Bounce records aren't +crashproof; there can be a huge delay between a failure and a bounce; +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. + +qmail-stop implementation: setuid to UID_SEND; kill -TERM -1. Or run +qmail-start under an external service controller, such as supervise; +that's why it runs in the foreground. 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 @@ -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 _slowness_ feature. Separate SMTP transactions have much lower latency. -The multiple-RCPT bandwidth gain _might_ be noticeable for a machine -that sends most messages to a smarthost. It would be easy to have -qmail-rspawn supply qmail-remote with all the addresses at once, as long -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.) +I've heard three complaints about bandwidth use from masochists sending +messages through a modem through a smarthost to thousands of users--- +without sublists! They can get much better performance with QMQP. 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. 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 -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 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 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) @@ -347,7 +332,7 @@ Configurable user database: Yup. BIND support: Yup. -Keyed files: Yes, in qmsmac. +Keyed files: Yes, in fastforward. 931/1413/Ident/TAP: Yup. @@ -358,7 +343,9 @@ List-owner handling: 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. @@ -420,12 +407,6 @@ I should clean up the bput/put choices. Some of the stralloc_0()s indicate that certain lower-level routines 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 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? diff --git a/TODO b/TODO index 6101add..5841c0a 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,23 @@ -do some serious coverage testing, preferably under Purify, without alloc slop -replace INTERNALS and THOUGHTS with a real paper describing qmail -reorganize qmail-inject to do most rw on characters, not tokens -allow concurrency over 255 -handle IPv6 +consider stripping vdoms for VERPs; tnx PJH +consider ~ in qmail-local for doing defaultdelivery (not recursively) +consider POP bulletins turn qmail-upq into a more serious queue-moving utility +consider fast-greeting option in qmail-smtpd +build a returnmail package + 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 mess822 in qmail-inject +use mess822 in qreceipt +use mess822 in qbiff +use mess822 in maildirwatch +eliminate token822, headerbody, hfield +replace INTERNALS and THOUGHTS with a real paper describing qmail +handle IPv6 rewrite everything from scratch -maybe allow root to clear tcpto on the fly diff --git a/UPGRADE b/UPGRADE index c6200ca..d648813 100644 --- a/UPGRADE +++ b/UPGRADE @@ -3,143 +3,64 @@ information generally), the qmail system comes with NO WARRANTY. It's 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 -overwrite the old qmail binaries. Furthermore, it may begin delivering -messages from the queue before you have had a chance to test it. +Here's how to upgrade to qmail 1.03. This procedure will overwrite the +old qmail binaries. Furthermore, it may begin delivering messages from +the queue before you have had a chance to test it. -WARNING: The qmail-start command line has changed. +WARNING for upgrades from 1.00 or 1.01: 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 for upgrades from 1.01: recipientmap is gone. The virtualdomains +mechanism has been expanded to support virtual users. Before starting, compare conf* to your old conf*, and make any necessary -changes. Do not copy your old conf*; the baseline has changed. +changes. You can copy conf* from 1.02. How to install: - 1. Compile the programs: - # make - 2. Create the formatted man pages, *.0: - # make man - 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 + 1. Compile the programs and create the formatted man pages: + # make it man + + 2. Inform your users that mail will not be accepted for a few minutes. + + 3. Disable deliveries by killing your old qmail-send. Wait for it to 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 - your tcpserver.) Wait for current qmail-smtpd processes to die. (If - you are running a QMTP server, disable that too.) - 6. Install the new binaries and man pages: - # rm /var/qmail/bin/* /var/qmail/man/*/* - # make setup - 7. Run instcheck to make sure it doesn't print any warnings: - # make check - 8. Reenable deliveries: - # env - PATH="/var/qmail/bin:$PATH" \ - qmail-start ./Mailbox splogger qmail & - Make sure to include the ./ in ./Mailbox. - 9. Insert ./Mailbox into the qmail-start line in your boot scripts. -10. Reenable SMTP service by restoring the smtp line in inetd.conf; kill + your tcpserver. If you are running a QMTP server, disable that too.) + Wait for current qmail-smtpd processes to die. + + 5. Install the new binaries and man pages: + # make setup check + + 6. If your boot scripts are using qmail-start instead of /var/qmail/rc: + Copy /var/qmail/boot/home to /var/qmail/rc. (Use home+df instead if + you have installed dot-forward; use proc or proc+df if you are using + procmail by default for local deliveries.) Compare /var/qmail/rc to + your qmail-start boot line, and edit /var/qmail/rc if necessary. + Replace your qmail-start boot line with + csh -cf '/var/qmail/rc &' + + 7. Reenable deliveries: + # csh -cf '/var/qmail/rc &' + + 8. Read TEST.deliver. + + 9. Reenable SMTP service by restoring the smtp line in inetd.conf; kill -HUP your inetd. (If you are using tcpserver, simply kill -CONT your tcpserver. If you are running a QMTP server, reenable that too.) - -How to test (steps 11-17 can be done before step 10): - -11. Look for a - qmail: running - line in syslog. (The big number is a splogger timestamp.) -12. Local-local test: Send yourself an empty message. (Replace ``me'' - with your username. Make sure to include the ``to:'' colon.) - % echo to: me | /var/qmail/bin/qmail-inject - The message will show up immediately in ~/Mailbox, and syslog will - show something like this: - qmail: new msg 53 - qmail: info msg 53: bytes 246 from qp 20345 uid 666 - qmail: starting delivery 1: msg 53 to local me@domain - qmail: delivery 1: success: did_1+0+0/ - qmail: end msg 53 - (53 is an inode number; 20345 is a process ID; your numbers will - probably be different.) -13. Local-error test: Send a message to a nonexistent local address. - % echo to: nonexistent | /var/qmail/bin/qmail-inject - qmail: new msg 53 - qmail: info msg 53: bytes 246 from qp 20351 uid 666 - qmail: starting delivery 2: msg 53 to local nonexistent@domain - qmail: delivery 2: failure: No_such_address.__#5.1.1_/ - qmail: bounce msg 53 qp 20357 - qmail: end msg 53 - qmail: new msg 54 - qmail: info msg 54: bytes 743 from <> qp 20357 uid 666 - qmail: starting delivery 3: msg 54 to local me@domain - qmail: delivery 3: success: did_1+0+0/ - qmail: end msg 54 - You will now have a bounce message in ~/Mailbox. -14. Local-remote test: Send an empty message to your account on another - machine. - % echo to: me@wherever | /var/qmail/bin/qmail-inject - qmail: new msg 53 - qmail: info msg 53: bytes 246 from qp 20372 uid 666 - qmail: starting delivery 4: msg 53 to remote me@wherever - qmail: delivery 4: success: 1.2.3.4_accepted_message./... - qmail: end msg 53 - There will be a pause between ``starting delivery'' and ``success''; - SMTP is slow. Check that the message is in your mailbox on the other - machine. -15. Local-postmaster test: Send mail to postmaster, any capitalization. - % echo to: POSTmaster | /var/qmail/bin/qmail-inject - Look for the message in ~alias/Mailbox. -16. Double-bounce test: Send a message with a completely bad envelope. - % /var/qmail/bin/qmail-inject -f nonexistent - To: unknownuser - Subject: testing - - This is a test. This is only a test. - % - (Use end-of-file, not dot, to end the message.) Look for the double - bounce in ~alias/Mailbox. -17. Group membership test: - % cat > ~me/.qmail-groups - |groups >> MYGROUPS; exit 0 - % /var/qmail/bin/qmail-inject me-groups < /dev/null - % cat ~me/MYGROUPS - MYGROUPS will show your normal gid and nothing else. (Under Solaris, - make sure to use /usr/ucb/groups; /usr/bin/groups is broken.) -18. SMTP server test: Forge some mail locally via SMTP. - % telnet 127.0.0.1 25 - Trying 127.0.0.1... - Connected to 127.0.0.1. - Escape character is '^]'. - 220 domain ESMTP - helo dude - 250-domain - 250-PIPELINING - 250 8BITMIME - mail - 250 ok - rcpt - 250 ok - data - 354 go ahead - Subject: testing - - This is a test. - . - 250 ok 812345679 qp 12345 - quit - 221 domain - Connection closed by foreign host. - % - Look for the message in your mailbox. -19. Remote-local test: Send yourself some mail from another machine. -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 - remote account, with your normal user agent. -22. Remote-postmaster test: Send mail from another machine to - PoStMaStEr@domain. Look for the message in ~alias/Mailbox. +10. Read TEST.receive. That's it! To report success: - % ( echo 'First M. Last'; cat `cat SYSDEPS` ) \ - | mail djb-qst@koobera.math.uic.edu -Replace First M. Last with your name. If you have questions about qmail, -contact qmail@pobox.com. + % ( echo 'First M. Last'; cat `cat SYSDEPS` ) | mail djb-qst@cr.yp.to +Replace First M. Last with your name. + +If you have questions about qmail, join the qmail mailing list; see +http://pobox.com/~djb/qmail.html. diff --git a/VERSION b/VERSION index 88da7bb..78945e5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -qmail 1.01 +qmail 1.03 diff --git a/binm1+df.sh b/binm1+df.sh new file mode 100644 index 0000000..0ff1a68 --- /dev/null +++ b/binm1+df.sh @@ -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 diff --git a/binm1.sh b/binm1.sh new file mode 100644 index 0000000..db79cbd --- /dev/null +++ b/binm1.sh @@ -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 diff --git a/binm2+df.sh b/binm2+df.sh new file mode 100644 index 0000000..4f78101 --- /dev/null +++ b/binm2+df.sh @@ -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 diff --git a/binm2.sh b/binm2.sh new file mode 100644 index 0000000..7905308 --- /dev/null +++ b/binm2.sh @@ -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 diff --git a/binm3+df.sh b/binm3+df.sh new file mode 100644 index 0000000..3d69401 --- /dev/null +++ b/binm3+df.sh @@ -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 diff --git a/binm3.sh b/binm3.sh new file mode 100644 index 0000000..eb139e6 --- /dev/null +++ b/binm3.sh @@ -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 diff --git a/bouncesaying.1 b/bouncesaying.1 new file mode 100644 index 0000000..d99a460 --- /dev/null +++ b/bouncesaying.1 @@ -0,0 +1,71 @@ +.TH bouncesaying 1 +.SH NAME +bouncesaying \- perhaps bounce each incoming message +.SH SYNOPSIS +in +.BR .qmail : +.B |bouncesaying +.I error +[ +.I program +[ +.I arg ... +] +] +.SH DESCRIPTION +.B bouncesaying +feeds each new mail message to +.I program +with the given arguments. +If +.I program +exits 0, +.B bouncesaying +prints +.I error +and bounces the message. + +If +.I program +exits 111, +.B bouncesaying +exits 111, +so delivery will be retried later. + +If +.I program +exits anything else +(or does not exist), +.B bouncesaying +exits 0, +so the rest of +.B .qmail +will be processed as usual. + +Note that +it is not safe for +.I program +to fork a child that +reads the message in the background. + +If +.I program +is not supplied, +.B bouncesaying +always bounces the message: + +.EX + |bouncesaying 'This address no longer accepts mail.' +.EE + +.B WARNING: +If you create a +.B .qmail +file to enable +.BR bouncesaying , +make sure to also add a line specifying delivery to your normal mailbox. +.SH "SEE ALSO" +condredirect(1), +except(1), +dot-qmail(5), +qmail-command(8) diff --git a/bouncesaying.c b/bouncesaying.c new file mode 100644 index 0000000..c7d0026 --- /dev/null +++ b/bouncesaying.c @@ -0,0 +1,41 @@ +#include "fork.h" +#include "strerr.h" +#include "error.h" +#include "wait.h" +#include "sig.h" +#include "exit.h" + +#define FATAL "bouncesaying: fatal: " + +void main(argc,argv) +int argc; +char **argv; +{ + int pid; + int wstat; + + if (!argv[1]) + strerr_die1x(100,"bouncesaying: usage: bouncesaying error [ program [ arg ... ] ]"); + + if (argv[2]) { + pid = fork(); + if (pid == -1) + strerr_die2sys(111,FATAL,"unable to fork: "); + if (pid == 0) { + execvp(argv[2],argv + 2); + if (error_temp(errno)) _exit(111); + _exit(100); + } + if (wait_pid(&wstat,pid) == -1) + strerr_die2x(111,FATAL,"wait failed"); + if (wait_crashed(wstat)) + strerr_die2x(111,FATAL,"child crashed"); + switch(wait_exitcode(wstat)) { + case 0: break; + case 111: strerr_die2x(111,FATAL,"temporary child error"); + default: _exit(0); + } + } + + strerr_die1x(100,argv[1]); +} diff --git a/commands.c b/commands.c new file mode 100644 index 0000000..b0d3f61 --- /dev/null +++ b/commands.c @@ -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(); + } +} diff --git a/commands.h b/commands.h new file mode 100644 index 0000000..da05a8d --- /dev/null +++ b/commands.h @@ -0,0 +1,12 @@ +#ifndef COMMANDS_H +#define COMMANDS_H + +struct commands { + char *text; + void (*fun)(); + void (*flush)(); +} ; + +extern int commands(); + +#endif diff --git a/condredirect.1 b/condredirect.1 index 7a1292e..9f9d3c4 100644 --- a/condredirect.1 +++ b/condredirect.1 @@ -48,7 +48,16 @@ it is not safe for .I program to fork a child that 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" +bouncesaying(1), +except(1), dot-qmail(5), qmail-command(8), qmail-queue(8) diff --git a/condredirect.c b/condredirect.c index c6a2e6d..593d2f5 100644 --- a/condredirect.c +++ b/condredirect.c @@ -7,81 +7,79 @@ #include "wait.h" #include "seek.h" #include "qmail.h" -#include "stralloc.h" -#include "subfd.h" +#include "strerr.h" #include "substdio.h" +#include "fmt.h" -void die_success() { _exit(0); } -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"); } +#define FATAL "condredirect: fatal: " struct qmail qqt; int mywrite(fd,buf,len) int fd; char *buf; int len; { - qmail_put(&qqt,buf,len); - return len; + qmail_put(&qqt,buf,len); + return len; } -substdio ssin; -substdio ssout; 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) int argc; char **argv; { - char *sender; - char *dtline; - int pid; - int wstat; - - if (!argv[1] || !argv[2]) - die_perm("condredirect: usage: condredirect newaddress program arg ...\n"); - - switch(pid = fork()) - { - case -1: die_temp("condredirect: fatal: unable to fork\n"); - case 0: - execvp(argv[2],argv + 2); - if (error_temp(errno)) _exit(111); - _exit(100); + char *sender; + char *dtline; + int pid; + int wstat; + char *qqx; + + if (!argv[1] || !argv[2]) + strerr_die1x(100,"condredirect: usage: condredirect newaddress program [ arg ... ]"); + + pid = fork(); + if (pid == -1) + strerr_die2sys(111,FATAL,"unable to fork: "); + if (pid == 0) { + execvp(argv[2],argv + 2); + if (error_temp(errno)) _exit(111); + _exit(100); } - if (wait_pid(&wstat,pid) != pid) - die_perm("condredirect: fatal: internal bug\n"); - if (wait_crashed(wstat)) die_temp("condredirect: fatal: child crashed\n"); - switch(wait_exitcode(wstat)) - { - case 0: break; - case 111: die_temp("condredirect: fatal: temporary child error\n"); - default: die_success(); + if (wait_pid(&wstat,pid) == -1) + strerr_die2x(111,FATAL,"wait failed"); + if (wait_crashed(wstat)) + strerr_die2x(111,FATAL,"child crashed"); + switch(wait_exitcode(wstat)) { + case 0: break; + case 111: strerr_die2x(111,FATAL,"temporary child error"); + default: _exit(0); } - if (seek_begin(0) == -1) die_temp("condredirect: fatal: unable to rewind\n"); - sig_pipeignore(); + if (seek_begin(0) == -1) + strerr_die2sys(111,FATAL,"unable to rewind: "); + sig_pipeignore(); + + sender = env_get("SENDER"); + if (!sender) strerr_die2x(100,FATAL,"SENDER not set"); + dtline = env_get("DTLINE"); + if (!dtline) strerr_die2x(100,FATAL,"DTLINE not set"); + + if (qmail_open(&qqt) == -1) + strerr_die2sys(111,FATAL,"unable to fork: "); + qmail_puts(&qqt,dtline); + if (substdio_copy(&ssout,&ssin) != 0) + strerr_die2sys(111,FATAL,"unable to read message: "); + substdio_flush(&ssout); + + num[fmt_ulong(num,qmail_qp(&qqt))] = 0; - sender = env_get("SENDER"); - if (!sender) die_perm("condredirect: fatal: SENDER not set\n"); - dtline = env_get("DTLINE"); - if (!dtline) die_perm("condredirect: fatal: DTLINE not set\n"); - - if (qmail_open(&qqt) == -1) die_temp("condredirect: fatal: unable to fork\n"); - 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) - die_temp("condredirect: fatal: error while reading message\n"); - substdio_flush(&ssout); - - qmail_from(&qqt,sender); - qmail_to(&qqt,argv[1]); - switch(qmail_close(&qqt)) - { - case 0: die_99(); - case QMAIL_TOOLONG: die_perm("condredirect: fatal: permanent qmail-queue error\n"); - default: die_temp("condredirect: fatal: temporary qmail-queue error\n"); - } + qmail_from(&qqt,sender); + qmail_to(&qqt,argv[1]); + qqx = qmail_close(&qqt); + if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1); + strerr_die2x(99,"condredirect: qp ",num); } diff --git a/conf-patrn b/conf-patrn index b0f20b8..70c72af 100644 --- a/conf-patrn +++ b/conf-patrn @@ -1,5 +1,6 @@ -022 +002 -These stat bits are not allowed in ~ and ~/.qmail. +These stat bits are not allowed in ~ and ~/.qmail. On most systems, the +default umask is 022 or 077, so 022 will work here. Note that ~ftp, ~www, ~uucp, etc. should be owned by root. diff --git a/conf-qmail b/conf-qmail index 1f4cd67..0267f30 100644 --- a/conf-qmail +++ b/conf-qmail @@ -2,3 +2,10 @@ This is the qmail home directory. It must be a local directory, not 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. diff --git a/config-fast.sh b/config-fast.sh new file mode 100644 index 0000000..d05cda9 --- /dev/null +++ b/config-fast.sh @@ -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!' diff --git a/qmail-config.sh b/config.sh similarity index 100% rename from qmail-config.sh rename to config.sh diff --git a/constmap.c b/constmap.c index 9a28191..722e3b8 100644 --- a/constmap.c +++ b/constmap.c @@ -6,17 +6,16 @@ static constmap_hash hash(s,len) char *s; int len; { - unsigned char ch; - constmap_hash h; - h = 5381; - while (len > 0) - { - ch = *s++ - 'A'; - if (ch <= 'Z' - 'A') ch += 'a' - 'A'; - h = ((h << 5) + h) ^ ch; - --len; + unsigned char ch; + constmap_hash h; + h = 5381; + while (len > 0) { + ch = *s++ - 'A'; + if (ch <= 'Z' - 'A') ch += 'a' - 'A'; + h = ((h << 5) + h) ^ ch; + --len; } - return h; + return h; } char *constmap(cm,s,len) @@ -24,19 +23,18 @@ struct constmap *cm; char *s; int len; { - constmap_hash h; - int pos; - h = hash(s,len); - pos = cm->first[h & cm->mask]; - while (pos != -1) - { - if (h == cm->hash[pos]) - if (len == cm->inputlen[pos]) - if (!case_diffb(cm->input[pos],len,s)) - return cm->input[pos] + cm->inputlen[pos] + 1; - pos = cm->next[pos]; + constmap_hash h; + int pos; + h = hash(s,len); + pos = cm->first[h & cm->mask]; + while (pos != -1) { + if (h == cm->hash[pos]) + if (len == cm->inputlen[pos]) + if (!case_diffb(cm->input[pos],len,s)) + return cm->input[pos] + cm->inputlen[pos] + 1; + pos = cm->next[pos]; } - return 0; + return 0; } int constmap_init(cm,s,len,flagcolon) @@ -45,79 +43,72 @@ char *s; int len; int flagcolon; { - int i; - int j; - int k; - int pos; - constmap_hash h; - - cm->num = 0; - for (j = 0;j < len;++j) if (!s[j]) ++cm->num; - - h = 64; - while (h && (h < cm->num)) h += h; - cm->mask = h - 1; - - cm->first = (int *) alloc(sizeof(int) * h); - if (cm->first) - { - cm->input = (char **) alloc(sizeof(char *) * cm->num); - if (cm->input) - { - cm->inputlen = (int *) alloc(sizeof(int) * cm->num); - if (cm->inputlen) - { - cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num); - if (cm->hash) - { - cm->next = (int *) alloc(sizeof(int) * cm->num); - if (cm->next) - { - for (h = 0;h <= cm->mask;++h) - cm->first[h] = -1; - pos = 0; - i = 0; - for (j = 0;j < len;++j) - if (!s[j]) - { - k = j - i; - if (flagcolon) - { - for (k = i;k < j;++k) - if (s[k] == ':') - break; - if (k >= j) { i = j + 1; continue; } - k -= i; + int i; + int j; + int k; + int pos; + constmap_hash h; + + cm->num = 0; + for (j = 0;j < len;++j) if (!s[j]) ++cm->num; + + h = 64; + while (h && (h < cm->num)) h += h; + cm->mask = h - 1; + + cm->first = (int *) alloc(sizeof(int) * h); + if (cm->first) { + cm->input = (char **) alloc(sizeof(char *) * cm->num); + if (cm->input) { + cm->inputlen = (int *) alloc(sizeof(int) * cm->num); + if (cm->inputlen) { + cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num); + if (cm->hash) { + cm->next = (int *) alloc(sizeof(int) * cm->num); + if (cm->next) { + for (h = 0;h <= cm->mask;++h) + cm->first[h] = -1; + pos = 0; + i = 0; + for (j = 0;j < len;++j) + if (!s[j]) { + k = j - i; + if (flagcolon) { + for (k = i;k < j;++k) + if (s[k] == ':') + break; + if (k >= j) { i = j + 1; continue; } + k -= i; } - cm->input[pos] = s + i; - cm->inputlen[pos] = k; - h = hash(s + i,k); - cm->hash[pos] = h; - h &= cm->mask; - cm->next[pos] = cm->first[h]; - cm->first[h] = pos; - ++pos; - i = j + 1; + cm->input[pos] = s + i; + cm->inputlen[pos] = k; + h = hash(s + i,k); + cm->hash[pos] = h; + h &= cm->mask; + cm->next[pos] = cm->first[h]; + cm->first[h] = pos; + ++pos; + i = j + 1; } - return 1; + return 1; } - alloc_free(cm->hash); + alloc_free(cm->hash); } - alloc_free(cm->inputlen); + alloc_free(cm->inputlen); } - alloc_free(cm->input); + alloc_free(cm->input); } - alloc_free(cm->first); + alloc_free(cm->first); } - return 0; + return 0; } void constmap_free(cm) struct constmap *cm; { - alloc_free(cm->next); - alloc_free(cm->hash); - alloc_free(cm->inputlen); - alloc_free(cm->input); - alloc_free(cm->first); + alloc_free(cm->next); + alloc_free(cm->hash); + alloc_free(cm->inputlen); + alloc_free(cm->input); + alloc_free(cm->first); } diff --git a/constmap.h b/constmap.h index 17fb1cb..3f29179 100644 --- a/constmap.h +++ b/constmap.h @@ -3,8 +3,7 @@ typedef unsigned long constmap_hash; -struct constmap - { +struct constmap { int num; constmap_hash mask; constmap_hash *hash; @@ -12,8 +11,7 @@ struct constmap int *next; char **input; int *inputlen; - } -; +} ; extern int constmap_init(); extern void constmap_free(); diff --git a/control.c b/control.c index 4cc80cf..b655352 100644 --- a/control.c +++ b/control.c @@ -79,7 +79,8 @@ char *fn; case 0: return 0; 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; return 1; } diff --git a/dns.c b/dns.c index bbb9770..ed42787 100644 --- a/dns.c +++ b/dns.c @@ -271,17 +271,16 @@ int pref; int r; struct ip_mx ix; - if (sa->len && (sa->s[0] == '[')) - { - if (!stralloc_copy(&glue,sa)) return DNS_MEM; - if (!stralloc_0(&glue)) return DNS_MEM; + if (!stralloc_copy(&glue,sa)) return DNS_MEM; + if (!stralloc_0(&glue)) return DNS_MEM; + if (glue.s[0]) { ix.pref = 0; - if (!glue.s[ip_scanbracket(glue.s,&ix.ip)]) + if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)]) { if (!ipalloc_append(ia,&ix)) return DNS_MEM; return 0; } - } + } switch(resolve(sa,T_A)) { @@ -316,6 +315,7 @@ unsigned long random; { int r; struct mx { stralloc sa; unsigned short p; } *mx; + struct ip_mx ix; int nummx; int i; int j; @@ -324,18 +324,16 @@ unsigned long random; if (!ipalloc_readyplus(ia,0)) return DNS_MEM; ia->len = 0; - if (sa->len && (sa->s[0] == '[')) - { - struct ip_mx ix; - if (!stralloc_copy(&glue,sa)) return DNS_MEM; - if (!stralloc_0(&glue)) return DNS_MEM; + if (!stralloc_copy(&glue,sa)) return DNS_MEM; + if (!stralloc_0(&glue)) return DNS_MEM; + if (glue.s[0]) { ix.pref = 0; - if (!glue.s[ip_scanbracket(glue.s,&ix.ip)]) + if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)]) { if (!ipalloc_append(ia,&ix)) return DNS_MEM; return 0; } - } + } switch(resolve(sa,T_MX)) { diff --git a/dot-qmail.9 b/dot-qmail.9 index 936067c..4fa1358 100644 --- a/dot-qmail.9 +++ b/dot-qmail.9 @@ -45,7 +45,7 @@ ignores the line. A program line begins with a vertical bar: .EX - |/usr/ucb/vacation djb + |preline /usr/ucb/vacation djb .EE .B qmail-local @@ -173,10 +173,10 @@ If is completely empty (0 bytes long), or does not exist, .B qmail-local follows the -.I aliasempty +.I defaultdelivery instructions set by your system administrator; normally -.I aliasempty +.I defaultdelivery is .BR ./Mailbox , so @@ -224,7 +224,7 @@ It's a good idea to test your new file as follows: .EX - qmail-local -n $USER $HOME $USER '' '' '' '' + qmail-local -n $USER ~ $USER '' '' '' '' ./Mailbox .EE .SH "EXTENSION ADDRESSES" In the @@ -274,7 +274,7 @@ If is completely empty, .B qmail-local follows the -.I aliasempty +.I defaultdelivery instructions set by your system administrator. If diff --git a/except.1 b/except.1 new file mode 100644 index 0000000..4198cc2 --- /dev/null +++ b/except.1 @@ -0,0 +1,33 @@ +.TH except 1 +.SH NAME +except \- reverse the exit code of a program +.SH SYNOPSIS +.B except +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B except +runs +.I program +with the given arguments. + +If +.I program +exits 0, +.B except +exits 100. +If +.I program +exits 111, +.B except +exits 111. +If +.I program +exits anything else, +.B except +exits 0. +.SH "SEE ALSO" +bouncesaying(1), +condredirect(1) diff --git a/except.c b/except.c new file mode 100644 index 0000000..c553b3b --- /dev/null +++ b/except.c @@ -0,0 +1,37 @@ +#include "fork.h" +#include "strerr.h" +#include "wait.h" +#include "error.h" +#include "exit.h" + +#define FATAL "except: fatal: " + +void main(argc,argv) +int argc; +char **argv; +{ + int pid; + int wstat; + + if (!argv[1]) + strerr_die1x(100,"except: usage: except program [ arg ... ]"); + + pid = fork(); + if (pid == -1) + strerr_die2sys(111,FATAL,"unable to fork: "); + if (pid == 0) { + execvp(argv[1],argv + 1); + if (error_temp(errno)) _exit(111); + _exit(100); + } + + if (wait_pid(&wstat,pid) == -1) + strerr_die2x(111,FATAL,"wait failed"); + if (wait_crashed(wstat)) + strerr_die2x(111,FATAL,"child crashed"); + switch(wait_exitcode(wstat)) { + case 0: _exit(100); + case 111: strerr_die2x(111,FATAL,"temporary child error"); + default: _exit(0); + } +} diff --git a/forgeries.7 b/forgeries.7 index c7517e8..cb99fa7 100644 --- a/forgeries.7 +++ b/forgeries.7 @@ -71,7 +71,7 @@ Fortunately, a system administrator can easily obtain a copy of a 931/1413/Ident/TAP server, such as .BR pidentd . Unfortunately, -many incompetent system administrators fail to do this, +some system administrators fail to do this, and are thus unable to figure out which local user was responsible for generating a message. diff --git a/forward.c b/forward.c index de03773..e7390aa 100644 --- a/forward.c +++ b/forward.c @@ -3,56 +3,58 @@ #include "exit.h" #include "env.h" #include "qmail.h" -#include "stralloc.h" -#include "subfd.h" +#include "strerr.h" #include "substdio.h" +#include "fmt.h" -void die_success() { _exit(0); } -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("forward: fatal: out of memory\n"); } +#define FATAL "forward: fatal: " + +void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); } struct qmail qqt; int mywrite(fd,buf,len) int fd; char *buf; int len; { - qmail_put(&qqt,buf,len); - return len; + qmail_put(&qqt,buf,len); + return len; } -substdio ssin; -substdio ssout; 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) int argc; char **argv; { - char *sender; - char *dtline; - - sig_pipeignore(); - - sender = env_get("NEWSENDER"); - if (!sender) die_perm("forward: fatal: NEWSENDER not set\n"); - dtline = env_get("DTLINE"); - if (!dtline) die_perm("forward: fatal: DTLINE not set\n"); - - if (qmail_open(&qqt) == -1) die_temp("forward: fatal: unable to fork\n"); - 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) - die_temp("forward: fatal: error while reading message\n"); - substdio_flush(&ssout); - - qmail_from(&qqt,sender); - while (*++argv) qmail_to(&qqt,*argv); - switch(qmail_close(&qqt)) - { - case 0: die_success(); - case QMAIL_TOOLONG: die_perm("forward: fatal: permanent qmail-queue error\n"); - default: die_temp("forward: fatal: temporary qmail-queue error\n"); - } + char *sender; + char *dtline; + char *qqx; + + sig_pipeignore(); + + sender = env_get("NEWSENDER"); + if (!sender) + strerr_die2x(100,FATAL,"NEWSENDER not set"); + dtline = env_get("DTLINE"); + if (!dtline) + strerr_die2x(100,FATAL,"DTLINE not set"); + + if (qmail_open(&qqt) == -1) + strerr_die2sys(111,FATAL,"unable to fork: "); + qmail_puts(&qqt,dtline); + if (substdio_copy(&ssout,&ssin) != 0) + strerr_die2sys(111,FATAL,"unable to read message: "); + substdio_flush(&ssout); + + num[fmt_ulong(num,qmail_qp(&qqt))] = 0; + + qmail_from(&qqt,sender); + while (*++argv) qmail_to(&qqt,*argv); + qqx = qmail_close(&qqt); + if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1); + strerr_die2x(0,"forward: qp ",num); } diff --git a/hfield.c b/hfield.c index 38ecebc..06de0be 100644 --- a/hfield.c +++ b/hfield.c @@ -29,6 +29,7 @@ static char *(hname[]) = { , "content-type" , "content-transfer-encoding" , "notice-requested-upon-delivery-to" +, "mail-followup-to" , 0 }; diff --git a/hfield.h b/hfield.h index 0f59b82..20b30a5 100644 --- a/hfield.h +++ b/hfield.h @@ -32,6 +32,7 @@ extern int hfield_valid(); #define H_CONTENTTYPE 25 #define H_CONTENTTRANSFERENCODING 26 #define H_NOTICEREQUESTEDUPONDELIVERYTO 27 -#define H_NUM 28 +#define H_MAILFOLLOWUPTO 28 +#define H_NUM 29 #endif diff --git a/hier.c b/hier.c new file mode 100644 index 0000000..28e568d --- /dev/null +++ b/hier.c @@ -0,0 +1,252 @@ +#include "auto_qmail.h" +#include "auto_split.h" +#include "auto_uids.h" +#include "fmt.h" +#include "fifo.h" + +char buf[100 + FMT_ULONG]; + +void dsplit(base,uid,mode) +char *base; /* must be under 100 bytes */ +int uid; +int mode; +{ + char *x; + unsigned long i; + + d(auto_qmail,base,uid,auto_gidq,mode); + + for (i = 0;i < auto_split;++i) { + x = buf; + x += fmt_str(x,base); + x += fmt_str(x,"/"); + x += fmt_ulong(x,i); + *x = 0; + + d(auto_qmail,buf,uid,auto_gidq,mode); + } +} + +void hier() +{ + h(auto_qmail,auto_uido,auto_gidq,0755); + + d(auto_qmail,"control",auto_uido,auto_gidq,0755); + d(auto_qmail,"users",auto_uido,auto_gidq,0755); + d(auto_qmail,"bin",auto_uido,auto_gidq,0755); + d(auto_qmail,"boot",auto_uido,auto_gidq,0755); + d(auto_qmail,"doc",auto_uido,auto_gidq,0755); + d(auto_qmail,"man",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat5",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat7",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat8",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/man1",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/man5",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/man7",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/man8",auto_uido,auto_gidq,0755); + + d(auto_qmail,"alias",auto_uida,auto_gidq,02755); + + d(auto_qmail,"queue",auto_uidq,auto_gidq,0750); + d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700); + d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700); + d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750); + d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700); + + dsplit("queue/mess",auto_uidq,0750); + dsplit("queue/info",auto_uids,0700); + dsplit("queue/local",auto_uids,0700); + dsplit("queue/remote",auto_uids,0700); + + d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750); + z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644); + z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600); + p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622); + + c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); + + c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.alias",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.ctl",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.ids",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.maildir",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.mbox",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.vsm",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","TEST.deliver",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","TEST.receive",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","REMOVE.sendmail",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","REMOVE.binmail",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2alias",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2ext",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2local",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2rem",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2virt",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.nullclient",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644); + + c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711); + c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-start",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-getpw",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-local",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-remote",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-inject",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","predate",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","datemail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","mailsubj",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-showctl",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qread",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qstat",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-tcpto",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-tcpok",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-pop3d",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-popup",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-qmqpc",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qmqpd",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qmtpd",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-smtpd",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","sendmail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","tcp-env",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qreceipt",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qsmhook",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qbiff",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","maildir2mbox",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","maildirwatch",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755); + + c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","envelopes.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","envelopes.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","maildir.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","maildir.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","mbox.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","mbox.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","dot-qmail.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","dot-qmail.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","qmail-control.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","qmail-control.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","qmail-header.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","qmail-header.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","qmail-log.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","qmail-log.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","qmail-users.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","qmail-users.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","tcp-environ.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","tcp-environ.0",auto_uido,auto_gidq,0644); + + c(auto_qmail,"man/man7","forgeries.7",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat7","forgeries.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man7","qmail-limits.7",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat7","qmail-limits.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man7","qmail.7",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat7","qmail.0",auto_uido,auto_gidq,0644); + + c(auto_qmail,"man/man1","forward.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","forward.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","condredirect.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","condredirect.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","bouncesaying.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","bouncesaying.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","except.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","except.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","maildirmake.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","maildirmake.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","maildir2mbox.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","maildir2mbox.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","maildirwatch.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","maildirwatch.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","mailsubj.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","mailsubj.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","qreceipt.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","qreceipt.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","qbiff.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","qbiff.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","preline.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","preline.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","tcp-env.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","tcp-env.0",auto_uido,auto_gidq,0644); + + c(auto_qmail,"man/man8","qmail-local.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-local.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-lspawn.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-lspawn.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-getpw.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-getpw.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-remote.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-remote.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-rspawn.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-rspawn.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-clean.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-clean.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-send.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-send.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-start.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-start.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","splogger.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","splogger.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-queue.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-queue.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-inject.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-inject.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-showctl.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-showctl.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-newmrh.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-newmrh.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-newu.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-newu.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-pw2u.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-pw2u.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qread.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qread.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qstat.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qstat.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-tcpok.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-tcpok.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-tcpto.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-tcpto.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-pop3d.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-pop3d.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-popup.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-popup.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qmqpc.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qmqpc.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qmqpd.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qmqpd.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qmtpd.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qmtpd.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-smtpd.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-smtpd.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-command.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-command.0",auto_uido,auto_gidq,0644); +} diff --git a/home+df.sh b/home+df.sh new file mode 100644 index 0000000..7885cdf --- /dev/null +++ b/home+df.sh @@ -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 diff --git a/home.sh b/home.sh new file mode 100644 index 0000000..c96c02b --- /dev/null +++ b/home.sh @@ -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 diff --git a/idedit.c b/idedit.c new file mode 100644 index 0000000..e6747b5 --- /dev/null +++ b/idedit.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include "readwrite.h" +#include "exit.h" +#include "scan.h" +#include "fmt.h" +#include "strerr.h" +#include "open.h" +#include "seek.h" +#include "fork.h" + +#define FATAL "idedit: fatal: " +#define WARNING "idedit: warning: " + +int fd; + +void byte(pos,value) +char *pos; +unsigned int value; +{ + unsigned long u; + unsigned char ch; + + if (pos[scan_ulong(pos,&u)]) return; + + if (seek_set(fd,(seek_pos) u) == -1) + strerr_die2sys(111,FATAL,"unable to seek: "); + + ch = value; + if (write(fd,&ch,1) != 1) + strerr_die2sys(111,FATAL,"unable to write: "); +} + +char *args[10]; + +void run() +{ + int pid; + int wstat; + + pid = fork(); + if (pid == -1) + strerr_die2sys(111,FATAL,"unable to fork: "); + + if (pid == 0) { + execv(*args,args); + strerr_die4sys(111,WARNING,"unable to run ",*args,": "); + } + + if (wait_pid(&wstat,pid) != pid) + strerr_die2sys(111,FATAL,"waitpid surprise"); +} + +void u(account,group,home,pos0,pos1,pos2,pos3) +char *account; +char *group; +char *home; +char *pos0; +char *pos1; +char *pos2; +char *pos3; +{ + struct passwd *pw; + unsigned int value; + + pw = getpwnam(account); + + if (!pw && group) { + args[0] = "add-account"; + args[1] = account; + args[2] = group; + args[3] = home; + args[4] = 0; + run(); + pw = getpwnam(account); + } + + if (!pw) + strerr_die3x(111,FATAL,"unable to find uid for ",account); + + value = pw->pw_uid; + byte(pos0,value); value >>= 8; + byte(pos1,value); value >>= 8; + byte(pos2,value); value >>= 8; + byte(pos3,value); value >>= 8; + if (value) + strerr_die3x(111,FATAL,"excessively large uid for ",account); +} + +void g(group,pos0,pos1,pos2,pos3) +char *group; +char *pos0; +char *pos1; +char *pos2; +char *pos3; +{ + struct group *gr; + unsigned int value; + + gr = getgrnam(group); + + if (!gr) { + args[0] = "add-group"; + args[1] = group; + args[2] = 0; + run(); + gr = getgrnam(group); + } + + if (!gr) + strerr_die3x(111,FATAL,"unable to find gid for ",group); + + value = gr->gr_gid; + byte(pos0,value); value >>= 8; + byte(pos1,value); value >>= 8; + byte(pos2,value); value >>= 8; + byte(pos3,value); value >>= 8; + if (value) + strerr_die3x(111,FATAL,"excessively large gid for ",group); +} + +void main(argc,argv) +int argc; +char **argv; +{ + if (argc < 42) _exit(100); + + fd = open_write(argv[1]); + if (fd == -1) strerr_die4sys(111,FATAL,"unable to open ",argv[1],": "); + + g("qmail",argv[34],argv[35],argv[36],argv[37]); + g("nofiles",argv[38],argv[39],argv[40],argv[41]); + + u("root",(char *) 0,"/",argv[14],argv[15],argv[16],argv[17]); + + u("qmaild","nofiles","/var/qmail",argv[6],argv[7],argv[8],argv[9]); + u("qmaill","nofiles","/var/qmail",argv[10],argv[11],argv[12],argv[13]); + u("qmailp","nofiles","/var/qmail",argv[18],argv[19],argv[20],argv[21]); + u("alias","nofiles","/var/qmail/alias",argv[2],argv[3],argv[4],argv[5]); + + u("qmailq","qmail","/var/qmail",argv[22],argv[23],argv[24],argv[25]); + u("qmailr","qmail","/var/qmail",argv[26],argv[27],argv[28],argv[29]); + u("qmails","qmail","/var/qmail",argv[30],argv[31],argv[32],argv[33]); + + _exit(0); +} diff --git a/install-big.c b/install-big.c new file mode 100644 index 0000000..df813df --- /dev/null +++ b/install-big.c @@ -0,0 +1,285 @@ +#include "auto_qmail.h" +#include "auto_split.h" +#include "auto_uids.h" +#include "fmt.h" +#include "fifo.h" + +char buf[100 + FMT_ULONG]; + +void dsplit(base,uid,mode) +char *base; /* must be under 100 bytes */ +int uid; +int mode; +{ + char *x; + unsigned long i; + + d(auto_qmail,base,uid,auto_gidq,mode); + + for (i = 0;i < auto_split;++i) { + x = buf; + x += fmt_str(x,base); + x += fmt_str(x,"/"); + x += fmt_ulong(x,i); + *x = 0; + + d(auto_qmail,buf,uid,auto_gidq,mode); + } +} + +void hier() +{ + h(auto_qmail,auto_uido,auto_gidq,0755); + + d(auto_qmail,"control",auto_uido,auto_gidq,0755); + d(auto_qmail,"users",auto_uido,auto_gidq,0755); + d(auto_qmail,"bin",auto_uido,auto_gidq,0755); + d(auto_qmail,"boot",auto_uido,auto_gidq,0755); + d(auto_qmail,"doc",auto_uido,auto_gidq,0755); + d(auto_qmail,"man",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat5",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat7",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat8",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/man1",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/man5",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/man7",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/man8",auto_uido,auto_gidq,0755); + + d(auto_qmail,"alias",auto_uida,auto_gidq,02755); + + d(auto_qmail,"queue",auto_uidq,auto_gidq,0750); + d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700); + d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700); + d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750); + d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700); + + dsplit("queue/mess",auto_uidq,0750); + dsplit("queue/info",auto_uids,0700); + dsplit("queue/local",auto_uids,0700); + dsplit("queue/remote",auto_uids,0700); + + d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750); + z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644); + z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600); + p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622); + + c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755); + c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); + + c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.alias",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.ctl",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.ids",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.maildir",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.mbox",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL.vsm",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","TEST.deliver",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","TEST.receive",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","REMOVE.sendmail",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","REMOVE.binmail",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2alias",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2ext",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2local",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2rem",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.local2virt",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.nullclient",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644); + + c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711); + c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-start",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-getpw",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-local",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-remote",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-inject",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","predate",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","datemail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","mailsubj",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-showctl",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qread",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qstat",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-tcpto",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-tcpok",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-pop3d",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-popup",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-qmqpc",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qmqpd",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qmtpd",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-smtpd",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","sendmail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","tcp-env",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qreceipt",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qsmhook",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qbiff",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","maildir2mbox",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","maildirwatch",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755); + + c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","envelopes.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","envelopes.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","maildir.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","maildir.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","mbox.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","mbox.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","dot-qmail.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","dot-qmail.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","qmail-control.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","qmail-control.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","qmail-header.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","qmail-header.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","qmail-log.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","qmail-log.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","qmail-users.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","qmail-users.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","tcp-environ.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","tcp-environ.0",auto_uido,auto_gidq,0644); + + c(auto_qmail,"man/man7","forgeries.7",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat7","forgeries.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man7","qmail-limits.7",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat7","qmail-limits.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man7","qmail.7",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat7","qmail.0",auto_uido,auto_gidq,0644); + + c(auto_qmail,"man/man1","forward.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","forward.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","condredirect.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","condredirect.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","bouncesaying.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","bouncesaying.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","except.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","except.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","maildirmake.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","maildirmake.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","maildir2mbox.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","maildir2mbox.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","maildirwatch.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","maildirwatch.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","mailsubj.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","mailsubj.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","qreceipt.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","qreceipt.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","qbiff.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","qbiff.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","preline.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","preline.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","tcp-env.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","tcp-env.0",auto_uido,auto_gidq,0644); + + c(auto_qmail,"man/man8","qmail-local.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-local.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-lspawn.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-lspawn.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-getpw.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-getpw.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-remote.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-remote.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-rspawn.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-rspawn.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-clean.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-clean.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-send.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-send.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-start.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-start.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","splogger.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","splogger.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-queue.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-queue.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-inject.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-inject.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-showctl.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-showctl.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-newmrh.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-newmrh.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-newu.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-newu.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-pw2u.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-pw2u.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qread.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qread.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qstat.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qstat.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-tcpok.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-tcpok.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-tcpto.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-tcpto.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-pop3d.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-pop3d.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-popup.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-popup.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qmqpc.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qmqpc.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qmqpd.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qmqpd.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-qmtpd.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-qmtpd.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-smtpd.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-smtpd.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-command.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-command.0",auto_uido,auto_gidq,0644); + + c(auto_qmail,"bin","dot-forward",auto_uido,auto_gidq,0755); + + c(auto_qmail,"man/man1","dot-forward.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","dot-forward.0",auto_uido,auto_gidq,0644); + + d(auto_qmail,"doc/fastforward",auto_uido,auto_gidq,0755); + + c(auto_qmail,"bin","fastforward",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","printforward",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","setforward",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","newaliases",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","printmaillist",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","setmaillist",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","newinclude",auto_uido,auto_gidq,0755); + + c(auto_qmail,"doc/fastforward","ALIASES",auto_uido,auto_gidq,0644); + + c(auto_qmail,"man/man1","fastforward.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","printforward.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","setforward.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","newaliases.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","printmaillist.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","setmaillist.1",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man1","newinclude.1",auto_uido,auto_gidq,0644); + + c(auto_qmail,"man/cat1","fastforward.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","printforward.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","setforward.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","newaliases.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","printmaillist.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","setmaillist.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat1","newinclude.0",auto_uido,auto_gidq,0644); +} diff --git a/install.c b/install.c index ffc09a6..95034f2 100644 --- a/install.c +++ b/install.c @@ -1,167 +1,164 @@ #include "substdio.h" -#include "stralloc.h" -#include "getln.h" +#include "strerr.h" +#include "error.h" +#include "open.h" #include "readwrite.h" #include "exit.h" -#include "open.h" -#include "error.h" -#include "strerr.h" -#include "byte.h" -#include "fifo.h" -stralloc target = {0}; -char *to; +extern void hier(); #define FATAL "install: fatal: " -void nomem() { strerr_die2x(111,FATAL,"out of memory"); } + +int fdsourcedir = -1; + +void h(home,uid,gid,mode) +char *home; +int uid; +int gid; +int mode; +{ + if (mkdir(home,0700) == -1) + if (errno != error_exist) + strerr_die4sys(111,FATAL,"unable to mkdir ",home,": "); + if (chown(home,uid,gid) == -1) + strerr_die4sys(111,FATAL,"unable to chown ",home,": "); + if (chmod(home,mode) == -1) + strerr_die4sys(111,FATAL,"unable to chmod ",home,": "); +} + +void d(home,subdir,uid,gid,mode) +char *home; +char *subdir; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (mkdir(subdir,0700) == -1) + if (errno != error_exist) + strerr_die6sys(111,FATAL,"unable to mkdir ",home,"/",subdir,": "); + if (chown(subdir,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown ",home,"/",subdir,": "); + if (chmod(subdir,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",subdir,": "); +} + +void p(home,fifo,uid,gid,mode) +char *home; +char *fifo; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (fifo_make(fifo,0700) == -1) + if (errno != error_exist) + strerr_die6sys(111,FATAL,"unable to mkfifo ",home,"/",fifo,": "); + if (chown(fifo,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown ",home,"/",fifo,": "); + if (chmod(fifo,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",fifo,": "); +} char inbuf[SUBSTDIO_INSIZE]; char outbuf[SUBSTDIO_OUTSIZE]; substdio ssin; substdio ssout; -void doit(line) -stralloc *line; +void c(home,subdir,file,uid,gid,mode) +char *home; +char *subdir; +char *file; +int uid; +int gid; +int mode; { - char *x; - unsigned int xlen; - unsigned int i; - char *type; - char *uidstr; - char *gidstr; - char *modestr; - char *mid; - char *name; - unsigned long uid; - unsigned long gid; - unsigned long mode; int fdin; int fdout; - unsigned long zlen; - - x = line->s; xlen = line->len; - - type = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - uidstr = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - gidstr = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - modestr = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - mid = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - name = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - if (!stralloc_copys(&target,to)) nomem(); - if (!stralloc_cats(&target,mid)) nomem(); - if (!stralloc_cats(&target,name)) nomem(); - if (!stralloc_0(&target)) nomem(); - - uid = -1; if (*uidstr) scan_ulong(uidstr,&uid); - gid = -1; if (*gidstr) scan_ulong(gidstr,&gid); - scan_8long(modestr,&mode); - - switch(*type) { - case 'z': - scan_ulong(type + 1,&zlen); - - fdout = open_trunc(target.s); - if (fdout == -1) - strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); - substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof(outbuf)); - - while (zlen--) - if (substdio_put(&ssout,"",1) == -1) - strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); - - if (substdio_flush(&ssout) == -1) - strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); - if (fsync(fdout) == -1) - strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); - close(fdout); - break; - - case 'p': - if (fifo_make(target.s,0700) == -1) - if (errno != error_exist) - strerr_die4sys(111,FATAL,"unable to mkfifo ",target.s,": "); - break; - - case 'd': - if (mkdir(target.s,0700) == -1) - if (errno != error_exist) - strerr_die4sys(111,FATAL,"unable to mkdir ",target.s,": "); - break; - - case 'c': - fdin = open_read(name); - if (fdin == -1) - strerr_die4sys(111,FATAL,"unable to read ",name,": "); - substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof(inbuf)); - - fdout = open_trunc(target.s); - if (fdout == -1) - strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); - substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof(outbuf)); - - switch(substdio_copy(&ssout,&ssin)) { - case -2: - strerr_die4sys(111,FATAL,"unable to read ",name,": "); - case -3: - strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); - } - - close(fdin); - if (substdio_flush(&ssout) == -1) - strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); - if (fsync(fdout) == -1) - strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); - close(fdout); - break; - - default: - return; + + if (fchdir(fdsourcedir) == -1) + strerr_die2sys(111,FATAL,"unable to switch back to source directory: "); + + fdin = open_read(file); + if (fdin == -1) + strerr_die4sys(111,FATAL,"unable to read ",file,": "); + substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof inbuf); + + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (chdir(subdir) == -1) + strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); + + fdout = open_trunc(file); + if (fdout == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf); + + switch(substdio_copy(&ssout,&ssin)) { + case -2: + strerr_die4sys(111,FATAL,"unable to read ",file,": "); + case -3: + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); } - if (chown(target.s,uid,gid) == -1) - strerr_die4sys(111,FATAL,"unable to chown ",target.s,": "); - if (chmod(target.s,mode) == -1) - strerr_die4sys(111,FATAL,"unable to chmod ",target.s,": "); + close(fdin); + if (substdio_flush(&ssout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (fsync(fdout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (close(fdout) == -1) /* NFS silliness */ + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + + if (chown(file,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": "); + if (chmod(file,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": "); } -char buf[256]; -substdio in = SUBSTDIO_FDBUF(read,0,buf,sizeof(buf)); -stralloc line = {0}; - -void main(argc,argv) -int argc; -char **argv; +void z(home,file,len,uid,gid,mode) +char *home; +char *file; +int len; +int uid; +int gid; +int mode; { - int match; + int fdout; - umask(077); + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + + fdout = open_trunc(file); + if (fdout == -1) + strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); + substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf); + + while (len-- > 0) + if (substdio_put(&ssout,"",1) == -1) + strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); + + if (substdio_flush(&ssout) == -1) + strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); + if (fsync(fdout) == -1) + strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); + if (close(fdout) == -1) /* NFS silliness */ + strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); + + if (chown(file,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown ",home,"/",file,": "); + if (chmod(file,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",file,": "); +} - to = argv[1]; - if (!to) strerr_die2x(100,FATAL,"install: usage: install dir"); +void main() +{ + fdsourcedir = open_read("."); + if (fdsourcedir == -1) + strerr_die2sys(111,FATAL,"unable to open current directory: "); - for (;;) { - if (getln(&in,&line,&match,'\n') == -1) - strerr_die2sys(111,FATAL,"unable to read input: "); - doit(&line); - if (!match) - _exit(0); - } + umask(077); + hier(); + _exit(0); } diff --git a/instcheck.c b/instcheck.c index 48db531..d41efda 100644 --- a/instcheck.c +++ b/instcheck.c @@ -1,120 +1,108 @@ #include #include -#include "substdio.h" -#include "stralloc.h" -#include "getln.h" +#include "strerr.h" +#include "error.h" #include "readwrite.h" #include "exit.h" -#include "error.h" -#include "strerr.h" -#include "byte.h" -stralloc target = {0}; -char *to; +extern void hier(); -#define WARNING "instcheck: warning: " #define FATAL "instcheck: fatal: " -void nomem() { strerr_die2x(111,FATAL,"out of memory"); } +#define WARNING "instcheck: warning: " -void doit(line) -stralloc *line; +void perm(prefix1,prefix2,prefix3,file,type,uid,gid,mode) +char *prefix1; +char *prefix2; +char *prefix3; +char *file; +int type; +int uid; +int gid; +int mode; { struct stat st; - char *x; - unsigned int xlen; - unsigned int i; - char *type; - char *uidstr; - char *gidstr; - char *modestr; - char *mid; - char *name; - unsigned long uid; - unsigned long gid; - unsigned long mode; - int ftype; - - x = line->s; xlen = line->len; - - type = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - uidstr = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - gidstr = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - modestr = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - mid = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - name = x; - i = byte_chr(x,xlen,':'); if (i == xlen) return; - x[i++] = 0; x += i; xlen -= i; - - if (!stralloc_copys(&target,to)) nomem(); - if (!stralloc_cats(&target,mid)) nomem(); - if (!stralloc_cats(&target,name)) nomem(); - if (!stralloc_0(&target)) nomem(); - - uid = -1; if (*uidstr) scan_ulong(uidstr,&uid); - gid = -1; if (*gidstr) scan_ulong(gidstr,&gid); - scan_8long(modestr,&mode); - switch(*type) { - case 'd': ftype = S_IFDIR; break; - case 'c': ftype = S_IFREG; break; - case 'z': ftype = S_IFREG; break; - case 'p': ftype = S_IFIFO; break; - default: return; - } - - if (stat(target.s,&st) == -1) { + if (stat(file,&st) == -1) { if (errno == error_noent) - strerr_warn3(WARNING,target.s," does not exist",0); + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," does not exist",0); else - strerr_warn4(WARNING,"unable to stat ",target.s,": ",&strerr_sys); + strerr_warn4(WARNING,"unable to stat .../",file,": ",&strerr_sys); return; } if ((uid != -1) && (st.st_uid != uid)) - strerr_warn3(WARNING,target.s," has wrong owner",0); + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong owner",0); if ((gid != -1) && (st.st_gid != gid)) - strerr_warn3(WARNING,target.s," has wrong group",0); + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong group",0); if ((st.st_mode & 07777) != mode) - strerr_warn3(WARNING,target.s," has wrong permissions",0); - if ((st.st_mode & S_IFMT) != ftype) - strerr_warn3(WARNING,target.s," has wrong type",0); + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong permissions",0); + if ((st.st_mode & S_IFMT) != type) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong type",0); } -char buf[256]; -substdio in = SUBSTDIO_FDBUF(read,0,buf,sizeof(buf)); -stralloc line = {0}; +void h(home,uid,gid,mode) +char *home; +int uid; +int gid; +int mode; +{ + perm("","","",home,S_IFDIR,uid,gid,mode); +} + +void d(home,subdir,uid,gid,mode) +char *home; +char *subdir; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",subdir,S_IFDIR,uid,gid,mode); +} -void main(argc,argv) -int argc; -char **argv; +void p(home,fifo,uid,gid,mode) +char *home; +char *fifo; +int uid; +int gid; +int mode; { - int match; + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",fifo,S_IFIFO,uid,gid,mode); +} - umask(077); +void c(home,subdir,file,uid,gid,mode) +char *home; +char *subdir; +char *file; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (chdir(subdir) == -1) + strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); + perm(".../",subdir,"/",file,S_IFREG,uid,gid,mode); +} - to = argv[1]; - if (!to) strerr_die2x(100,FATAL,"instcheck: usage: instcheck dir"); +void z(home,file,len,uid,gid,mode) +char *home; +char *file; +int len; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",file,S_IFREG,uid,gid,mode); +} - for (;;) { - if (getln(&in,&line,&match,'\n') == -1) - strerr_die2sys(111,FATAL,"unable to read input: "); - doit(&line); - if (!match) - _exit(0); - } +void main() +{ + hier(); + _exit(0); } diff --git a/maildir.5 b/maildir.5 index 54ddb89..5da9573 100644 --- a/maildir.5 +++ b/maildir.5 @@ -209,7 +209,7 @@ or rename as .BR cur/\fIunique:info . See -.B http://pobox.com/~djb/maildir.html +.B http://pobox.com/~djb/proto/maildir.html for the meaning of .IR info . diff --git a/maildirmake.c b/maildirmake.c index f9822ec..9863fef 100644 --- a/maildirmake.c +++ b/maildirmake.c @@ -1,22 +1,24 @@ -#include "subfd.h" -#include "substdio.h" -#include "error.h" +#include "strerr.h" #include "exit.h" -void die(s) char *s; { substdio_putsflush(subfderr,s); _exit(111); } +#define FATAL "maildirmake: fatal: " void main(argc,argv) int argc; char **argv; { - umask(077); - if (!argv[1]) die("usage: maildirmake name\n"); - if (mkdir(argv[1],0700)) - if (errno == error_exist) die("fatal: directory already exists\n"); - else die("fatal: unable to mkdir\n"); - if (chdir(argv[1])) die("fatal: unable to chdir\n"); - if (mkdir("tmp",0700)) die("fatal: unable to make tmp/ subdir\n"); - if (mkdir("new",0700)) die("fatal: unable to make new/ subdir\n"); - if (mkdir("cur",0700)) die("fatal: unable to make cur/ subdir\n"); - _exit(0); + umask(077); + if (!argv[1]) + strerr_die1x(100,"maildirmake: usage: maildirmake name"); + if (mkdir(argv[1],0700) == -1) + strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],": "); + if (chdir(argv[1]) == -1) + strerr_die4sys(111,FATAL,"unable to chdir to ",argv[1],": "); + if (mkdir("tmp",0700) == -1) + 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); } diff --git a/ndelay.c b/ndelay.c index 207e7f2..438d1d8 100644 --- a/ndelay.c +++ b/ndelay.c @@ -2,8 +2,12 @@ #include #include "ndelay.h" +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + int ndelay_on(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); } diff --git a/ndelay_off.c b/ndelay_off.c index 2c89dc3..86f8fbf 100644 --- a/ndelay_off.c +++ b/ndelay_off.c @@ -2,8 +2,12 @@ #include #include "ndelay.h" +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + int ndelay_off(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); } diff --git a/predate.c b/predate.c index b011dc5..9648f6e 100644 --- a/predate.c +++ b/predate.c @@ -5,11 +5,14 @@ #include "wait.h" #include "fd.h" #include "fmt.h" +#include "strerr.h" #include "substdio.h" #include "subfd.h" #include "readwrite.h" #include "exit.h" +#define FATAL "predate: fatal: " + static char *montab[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; @@ -34,30 +37,22 @@ char **argv; sig_pipeignore(); - if (!argv[1]) { - substdio_putsflush(subfderr,"predate: usage: predate child\n"); - _exit(100); - } + if (!argv[1]) + strerr_die1x(100,"predate: usage: predate child"); - if (pipe(pi) == -1) { - substdio_putsflush(subfderr,"predate: fatal: unable to create pipe\n"); - _exit(111); - } + if (pipe(pi) == -1) + strerr_die2sys(111,FATAL,"unable to create pipe: "); switch(pid = fork()) { case -1: - substdio_putsflush(subfderr,"predate: fatal: unable to fork\n"); - _exit(111); + strerr_die2sys(111,FATAL,"unable to fork: "); case 0: close(pi[1]); - if (fd_move(0,pi[0]) == -1) { - substdio_putsflush(subfderr,"predate: fatal: unable to set up fds\n"); - _exit(111); - } + if (fd_move(0,pi[0]) == -1) + strerr_die2sys(111,FATAL,"unable to set up fds: "); sig_pipedefault(); execvp(argv[1],argv + 1); - substdio_putsflush(subfderr,"predate: fatal: unable to exec\n"); - _exit(111); + strerr_die4sys(111,FATAL,"unable to run ",argv[1],": "); } close(pi[0]); substdio_fdbuf(&ss,write,pi[1],outbuf,sizeof(outbuf)); @@ -113,13 +108,9 @@ char **argv; substdio_flush(&ss); close(pi[1]); - if (wait_pid(&wstat,pid) == -1) { - substdio_putsflush(subfderr,"predate: fatal: wait failed\n"); - _exit(111); - } - if (wait_crashed(wstat)) { - substdio_putsflush(subfderr,"predate: fatal: child crashed\n"); - _exit(111); - } + if (wait_pid(&wstat,pid) == -1) + strerr_die2sys(111,FATAL,"wait failed: "); + if (wait_crashed(wstat)) + strerr_die2x(111,FATAL,"child crashed"); _exit(wait_exitcode(wstat)); } diff --git a/preline.c b/preline.c index 8e76485..1a4cef8 100644 --- a/preline.c +++ b/preline.c @@ -1,7 +1,7 @@ #include "fd.h" #include "sgetopt.h" #include "readwrite.h" -#include "subfd.h" +#include "strerr.h" #include "substdio.h" #include "exit.h" #include "fork.h" @@ -10,78 +10,81 @@ #include "sig.h" #include "error.h" -void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); } -void die_usage() { die(100,"preline: fatal: incorrect usage\n"); } -void die_temp() { die(111,"preline: fatal: temporary problem\n"); } -void die_read() { die(111,"preline: fatal: unable to read message\n"); } -void die_badcmd() { die(100,"preline: fatal: command not found\n"); } +#define FATAL "preline: fatal: " + +void die_usage() +{ + strerr_die1x(100,"preline: usage: preline cmd [ arg ... ]"); +} int flagufline = 1; char *ufline; int flagrpline = 1; char *rpline; int flagdtline = 1; char *dtline; -substdio ssout; char outbuf[SUBSTDIO_OUTSIZE]; -substdio ssin; 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) int argc; char **argv; { - int opt; - int pi[2]; - int pid; - int wstat; - - sig_pipeignore(); - - if (!(ufline = env_get("UFLINE"))) die_usage(); - if (!(rpline = env_get("RPLINE"))) die_usage(); - if (!(dtline = env_get("DTLINE"))) die_usage(); - - while ((opt = getopt(argc,argv,"frdFRD")) != opteof) - switch(opt) - { - case 'f': flagufline = 0; break; - case 'r': flagrpline = 0; break; - case 'd': flagdtline = 0; break; - case 'F': flagufline = 1; break; - case 'R': flagrpline = 1; break; - case 'D': flagdtline = 1; break; - default: - _exit(100); + int opt; + int pi[2]; + int pid; + int wstat; + + sig_pipeignore(); + + if (!(ufline = env_get("UFLINE"))) die_usage(); + if (!(rpline = env_get("RPLINE"))) die_usage(); + if (!(dtline = env_get("DTLINE"))) die_usage(); + + while ((opt = getopt(argc,argv,"frdFRD")) != opteof) + switch(opt) { + case 'f': flagufline = 0; break; + case 'r': flagrpline = 0; break; + case 'd': flagdtline = 0; break; + case 'F': flagufline = 1; break; + case 'R': flagrpline = 1; break; + case 'D': flagdtline = 1; break; + default: die_usage(); } - argc -= optind; - argv += optind; - if (!*argv) die_usage(); + argc -= optind; + argv += optind; + if (!*argv) die_usage(); + + if (pipe(pi) == -1) + strerr_die2sys(111,FATAL,"unable to create pipe: "); - if (pipe(pi) == -1) die_temp(); + pid = fork(); + if (pid == -1) + strerr_die2sys(111,FATAL,"unable to fork: "); - switch(pid = fork()) - { - case -1: - die_temp(); - case 0: - close(pi[1]); - if (fd_move(0,pi[0])) die_temp(); - sig_pipedefault(); - execvp(*argv,argv); - if (error_temp(errno)) die_temp(); - die_badcmd(); + if (pid == 0) { + close(pi[1]); + if (fd_move(0,pi[0]) == -1) + strerr_die2sys(111,FATAL,"unable to set up fds: "); + sig_pipedefault(); + execvp(*argv,argv); + strerr_die4sys(error_temp(errno) ? 111 : 100,FATAL,"unable to run ",*argv,": "); } - close(pi[0]); - - substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf)); - substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); - if (flagufline) substdio_bputs(&ssout,ufline); - if (flagrpline) substdio_bputs(&ssout,rpline); - if (flagdtline) substdio_bputs(&ssout,dtline); - if (substdio_copy(&ssout,&ssin) == -2) die_read(); - substdio_flush(&ssout); - close(pi[1]); - - if (wait_pid(&wstat,pid) == -1) die_temp(); - if (wait_crashed(wstat)) die_temp(); - _exit(wait_exitcode(wstat)); + close(pi[0]); + if (fd_move(1,pi[1]) == -1) + strerr_die2sys(111,FATAL,"unable to set up fds: "); + + if (flagufline) substdio_bputs(&ssout,ufline); + if (flagrpline) substdio_bputs(&ssout,rpline); + if (flagdtline) substdio_bputs(&ssout,dtline); + if (substdio_copy(&ssout,&ssin) != 0) + strerr_die2sys(111,FATAL,"unable to copy input: "); + substdio_flush(&ssout); + close(1); + + if (wait_pid(&wstat,pid) == -1) + strerr_die2sys(111,FATAL,"wait failed: "); + if (wait_crashed(wstat)) + strerr_die2x(111,FATAL,"child crashed"); + _exit(wait_exitcode(wstat)); } diff --git a/proc+df.sh b/proc+df.sh new file mode 100644 index 0000000..eb9e92c --- /dev/null +++ b/proc+df.sh @@ -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 diff --git a/proc.sh b/proc.sh new file mode 100644 index 0000000..3c76220 --- /dev/null +++ b/proc.sh @@ -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 diff --git a/qlist.1 b/qlist.1 deleted file mode 100644 index 118b53b..0000000 --- a/qlist.1 +++ /dev/null @@ -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) diff --git a/qlist.c b/qlist.c deleted file mode 100644 index 230476f..0000000 --- a/qlist.c +++ /dev/null @@ -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(); - } -} diff --git a/qlist2.sh b/qlist2.sh deleted file mode 100644 index 9e31a2a..0000000 --- a/qlist2.sh +++ /dev/null @@ -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"} diff --git a/qmail-command.8 b/qmail-command.8 index c22180e..ad46377 100644 --- a/qmail-command.8 +++ b/qmail-command.8 @@ -37,7 +37,7 @@ file, so it is not safe for .I command to fork a child that reads the message in the background while the parent exits. - +.SH "EXIT CODES" .IR command 's exit codes are interpreted as follows: 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); 111 means that the delivery failed but should be tried again in a little while (soft error). + Currently 64, 65, 70, 76, 77, 78, and 112 are considered hard errors, and all other codes are considered soft errors, but .I command should avoid relying on this. - +.SH "ENVIRONMENT VARIABLES" .B qmail-local supplies several useful environment variables to .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 is the envelope sender address. .B NEWSENDER @@ -82,9 +88,22 @@ is the part. .B EXT is the -.B .qmail -extension, +address extension, .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 is the portion of .B EXT @@ -95,6 +114,18 @@ following the second dash; .B EXT4 is the portion 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 and .B RPLINE @@ -112,11 +143,6 @@ line that adds to .IR mbox -format 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" dot-qmail(5), envelopes(5), diff --git a/qmail-control.9 b/qmail-control.9 index 7474a33..503ce93 100644 --- a/qmail-control.9 +++ b/qmail-control.9 @@ -23,6 +23,7 @@ in .IR badmailfrom , .IR locals , .IR percenthack , +.IR qmqpservers , .IR rcpthosts , .IR smtproutes , and @@ -46,6 +47,7 @@ control default used by .I concurrencyremote \fR20 \fRqmail-send .I defaultdomain \fIme \fRqmail-inject .I defaulthost \fIme \fRqmail-inject +.I databytes \fR0 \fRqmail-smtpd .I doublebouncehost \fIme \fRqmail-send .I doublebounceto \fRpostmaster \fRqmail-send .I envnoathost \fIme \fRqmail-send @@ -53,11 +55,12 @@ control default used by .I idhost \fIme \fRqmail-inject .I localiphost \fIme \fRqmail-smtpd .I locals \fIme \fRqmail-send +.I morercpthosts \fR(none) \fRqmail-smtpd .I percenthack \fR(none) \fRqmail-send .I plusdomain \fIme \fRqmail-inject +.I qmqpservers \fR(none) \fRqmail-qmqpc .I queuelifetime \fR604800 \fRqmail-send .I rcpthosts \fR(none) \fRqmail-smtpd -.I recipientmap \fR(none) \fRqmail-send .I smtpgreeting \fIme \fRqmail-smtpd .I smtproutes \fR(none) \fRqmail-remote .I timeoutconnect \fR60 \fRqmail-remote @@ -68,6 +71,7 @@ control default used by .RE .SH "SEE ALSO" qmail-inject(8), +qmail-qmqpc(8), qmail-remote(8), qmail-send(8), qmail-showctl(8), diff --git a/qmail-getpw.9 b/qmail-getpw.9 index 86befb2..0f12e1c 100644 --- a/qmail-getpw.9 +++ b/qmail-getpw.9 @@ -42,7 +42,12 @@ The operating system's .B getpwnam function, which is at the heart of .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" .B qmail-getpw considers an account in diff --git a/qmail-getpw.c b/qmail-getpw.c index 4833aac..128c682 100644 --- a/qmail-getpw.c +++ b/qmail-getpw.c @@ -33,7 +33,9 @@ int userext() byte_copy(username,extension - local,local); username[extension - local] = 0; case_lowers(username); + errno = 0; pw = getpwnam(username); + if (errno == error_txtbsy) _exit(QLX_SYS); if (pw) if (pw->pw_uid) if (stat(pw->pw_dir,&st) == 0) { diff --git a/qmail-header.5 b/qmail-header.5 index f15c850..d90323a 100644 --- a/qmail-header.5 +++ b/qmail-header.5 @@ -11,7 +11,8 @@ The main function of .B qmail-inject is to make sure that each outgoing message has an appropriate header. -For more detailed information, see RFC 822 and RFC 1123. +For more detailed information, see +.BR http://pobox.com/~djb/proto/immhf.html . .SH "MESSAGE STRUCTURE" A message contains a series of .I header fields\fR, @@ -239,7 +240,7 @@ does not create any fields. .SH "RESENT MESSAGES" A message is -.I forwarded +.I resent if it contains any of the following fields: .BR Resent-Sender , .BR Resent-From , @@ -250,7 +251,7 @@ if it contains any of the following fields: .BR Resent-Date , .BR Resent-Message-ID . -If a message is forwarded, +If a message is resent, .B qmail-inject changes its behavior as follows. diff --git a/qmail-hier.c b/qmail-hier.c deleted file mode 100644 index eff007e..0000000 --- a/qmail-hier.c +++ /dev/null @@ -1,248 +0,0 @@ -#include "subfd.h" -#include "substdio.h" -#include "auto_split.h" -#include "auto_uids.h" -#include "fmt.h" - -char strnum[FMT_ULONG]; - -void uidgid(uid) -int uid; -{ - substdio_put(subfdout,strnum,fmt_ulong(strnum,(unsigned long) uid)); - substdio_puts(subfdout,":"); - substdio_put(subfdout,strnum,fmt_ulong(strnum,(unsigned long) auto_gidq)); - substdio_puts(subfdout,":"); -} - -void copy(uid,mode,sub,fn) -int uid; -char *mode; -char *sub; -char *fn; -{ - substdio_puts(subfdout,"c:"); - uidgid(uid); - substdio_puts(subfdout,mode); - substdio_puts(subfdout,":"); - substdio_puts(subfdout,sub); - substdio_puts(subfdout,":"); - substdio_puts(subfdout,fn); - substdio_puts(subfdout,":\n"); -} - -void dir(uid,mode,fn) -int uid; -char *mode; -char *fn; -{ - substdio_puts(subfdout,"d:"); - uidgid(uid); - substdio_puts(subfdout,mode); - substdio_puts(subfdout,":"); - substdio_puts(subfdout,fn); - substdio_puts(subfdout,"::\n"); -} - -void dirsplit(uid,mode,fn) -int uid; -char *mode; -char *fn; -{ - unsigned long i; - dir(uid,mode,fn); - for (i = 0;i < auto_split;++i) { - substdio_puts(subfdout,"d:"); - uidgid(uid); - substdio_puts(subfdout,mode); - substdio_puts(subfdout,":"); - substdio_puts(subfdout,fn); - substdio_puts(subfdout,":/"); - substdio_put(subfdout,strnum,fmt_ulong(strnum,i)); - substdio_puts(subfdout,":\n"); - } -} - -void main() -{ - dir(auto_uido,"755",""); - dir(auto_uido,"755","/control"); - dir(auto_uido,"755","/users"); - dir(auto_uido,"755","/bin"); - dir(auto_uido,"755","/man"); - dir(auto_uido,"755","/man/cat1"); - dir(auto_uido,"755","/man/cat5"); - dir(auto_uido,"755","/man/cat7"); - dir(auto_uido,"755","/man/cat8"); - dir(auto_uido,"755","/man/man1"); - dir(auto_uido,"755","/man/man5"); - dir(auto_uido,"755","/man/man7"); - dir(auto_uido,"755","/man/man8"); - - dir(auto_uida,"755","/alias"); - dir(auto_uidq,"750","/queue"); - dir(auto_uidq,"700","/queue/pid"); - dir(auto_uidq,"700","/queue/intd"); - dir(auto_uidq,"750","/queue/todo"); - dir(auto_uidq,"750","/queue/lock"); - dir(auto_uids,"700","/queue/bounce"); - - substdio_puts(subfdout,"z0:"); - uidgid(auto_uids); - substdio_puts(subfdout,"600:/queue/lock/:sendmutex:\n"); - - substdio_puts(subfdout,"z1024:"); - uidgid(auto_uidr); - substdio_puts(subfdout,"644:/queue/lock/:tcpto:\n"); - - substdio_puts(subfdout,"p:"); - uidgid(auto_uids); - substdio_puts(subfdout,"622:/queue/lock/:trigger:\n"); - - dirsplit(auto_uidq,"750","/queue/mess"); - dirsplit(auto_uids,"700","/queue/info"); - dirsplit(auto_uids,"700","/queue/local"); - dirsplit(auto_uids,"700","/queue/remote"); - - copy(auto_uidq,"4711","/bin/","qmail-queue"); - copy(auto_uido,"700","/bin/","qmail-lspawn"); - copy(auto_uido,"700","/bin/","qmail-start"); - copy(auto_uido,"711","/bin/","qmail-getpw"); - copy(auto_uido,"711","/bin/","qmail-local"); - copy(auto_uido,"711","/bin/","qmail-remote"); - copy(auto_uido,"711","/bin/","qmail-rspawn"); - copy(auto_uido,"711","/bin/","qmail-clean"); - copy(auto_uido,"711","/bin/","qmail-send"); - copy(auto_uido,"711","/bin/","splogger"); - copy(auto_uido,"700","/bin/","qmail-newu"); - copy(auto_uido,"711","/bin/","qmail-pw2u"); - copy(auto_uido,"755","/bin/","qmail-inject"); - copy(auto_uido,"755","/bin/","predate"); - copy(auto_uido,"755","/bin/","datemail"); - copy(auto_uido,"755","/bin/","mailsubj"); - copy(auto_uido,"755","/bin/","qmail-showctl"); - copy(auto_uido,"755","/bin/","qmail-qread"); - copy(auto_uido,"755","/bin/","qmail-qstat"); - copy(auto_uido,"755","/bin/","qmail-tcpto"); - copy(auto_uido,"755","/bin/","qmail-pop3d"); - copy(auto_uido,"700","/bin/","qmail-popup"); - copy(auto_uido,"755","/bin/","qmail-qmtpd"); - copy(auto_uido,"755","/bin/","qmail-smtpd"); - copy(auto_uido,"755","/bin/","sendmail"); - 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/","qsmhook"); - copy(auto_uido,"755","/bin/","qbiff"); - copy(auto_uido,"755","/bin/","forward"); - copy(auto_uido,"755","/bin/","preline"); - copy(auto_uido,"755","/bin/","condredirect"); - copy(auto_uido,"755","/bin/","maildirmake"); - copy(auto_uido,"755","/bin/","maildir2mbox"); - copy(auto_uido,"755","/bin/","maildirwatch"); - copy(auto_uido,"755","/bin/","qail"); - copy(auto_uido,"755","/bin/","elq"); - copy(auto_uido,"755","/bin/","pinq"); - - copy(auto_uido,"644","/man/man5/","addresses.5"); - copy(auto_uido,"644","/man/cat5/","addresses.0"); - copy(auto_uido,"644","/man/man5/","envelopes.5"); - copy(auto_uido,"644","/man/cat5/","envelopes.0"); - copy(auto_uido,"644","/man/man5/","maildir.5"); - copy(auto_uido,"644","/man/cat5/","maildir.0"); - copy(auto_uido,"644","/man/man5/","mbox.5"); - copy(auto_uido,"644","/man/cat5/","mbox.0"); - copy(auto_uido,"644","/man/man5/","dot-qmail.5"); - copy(auto_uido,"644","/man/cat5/","dot-qmail.0"); - copy(auto_uido,"644","/man/man5/","qmail-control.5"); - copy(auto_uido,"644","/man/cat5/","qmail-control.0"); - copy(auto_uido,"644","/man/man5/","qmail-header.5"); - copy(auto_uido,"644","/man/cat5/","qmail-header.0"); - copy(auto_uido,"644","/man/man5/","qmail-log.5"); - copy(auto_uido,"644","/man/cat5/","qmail-log.0"); - copy(auto_uido,"644","/man/man5/","qmail-users.5"); - copy(auto_uido,"644","/man/cat5/","qmail-users.0"); - copy(auto_uido,"644","/man/man5/","tcp-environ.5"); - copy(auto_uido,"644","/man/cat5/","tcp-environ.0"); - - copy(auto_uido,"644","/man/man7/","forgeries.7"); - copy(auto_uido,"644","/man/cat7/","forgeries.0"); - copy(auto_uido,"644","/man/man7/","qmail-limits.7"); - 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/cat7/","qmail.0"); - - copy(auto_uido,"644","/man/man1/","forward.1"); - copy(auto_uido,"644","/man/cat1/","forward.0"); - copy(auto_uido,"644","/man/man1/","condredirect.1"); - copy(auto_uido,"644","/man/cat1/","condredirect.0"); - copy(auto_uido,"644","/man/man1/","maildirmake.1"); - copy(auto_uido,"644","/man/cat1/","maildirmake.0"); - copy(auto_uido,"644","/man/man1/","maildir2mbox.1"); - copy(auto_uido,"644","/man/cat1/","maildir2mbox.0"); - copy(auto_uido,"644","/man/man1/","maildirwatch.1"); - copy(auto_uido,"644","/man/cat1/","maildirwatch.0"); - copy(auto_uido,"644","/man/man1/","mailsubj.1"); - 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/cat1/","qreceipt.0"); - copy(auto_uido,"644","/man/man1/","qbiff.1"); - copy(auto_uido,"644","/man/cat1/","qbiff.0"); - copy(auto_uido,"644","/man/man1/","preline.1"); - copy(auto_uido,"644","/man/cat1/","preline.0"); - copy(auto_uido,"644","/man/man1/","tcp-env.1"); - copy(auto_uido,"644","/man/cat1/","tcp-env.0"); - - copy(auto_uido,"644","/man/man8/","qmail-local.8"); - copy(auto_uido,"644","/man/cat8/","qmail-local.0"); - copy(auto_uido,"644","/man/man8/","qmail-lspawn.8"); - copy(auto_uido,"644","/man/cat8/","qmail-lspawn.0"); - copy(auto_uido,"644","/man/man8/","qmail-getpw.8"); - copy(auto_uido,"644","/man/cat8/","qmail-getpw.0"); - copy(auto_uido,"644","/man/man8/","qmail-remote.8"); - copy(auto_uido,"644","/man/cat8/","qmail-remote.0"); - copy(auto_uido,"644","/man/man8/","qmail-rspawn.8"); - copy(auto_uido,"644","/man/cat8/","qmail-rspawn.0"); - copy(auto_uido,"644","/man/man8/","qmail-clean.8"); - copy(auto_uido,"644","/man/cat8/","qmail-clean.0"); - copy(auto_uido,"644","/man/man8/","qmail-send.8"); - copy(auto_uido,"644","/man/cat8/","qmail-send.0"); - copy(auto_uido,"644","/man/man8/","qmail-start.8"); - copy(auto_uido,"644","/man/cat8/","qmail-start.0"); - copy(auto_uido,"644","/man/man8/","splogger.8"); - copy(auto_uido,"644","/man/cat8/","splogger.0"); - copy(auto_uido,"644","/man/man8/","qmail-queue.8"); - copy(auto_uido,"644","/man/cat8/","qmail-queue.0"); - copy(auto_uido,"644","/man/man8/","qmail-inject.8"); - copy(auto_uido,"644","/man/cat8/","qmail-inject.0"); - copy(auto_uido,"644","/man/man8/","qmail-showctl.8"); - copy(auto_uido,"644","/man/cat8/","qmail-showctl.0"); - copy(auto_uido,"644","/man/man8/","qmail-newu.8"); - copy(auto_uido,"644","/man/cat8/","qmail-newu.0"); - copy(auto_uido,"644","/man/man8/","qmail-pw2u.8"); - copy(auto_uido,"644","/man/cat8/","qmail-pw2u.0"); - copy(auto_uido,"644","/man/man8/","qmail-qread.8"); - copy(auto_uido,"644","/man/cat8/","qmail-qread.0"); - copy(auto_uido,"644","/man/man8/","qmail-qstat.8"); - copy(auto_uido,"644","/man/cat8/","qmail-qstat.0"); - copy(auto_uido,"644","/man/man8/","qmail-tcpto.8"); - copy(auto_uido,"644","/man/cat8/","qmail-tcpto.0"); - copy(auto_uido,"644","/man/man8/","qmail-pop3d.8"); - copy(auto_uido,"644","/man/cat8/","qmail-pop3d.0"); - copy(auto_uido,"644","/man/man8/","qmail-popup.8"); - copy(auto_uido,"644","/man/cat8/","qmail-popup.0"); - copy(auto_uido,"644","/man/man8/","qmail-qmtpd.8"); - copy(auto_uido,"644","/man/cat8/","qmail-qmtpd.0"); - copy(auto_uido,"644","/man/man8/","qmail-smtpd.8"); - copy(auto_uido,"644","/man/cat8/","qmail-smtpd.0"); - copy(auto_uido,"644","/man/man8/","qmail-command.8"); - copy(auto_uido,"644","/man/cat8/","qmail-command.0"); - - substdio_flush(subfdout); - _exit(0); -} diff --git a/qmail-inject.8 b/qmail-inject.8 index 3a05328..59e11a7 100644 --- a/qmail-inject.8 +++ b/qmail-inject.8 @@ -76,6 +76,21 @@ and letters described below. 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 .B QMAILINJECT environment variable diff --git a/qmail-inject.c b/qmail-inject.c index d6083a7..753c18a 100644 --- a/qmail-inject.c +++ b/qmail-inject.c @@ -21,6 +21,7 @@ #include "headerbody.h" #include "auto_qmail.h" #include "newfield.h" +#include "constmap.h" #define LINELEN 80 @@ -63,14 +64,10 @@ void die_nomem() { void die_invalid(sa) stralloc *sa; { substdio_putsflush(subfderr,"qmail-inject: fatal: invalid header field: "); 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() { substdio_putsflush(subfderr,"qmail-inject: fatal: unable to run qmail-queue\n"); temp(); } void die_chdir() { 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() { if (errno == error_nomem) die_nomem(); 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_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_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus) @@ -99,12 +83,15 @@ static stralloc sauninit = {0}; saa savedh = {0}; saa hrlist = {0}; +saa tocclist = {0}; saa hrrlist = {0}; saa reciplist = {0}; int flagresent; void exitnicely() { + char *qqx; + if (!flagqueue) substdio_flush(subfdout); if (flagqueue) @@ -133,19 +120,22 @@ void exitnicely() qmail_to(&qqt,hrlist.sa[i].s); } - switch(qmail_close(&qqt)) - { - case 0: break; - case QMAIL_CRASHED: die_qqsig(); - case QMAIL_USAGE: case QMAIL_BUG: die_bug(); - case QMAIL_EXECSOFT: die_exec(); - case QMAIL_NOMEM: die_nomem(); - case QMAIL_READ: die_comm(); - case QMAIL_WRITE: die_qqwrite(); - case QMAIL_TOOLONG: die_qqtoolong(); - case QMAIL_TIMEOUT: die_qqtimeout(); - default: die_qq(); - } + qqx = qmail_close(&qqt); + if (*qqx) + if (*qqx == 'D') { + substdio_puts(subfderr,"qmail-inject: fatal: "); + substdio_puts(subfderr,qqx + 1); + substdio_puts(subfderr,"\n"); + substdio_flush(subfderr); + perm(); + } + else { + substdio_puts(subfderr,"qmail-inject: fatal: "); + substdio_puts(subfderr,qqx + 1); + substdio_puts(subfderr,"\n"); + substdio_flush(subfderr); + temp(); + } } _exit(0); @@ -324,11 +314,10 @@ token822_alloc *addr; return 1; } -void rwrecip(addr,xl) +void rwappend(addr,xl) token822_alloc *addr; saa *xl; { - rwgeneric(addr); token822_reverse(addr); if (!saa_readyplus(xl,1)) die_nomem(); xl->sa[xl->len] = sauninit; @@ -338,9 +327,11 @@ saa *xl; } int rwhrr(addr) token822_alloc *addr; -{ rwrecip(addr,&hrrlist); return 1; } +{ rwgeneric(addr); rwappend(addr,&hrrlist); return 1; } 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]; stralloc hfbuf = {0}; @@ -351,51 +342,47 @@ token822_alloc hfaddr = {0}; void doheaderfield(h) stralloc *h; { - int htype; - int flagrewrite; - int flagrecip; - int flagrr; - - htype = hfield_known(h->s,h->len); - if (flagdeletefrom) if (htype == H_FROM) return; - if (flagdeletemessid) if (htype == H_MESSAGEID) return; - if (flagdeletesender) if (htype == H_RETURNPATH) return; - - if (htype) - htypeseen[htype] = 1; - else - if (!hfield_valid(h->s,h->len)) - die_invalid(h); - - flagrewrite = 0; - flagrecip = 0; - flagrr = 0; - switch(htype) - { - case H_R_TO: case H_R_CC: case H_R_BCC: - flagrr = 1; - case H_TO: case H_CC: case H_BCC: case H_APPARENTLYTO: - flagrecip = 1; - case H_SENDER: case H_FROM: case H_REPLYTO: - case H_RETURNRECEIPTTO: case H_ERRORSTO: case H_RETURNPATH: - case H_R_SENDER: case H_R_FROM: case H_R_REPLYTO: - flagrewrite = 1; - break; + int htype; + int (*rw)() = 0; + + htype = hfield_known(h->s,h->len); + if (flagdeletefrom) if (htype == H_FROM) return; + if (flagdeletemessid) if (htype == H_MESSAGEID) return; + if (flagdeletesender) if (htype == H_RETURNPATH) return; + + if (htype) + htypeseen[htype] = 1; + else + if (!hfield_valid(h->s,h->len)) + die_invalid(h); + + switch(htype) { + case H_TO: case H_CC: + rw = rwtocc; break; + case H_BCC: case H_APPARENTLYTO: + rw = rwhr; break; + case H_R_TO: case H_R_CC: case H_R_BCC: + rw = rwhrr; break; + case H_RETURNPATH: + rw = rwreturn; break; + case H_SENDER: case H_FROM: case H_REPLYTO: + case H_RETURNRECEIPTTO: case H_ERRORSTO: + case H_R_SENDER: case H_R_FROM: case H_R_REPLYTO: + rw = rwsender; break; } - if (flagrewrite) - { - doordie(h,token822_parse(&hfin,h,&hfbuf)); - doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,(htype == H_RETURNPATH) ? rwreturn : (flagrecip ? (flagrr ? rwhrr : rwhr) : rwsender))); - if (token822_unparse(h,&hfrewrite,LINELEN) != 1) - die_nomem(); + if (rw) { + doordie(h,token822_parse(&hfin,h,&hfbuf)); + doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,rw)); + if (token822_unparse(h,&hfrewrite,LINELEN) != 1) + die_nomem(); } - - if (htype == H_BCC) return; - if (htype == H_R_BCC) return; - if (htype == H_RETURNPATH) return; - if (htype == H_CONTENTLENGTH) return; /* some things are just too stupid */ - savedh_append(h); + + if (htype == H_BCC) return; + if (htype == H_R_BCC) return; + if (htype == H_RETURNPATH) return; + if (htype == H_CONTENTLENGTH) return; /* some things are just too stupid */ + savedh_append(h); } void dobody(h) @@ -421,7 +408,8 @@ char *s; perm(); } token822_reverse(&tr); - rwrecip(&tr,&reciplist); + rwgeneric(&tr); + rwappend(&tr,&reciplist); } stralloc defaultfrom = {0}; @@ -526,6 +514,53 @@ void dodefaultreturnpath() 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() { flagresent = @@ -596,6 +631,7 @@ void finishheader() } if (!htypeseen[H_TO] && !htypeseen[H_CC]) puts("Cc: recipient list not shown: ;\n"); + finishmft(); } savedh_print(); @@ -606,6 +642,9 @@ void getcontrols() static stralloc sa = {0}; char *x; + mft_init(); + + if (chdir(auto_qmail) == -1) die_chdir(); if (control_init() == -1) die_read(); if (control_rldef(&control_defaultdomain,"control/defaultdomain",1,"defaultdomain") != 1) @@ -688,11 +727,10 @@ char **argv; recipstrategy = RECIP_DEFAULT; flagqueue = 1; - if (chdir(auto_qmail) == -1) - die_chdir(); getcontrols(); if (!saa_readyplus(&hrlist,1)) die_nomem(); + if (!saa_readyplus(&tocclist,1)) die_nomem(); if (!saa_readyplus(&hrrlist,1)) die_nomem(); if (!saa_readyplus(&reciplist,1)) die_nomem(); diff --git a/qmail-local.8 b/qmail-local.8 index 847c39c..c047697 100644 --- a/qmail-local.8 +++ b/qmail-local.8 @@ -13,7 +13,7 @@ qmail-local \- deliver or forward a mail message .I ext .I domain .I sender -.I aliasempty +.I defaultdelivery .SH DESCRIPTION .B qmail-local reads a mail message @@ -69,7 +69,7 @@ treats a nonexistent the same way as an empty .BR .qmail\fIext : namely, following the delivery instructions in -.IR aliasempty . +.IR defaultdelivery . The standard input for .B qmail-local diff --git a/qmail-local.c b/qmail-local.c index 5c441cf..cd01602 100644 --- a/qmail-local.c +++ b/qmail-local.c @@ -12,6 +12,7 @@ #include "seek.h" #include "substdio.h" #include "getln.h" +#include "strerr.h" #include "subfd.h" #include "sgetopt.h" #include "alloc.h" @@ -28,40 +29,17 @@ #include "gfrom.h" #include "auto_patrn.h" -void err(s) char *s; { substdio_putsflush(subfderr,s); } -void soft() { _exit(111); } -void hard() { _exit(100); } - -void temp_childcrashed() { err("Aack, child crashed. (#4.3.0)\n"); soft(); } -void temp_rewind() { err("Unable to rewind message. (#4.3.0)\n"); soft(); } -void temp_fork() { err("Unable to fork. (#4.3.0)\n"); soft(); } -void temp_read() { err("Error while reading message. (#4.3.0)\n"); soft(); } -void temp_write() { err("Error while writing message. (#4.3.0)\n"); soft(); } -void temp_child() { err("Temporary error in forwarding message. (#4.3.0)\n"); soft(); } -void temp_maildirtimeout() { err("Timeout on maildir delivery. (#4.3.0)\n"); soft(); } -void temp_maildir() { err("Temporary error on maildir delivery. (#4.3.0)\n"); soft(); } -void temp_nomaildir() { err("Unable to chdir to maildir. (#4.2.1)\n"); soft(); } -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"); } +void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); } + +void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); } +void temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); } +void temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); } +void temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); } +void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); } +void temp_slowlock() +{ strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); } +void temp_qmail(fn) char *fn; +{ strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); } int flagdoit; int flag99; @@ -75,7 +53,7 @@ char *host; char *sender; char *aliasempty; -stralloc dashext = {0}; +stralloc safeext = {0}; stralloc ufline = {0}; stralloc rpline = {0}; stralloc envrecip = {0}; @@ -172,7 +150,7 @@ char *fn; temp_fork(); case 0: maildir_child(fn); - soft(); + _exit(111); } wait_pid(&wstat,child); @@ -181,15 +159,13 @@ char *fn; switch(wait_exitcode(wstat)) { case 0: break; - case 2: temp_nomaildir(); - case 3: temp_maildirtimeout(); - case 4: temp_read(); - default: temp_maildir(); + case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)"); + case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)"); + case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)"); + default: strerr_die1x(111,"Temporary error on maildir delivery. (#4.3.0)"); } } -void slowlock() { temp_slowlock(); } - void mailfile(fn) char *fn; { @@ -203,9 +179,10 @@ char *fn; if (seek_begin(0) == -1) temp_rewind(); 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); flaglocked = (lock_ex(fd) != -1); alarm(0); @@ -222,7 +199,11 @@ char *fn; for (;;) { 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 (gfrom(messline.s,messline.len)) if (substdio_bput(&ssout,">",1)) goto writeerrs; @@ -240,9 +221,10 @@ char *fn; return; writeerrs: + strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0); if (flaglocked) seek_trunc(fd,pos); close(fd); - temp_write(); + _exit(111); } void mailprogram(prog) @@ -259,15 +241,10 @@ char *prog; case -1: temp_fork(); 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(); - execvp(*args,args); - if (errno == error_txtbsy) { err("Text busy. (#4.3.0)\n"); soft(); } - 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(); + execv(*args,args); + strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)"); } wait_pid(&wstat,child); @@ -276,10 +253,10 @@ char *prog; switch(wait_exitcode(wstat)) { 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 99: flag99 = 1; break; - default: soft(); + default: _exit(111); } } @@ -289,6 +266,7 @@ void mailforward(recips) char **recips; { struct qmail qqt; + char *qqx; substdio ss; int match; @@ -306,13 +284,9 @@ char **recips; while (match); qmail_from(&qqt,ueo.s); while (*recips) qmail_to(&qqt,*recips++); - switch(qmail_close(&qqt)) - { - case QMAIL_TOOLONG: bounce_childperm(); - case QMAIL_READ: temp_read(); - case 0: return; - default: temp_child(); - } + qqx = qmail_close(&qqt); + if (!*qqx) return; + strerr_die3x(*qqx == 'D' ? 100 : 111,"Unable to forward message: ",qqx + 1,"."); } void bouncexf() @@ -330,7 +304,7 @@ void bouncexf() break; if (messline.len == 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; - if (stat(".",&st) == -1) temp_homestat(); - if (st.st_mode & auto_patrn) temp_homewritable(); + if (stat(".",&st) == -1) + 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 (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) @@ -350,54 +329,86 @@ char *dashowner; struct stat st; 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_0(&qme)) temp_nomem(); if (stat(qme.s,&st) == -1) { - if (error_temp(errno)) temp_nfsqmail(); + if (error_temp(errno)) temp_qmail(qme.s); return -1; } return 0; } -int qmeopen(cutable) +int qmeexists(fd,cutable) +int *fd; int *cutable; { - int fd; - struct stat st; - int i; + struct stat st; - i = dashext.len; - for (;;) - { - if (!stralloc_copys(&qme,".qmail")) temp_nomem(); - if (!stralloc_catb(&qme,dashext.s,i)) temp_nomem(); - if (i < dashext.len) if (!stralloc_cats(&qme,"-default")) temp_nomem(); - if (!stralloc_0(&qme)) temp_nomem(); - fd = open_read(qme.s); - if (fd == -1) - { - if (error_temp(errno)) temp_nfsqmail(); - if (errno == error_perm) temp_denyqmail(); - if (errno == error_acces) temp_denyqmail(); + 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; + + if (!stralloc_copys(&qme,".qmail")) temp_nomem(); + if (!stralloc_cats(&qme,dash)) temp_nomem(); + if (!stralloc_cat(&qme,&safeext)) temp_nomem(); + if (qmeexists(fd,cutable)) { + if (safeext.len >= 7) { + i = safeext.len - 7; + if (!byte_diff("default",7,safeext.s + i)) + if (i <= str_len(ext)) /* paranoia */ + if (!env_put2("DEFAULT",ext + i)) temp_nomem(); } - else - { - 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; + return; + } + + 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; } - close(fd); } - if (!i) return -1; - do - if (dashext.s[--i] == '-') break; - while (i); - } + + *fd = -1; } unsigned long count_file = 0; @@ -446,7 +457,7 @@ char **argv; char **recips; datetime_sec starttime; int flagforwardonly; - char *extx; + char *x; umask(077); sig_pipeignore(); @@ -459,9 +470,8 @@ char **argv; { case 'n': flagdoit = 0; break; case 'N': flagdoit = 1; break; - case '?': default: - hard(); + usage(); } argc -= optind; argv += optind; @@ -477,7 +487,8 @@ char **argv; if (*argv) 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(); if (!env_put2("HOST",host)) temp_nomem(); @@ -542,25 +553,40 @@ char **argv; if (!stralloc_0(&foo)) temp_nomem(); if (!env_put2("UFLINE",foo.s)) temp_nomem(); - if (!stralloc_copys(&dashext,dash)) temp_nomem(); - if (!stralloc_cats(&dashext,ext)) temp_nomem(); - for (i = 0;i < dashext.len;++i) - if (dashext.s[i] == '.') - dashext.s[i] = ':'; - case_lowerb(dashext.s,dashext.len); - - extx = ext; - if (!env_put2("EXT",extx)) temp_nomem(); - extx += str_chr(extx,'-'); if (*extx) ++extx; - if (!env_put2("EXT2",extx)) temp_nomem(); - extx += str_chr(extx,'-'); if (*extx) ++extx; - if (!env_put2("EXT3",extx)) temp_nomem(); - extx += str_chr(extx,'-'); if (*extx) ++extx; - if (!env_put2("EXT4",extx)) temp_nomem(); + x = ext; + if (!env_put2("EXT",x)) temp_nomem(); + x += str_chr(x,'-'); if (*x) ++x; + if (!env_put2("EXT2",x)) temp_nomem(); + x += str_chr(x,'-'); if (*x) ++x; + if (!env_put2("EXT3",x)) temp_nomem(); + x += str_chr(x,'-'); if (*x) ++x; + if (!env_put2("EXT4",x)) temp_nomem(); + + if (!stralloc_copys(&safeext,ext)) temp_nomem(); + case_lowerb(safeext.s,safeext.len); + for (i = 0;i < safeext.len;++i) + if (safeext.s[i] == '.') + safeext.s[i] = ':'; + + i = str_len(host); + 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; - fd = qmeopen(&flagforwardonly); - if (fd == -1) if (*dash) bounce_ext(); + qmesearch(&fd,&flagforwardonly); + 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 (str_diff(sender,"")) @@ -625,13 +651,13 @@ char **argv; { case 0: /* k == i */ if (i) break; - temp_blankline(); + strerr_die1x(111,"Uh-oh: first line of .qmail file is blank. (#4.2.1)"); case '#': break; case '.': case '/': ++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 (flagdoit) maildir(cmds.s + i); else sayit("maildir ",cmds.s + i,k - i); @@ -641,7 +667,7 @@ char **argv; break; case '|': ++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); else sayit("program ",cmds.s + i + 1,k - i - 1); break; diff --git a/qmail-log.5 b/qmail-log.5 index c039156..98cef63 100644 --- a/qmail-log.5 +++ b/qmail-log.5 @@ -5,31 +5,22 @@ qmail-log \- the qmail activity record .B qmail-send prints a series of lines describing its activities. Each possible line is described below. -.SH "STARTING AND STOPPING" -.TP -.B running -.B qmail-send -is ready to deliver messages. -.TP -.B local deliveries will be put on hold -The local concurrency limit is 0, so -.B qmail-send -will not perform any local deliveries. +.SH "STATUS" .TP -.B remote deliveries will be put on hold -The remote concurrency limit is 0, so +.B status: local \fIl\fB/\fIL\fB remote \fIr\fB/\fIR\fB ... .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 +is waiting for +.I l +local deliveries +and +.I r +remote deliveries. +The concurrency limits are +.I L +and +.IR R . +.TP +.B status: exiting .B qmail-send is done. .SH "FATAL PROBLEMS" diff --git a/qmail-lspawn.8 b/qmail-lspawn.8 index 111329d..da01741 100644 --- a/qmail-lspawn.8 +++ b/qmail-lspawn.8 @@ -3,7 +3,7 @@ qmail-lspawn \- schedule local deliveries .SH SYNOPSIS .B qmail-lspawn -.I aliasempty +.I defaultdelivery .SH DESCRIPTION .B qmail-lspawn reads a series of local delivery commands from descriptor 0, @@ -12,7 +12,7 @@ invokes to perform the deliveries, and prints the results to descriptor 1. It passes -.I aliasempty +.I defaultdelivery to .B qmail-local as the default delivery instruction. diff --git a/qmail-newmrh.9 b/qmail-newmrh.9 new file mode 100644 index 0000000..2f02f10 --- /dev/null +++ b/qmail-newmrh.9 @@ -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) diff --git a/qmail-newmrh.c b/qmail-newmrh.c new file mode 100644 index 0000000..25a4a10 --- /dev/null +++ b/qmail-newmrh.c @@ -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); +} diff --git a/qmail-pop3d.8 b/qmail-pop3d.8 index b85abaa..de6b2ba 100644 --- a/qmail-pop3d.8 +++ b/qmail-pop3d.8 @@ -29,7 +29,7 @@ which checks the password and sets up environment variables. has a 20-minute idle timeout. .B qmail-pop3d -supports UIDL and TOP. +supports UIDL, TOP, and LAST. .B qmail-pop3d appends an extra blank line to every message diff --git a/qmail-pop3d.c b/qmail-pop3d.c index c3ff0a6..51976c2 100644 --- a/qmail-pop3d.c +++ b/qmail-pop3d.c @@ -1,60 +1,69 @@ #include #include -#include "direntry.h" +#include "commands.h" #include "sig.h" #include "getln.h" #include "stralloc.h" #include "substdio.h" #include "alloc.h" -#include "datetime.h" -#include "prot.h" #include "open.h" #include "prioq.h" #include "scan.h" #include "fmt.h" -#include "error.h" #include "str.h" #include "exit.h" -#include "now.h" +#include "maildir.h" #include "readwrite.h" +#include "timeoutread.h" +#include "timeoutwrite.h" -int timeout = 1200; +void die() { _exit(0); } -char ssoutbuf[1024]; -substdio ssout = SUBSTDIO_FDBUF(write,1,ssoutbuf,sizeof(ssoutbuf)); +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 timeoutread(fd,buf,n) int fd; char *buf; int n; +int safewrite(fd,buf,len) int fd; char *buf; int len; { - int r; int saveerrno; - alarm(timeout); - r = read(fd,buf,n); saveerrno = errno; - alarm(0); - errno = saveerrno; return r; + int r; + r = timeoutwrite(1200,fd,buf,len); + if (r <= 0) die(); + return r; } -char ssinbuf[128]; -substdio ssin = SUBSTDIO_FDBUF(timeoutread,0,ssinbuf,sizeof(ssinbuf)); +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 die() { _exit(0); } +void put(buf,len) char *buf; int len; +{ + substdio_put(&ssout,buf,len); +} void puts(s) char *s; { - if (substdio_puts(&ssout,s) == -1) die(); + substdio_puts(&ssout,s); } void flush() { - if (substdio_flush(&ssout) == -1) die(); + substdio_flush(&ssout); } void err(s) char *s; { - puts("-ERR "); - puts(s); - puts("\r\n"); - if (substdio_flush(&ssout) == -1) die(); + puts("-ERR "); + puts(s); + puts("\r\n"); + flush(); } + 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_scan() { err("unable to scan $HOME/Maildir"); die(); } void err_syntax() { err("syntax error"); } void err_unimpl() { err("unimplemented"); } @@ -65,333 +74,232 @@ void err_nosuch() { err("unable to open that message"); } void err_nounlink() { err("unable to unlink all deleted messages"); } 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}; + +void blast(ssfrom,limit) +substdio *ssfrom; +unsigned long limit; +{ + int match; + int inheaders = 1; + + for (;;) { + if (getln(ssfrom,&line,&match,'\n') != 0) die(); + if (!match && !line.len) break; + if (match) --line.len; /* no way to pass this info over POP */ + if (limit) if (!inheaders) if (!--limit) break; + if (!line.len) + inheaders = 0; + else + if (line.s[0] == '.') + put(".",1); + put(line.s,line.len); + put("\r\n",2); + if (!match) break; + } + put("\r\n.\r\n",5); + flush(); +} stralloc filenames = {0}; prioq pq = {0}; -stralloc newname = {0}; -struct message - { +struct message { int flagdeleted; unsigned long size; char *fn; - } -*m; +} *m; int numm; -substdio ssmsg; char ssmsgbuf[1024]; - - -void blast(ssfrom,limit) -substdio *ssfrom; -unsigned long limit; -{ - int match; - int inheaders = 1; - - for (;;) - { - if (getln(ssfrom,&dataline,&match,'\n') != 0) die(); - if (!match && !dataline.len) break; - if (match) --dataline.len; /* no way to pass this info over POP */ - if (limit) if (!inheaders) if (!--limit) break; - if (!dataline.len) - inheaders = 0; - else - if (dataline.s[0] == '.') - substdio_put(&ssout,".",1); - if (substdio_put(&ssout,dataline.s,dataline.len) == -1) die(); - if (substdio_put(&ssout,"\r\n",2) == -1) die(); - if (!match) break; - } - if (substdio_put(&ssout,"\r\n.\r\n",5) == -1) die(); - if (substdio_flush(&ssout) == -1) die(); -} +int last = 0; void getlist() { - unsigned long pos; - datetime_sec time; - DIR *dir; - direntry *d; - struct prioq_elt pe; - struct stat st; - int i; - - numm = 0; - - 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); - } - - m = (struct message *) alloc(numm * sizeof(struct message)); - if (!m) die_nomem(); - - for (i = 0;i < numm;++i) - { - if (!prioq_min(&pq,&pe)) { numm = i; break; } - prioq_delmin(&pq); - m[i].fn = filenames.s + pe.id; - m[i].flagdeleted = 0; - if (stat(m[i].fn,&st) == -1) - m[i].size = 0; - else - m[i].size = st.st_size; + struct prioq_elt pe; + struct stat st; + int i; + + maildir_clean(&line); + if (maildir_scan(&pq,&filenames,1,1) == -1) die_scan(); + + numm = pq.p ? pq.len : 0; + m = (struct message *) alloc(numm * sizeof(struct message)); + if (!m) die_nomem(); + + for (i = 0;i < numm;++i) { + if (!prioq_min(&pq,&pe)) { numm = i; break; } + prioq_delmin(&pq); + m[i].fn = filenames.s + pe.id; + m[i].flagdeleted = 0; + if (stat(m[i].fn,&st) == -1) + m[i].size = 0; + else + m[i].size = st.st_size; } } -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; +void pop3_stat() { - puts(fn + 4); - puts("\r\n"); + int i; + unsigned long total; + + total = 0; + for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size; + puts("+OK "); + put(strnum,fmt_uint(strnum,numm)); + puts(" "); + put(strnum,fmt_ulong(strnum,total)); + puts("\r\n"); + flush(); } -void pop3_stat() +void pop3_rset() { - int i; - unsigned long total; - - total = 0; - for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size; - puts("+OK "); - printint(numm); - printlong(total); - flush(); + int i; + for (i = 0;i < numm;++i) m[i].flagdeleted = 0; + last = 0; + okay(); } -void pop3_rset() +void pop3_last() { - int i; - for (i = 0;i < numm;++i) m[i].flagdeleted = 0; - okay(); + puts("+OK "); + put(strnum,fmt_uint(strnum,last)); + puts("\r\n"); + flush(); } void pop3_quit() { - int i; - for (i = 0;i < numm;++i) - if (m[i].flagdeleted) - if (unlink(m[i].fn) == -1) err_nounlink(); - okay(); - die(); + int i; + for (i = 0;i < numm;++i) + if (m[i].flagdeleted) { + 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(); + die(); } int msgno(arg) char *arg; { - unsigned long u; - if (!arg) { err_syntax(); return -1; } - if (!scan_ulong(arg,&u)) { err_syntax(); return -1; } - if (!u) { err_nozero(); return -1; } - --u; - if (u >= numm) { err_toobig(); return -1; } - if (m[u].flagdeleted) { err_deleted(); return -1; } - return u; + unsigned long u; + if (!scan_ulong(arg,&u)) { err_syntax(); return -1; } + if (!u) { err_nozero(); return -1; } + --u; + if (u >= numm) { err_toobig(); return -1; } + if (m[u].flagdeleted) { err_deleted(); return -1; } + return u; } void pop3_dele(arg) char *arg; { - int i; + int i; + i = msgno(arg); + if (i == -1) return; + m[i].flagdeleted = 1; + if (i + 1 > last) last = i + 1; + okay(); +} - i = msgno(arg); - if (i == -1) return; - m[i].flagdeleted = 1; - 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; { - unsigned int i; - - if (arg) - { - i = msgno(arg); - if (i == -1) return; - puts("+OK "); - printint(i + 1); - if (flaguidl) printfn(m[i].fn); else printlong(m[i].size); + unsigned int i; + if (*arg) { + i = msgno(arg); + if (i == -1) return; + puts("+OK "); + list(i,flaguidl); } - else - { - okay(); - - for (i = 0;i < numm;++i) - if (!m[i].flagdeleted) - { - printint(i + 1); - if (flaguidl) printfn(m[i].fn); else printlong(m[i].size); - } - puts(".\r\n"); + else { + okay(); + for (i = 0;i < numm;++i) + if (!m[i].flagdeleted) + list(i,flaguidl); + puts(".\r\n"); } - flush(); + flush(); } void pop3_uidl(arg) char *arg; { dolisting(arg,1); } void pop3_list(arg) char *arg; { dolisting(arg,0); } +substdio ssmsg; char ssmsgbuf[1024]; + void pop3_top(arg) char *arg; { - int i; - unsigned long limit; - int fd; - - i = msgno(arg); - if (i == -1) return; - - arg += scan_ulong(arg,&limit); - while (*arg == ' ') ++arg; - if (scan_ulong(arg,&limit)) ++limit; else limit = 0; - - fd = open_read(m[i].fn); - if (fd == -1) { err_nosuch(); return; } - okay(); - substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); - blast(&ssmsg,limit); - close(fd); + int i; + unsigned long limit; + int fd; + + i = msgno(arg); + if (i == -1) return; + + arg += scan_ulong(arg,&limit); + while (*arg == ' ') ++arg; + if (scan_ulong(arg,&limit)) ++limit; else limit = 0; + + fd = open_read(m[i].fn); + if (fd == -1) { err_nosuch(); return; } + okay(); + substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); + blast(&ssmsg,limit); + close(fd); } -static struct { void (*fun)(); char *text; } pop3cmd[] = { - { pop3_quit, "quit" } -, { pop3_stat, "stat" } -, { pop3_list, "list" } -, { pop3_uidl, "uidl" } -, { pop3_dele, "dele" } -, { pop3_top, "retr" } -, { pop3_rset, "rset" } -, { pop3_last, "last" } -, { pop3_top, "top" } -, { 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_unimpl(); -} +struct commands pop3commands[] = { + { "quit", pop3_quit, 0 } +, { "stat", pop3_stat, 0 } +, { "list", pop3_list, 0 } +, { "uidl", pop3_uidl, 0 } +, { "dele", pop3_dele, 0 } +, { "retr", pop3_top, 0 } +, { "rset", pop3_rset, 0 } +, { "last", pop3_last, 0 } +, { "top", pop3_top, 0 } +, { "noop", okay, 0 } +, { 0, err_unimpl, 0 } +} ; void main(argc,argv) int argc; char **argv; { - static stralloc cmd = {0}; - int match; - - sig_alarmcatch(die); - sig_pipeignore(); - - if (!argv[1]) die_nomaildir(); - if (chdir(argv[1]) == -1) die_nomaildir(); - - getlist(); - - okay(); - - for (;;) - { - 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); - } + sig_alarmcatch(die); + sig_pipeignore(); + + if (!argv[1]) die_nomaildir(); + if (chdir(argv[1]) == -1) die_nomaildir(); + + getlist(); + + okay(); + commands(&ssin,pop3commands); + die(); } diff --git a/qmail-popup.c b/qmail-popup.c index f8c80a3..fbcc99b 100644 --- a/qmail-popup.c +++ b/qmail-popup.c @@ -1,53 +1,59 @@ -#include -#include +#include "commands.h" #include "fd.h" #include "sig.h" -#include "getln.h" #include "stralloc.h" #include "substdio.h" -#include "subfd.h" #include "alloc.h" -#include "datetime.h" -#include "error.h" #include "wait.h" #include "str.h" +#include "byte.h" #include "now.h" #include "fmt.h" #include "exit.h" #include "readwrite.h" +#include "timeoutread.h" +#include "timeoutwrite.h" -int timeout = 1200; +void die() { _exit(1); } -int timeoutread(fd,buf,n) int fd; char *buf; int n; +int saferead(fd,buf,len) int fd; char *buf; int len; { - int r; int saveerrno; - alarm(timeout); - r = read(fd,buf,n); saveerrno = errno; - alarm(0); - errno = saveerrno; return r; + int r; + r = timeoutread(1200,fd,buf,len); + if (r <= 0) die(); + return r; } -char ssinbuf[128]; -substdio ssin = SUBSTDIO_FDBUF(timeoutread,0,ssinbuf,sizeof(ssinbuf)); +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[128]; +substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); -void die() { _exit(1); } -void out(s) char *s; +char ssinbuf[128]; +substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); + +void puts(s) char *s; { - if (substdio_puts(subfdoutsmall,s) == -1) die(); + substdio_puts(&ssout,s); } -void outflush(s) char *s; +void flush() { - out(s); - if (substdio_flush(subfdoutsmall) == -1) die(); + substdio_flush(&ssout); } void err(s) char *s; { - if (substdio_puts(subfdoutsmall,"-ERR ") == -1) die(); - if (substdio_puts(subfdoutsmall,s) == -1) die(); - if (substdio_puts(subfdoutsmall,"\r\n") == -1) die(); - if (substdio_flush(subfdoutsmall) == -1) die(); + puts("-ERR "); + puts(s); + puts("\r\n"); + flush(); } + void die_usage() { err("usage: popup hostname subprogram"); die(); } void die_nomem() { err("out of memory"); 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_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]; @@ -77,143 +84,100 @@ char *user; unsigned int userlen; /* including 0 byte */ char *pass; { - int child; - int wstat; - int pi[2]; - int i; - - if (fd_copy(2,1) == -1) die_pipe(); - close(3); - if (pipe(pi) == -1) die_pipe(); - if (pi[0] != 3) die_pipe(); - switch(child = fork()) - { - case -1: - die_fork(); - case 0: - close(pi[1]); - sig_pipedefault(); - execvp(*childargs,childargs); - _exit(1); + int child; + int wstat; + int pi[2]; + + if (fd_copy(2,1) == -1) die_pipe(); + close(3); + if (pipe(pi) == -1) die_pipe(); + if (pi[0] != 3) die_pipe(); + switch(child = fork()) { + case -1: + die_fork(); + case 0: + close(pi[1]); + sig_pipedefault(); + execvp(*childargs,childargs); + _exit(1); } - close(pi[0]); - substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof(upbuf)); - if (substdio_put(&ssup,user,userlen) == -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,unique) == -1) die_write(); - if (substdio_puts(&ssup,hostname) == -1) die_write(); - if (substdio_put(&ssup,">",2) == -1) die_write(); - if (substdio_flush(&ssup) == -1) die_write(); - close(pi[1]); - for (i = 0;pass[i];++i) pass[i] = 0; - for (i = 0;i < sizeof(upbuf);++i) upbuf[i] = 0; - if (wait_pid(&wstat,child) == -1) die(); - if (wait_crashed(wstat)) die_childcrashed(); - if (wait_exitcode(wstat)) die_badauth(); - die(); + close(pi[0]); + substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf); + if (substdio_put(&ssup,user,userlen) == -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,unique) == -1) die_write(); + if (substdio_puts(&ssup,hostname) == -1) die_write(); + if (substdio_put(&ssup,">",2) == -1) die_write(); + if (substdio_flush(&ssup) == -1) die_write(); + close(pi[1]); + byte_zero(pass,str_len(pass)); + byte_zero(upbuf,sizeof upbuf); + if (wait_pid(&wstat,child) == -1) die(); + if (wait_crashed(wstat)) die_childcrashed(); + if (wait_exitcode(wstat)) die_badauth(); + die(); } void pop3_greet() { - char *s; - s = unique; - s += fmt_uint(s,getpid()); - *s++ = '.'; - s += fmt_ulong(s,(unsigned long) now()); - *s++ = '@'; - *s++ = 0; - - out("+OK <"); - out(unique); - out(hostname); - outflush(">\r\n"); + char *s; + s = unique; + s += fmt_uint(s,getpid()); + *s++ = '.'; + s += fmt_ulong(s,(unsigned long) now()); + *s++ = '@'; + *s++ = 0; + puts("+OK <"); + puts(unique); + puts(hostname); + puts(">\r\n"); + flush(); } void pop3_user(arg) char *arg; { - if (!arg) { err_syntax(); return; } - okay(); - seenuser = 1; - if (!stralloc_copys(&username,arg)) die_nomem(); - if (!stralloc_0(&username)) die_nomem(); + if (!*arg) { err_syntax(); return; } + okay(); + seenuser = 1; + if (!stralloc_copys(&username,arg)) die_nomem(); + if (!stralloc_0(&username)) die_nomem(); } void pop3_pass(arg) char *arg; { - if (!seenuser) { err_wantuser(); return; } - if (!arg) { err_syntax(); return; } - doanddie(username.s,username.len,arg); + if (!seenuser) { err_wantuser(); return; } + if (!*arg) { err_syntax(); return; } + doanddie(username.s,username.len,arg); } void pop3_apop(arg) char *arg; { - char *space; - if (!arg) { err_syntax(); return; } - space = arg + str_chr(arg,' '); - if (!*space) { err_syntax(); return; } - *space++ = 0; - doanddie(arg,space - arg,space); + char *space; + space = arg + str_chr(arg,' '); + if (!*space) { err_syntax(); return; } + *space++ = 0; + doanddie(arg,space - arg,space); } -void pop3_quit() { okay(); die(); } - -static struct { void (*fun)(); char *text; } pop3cmd[] = { - { pop3_user, "user" } -, { pop3_pass, "pass" } -, { pop3_apop, "apop" } -, { pop3_quit, "quit" } -, { 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(); -} +struct commands pop3commands[] = { + { "user", pop3_user, 0 } +, { "pass", pop3_pass, 0 } +, { "apop", pop3_apop, 0 } +, { "quit", pop3_quit, 0 } +, { "noop", okay, 0 } +, { 0, err_authoriz, 0 } +} ; void main(argc,argv) int argc; char **argv; { - static stralloc cmd = {0}; - int match; - - sig_alarmcatch(die); - sig_pipeignore(); - - hostname = argv[1]; - if (!hostname) die_usage(); - childargs = argv + 2; - if (!*childargs) die_usage(); - - pop3_greet(); - - for (;;) - { - 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); - } + sig_alarmcatch(die); + sig_pipeignore(); + + hostname = argv[1]; + if (!hostname) die_usage(); + childargs = argv + 2; + if (!*childargs) die_usage(); + + pop3_greet(); + commands(&ssin,pop3commands); + die(); } diff --git a/qmail-pw2u.9 b/qmail-pw2u.9 index a62df8a..932cd4d 100644 --- a/qmail-pw2u.9 +++ b/qmail-pw2u.9 @@ -4,7 +4,7 @@ qmail-pw2u \- build address assignments from a passwd file .SH SYNOPSIS .B qmail-pw2u [ -.B \-ohHuUC +.B \-/ohHuUC ] [ .B \-c\fIchar @@ -160,7 +160,7 @@ Each line has the form .I sub will be handled by -.IR home\fB/.qmail-\fIpre , +.IR home\fB/.qmail\-\fIpre , where .I home is @@ -168,7 +168,7 @@ is home directory; .I sub\fBBREAK\fIext will be handled by -.IR home\fB/.qmail-\fIpre\fB-\fIext . +.IR home\fB/.qmail\-\fIpre\fB\-\fIext . .TP .B append Extra assignments, @@ -228,6 +228,12 @@ in place of .TP .B \-C Disable the user-extension mechanism. +.TP +.B \-/ +Use +.IR home\fB/.qmail\-/ ... +instead of +.IR home\fB/.qmail\- ... .SH "SEE ALSO" qmail-users(5), qmail-lspawn(8), diff --git a/qmail-pw2u.c b/qmail-pw2u.c index 5889f1d..4146067 100644 --- a/qmail-pw2u.c +++ b/qmail-pw2u.c @@ -67,6 +67,7 @@ void die_user(s,len) char *s; unsigned int len; _exit(111); } +char *dashcolon = "-:"; int flagalias = 0; int flagnoupper = 1; int homestrategy = 2; @@ -154,7 +155,8 @@ void doaccount() if (str_equal(user.s,auto_usera)) { if (substdio_puts(subfdout,"+") == -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; } @@ -180,7 +182,8 @@ void doaccount() if (substdio_put(subfdout,mailnames,i) == -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_puts(subfdout,"-::\n") == -1) die_write(); + if (substdio_puts(subfdout,dashcolon) == -1) die_write(); + if (substdio_puts(subfdout,":\n") == -1) die_write(); } mailnames += i; @@ -206,7 +209,7 @@ void dosubuser() if (substdio_puts(subfdout,"=") == -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,"-:") == -1) die_write(); + if (substdio_puts(subfdout,dashcolon) == -1) die_write(); if (substdio_put(subfdout,x,i) == -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,auto_break,1) == -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_puts(subfdout,"-:\n") == -1) die_write(); } @@ -232,8 +235,9 @@ char **argv; int opt; int match; - while ((opt = getopt(argc,argv,"ohHuUc:C")) != opteof) + while ((opt = getopt(argc,argv,"/ohHuUc:C")) != opteof) switch(opt) { + case '/': dashcolon = "-/:"; break; case 'o': homestrategy = 2; break; case 'h': homestrategy = 1; break; case 'H': homestrategy = 0; break; diff --git a/qmail-qmqpc.8 b/qmail-qmqpc.8 new file mode 100644 index 0000000..e11a15e --- /dev/null +++ b/qmail-qmqpc.8 @@ -0,0 +1,29 @@ +.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 . +.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) diff --git a/qmail-qmqpc.c b/qmail-qmqpc.c new file mode 100644 index 0000000..d5adf05 --- /dev/null +++ b/qmail-qmqpc.c @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#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); +} diff --git a/qmail-qmqpd.8 b/qmail-qmqpd.8 new file mode 100644 index 0000000..5142dfa --- /dev/null +++ b/qmail-qmqpd.8 @@ -0,0 +1,25 @@ +.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. +.SH "SEE ALSO" +tcp-env(1), +tcpserver(1), +tcp-environ(5), +qmail-qmqpc(8), +qmail-queue(8) diff --git a/qmail-qmqpd.c b/qmail-qmqpd.c new file mode 100644 index 0000000..86cb284 --- /dev/null +++ b/qmail-qmqpd.c @@ -0,0 +1,174 @@ +#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)"; + + substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result))); + substdio_puts(&ssout,":"); + substdio_puts(&ssout,result); + substdio_puts(&ssout,","); + substdio_flush(&ssout); + _exit(0); +} diff --git a/qmail-qmtpd.8 b/qmail-qmtpd.8 index 0b52452..244fdbf 100644 --- a/qmail-qmtpd.8 +++ b/qmail-qmtpd.8 @@ -16,9 +16,12 @@ see .B qmail-qmtpd supports the -.I rcpthosts +.IR rcpthosts , +.IR morercpthosts , +.BR RELAYCLIENT , +.IR databytes , and -.B RELAYCLIENT +.B DATABYTES mechanisms described in .BR qmail-smtpd(8) . .SH "SEE ALSO" diff --git a/qmail-qmtpd.c b/qmail-qmtpd.c index fab2a0d..df911a6 100644 --- a/qmail-qmtpd.c +++ b/qmail-qmtpd.c @@ -1,52 +1,66 @@ #include "stralloc.h" #include "substdio.h" -#include "subfd.h" #include "qmail.h" #include "now.h" #include "str.h" #include "fmt.h" #include "env.h" #include "sig.h" +#include "rcpthosts.h" #include "auto_qmail.h" -#include "now.h" -#include "datetime.h" -#include "date822fmt.h" #include "readwrite.h" #include "control.h" -#include "constmap.h" #include "received.h" -struct qmail qqt; - -void dropped() { _exit(0); } void badproto() { _exit(100); } void resources() { _exit(111); } -void sigalrm() { _exit(111); } -unsigned long getlen() +int safewrite(fd,buf,len) int fd; char *buf; int len; { - unsigned long len; - char ch; + int r; + r = write(fd,buf,len); + if (r <= 0) _exit(0); + return r; +} + +char ssoutbuf[256]; +substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); - len = 0; - for (;;) - { - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); - if (ch == ':') return len; - if (len > 200000000) resources(); - len = 10 * len + (ch - '0'); +int saferead(fd,buf,len) int fd; char *buf; int len; +{ + int r; + substdio_flush(&ssout); + r = read(fd,buf,len); + if (r <= 0) _exit(0); + return r; +} + +char ssinbuf[512]; +substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); + +unsigned long getlen() +{ + unsigned long len = 0; + char ch; + for (;;) { + substdio_get(&ssin,&ch,1); + if (ch == ':') return len; + if (len > 200000000) resources(); + len = 10 * len + (ch - '0'); } } void getcomma() { - char ch; - - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); - if (ch != ',') badproto(); + char ch; + substdio_get(&ssin,&ch,1); + if (ch != ',') badproto(); } -struct datetime dt; +unsigned int databytes = 0; +unsigned int bytestooverflow = 0; +struct qmail qq; + char buf[1000]; char buf2[100]; @@ -57,225 +71,198 @@ char *local; stralloc failure = {0}; -int flagrcpthosts; -stralloc rcpthosts = {0}; -struct constmap maprcpthosts; char *relayclient; int relayclientlen; -int addrallowed(buf,len) char *buf; int len; -{ - int j; - if (!flagrcpthosts) return 1; - j = byte_rchr(buf,len,'@'); - if (j >= len) return 1; - if (constmap(&maprcpthosts,buf + j + 1,len - j - 1)) return 1; - for (;j < len;++j) - if (buf[j] == '.') - if (constmap(&maprcpthosts,buf + j,len - j)) return 1; - return 0; -} - main() { - char ch; - int i; - unsigned long biglen; - unsigned long len; - int flagdos; - int flagsenderok; - unsigned long qp; - char *result; - - sig_pipeignore(); - sig_alarmcatch(sigalrm); - alarm(3600); - - if (chdir(auto_qmail) == -1) resources(); - - if (control_init() == -1) resources(); - flagrcpthosts = control_readfile(&rcpthosts,"control/rcpthosts",0); - if (flagrcpthosts == -1) resources(); - if (flagrcpthosts) - if (!constmap_init(&maprcpthosts,rcpthosts.s,rcpthosts.len,0)) resources(); - relayclient = env_get("RELAYCLIENT"); - relayclientlen = relayclient ? str_len(relayclient) : 0; - - 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"; - - for (;;) - { - if (!stralloc_copys(&failure,"")) resources(); - flagsenderok = 1; - - len = getlen(); - if (len == 0) badproto(); - - if (qmail_open(&qqt) == -1) resources(); - qp = qmail_qp(&qqt); - - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); - --len; - - if (ch == 10) flagdos = 0; - else if (ch == 13) flagdos = 1; - else badproto(); - - received(&qqt,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0); - - /* XXX: check for loops? only if len is big? */ - - if (flagdos) - while (len > 0) - { - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); - --len; - while ((ch == 13) && len) - { - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); - --len; - if (ch == 10) break; - qmail_put(&qqt,"\015",1); + char ch; + int i; + unsigned long biglen; + unsigned long len; + int flagdos; + int flagsenderok; + int flagbother; + unsigned long qp; + char *result; + char *x; + unsigned long u; + + sig_pipeignore(); + sig_alarmcatch(resources); + alarm(3600); + + if (chdir(auto_qmail) == -1) resources(); + + if (control_init() == -1) resources(); + if (rcpthosts_init() == -1) resources(); + relayclient = env_get("RELAYCLIENT"); + relayclientlen = relayclient ? str_len(relayclient) : 0; + + if (control_readint(&databytes,"control/databytes") == -1) resources(); + x = env_get("DATABYTES"); + if (x) { scan_ulong(x,&u); databytes = u; } + if (!(databytes + 1)) --databytes; + + 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"; + + for (;;) { + if (!stralloc_copys(&failure,"")) resources(); + flagsenderok = 1; + + len = getlen(); + if (len == 0) badproto(); + + if (databytes) bytestooverflow = databytes + 1; + if (qmail_open(&qq) == -1) resources(); + qp = qmail_qp(&qq); + + substdio_get(&ssin,&ch,1); + --len; + if (ch == 10) flagdos = 0; + else if (ch == 13) flagdos = 1; + else badproto(); + + received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0); + + /* XXX: check for loops? only if len is big? */ + + if (flagdos) + while (len > 0) { + substdio_get(&ssin,&ch,1); + --len; + while ((ch == 13) && len) { + substdio_get(&ssin,&ch,1); + --len; + if (ch == 10) break; + if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qq); + qmail_put(&qq,"\015",1); } - qmail_put(&qqt,&ch,1); + if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qq); + qmail_put(&qq,&ch,1); } - else - while (len > 0) /* XXX: could speed this up, obviously */ - { - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); - --len; - qmail_put(&qqt,&ch,1); + else { + if (databytes) + if (len > databytes) { + bytestooverflow = 0; + qmail_fail(&qq); + } + while (len > 0) { /* XXX: could speed this up, obviously */ + substdio_get(&ssin,&ch,1); + --len; + qmail_put(&qq,&ch,1); } - getcomma(); - - len = getlen(); - - if (len >= 1000) - { - buf[0] = 0; - flagsenderok = 0; - for (i = 0;i < len;++i) - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); } - else - { - for (i = 0;i < len;++i) - { - if (substdio_get(subfdinsmall,buf + i,1) < 1) dropped(); - if (!buf[i]) flagsenderok = 0; + getcomma(); + + len = getlen(); + + if (len >= 1000) { + buf[0] = 0; + flagsenderok = 0; + for (i = 0;i < len;++i) + substdio_get(&ssin,&ch,1); + } + else { + for (i = 0;i < len;++i) { + substdio_get(&ssin,buf + i,1); + if (!buf[i]) flagsenderok = 0; } - buf[len] = 0; + buf[len] = 0; } - getcomma(); - - qmail_from(&qqt,buf); - if (!flagsenderok) qmail_fail(&qqt); - - biglen = getlen(); - while (biglen > 0) - { - if (!stralloc_append(&failure,"")) resources(); - - len = 0; - for (;;) - { - if (!biglen) badproto(); - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); - --biglen; - if (ch == ':') break; - if (len > 200000000) resources(); - len = 10 * len + (ch - '0'); + getcomma(); + + flagbother = 0; + qmail_from(&qq,buf); + if (!flagsenderok) qmail_fail(&qq); + + biglen = getlen(); + while (biglen > 0) { + if (!stralloc_append(&failure,"")) resources(); + + len = 0; + for (;;) { + if (!biglen) badproto(); + substdio_get(&ssin,&ch,1); + --biglen; + if (ch == ':') break; + if (len > 200000000) resources(); + len = 10 * len + (ch - '0'); } - if (len >= biglen) badproto(); - if (len + relayclientlen >= 1000) - { - failure.s[failure.len - 1] = 'L'; - for (i = 0;i < len;++i) - if (substdio_get(subfdinsmall,&ch,1) < 1) dropped(); + if (len >= biglen) badproto(); + if (len + relayclientlen >= 1000) { + failure.s[failure.len - 1] = 'L'; + for (i = 0;i < len;++i) + substdio_get(&ssin,&ch,1); } - else - { - for (i = 0;i < len;++i) - { - if (substdio_get(subfdinsmall,buf + i,1) < 1) dropped(); - if (!buf[i]) failure.s[failure.len - 1] = 'N'; + else { + for (i = 0;i < len;++i) { + substdio_get(&ssin,buf + i,1); + if (!buf[i]) failure.s[failure.len - 1] = 'N'; + } + buf[len] = 0; + + if (relayclient) + str_copy(buf + len,relayclient); + else + switch(rcpthosts(buf,len)) { + case -1: resources(); + case 0: failure.s[failure.len - 1] = 'D'; + } + + if (!failure.s[failure.len - 1]) { + qmail_to(&qq,buf); + flagbother = 1; } - buf[len] = 0; - - if (relayclient) - str_copy(buf + len,relayclient); - else - if (!addrallowed(buf,len)) failure.s[failure.len - 1] = 'D'; - - if (!failure.s[failure.len - 1]) - qmail_to(&qqt,buf); } - getcomma(); - biglen -= (len + 1); + getcomma(); + biglen -= (len + 1); } - getcomma(); - - switch(qmail_close(&qqt)) - { - case 0: result = 0; break; - case QMAIL_WAITPID: result = "Zqq waitpid surprise (#4.3.0)"; break; - case QMAIL_CRASHED: result = "Zqq crashed (#4.3.0)"; break; - case QMAIL_USAGE: result = "Zqq usage surprise (#4.3.0)"; break; - case QMAIL_SYS: result = "Zqq system error (#4.3.0)"; break; - case QMAIL_READ: result = "Zqq read error (#4.3.0)"; break; - case QMAIL_WRITE: result = "Zqq write error or disk full (#4.3.0)"; break; - case QMAIL_NOMEM: result = "Zqq out of memory (#4.3.0)"; break; - case QMAIL_EXECSOFT: result = "Zcould not exec qq (#4.3.0)"; break; - case QMAIL_TIMEOUT: result = "Zqq timeout (#4.3.0)"; break; - case QMAIL_TOOLONG: result = "Dqq toolong surprise (#5.1.3)"; break; - default: result = "Zqq internal bug (#4.3.0)"; break; + getcomma(); + + if (!flagbother) qmail_fail(&qq); + result = qmail_close(&qq); + if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)"; + if (databytes) if (!bytestooverflow) result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)"; + + if (*result) + len = str_len(result); + else { + /* success! */ + len = 0; + len += fmt_str(buf2 + len,"Kok "); + len += fmt_ulong(buf2 + len,(unsigned long) now()); + len += fmt_str(buf2 + len," qp "); + len += fmt_ulong(buf2 + len,qp); + buf2[len] = 0; + result = buf2; } - - if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)"; - - if (result) - len = str_len(result); - else - { - /* success! */ - len = 0; - len += fmt_str(buf2 + len,"Kok "); - len += fmt_ulong(buf2 + len,(unsigned long) now()); - len += fmt_str(buf2 + len," qp "); - len += fmt_ulong(buf2 + len,qp); - buf2[len] = 0; - result = buf2; - } - - len = fmt_ulong(buf,len); - buf[len++] = ':'; - len += fmt_str(buf + len,result); - buf[len++] = ','; - - for (i = 0;i < failure.len;++i) - switch(failure.s[i]) - { - case 0: - if (substdio_put(subfdoutsmall,buf,len) == -1) - dropped(); - break; - case 'D': - if (substdio_puts(subfdoutsmall,"66:Dsorry, that domain isn't in my list of allowed rcpthosts (#5.7.1),") == -1) - dropped(); - break; - default: - if (substdio_puts(subfdoutsmall,"46:Dsorry, I can't handle that recipient (#5.1.3),") == -1) - dropped(); - break; + + len = fmt_ulong(buf,len); + buf[len++] = ':'; + len += fmt_str(buf + len,result); + buf[len++] = ','; + + for (i = 0;i < failure.len;++i) + switch(failure.s[i]) { + case 0: + substdio_put(&ssout,buf,len); + break; + case 'D': + substdio_puts(&ssout,"66:Dsorry, that domain isn't in my list of allowed rcpthosts (#5.7.1),"); + break; + default: + substdio_puts(&ssout,"46:Dsorry, I can't handle that recipient (#5.1.3),"); + break; } - - /* subfdoutsmall will be flushed when we read from the network again */ + + /* ssout will be flushed when we read from the network again */ } } diff --git a/qmail-qstat.sh b/qmail-qstat.sh index 21a8c00..26a6d3f 100644 --- a/qmail-qstat.sh +++ b/qmail-qstat.sh @@ -1,3 +1,7 @@ cd QMAIL -echo messages in queue: `find queue/mess -type f -print | wc -l` -echo messages in queue but not yet preprocessed: `find queue/todo -type f -print | wc -l` +messdirs=`echo queue/mess/* | wc -w` +messfiles=`find queue/mess/* -print | wc -w` +tododirs=`echo queue/todo | wc -w` +todofiles=`find queue/todo -print | wc -w` +echo messages in queue: `expr $messfiles - $messdirs` +echo messages in queue but not yet preprocessed: `expr $todofiles - $tododirs` diff --git a/qmail-queue.8 b/qmail-queue.8 index 33ca546..12eea0c 100644 --- a/qmail-queue.8 +++ b/qmail-queue.8 @@ -25,7 +25,7 @@ sees end-of-file before the extra 0 byte, it aborts without placing the message into the queue. Every envelope recipient address -must contain a username, +should contain a username, an @ sign, and a fully qualified domain name. @@ -40,19 +40,116 @@ and does not enforce any restrictions on its contents. However, the recipients probably expect to see a proper header, as described in .BR qmail-header(5) . +.SH "FILESYSTEM RESTRICTIONS" +.B qmail-queue +imposes two constraints on the queue structure: +each +.B mess +subdirectory must be in the same filesystem as the +.B pid +directory; and each +.B todo +subdirectory must be in the same filesystem as the +.B intd +directory. .SH "EXIT CODES" -0 if .B qmail-queue -has successfully queued the message, -nonzero if +does not print diagnostics. +It exits +0 if +it has successfully queued the message. +It exits between 1 and 99 if +it has failed to queue the message. + +All .B qmail-queue -has failed to queue the message. +error codes between 11 and 40 +indicate permanent errors: +.TP 5 +.B 11 +Address too long. +.TP +.B 31 +Mail server permanently refuses to send the message to any recipients. +(Not used by +.BR qmail-queue , +but can be used by programs offering the same interface.) +.PP +All other .B qmail-queue -does not print diagnostics. +error codes indicate temporary errors: +.TP 5 +.B 51 +Out of memory. +.TP +.B 52 +Timeout. +.TP +.B 53 +Write error; e.g., disk full. +.TP +.B 54 +Unable to read the message or envelope. +.TP +.B 55 +Unable to read a configuration file. +(Not used by +.BR qmail-queue .) +.TP +.B 56 +Problem making a network connection from this host. +(Not used by +.BR qmail-queue .) +.TP +.B 61 +Problem with the qmail home directory. +.TP +.B 62 +Problem with the queue directory. +.TP +.B 63 +Problem with queue/pid. +.TP +.B 64 +Problem with queue/mess. +.TP +.B 65 +Problem with queue/intd. +.TP +.B 66 +Problem with queue/todo. +.TP +.B 71 +Mail server temporarily refuses to send the message to any recipients. +(Not used by +.BR qmail-queue .) +.TP +.B 72 +Connection to mail server timed out. +(Not used by +.BR qmail-queue .) +.TP +.B 73 +Connection to mail server rejected. +(Not used by +.BR qmail-queue .) +.TP +.B 74 +Connection to mail server succeeded, +but communication failed. +(Not used by +.BR qmail-queue .) +.TP +.B 81 +Internal bug; e.g., segmentation fault. +.TP +.B 91 +Envelope format error. .SH "SEE ALSO" addresses(5), envelopes(5), qmail-header(5), qmail-inject(8), +qmail-qmqpc(8), qmail-send(8), qmail-smtpd(8) diff --git a/qmail-queue.c b/qmail-queue.c index 26483b2..4b39a8f 100644 --- a/qmail-queue.c +++ b/qmail-queue.c @@ -55,10 +55,10 @@ void cleanup() } void die(e) int e; { _exit(e); } -void die_write() { cleanup(); die(122); } -void die_read() { cleanup(); die(121); } -void sigalrm() { /* thou shalt not clean up here */ die(124); } -void sigbug() { die(101); } +void die_write() { cleanup(); die(53); } +void die_read() { cleanup(); die(54); } +void sigalrm() { /* thou shalt not clean up here */ die(52); } +void sigbug() { die(81); } unsigned int receivedlen; char *received; @@ -93,7 +93,7 @@ void received_setup() { receivedlen = receivedfmt((char *) 0); received = alloc(receivedlen + 1); - if (!received) die(123); + if (!received) die(51); receivedfmt(received); } @@ -123,7 +123,7 @@ int flagsplit; char *s; s = alloc(fmtqfn((char *) 0,dirslash,messnum,flagsplit)); - if (!s) die(123); + if (!s) die(51); fmtqfn(s,dirslash,messnum,flagsplit); return s; } @@ -136,17 +136,17 @@ void pidopen() seq = 1; len = pidfmt((char *) 0,seq); pidfn = alloc(len); - if (!pidfn) die(123); + if (!pidfn) die(51); for (seq = 1;seq < 10;++seq) { - if (pidfmt((char *) 0,seq) > len) die(101); /* paranoia */ + if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */ pidfmt(pidfn,seq); messfd = open_excl(pidfn); if (messfd != -1) return; } - die(103); + die(63); } char tmp[FMT_ULONG]; @@ -158,8 +158,8 @@ void main() sig_blocknone(); umask(033); - if (chdir(auto_qmail) == -1) die(102); - if (chdir("queue") == -1) die(102); + if (chdir(auto_qmail) == -1) die(61); + if (chdir("queue") == -1) die(62); mypid = getpid(); uid = getuid(); @@ -176,15 +176,15 @@ void main() alarm(DEATH); pidopen(); - if (fstat(messfd,&pidst) == -1) die(104); + if (fstat(messfd,&pidst) == -1) die(63); messnum = pidst.st_ino; messfn = fnnum("mess/",1); todofn = fnnum("todo/",0); intdfn = fnnum("intd/",0); - if (link(pidfn,messfn) == -1) die(105); - if (unlink(pidfn) == -1) die(105); + if (link(pidfn,messfn) == -1) die(64); + if (unlink(pidfn) == -1) die(63); flagmademess = 1; substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf)); @@ -202,7 +202,7 @@ void main() if (fsync(messfd) == -1) die_write(); intdfd = open_excl(intdfn); - if (intdfd == -1) die(108); + if (intdfd == -1) die(65); flagmadeintd = 1; substdio_fdbuf(&ssout,write,intdfd,outbuf,sizeof(outbuf)); @@ -217,7 +217,7 @@ void main() if (substdio_bput(&ssout,"",1) == -1) die_write(); if (substdio_get(&ssin,&ch,1) < 1) die_read(); - if (ch != 'F') die(112); + if (ch != 'F') die(91); if (substdio_bput(&ssout,&ch,1) == -1) die_write(); for (len = 0;len < ADDR;++len) { @@ -225,7 +225,7 @@ void main() if (substdio_put(&ssout,&ch,1) == -1) die_write(); if (!ch) break; } - if (len >= ADDR) die(115); + if (len >= ADDR) die(11); if (substdio_bput(&ssout,QUEUE_EXTRA,QUEUE_EXTRALEN) == -1) die_write(); @@ -233,7 +233,7 @@ void main() { if (substdio_get(&ssin,&ch,1) < 1) die_read(); if (!ch) break; - if (ch != 'T') die(112); + if (ch != 'T') die(91); if (substdio_bput(&ssout,&ch,1) == -1) die_write(); for (len = 0;len < ADDR;++len) { @@ -241,13 +241,13 @@ void main() if (substdio_bput(&ssout,&ch,1) == -1) die_write(); if (!ch) break; } - if (len >= ADDR) die(115); + if (len >= ADDR) die(11); } if (substdio_flush(&ssout) == -1) die_write(); if (fsync(intdfd) == -1) die_write(); - if (link(intdfn,todofn) == -1) die(106); + if (link(intdfn,todofn) == -1) die(66); triggerpull(); die(0); diff --git a/qmail-remote.8 b/qmail-remote.8 index 552ac92..08bae85 100644 --- a/qmail-remote.8 +++ b/qmail-remote.8 @@ -142,8 +142,6 @@ had .I relay as its only MX. (It will also avoid doing any CNAME lookups on -.I sender -and .IR recip .) .I host may include a colon and a port number to use instead of the @@ -203,4 +201,5 @@ envelopes(5), qmail-control(5), qmail-send(8), qmail-smtpd(8), +qmail-tcpok(8), qmail-tcpto(8) diff --git a/qmail-remote.c b/qmail-remote.c index 4495b69..7d65473 100644 --- a/qmail-remote.c +++ b/qmail-remote.c @@ -3,7 +3,6 @@ #include #include #include "sig.h" -#include "getln.h" #include "stralloc.h" #include "substdio.h" #include "subfd.h" @@ -25,6 +24,7 @@ #include "exit.h" #include "constmap.h" #include "tcpto.h" +#include "readwrite.h" #include "timeoutconn.h" #include "timeoutread.h" #include "timeoutwrite.h" @@ -48,14 +48,13 @@ saa reciplist = {0}; struct ip_address partner; -void out(s) char *s; { if (substdio_puts(subfdout,s) == -1) _exit(0); } -void zero() { if (substdio_put(subfdout,"\0",1) == -1) _exit(0); } -void zerodie() { zero(); substdio_flush(subfdout); _exit(0); } - +void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } +void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } +void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); } void outsafe(sa) stralloc *sa; { int i; char ch; for (i = 0;i < sa->len;++i) { ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; -if (substdio_put(subfdout,&ch,1) == -1) _exit(0); } } +if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } void temp_oserr() { out("Z\ @@ -87,251 +86,191 @@ Sorry. Although I'm listed as a best-preference MX or A for that host,\n\ it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n"); zerodie(); } -int timeout = 1200; +void outhost() +{ + char x[IPFMT]; + if (substdio_put(subfdoutsmall,x,ip_fmt(x,&partner)) == -1) _exit(0); +} + +int flagcritical = 0; + +void dropped() { + out("ZConnected to "); + outhost(); + out(" but connection died. "); + if (flagcritical) out("Possible duplicate! "); + out("(#4.4.2)\n"); + zerodie(); +} + int timeoutconnect = 60; +int smtpfd; +int timeout = 1200; -void getcontrols() +int saferead(fd,buf,len) int fd; char *buf; int len; { - int r; - if (control_init() == -1) - { if (errno == error_nomem) temp_nomem(); temp_control(); } - - if (control_readint(&timeout,"control/timeoutremote") == -1) - { if (errno == error_nomem) temp_nomem(); temp_control(); } - if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1) - { if (errno == error_nomem) temp_nomem(); temp_control(); } - - r = control_rldef(&helohost,"control/helohost",1,(char *) 0); - if (r == -1) if (errno == error_nomem) temp_nomem(); - if (r != 1) temp_control(); - - switch(control_readfile(&routes,"control/smtproutes",0)) - { - case -1: - if (errno == error_nomem) temp_nomem(); temp_control(); - case 0: - if (!constmap_init(&maproutes,"",0,1)) temp_nomem(); break; - case 1: - if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break; - } + int r; + r = timeoutread(timeout,smtpfd,buf,len); + if (r <= 0) dropped(); + return r; +} +int safewrite(fd,buf,len) int fd; char *buf; int len; +{ + int r; + r = timeoutwrite(timeout,smtpfd,buf,len); + if (r <= 0) dropped(); + return r; } +char inbuf[1024]; +substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); char smtptobuf[1024]; +substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf); char smtpfrombuf[128]; -stralloc smtpline = {0}; +substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf); + stralloc smtptext = {0}; -void outsmtptext() +void get(ch) +char *ch; { - int i; - if (smtptext.s) if (smtptext.len) if (smtptext.len < HUGESMTPTEXT) - { - if (substdio_puts(subfdout,"Remote host said: ") == -1) _exit(0); - for (i = 0;i < smtptext.len;++i) - if (!smtptext.s[i]) smtptext.s[i] = '?'; - if (substdio_put(subfdout,smtptext.s,smtptext.len) == -1) _exit(0); - smtptext.len = 0; - } + substdio_get(&smtpfrom,ch,1); + if (*ch != '\r') + if (smtptext.len < HUGESMTPTEXT) + if (!stralloc_append(&smtptext,ch)) temp_nomem(); } -unsigned long smtpcode(ss) -substdio *ss; +unsigned long smtpcode() { - int match; - unsigned long code; - - if (!stralloc_copys(&smtptext,"")) return 421; - do - { - if (getln(ss,&smtpline,&match,'\n') != 0) return 421; - if (!match) return 421; - if ((smtpline.len >= 2) && (smtpline.s[smtpline.len - 2] == '\r')) - { - smtpline.s[smtpline.len - 2] = '\n'; - --smtpline.len; - } - if (!stralloc_cat(&smtptext,&smtpline)) return 421; - if (scan_nbblong(smtpline.s,smtpline.len,10,0,&code) != 3) return 421; - if (smtpline.len == 3) return code; + unsigned char ch; + unsigned long code; + + if (!stralloc_copys(&smtptext,"")) temp_nomem(); + + get(&ch); code = ch - '0'; + get(&ch); code = code * 10 + (ch - '0'); + get(&ch); code = code * 10 + (ch - '0'); + for (;;) { + get(&ch); + if (ch != '-') break; + while (ch != '\n') get(&ch); + get(&ch); + get(&ch); + get(&ch); } - while (smtpline.s[3] == '-'); + while (ch != '\n') get(&ch); - return code; + return code; } -void outhost() -{ - char x[IPFMT]; - - x[ip_fmt(x,&partner)] = 0; - out(x); -} - -void writeerr() +void outsmtptext() { - out("ZConnected to "); outhost(); - out(" but communications failed. (#4.4.2)\n"); - zerodie(); + int i; + if (smtptext.s) if (smtptext.len) { + out("Remote host said: "); + for (i = 0;i < smtptext.len;++i) + if (!smtptext.s[i]) smtptext.s[i] = '?'; + if (substdio_put(subfdoutsmall,smtptext.s,smtptext.len) == -1) _exit(0); + smtptext.len = 0; + } } -void quit(ssto,ssfrom) -substdio *ssto; -substdio *ssfrom; +void quit(prepend,append) +char *prepend; +char *append; { - outsmtptext(); - if (substdio_putsflush(ssto,"QUIT\r\n") != -1) - smtpcode(ssfrom); /* protocol design stupidity */ - zerodie(); + substdio_putsflush(&smtpto,"QUIT\r\n"); + /* waiting for remote side is just too ridiculous */ + out(prepend); + outhost(); + out(append); + out(".\n"); + outsmtptext(); + zerodie(); } -stralloc dataline = {0}; - -void blast(ssto,ssfrom) -substdio *ssto; -substdio *ssfrom; +void blast() { - int match; - - for (;;) - { - if (getln(ssfrom,&dataline,&match,'\n') != 0) temp_read(); - if (!match && !dataline.len) break; - if (!match) perm_partialline(); - --dataline.len; - if (dataline.len && (dataline.s[0] == '.')) - if (substdio_put(ssto,".",1) == -1) writeerr(); - if (substdio_put(ssto,dataline.s,dataline.len) == -1) writeerr(); - if (substdio_put(ssto,"\r\n",2) == -1) writeerr(); + int r; + char ch; + + for (;;) { + r = substdio_get(&ssin,&ch,1); + if (r == 0) break; + if (r == -1) temp_read(); + if (ch == '.') + substdio_put(&smtpto,".",1); + while (ch != '\n') { + substdio_put(&smtpto,&ch,1); + r = substdio_get(&ssin,&ch,1); + if (r == 0) perm_partialline(); + if (r == -1) temp_read(); + } + substdio_put(&smtpto,"\r\n",2); } - if (substdio_put(ssto,".\r\n",3) == -1) writeerr(); - if (substdio_flush(ssto) == -1) writeerr(); + + flagcritical = 1; + substdio_put(&smtpto,".\r\n",3); + substdio_flush(&smtpto); } stralloc recip = {0}; -void smtp(fd) -int fd; +void smtp() { - substdio ssto; - substdio ssfrom; - unsigned long code; - int flaganyrecipok; - int i; - - substdio_fdbuf(&ssto,timeoutwrite,TIMEOUTWRITE(timeout,fd),smtptobuf,sizeof(smtptobuf)); - substdio_fdbuf(&ssfrom,timeoutread,TIMEOUTREAD(timeout,fd),smtpfrombuf,sizeof(smtpfrombuf)); - - if (smtpcode(&ssfrom) != 220) - { - out("ZConnected to "); outhost(); out(" but greeting failed.\n"); - quit(&ssto,&ssfrom); - } - - if (substdio_puts(&ssto,"HELO ") == -1) writeerr(); - if (substdio_put(&ssto,helohost.s,helohost.len) == -1) writeerr(); - if (substdio_puts(&ssto,"\r\n") == -1) writeerr(); - if (substdio_flush(&ssto) == -1) writeerr(); - - if (smtpcode(&ssfrom) != 250) - { - out("ZConnected to "); outhost(); out(" but my name was rejected.\n"); - quit(&ssto,&ssfrom); - } - - if (substdio_puts(&ssto,"MAIL FROM:<") == -1) writeerr(); - if (substdio_put(&ssto,sender.s,sender.len) == -1) writeerr(); - if (substdio_puts(&ssto,">\r\n") == -1) writeerr(); - if (substdio_flush(&ssto) == -1) writeerr(); - - code = smtpcode(&ssfrom); - if (code >= 500) - { - out("DConnected to "); outhost(); out(" but sender was rejected.\n"); - quit(&ssto,&ssfrom); - } - if (code >= 400) - { - out("ZConnected to "); outhost(); out(" but sender was rejected.\n"); - quit(&ssto,&ssfrom); - } - - flaganyrecipok = 0; - for (i = 0;i < reciplist.len;++i) - { - if (substdio_puts(&ssto,"RCPT TO:<") == -1) writeerr(); - if (substdio_put(&ssto,reciplist.sa[i].s,reciplist.sa[i].len) == -1) writeerr(); - if (substdio_puts(&ssto,">\r\n") == -1) writeerr(); - if (substdio_flush(&ssto) == -1) writeerr(); - - code = smtpcode(&ssfrom); - if (code == 421) - { - out("ZConnected to "); outhost(); out(" but connection died.\n"); - quit(&ssto,&ssfrom); - } - if (code >= 500) - { - out("h"); outhost(); out(" does not like recipient.\n"); - outsmtptext(); zero(); + unsigned long code; + int flagbother; + int i; + + if (smtpcode() != 220) quit("ZConnected to "," but greeting failed"); + + substdio_puts(&smtpto,"HELO "); + substdio_put(&smtpto,helohost.s,helohost.len); + substdio_puts(&smtpto,"\r\n"); + substdio_flush(&smtpto); + if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected"); + + substdio_puts(&smtpto,"MAIL FROM:<"); + substdio_put(&smtpto,sender.s,sender.len); + substdio_puts(&smtpto,">\r\n"); + substdio_flush(&smtpto); + code = smtpcode(); + if (code >= 500) quit("DConnected to "," but sender was rejected"); + if (code >= 400) quit("ZConnected to "," but sender was rejected"); + + flagbother = 0; + for (i = 0;i < reciplist.len;++i) { + substdio_puts(&smtpto,"RCPT TO:<"); + substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len); + substdio_puts(&smtpto,">\r\n"); + substdio_flush(&smtpto); + code = smtpcode(); + if (code >= 500) { + out("h"); outhost(); out(" does not like recipient.\n"); + outsmtptext(); zero(); } - else if (code >= 400) - { - out("s"); outhost(); out(" does not like recipient.\n"); - outsmtptext(); zero(); + else if (code >= 400) { + out("s"); outhost(); out(" does not like recipient.\n"); + outsmtptext(); zero(); } - else - { - out("r"); zero(); - flaganyrecipok = 1; + else { + out("r"); zero(); + flagbother = 1; } } - - if (!flaganyrecipok) - { - out("DGiving up.\n"); - quit(&ssto,&ssfrom); - } - - if (substdio_putsflush(&ssto,"DATA\r\n") == -1) writeerr(); - - code = smtpcode(&ssfrom); - if (code == 421) - { - out("ZConnected to "); outhost(); out(" but connection died.\n"); - quit(&ssto,&ssfrom); - } - if (code >= 500) - { - out("D"); outhost(); out(" failed on DATA command.\n"); - quit(&ssto,&ssfrom); - } - if (code >= 400) - { - out("Z"); outhost(); out(" failed on DATA command.\n"); - quit(&ssto,&ssfrom); - } - - blast(&ssto,subfdin); - - code = smtpcode(&ssfrom); - if (code == 421) - { - out("ZConnected to "); outhost(); out(" but connection died. Possible duplicate!\n"); - quit(&ssto,&ssfrom); - } - if (code >= 500) - { - out("D"); outhost(); out(" failed after I sent the message.\n"); - quit(&ssto,&ssfrom); - } - if (code >= 400) - { - out("Z"); outhost(); out(" failed after I sent the message.\n"); - quit(&ssto,&ssfrom); - } - - out("K"); outhost(); out(" accepted message.\n"); - quit(&ssto,&ssfrom); + if (!flagbother) quit("DGiving up on ",""); + + substdio_putsflush(&smtpto,"DATA\r\n"); + code = smtpcode(); + if (code >= 500) quit("D"," failed on DATA command"); + if (code >= 400) quit("Z"," failed on DATA command"); + + blast(); + code = smtpcode(); + flagcritical = 0; + if (code >= 500) quit("D"," failed after I sent the message"); + if (code >= 400) quit("Z"," failed after I sent the message"); + quit("K"," accepted message"); } stralloc canonhost = {0}; @@ -343,138 +282,146 @@ char *s; int *flagalias; int flagcname; { - int j; - - *flagalias = flagcname; - - j = str_rchr(s,'@'); - if (!s[j]) - { - if (!stralloc_copys(saout,s)) temp_nomem(); - return; + int j; + + *flagalias = flagcname; + + j = str_rchr(s,'@'); + if (!s[j]) { + if (!stralloc_copys(saout,s)) temp_nomem(); + return; } - if (!stralloc_copys(&canonbox,s)) temp_nomem(); - canonbox.len = j; - if (!quote(saout,&canonbox)) temp_nomem(); - if (!stralloc_cats(saout,"@")) temp_nomem(); - - if (!stralloc_copys(&canonhost,s + j + 1)) temp_nomem(); - if (flagcname) - switch(dns_cname(&canonhost)) - { - case 0: *flagalias = 0; break; - case DNS_MEM: temp_nomem(); - case DNS_SOFT: temp_dnscanon(); - case DNS_HARD: ; /* alias loop, not our problem */ + if (!stralloc_copys(&canonbox,s)) temp_nomem(); + canonbox.len = j; + if (!quote(saout,&canonbox)) temp_nomem(); + if (!stralloc_cats(saout,"@")) temp_nomem(); + + if (!stralloc_copys(&canonhost,s + j + 1)) temp_nomem(); + if (flagcname) + switch(dns_cname(&canonhost)) { + case 0: *flagalias = 0; break; + case DNS_MEM: temp_nomem(); + case DNS_SOFT: temp_dnscanon(); + case DNS_HARD: ; /* alias loop, not our problem */ } - if (!stralloc_cat(saout,&canonhost)) temp_nomem(); + if (!stralloc_cat(saout,&canonhost)) temp_nomem(); +} + +void getcontrols() +{ + if (control_init() == -1) temp_control(); + if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control(); + if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1) + temp_control(); + if (control_rldef(&helohost,"control/helohost",1,(char *) 0) != 1) + temp_control(); + switch(control_readfile(&routes,"control/smtproutes",0)) { + case -1: + temp_control(); + case 0: + if (!constmap_init(&maproutes,"",0,1)) temp_nomem(); break; + case 1: + if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break; + } } void main(argc,argv) int argc; char **argv; { - static ipalloc ip = {0}; - int i; - unsigned long random; - char **recips; - unsigned long prefme; - int flagallaliases; - int flagalias; - char *relayhost; - - sig_pipeignore(); - if (argc < 4) perm_usage(); - if (chdir(auto_qmail) == -1) temp_chdir(); - getcontrols(); - - - if (!stralloc_copys(&host,argv[1])) temp_nomem(); - - relayhost = 0; - for (i = 0;i <= host.len;++i) - if ((i == 0) || (i == host.len) || (host.s[i] == '.')) - if (relayhost = constmap(&maproutes,host.s + i,host.len - i)) - break; - if (relayhost && !*relayhost) relayhost = 0; - - if (relayhost) - { - i = str_chr(relayhost,':'); - if (relayhost[i]) - { - scan_ulong(relayhost + i + 1,&port); - relayhost[i] = 0; + static ipalloc ip = {0}; + int i; + unsigned long random; + char **recips; + unsigned long prefme; + int flagallaliases; + int flagalias; + char *relayhost; + + sig_pipeignore(); + if (argc < 4) perm_usage(); + if (chdir(auto_qmail) == -1) temp_chdir(); + getcontrols(); + + + if (!stralloc_copys(&host,argv[1])) temp_nomem(); + + relayhost = 0; + for (i = 0;i <= host.len;++i) + if ((i == 0) || (i == host.len) || (host.s[i] == '.')) + if (relayhost = constmap(&maproutes,host.s + i,host.len - i)) + break; + if (relayhost && !*relayhost) relayhost = 0; + + if (relayhost) { + i = str_chr(relayhost,':'); + if (relayhost[i]) { + scan_ulong(relayhost + i + 1,&port); + relayhost[i] = 0; } - if (!stralloc_copys(&host,relayhost)) temp_nomem(); + if (!stralloc_copys(&host,relayhost)) temp_nomem(); } - addrmangle(&sender,argv[2],&flagalias,!relayhost); - - if (!saa_readyplus(&reciplist,0)) temp_nomem(); - if (ipme_init() != 1) temp_oserr(); - - flagallaliases = 1; - recips = argv + 3; - while (*recips) - { - if (!saa_readyplus(&reciplist,1)) temp_nomem(); - reciplist.sa[reciplist.len] = sauninit; - addrmangle(reciplist.sa + reciplist.len,*recips,&flagalias,!relayhost); - if (!flagalias) flagallaliases = 0; - ++reciplist.len; - ++recips; + addrmangle(&sender,argv[2],&flagalias,0); + + if (!saa_readyplus(&reciplist,0)) temp_nomem(); + if (ipme_init() != 1) temp_oserr(); + + flagallaliases = 1; + recips = argv + 3; + while (*recips) { + if (!saa_readyplus(&reciplist,1)) temp_nomem(); + reciplist.sa[reciplist.len] = sauninit; + addrmangle(reciplist.sa + reciplist.len,*recips,&flagalias,!relayhost); + if (!flagalias) flagallaliases = 0; + ++reciplist.len; + ++recips; } - - random = now() + (getpid() << 16); - switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) - { - case DNS_MEM: temp_nomem(); - case DNS_SOFT: temp_dns(); - case DNS_HARD: perm_dns(); - case 1: - if (ip.len <= 0) temp_dns(); + + random = now() + (getpid() << 16); + switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) { + case DNS_MEM: temp_nomem(); + case DNS_SOFT: temp_dns(); + case DNS_HARD: perm_dns(); + case 1: + if (ip.len <= 0) temp_dns(); } - - if (ip.len <= 0) perm_nomx(); - - prefme = 100000; - for (i = 0;i < ip.len;++i) - if (ipme_is(&ip.ix[i].ip)) - if (ip.ix[i].pref < prefme) - prefme = ip.ix[i].pref; - - if (relayhost) prefme = 300000; - if (flagallaliases) prefme = 500000; - - for (i = 0;i < ip.len;++i) - if (ip.ix[i].pref < prefme) - break; - - if (i >= ip.len) - perm_ambigmx(); - - for (i = 0;i < ip.len;++i) if (ip.ix[i].pref < prefme) - { - int s; - - if (tcpto(&ip.ix[i].ip)) continue; - - s = socket(AF_INET,SOCK_STREAM,0); - if (s == -1) temp_oserr(); - - if (timeoutconn(s,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) - { - tcpto_err(&ip.ix[i].ip,0); - partner = ip.ix[i].ip; - smtp(s); /* does not return */ + + if (ip.len <= 0) perm_nomx(); + + prefme = 100000; + for (i = 0;i < ip.len;++i) + if (ipme_is(&ip.ix[i].ip)) + if (ip.ix[i].pref < prefme) + prefme = ip.ix[i].pref; + + if (relayhost) prefme = 300000; + if (flagallaliases) prefme = 500000; + + for (i = 0;i < ip.len;++i) + if (ip.ix[i].pref < prefme) + break; + + if (i >= ip.len) + perm_ambigmx(); + + for (i = 0;i < ip.len;++i) if (ip.ix[i].pref < prefme) { + if (tcpto(&ip.ix[i].ip)) continue; + + smtpfd = socket(AF_INET,SOCK_STREAM,0); + if (smtpfd == -1) temp_oserr(); + + if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) { + tcpto_err(&ip.ix[i].ip,0); + partner = ip.ix[i].ip; + smtp(); /* does not return */ } - tcpto_err(&ip.ix[i].ip,errno == error_timeout); - close(s); + tcpto_err(&ip.ix[i].ip,errno == error_timeout); + close(smtpfd); } - - temp_noconn(); + + temp_noconn(); } diff --git a/qmail-send.9 b/qmail-send.9 index 3be8602..acb04d0 100644 --- a/qmail-send.9 +++ b/qmail-send.9 @@ -164,7 +164,7 @@ so the percent hack may be applied repeatedly. handles .I percenthack before -.IR recipientmap . +.IR locals . .TP 5 .I queuelifetime Number of seconds @@ -176,42 +176,23 @@ will try the message once more, but it will treat any temporary delivery failures as permanent failures. .TP 5 -.I recipientmap -List of redirections, one per line. -Each redirection has the form -.IR recipient\fB:\fIrewritten , -without any extra spaces. -When -.B qmail-send -sees the address -.IR recipient , -it replaces it with -.IR rewritten . -Both -.I recipient -and -.I rewritten -must include domain names. -.B qmail-send -handles -.I recipientmap -before -.IR locals . -.TP 5 .I virtualdomains -List of virtual domains, one per line. -Each virtual domain has the form -.IR domain\fB:\fIprepend , +List of virtual users or domains, one per line. +A virtual user has the form +.IR user\fB@\fIdomain\fB:\fIprepend , without any extra spaces. When .B qmail-send -sees a recipient address at -.IR domain , -say +sees the recipient address .IR user\fB@\fIdomain , it converts it to .I prepend\fB-\fIuser\fB@\fIdomain and treats it as local. + +A virtual domain has the form +.IR domain\fB:\fIprepend . +It applies to any recipient address at +.IR domain . For example, if .EX @@ -226,6 +207,7 @@ and a message arrives for will rewrite the recipient address as .B joeBREAKfoo-info@nowhere.mil and deliver the message locally. + .I virtualdomains may contain wildcards: diff --git a/qmail-send.c b/qmail-send.c index 5f1d1cd..c31b522 100644 --- a/qmail-send.c +++ b/qmail-send.c @@ -48,8 +48,6 @@ stralloc percenthack = {0}; struct constmap mappercenthack; stralloc locals = {0}; struct constmap maplocals; -stralloc redir = {0}; -struct constmap mapredir; stralloc vdoms = {0}; struct constmap mapvdoms; stralloc envnoathost = {0}; @@ -63,10 +61,7 @@ char strnum3[FMT_ULONG]; #define CHANNELS 2 char *chanaddr[CHANNELS] = { "local/", "remote/" }; -char *channodelmsg[CHANNELS] = { - "local deliveries will be put on hold\n" -, "remote deliveries will be put on hold\n" -}; +char *chanstatusmsg[CHANNELS] = { " local ", " remote " }; char *tochan[CHANNELS] = { " to local ", " to remote " }; int chanfdout[CHANNELS] = { 1, 3 }; int chanfdin[CHANNELS] = { 2, 4 }; @@ -124,7 +119,7 @@ char *recip; int j; char *x; static stralloc addr = {0}; - static stralloc domain = {0}; + int at; if (!stralloc_copys(&rwline,"T")) return 0; if (!stralloc_copys(&addr,recip)) return 0; @@ -143,38 +138,26 @@ char *recip; addr.s[i] = '@'; } - if (x = constmap(&mapredir,addr.s,addr.len)) - if (x[str_chr(x,'@')]) - if (!stralloc_copys(&addr,x)) return 0; + at = byte_rchr(addr.s,addr.len,'@'); - i = byte_rchr(addr.s,addr.len,'@'); - if (!stralloc_copyb(&domain,addr.s + i + 1,addr.len - i - 1)) return 0; - addr.len = i; - - if (constmap(&maplocals,domain.s,domain.len)) { + if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) { if (!stralloc_cat(&rwline,&addr)) return 0; - if (!stralloc_cats(&rwline,"@")) return 0; - if (!stralloc_cat(&rwline,&domain)) return 0; if (!stralloc_0(&rwline)) return 0; return 1; } - for (i = 0;i <= domain.len;++i) - if ((i == 0) || (i == domain.len) || (domain.s[i] == '.')) - if (x = constmap(&mapvdoms,domain.s + i,domain.len - i)) { + for (i = 0;i <= addr.len;++i) + if (!i || (i == at + 1) || (i == addr.len) || ((i > at) && (addr.s[i] == '.'))) + if (x = constmap(&mapvdoms,addr.s + i,addr.len - i)) { if (!*x) break; if (!stralloc_cats(&rwline,x)) return 0; if (!stralloc_cats(&rwline,"-")) return 0; if (!stralloc_cat(&rwline,&addr)) return 0; - if (!stralloc_cats(&rwline,"@")) return 0; - if (!stralloc_cat(&rwline,&domain)) return 0; if (!stralloc_0(&rwline)) return 0; return 1; } if (!stralloc_cat(&rwline,&addr)) return 0; - if (!stralloc_cats(&rwline,"@")) return 0; - if (!stralloc_cat(&rwline,&domain)) return 0; if (!stralloc_0(&rwline)) return 0; return 2; } @@ -767,7 +750,7 @@ I tried to deliver a bounce message to this address, but the bounce bounced!\n\ qmail_from(&qqt,bouncesender); qmail_to(&qqt,bouncerecip); - if (qmail_close(&qqt)) + if (*qmail_close(&qqt)) { log1("warning: trouble injecting bounce message, will try later\n"); return 0; } strnum2[fmt_ulong(strnum2,id)] = 0; @@ -798,10 +781,26 @@ struct del unsigned long masterdelid = 1; unsigned int concurrency[CHANNELS] = { 10, 20 }; +unsigned int concurrencyused[CHANNELS] = { 0, 0 }; struct del *d[CHANNELS]; stralloc dline[CHANNELS]; char delbuf[2048]; +void del_status() +{ + int c; + + log1("status:"); + for (c = 0;c < CHANNELS;++c) { + strnum2[fmt_ulong(strnum2,(unsigned long) concurrencyused[c])] = 0; + strnum3[fmt_ulong(strnum3,(unsigned long) concurrency[c])] = 0; + log2(chanstatusmsg[c],strnum2); + log2("/",strnum3); + } + if (flagexitasap) log1(" exitasap"); + log1("\n"); +} + void del_init() { int c; @@ -816,49 +815,22 @@ void del_init() dline[c].s = 0; while (!stralloc_copys(&dline[c],"")) nomem(); } + del_status(); } int del_canexit() { - int i; int c; for (c = 0;c < CHANNELS;++c) if (flagspawnalive[c]) /* if dead, nothing we can do about its jobs */ - for (i = 0;i < concurrency[c];++i) - if (d[c][i].used) return 0; + if (concurrencyused[c]) return 0; return 1; } -static int del_lastsaid = 0; - -void del_saywhynoexit() -{ - int i; - int c; - int n; - n = 0; - for (c = 0;c < CHANNELS;++c) - if (flagspawnalive[c]) - for (i = 0;i < concurrency[c];++i) - if (d[c][i].used) - ++n; - if (!del_lastsaid || (n < del_lastsaid)) - { - strnum2[fmt_ulong(strnum2,(unsigned long) n)] = 0; - log3("number of deliveries left before exiting: ",strnum2,"\n"); - del_lastsaid = n; - } -} - int del_avail(c) int c; { - int i; - - if (!flagspawnalive[c]) return 0; - if (!comm_canwrite(c)) return 0; - for (i = 0;i < concurrency[c];++i) if (!d[c][i].used) return 1; - return 0; + return flagspawnalive[c] && comm_canwrite(c) && (concurrencyused[c] < concurrency[c]); } void del_start(j,mpos,recip) @@ -881,7 +853,7 @@ char *recip; d[c][i].j = j; ++jo[j].refs; d[c][i].delid = masterdelid++; d[c][i].mpos = mpos; - d[c][i].used = 1; + d[c][i].used = 1; ++concurrencyused[c]; comm_write(c,i,jo[j].id,jo[j].sender.s,recip); @@ -891,6 +863,7 @@ char *recip; log3(": msg ",strnum3,tochan[c]); logsafe(recip); log1("\n"); + del_status(); } void markdone(c,id,pos) @@ -975,7 +948,8 @@ int c; log3("delivery ",strnum3,": report mangled, will defer\n"); } job_close(d[c][delnum].j); - d[c][delnum].used = 0; + d[c][delnum].used = 0; --concurrencyused[c]; + del_status(); } dline[c].len = 0; } @@ -1487,12 +1461,6 @@ int getcontrols() { if (control_init() == -1) return 0; case 0: if (!constmap_init(&mappercenthack,"",0,0)) return 0; break; case 1: if (!constmap_init(&mappercenthack,percenthack.s,percenthack.len,0)) return 0; break; } - switch(control_readfile(&redir,"control/recipientmap",0)) - { - case -1: return 0; - case 0: if (!constmap_init(&mapredir,"",0,1)) return 0; break; - case 1: if (!constmap_init(&mapredir,redir.s,redir.len,1)) return 0; break; - } switch(control_readfile(&vdoms,"control/virtualdomains",0)) { case -1: return 0; @@ -1589,14 +1557,8 @@ void main() numjobs += concurrency[c]; } - log1("running\n"); - fnmake_init(); - for (c = 0;c < CHANNELS;++c) - if (!concurrency[c]) - log1(channodelmsg[c]); - comm_init(); pqstart(); @@ -1608,8 +1570,6 @@ void main() while (!flagexitasap || !del_canexit()) { - if (flagexitasap) del_saywhynoexit(); - recent = now(); if (flagrunasap) { flagrunasap = 0; pqrun(); } @@ -1647,6 +1607,6 @@ void main() } } pqfinish(); - log1("exiting\n"); + log1("status: exiting\n"); _exit(0); } diff --git a/qmail-showctl.c b/qmail-showctl.c index 5134ebc..a24aa63 100644 --- a/qmail-showctl.c +++ b/qmail-showctl.c @@ -1,3 +1,5 @@ +#include +#include #include "substdio.h" #include "subfd.h" #include "exit.h" @@ -7,7 +9,12 @@ #include "constmap.h" #include "stralloc.h" #include "direntry.h" +#include "auto_uids.h" #include "auto_qmail.h" +#include "auto_break.h" +#include "auto_patrn.h" +#include "auto_spawn.h" +#include "auto_split.h" stralloc me = {0}; int meok; @@ -93,7 +100,7 @@ char *pre; } } -void do_lst(fn,def,pre,post) +int do_lst(fn,def,pre,post) char *fn; char *def; char *pre; @@ -110,7 +117,7 @@ char *post; substdio_puts(subfdout,"(Default.) "); substdio_puts(subfdout,def); substdio_puts(subfdout,"\n"); - break; + return 0; case 1: substdio_puts(subfdout,"\n"); i = 0; @@ -122,10 +129,10 @@ char *post; substdio_puts(subfdout,"\n"); i = j + 1; } - break; + return 1; default: substdio_puts(subfdout,"Oops! Trouble reading this file.\n"); - break; + return -1; } } @@ -133,10 +140,52 @@ void main() { DIR *dir; direntry *d; + struct stat stmrh; + struct stat stmrhcdb; - substdio_puts(subfdout,"The qmail control files are stored in "); + substdio_puts(subfdout,"qmail home directory: "); substdio_puts(subfdout,auto_qmail); - substdio_puts(subfdout,"/control.\n"); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"user-ext delimiter: "); + substdio_puts(subfdout,auto_break); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"paternalism (in decimal): "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_patrn)); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"silent concurrency limit: "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_spawn)); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"subdirectory split: "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_split)); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"user ids: "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uida)); + substdio_puts(subfdout,", "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidd)); + substdio_puts(subfdout,", "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidl)); + substdio_puts(subfdout,", "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uido)); + substdio_puts(subfdout,", "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidp)); + substdio_puts(subfdout,", "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidq)); + substdio_puts(subfdout,", "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidr)); + substdio_puts(subfdout,", "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uids)); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"group ids: "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_gidn)); + substdio_puts(subfdout,", "); + substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_gidq)); + substdio_puts(subfdout,".\n"); if (chdir(auto_qmail) == -1) { substdio_puts(subfdout,"Oops! Unable to chdir to "); @@ -170,6 +219,7 @@ void main() do_str("bouncehost",1,"bouncehost","Bounce host name is "); do_int("concurrencylocal","10","Local concurrency is ",""); do_int("concurrencyremote","20","Remote concurrency is ",""); + do_int("databytes","0","SMTP DATA limit is "," bytes"); do_str("defaultdomain",1,"defaultdomain","Default domain name is "); do_str("defaulthost",1,"defaulthost","Default host name is "); do_str("doublebouncehost",1,"doublebouncehost","2B recipient host: "); @@ -182,9 +232,29 @@ void main() do_str("me",0,"undefined! Uh-oh","My name is "); do_lst("percenthack","The percent hack is not allowed.","The percent hack is allowed for user%host@","."); do_str("plusdomain",1,"plusdomain","Plus domain name is "); + do_lst("qmqpservers","No QMQP servers.","QMQP server: ","."); do_int("queuelifetime","604800","Message lifetime in the queue is "," seconds"); - do_lst("rcpthosts","SMTP clients may send messages to any recipient.","SMTP clients may send messages to recipients at ","."); - do_lst("recipientmap","No redirections.","Redirection: ",""); + + if (do_lst("rcpthosts","SMTP clients may send messages to any recipient.","SMTP clients may send messages to recipients at ",".")) + do_lst("morercpthosts","No effect.","SMTP clients may send messages to recipients at ","."); + else + do_lst("morercpthosts","No rcpthosts; morercpthosts is irrelevant.","No rcpthosts; doesn't matter that morercpthosts has ","."); + /* XXX: check morercpthosts.cdb contents */ + substdio_puts(subfdout,"\nmorercpthosts.cdb: "); + if (stat("morercpthosts",&stmrh) == -1) + if (stat("morercpthosts.cdb",&stmrhcdb) == -1) + substdio_puts(subfdout,"(Default.) No effect.\n"); + else + substdio_puts(subfdout,"Oops! morercpthosts.cdb exists but morercpthosts doesn't.\n"); + else + if (stat("morercpthosts.cdb",&stmrhcdb) == -1) + substdio_puts(subfdout,"Oops! morercpthosts exists but morercpthosts.cdb doesn't.\n"); + else + if (stmrh.st_mtime > stmrhcdb.st_mtime) + substdio_puts(subfdout,"Oops! morercpthosts.cdb is older than morercpthosts.\n"); + else + substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n"); + do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 "); do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ",""); do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds"); @@ -202,6 +272,7 @@ void main() if (str_equal(d->d_name,"bouncehost")) continue; if (str_equal(d->d_name,"concurrencylocal")) continue; if (str_equal(d->d_name,"concurrencyremote")) continue; + if (str_equal(d->d_name,"databytes")) continue; if (str_equal(d->d_name,"defaultdomain")) continue; if (str_equal(d->d_name,"defaulthost")) continue; if (str_equal(d->d_name,"doublebouncehost")) continue; @@ -212,11 +283,13 @@ void main() if (str_equal(d->d_name,"localiphost")) continue; if (str_equal(d->d_name,"locals")) continue; if (str_equal(d->d_name,"me")) continue; + if (str_equal(d->d_name,"morercpthosts")) continue; + if (str_equal(d->d_name,"morercpthosts.cdb")) continue; if (str_equal(d->d_name,"percenthack")) continue; if (str_equal(d->d_name,"plusdomain")) continue; + if (str_equal(d->d_name,"qmqpservers")) continue; if (str_equal(d->d_name,"queuelifetime")) continue; if (str_equal(d->d_name,"rcpthosts")) continue; - if (str_equal(d->d_name,"recipientmap")) continue; if (str_equal(d->d_name,"smtpgreeting")) continue; if (str_equal(d->d_name,"smtproutes")) continue; if (str_equal(d->d_name,"timeoutconnect")) continue; diff --git a/qmail-smtpd.8 b/qmail-smtpd.8 index f1cb4a2..c4640b8 100644 --- a/qmail-smtpd.8 +++ b/qmail-smtpd.8 @@ -28,6 +28,9 @@ supports ESMTP, including the 8BITMIME and PIPELINING options. .B qmail-smtpd converts the SMTP newline convention into the UNIX newline convention by converting CR LF into LF. +It returns a temporary error and drops the connection on bare LFs; +see +.BR http://pobox.com/~djb/docs/smtplf.html . .B qmail-smtpd accepts messages that contain long lines or non-ASCII characters, @@ -47,6 +50,33 @@ may be of the form meaning every address at .IR host . .TP 5 +.I databytes +Maximum number of bytes allowed in a message, +or 0 for no limit. +Default: 0. +If a message exceeds this limit, +.B qmail-smtpd +returns a permanent error code to the client; +in contrast, if +the disk is full or +.B qmail-smtpd +hits a resource limit, +.B qmail-smtpd +returns a temporary error code. + +.I databytes +counts bytes as stored on disk, not as transmitted through the network. +It does not count the +.B qmail-smtpd +Received line, the +.B qmail-queue +Received line, or the envelope. + +If the environment variable +.B DATABYTES +is set, it overrides +.IR databytes . +.TP 5 .I localiphost Replacement host name for local IP addresses. Default: @@ -67,6 +97,29 @@ with This is done before .IR rcpthosts . .TP 5 +.I morercpthosts +Extra allowed RCPT domains. +If +.I rcpthosts +and +.I morercpthosts +both exist, +.I morercpthosts +is effectively appended to +.IR rcpthosts . + +You must run +.B qmail-newmrh +whenever +.I morercpthosts +changes. + +Rule of thumb for large sites: +Put your 50 most commonly used domains into +.IR rcpthosts , +and the rest into +.IR morercpthosts . +.TP 5 .I rcpthosts Allowed RCPT domains. If @@ -121,5 +174,6 @@ tcp-env(1), tcp-environ(5), qmail-control(5), qmail-inject(8), +qmail-newmrh(8), qmail-queue(8), qmail-remote(8) diff --git a/qmail-smtpd.c b/qmail-smtpd.c index 50cfc0a..1e28c88 100644 --- a/qmail-smtpd.c +++ b/qmail-smtpd.c @@ -1,6 +1,5 @@ #include "sig.h" #include "readwrite.h" -#include "getln.h" #include "stralloc.h" #include "substdio.h" #include "alloc.h" @@ -14,57 +13,68 @@ #include "qmail.h" #include "str.h" #include "fmt.h" +#include "scan.h" #include "byte.h" #include "case.h" #include "env.h" #include "now.h" #include "exit.h" +#include "rcpthosts.h" +#include "timeoutread.h" +#include "timeoutwrite.h" +#include "commands.h" #define MAXHOPS 100 +unsigned int databytes = 0; int timeout = 1200; -char ssoutbuf[512]; -substdio ssout = SUBSTDIO_FDBUF(write,1,ssoutbuf,sizeof(ssoutbuf)); - -void die() { substdio_flush(&ssout); _exit(1); } -void flush() { if (substdio_flush(&ssout) == -1) _exit(1); } -void out(s) char *s; { if (substdio_puts(&ssout,s) == -1) die(); } - -int timeoutread(fd,buf,n) int fd; char *buf; int n; +int safewrite(fd,buf,len) int fd; char *buf; int len; { - int r; int saveerrno; - flush(); - alarm(timeout); - r = read(fd,buf,n); saveerrno = errno; - alarm(0); - errno = saveerrno; return r; + int r; + r = timeoutwrite(timeout,fd,buf,len); + if (r <= 0) _exit(1); + return r; } -char ssinbuf[1024]; -substdio ssin = SUBSTDIO_FDBUF(timeoutread,0,ssinbuf,sizeof(ssinbuf)); +char ssoutbuf[512]; +substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); +void flush() { substdio_flush(&ssout); } +void out(s) char *s; { substdio_puts(&ssout,s); } -void outofmem() { out("421 out of memory (#4.3.0)\r\n"); die(); } -void sigalrm() { out("451 timeout (#4.4.2)\r\n"); die(); } +void die_read() { _exit(1); } +void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); } +void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); } +void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); } +void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); } +void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); } -struct qmail qqt; -stralloc greeting = {0}; -int liphostok = 0; -stralloc liphost = {0}; -int rhok = 0; -stralloc rcpthosts = {0}; -struct constmap maprcpthosts; -int bmfok = 0; -stralloc bmf = {0}; -struct constmap mapbmf; -int flagbarf; /* defined if seenmail */ +void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } +void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } +void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); } +void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } +void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } +void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); } +void err_noop() { out("250 ok\r\n"); } +void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); } +void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } -stralloc helohost = {0}; -stralloc mailfrom = {0}; -stralloc rcptto = {0}; -int seenmail = 0; -stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */ +stralloc greeting = {0}; + +void smtp_greet(code) char *code; +{ + substdio_puts(&ssout,code); + substdio_put(&ssout,greeting.s,greeting.len); +} +void smtp_help() +{ + out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n"); +} +void smtp_quit() +{ + smtp_greet("221 "); out("\r\n"); flush(); _exit(0); +} char *remoteip; char *remotehost; @@ -72,378 +82,340 @@ char *remoteinfo; char *local; char *relayclient; -void dohelo(arg) char *arg; -{ - if (!stralloc_copys(&helohost,arg)) outofmem(); - if (!stralloc_0(&helohost)) outofmem(); -} +stralloc helohost = {0}; +char *fakehelo; /* pointer into helohost, or 0 */ -void getenvs() -{ - remoteip = env_get("TCPREMOTEIP"); - if (!remoteip) remoteip = "unknown"; - local = env_get("TCPLOCALHOST"); - if (!local) local = env_get("TCPLOCALIP"); - if (!local) local = "unknown"; - remotehost = env_get("TCPREMOTEHOST"); - if (!remotehost) remotehost = "unknown"; - remoteinfo = env_get("TCPREMOTEINFO"); - relayclient = env_get("RELAYCLIENT"); - dohelo(remotehost); +void dohelo(arg) char *arg; { + if (!stralloc_copys(&helohost,arg)) die_nomem(); + if (!stralloc_0(&helohost)) die_nomem(); + fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0; } -void straynewline() -{ - out("451 \ -Put ,E=\\r\\n at the end of Mether, Mtcp, or Msmtp in sendmail.cf \ -if you are using Solaris 2.5 (fixed in 2.5.1). \ -I cannot accept messages with stray newlines. \ -Many SMTP servers will time out waiting for \\r\\n.\\r\\n.\ -\r\n"); - die(); -} +int liphostok = 0; +stralloc liphost = {0}; +int bmfok = 0; +stralloc bmf = {0}; +struct constmap mapbmf; -void blast(ssfrom,hops) -substdio *ssfrom; -int *hops; +void setup() { - char ch; - int state; - int flaginheader; - int pos; /* number of bytes since most recent \n, if fih */ - int flagmaybex; /* 1 if this line might match RECEIVED, if fih */ - int flagmaybey; /* 1 if this line might match \r\n, if fih */ - int flagmaybez; /* 1 if this line might match DELIVERED, if fih */ - - state = 1; - *hops = 0; - flaginheader = 1; - pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; - for (;;) - { - if (substdio_get(ssfrom,&ch,1) <= 0) die(); - if (flaginheader) - { - if (pos < 9) - { - if (ch != "delivered"[pos]) if (ch != "DELIVERED"[pos]) flagmaybez = 0; - if (flagmaybez) if (pos == 8) ++*hops; - if (pos < 8) - if (ch != "received"[pos]) if (ch != "RECEIVED"[pos]) flagmaybex = 0; - if (flagmaybex) if (pos == 7) ++*hops; - if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; - if (flagmaybey) if (pos == 1) flaginheader = 0; - } - ++pos; - if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } - } - switch(state) - { - case 0: - if (ch == '\n') straynewline(); - if (ch == '\r') { state = 4; continue; } - break; - case 1: /* \r\n */ - if (ch == '\n') straynewline(); - if (ch == '.') { state = 2; continue; } - if (ch == '\r') { state = 4; continue; } - state = 0; - break; - case 2: /* \r\n + . */ - if (ch == '\n') straynewline(); - if (ch == '\r') { state = 3; continue; } - state = 0; - break; - case 3: /* \r\n + .\r */ - if (ch == '\n') return; - qmail_put(&qqt,".\r",2); - if (ch == '\r') { state = 4; continue; } - state = 0; - break; - case 4: /* + \r */ - if (ch == '\n') { state = 1; break; } - if (ch != '\r') { qmail_put(&qqt,"\r",1); state = 0; } - } - qmail_put(&qqt,&ch,1); - } + char *x; + unsigned long u; + + if (control_init() == -1) die_control(); + if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1) + die_control(); + liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0); + if (liphostok == -1) die_control(); + if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control(); + if (timeout <= 0) timeout = 1; + + if (rcpthosts_init() == -1) die_control(); + + bmfok = control_readfile(&bmf,"control/badmailfrom",0); + if (bmfok == -1) die_control(); + if (bmfok) + if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); + + if (control_readint(&databytes,"control/databytes") == -1) die_control(); + x = env_get("DATABYTES"); + if (x) { scan_ulong(x,&u); databytes = u; } + if (!(databytes + 1)) --databytes; + + remoteip = env_get("TCPREMOTEIP"); + if (!remoteip) remoteip = "unknown"; + local = env_get("TCPLOCALHOST"); + if (!local) local = env_get("TCPLOCALIP"); + if (!local) local = "unknown"; + remotehost = env_get("TCPREMOTEHOST"); + if (!remotehost) remotehost = "unknown"; + remoteinfo = env_get("TCPREMOTEINFO"); + relayclient = env_get("RELAYCLIENT"); + dohelo(remotehost); } + +stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */ + int addrparse(arg) char *arg; { - int i; - char ch; - struct ip_address ip; - int flagesc; - int flagquoted; - - arg += str_chr(arg,'<'); - if (*arg != '<') return 0; - ++arg; - - /* strip source route */ - if (*arg == '@') while (*arg) if (*arg++ == ':') break; - - if (!*arg) return 0; - if (!stralloc_copys(&addr,"")) outofmem(); - flagesc = 0; - flagquoted = 0; - for (i = 0;ch = arg[i];++i) /* copy arg to addr, stripping quotes */ - { - if (flagesc) - { if (!stralloc_append(&addr,&ch)) outofmem(); flagesc = 0; } - else - { - if (!flagquoted && (ch == '>')) break; - switch(ch) - { - case '\\': flagesc = 1; break; - case '"': flagquoted = !flagquoted; break; - default: if (!stralloc_append(&addr,&ch)) outofmem(); + int i; + char ch; + char terminator; + struct ip_address ip; + int flagesc; + int flagquoted; + + terminator = '>'; + i = str_chr(arg,'<'); + if (arg[i]) + arg += i + 1; + else { /* partner should go read rfc 821 */ + terminator = ' '; + arg += str_chr(arg,':'); + if (*arg == ':') ++arg; + while (*arg == ' ') ++arg; + } + + /* strip source route */ + if (*arg == '@') while (*arg) if (*arg++ == ':') break; + + if (!stralloc_copys(&addr,"")) die_nomem(); + flagesc = 0; + flagquoted = 0; + for (i = 0;ch = arg[i];++i) { /* copy arg to addr, stripping quotes */ + if (flagesc) { + if (!stralloc_append(&addr,&ch)) die_nomem(); + flagesc = 0; + } + else { + if (!flagquoted && (ch == terminator)) break; + switch(ch) { + case '\\': flagesc = 1; break; + case '"': flagquoted = !flagquoted; break; + default: if (!stralloc_append(&addr,&ch)) die_nomem(); } } } - if (!ch) return 0; - if (!stralloc_append(&addr,"")) outofmem(); - ++i; - while (arg[i]) - { - if (!case_diffs(arg + i," BODY=8BITMIME")) i += 14; - else if (!case_diffs(arg + i," BODY=7BIT")) i += 10; - else return 0; - } - - if (liphostok) - { - i = byte_rchr(addr.s,addr.len,'@'); - if (i < addr.len) /* if not, partner should go read rfc 821 */ - if (addr.s[i + 1] == '[') - if (!addr.s[i + 1 + ip_scanbracket(addr.s + i + 1,&ip)]) - if (ipme_is(&ip)) - { - addr.len = i + 1; - if (!stralloc_cat(&addr,&liphost)) outofmem(); - if (!stralloc_0(&addr)) outofmem(); + /* could check for termination failure here, but why bother? */ + if (!stralloc_append(&addr,"")) die_nomem(); + + if (liphostok) { + i = byte_rchr(addr.s,addr.len,'@'); + if (i < addr.len) /* if not, partner should go read rfc 821 */ + if (addr.s[i + 1] == '[') + if (!addr.s[i + 1 + ip_scanbracket(addr.s + i + 1,&ip)]) + if (ipme_is(&ip)) { + addr.len = i + 1; + if (!stralloc_cat(&addr,&liphost)) die_nomem(); + if (!stralloc_0(&addr)) die_nomem(); } } - return 1; + if (addr.len > 900) return 0; + return 1; } -int addrallowed() +int bmfcheck() { - int j; - if (!rhok) return 1; - j = byte_rchr(addr.s,addr.len,'@'); - if (j >= addr.len) return 1; /* can be taken care of by envnoathost */ - if (constmap(&maprcpthosts,addr.s + j + 1,addr.len - j - 2)) return 1; - for (;j < addr.len;++j) - if (addr.s[j] == '.') - if (constmap(&maprcpthosts,addr.s + j,addr.len - j - 1)) return 1; - return 0; + int j; + if (!bmfok) return 0; + if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1; + j = byte_rchr(addr.s,addr.len,'@'); + if (j < addr.len) + if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1; + return 0; } -void bmfcheck() +int addrallowed() { - int j; - flagbarf = 0; - if (!bmfok) return; - if (constmap(&mapbmf,addr.s,addr.len - 1)) { flagbarf = 1; return; } - j = byte_rchr(addr.s,addr.len,'@'); - if (j < addr.len) - if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) flagbarf = 1; + int r; + r = rcpthosts(addr.s,str_len(addr.s)); + if (r == -1) die_control(); + return r; } -void smtp_greet(code) char *code; { - if (substdio_puts(&ssout,code) == -1) die(); - if (substdio_put(&ssout,greeting.s,greeting.len) == -1) die(); } -void smtp_quit() { smtp_greet("221 "); out("\r\n"); die(); } -void smtp_help() { out("214-qmail home page: http://pobox.com/~djb/qmail.html\r\n214 send comments to qmail@pobox.com\r\n"); } -void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } -void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } -void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } -void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); } -void err_seenmail() { out("503 one MAIL per message (#5.5.1)\r\n"); } -void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } -void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); } -void err_noop() { out("250 ok\r\n"); } -void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); } -void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } -void smtp_helo(arg) char *arg; { - smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); - seenmail = 0; - dohelo(arg ? arg : ""); } -void smtp_rset() { - seenmail = 0; - out("250 flushed\r\n"); } -void smtp_mail(arg) char *arg; { - if (seenmail) { err_seenmail(); return; } - if (!arg) { err_syntax(); return; } - if (!addrparse(arg)) { err_syntax(); return; } - bmfcheck(); - seenmail = 1; out("250 ok\r\n"); - if (!stralloc_copys(&rcptto,"")) outofmem(); - if (!stralloc_copys(&mailfrom,addr.s)) outofmem(); - if (!stralloc_0(&mailfrom)) outofmem(); } + +int seenmail = 0; +int flagbarf; /* defined if seenmail */ +stralloc mailfrom = {0}; +stralloc rcptto = {0}; + +void smtp_helo(arg) char *arg; +{ + smtp_greet("250 "); out("\r\n"); + seenmail = 0; dohelo(arg); +} +void smtp_ehlo(arg) char *arg; +{ + smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); + seenmail = 0; dohelo(arg); +} +void smtp_rset() +{ + seenmail = 0; + out("250 flushed\r\n"); +} +void smtp_mail(arg) char *arg; +{ + if (!addrparse(arg)) { err_syntax(); return; } + flagbarf = bmfcheck(); + seenmail = 1; + if (!stralloc_copys(&rcptto,"")) die_nomem(); + if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); + if (!stralloc_0(&mailfrom)) die_nomem(); + out("250 ok\r\n"); +} void smtp_rcpt(arg) char *arg; { - if (!seenmail) { err_wantmail(); return; } - if (!arg) { err_syntax(); return; } - if (!addrparse(arg)) { err_syntax(); return; } - if (flagbarf) { err_bmf(); return; } - if (relayclient) - { - --addr.len; - if (!stralloc_cats(&addr,relayclient)) outofmem(); - if (!stralloc_0(&addr)) outofmem(); + if (!seenmail) { err_wantmail(); return; } + if (!addrparse(arg)) { err_syntax(); return; } + if (flagbarf) { err_bmf(); return; } + if (relayclient) { + --addr.len; + if (!stralloc_cats(&addr,relayclient)) die_nomem(); + if (!stralloc_0(&addr)) die_nomem(); } - else - if (!addrallowed()) { err_nogateway(); return; } - out("250 ok\r\n"); - if (!stralloc_cats(&rcptto,"T")) outofmem(); - if (!stralloc_cats(&rcptto,addr.s)) outofmem(); - if (!stralloc_0(&rcptto)) outofmem(); } + else + if (!addrallowed()) { err_nogateway(); return; } + if (!stralloc_cats(&rcptto,"T")) die_nomem(); + if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); + if (!stralloc_0(&rcptto)) die_nomem(); + out("250 ok\r\n"); +} -char accept_buf[FMT_ULONG]; -void acceptmessage(qp) unsigned long qp; + +int saferead(fd,buf,len) int fd; char *buf; int len; { - datetime_sec when; - when = now(); - out("250 ok "); - accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0; - out(accept_buf); - out(" qp "); - accept_buf[fmt_ulong(accept_buf,qp)] = 0; - out(accept_buf); - out("\r\n"); + int r; + flush(); + r = timeoutread(timeout,fd,buf,len); + if (r == -1) if (errno == error_timeout) die_alarm(); + if (r <= 0) die_read(); + return r; } -void smtp_data() { - int hops; int r; unsigned long qp; - if (!seenmail) { err_wantmail(); return; } - if (!rcptto.len) { err_wantrcpt(); return; } - seenmail = 0; - if (qmail_open(&qqt) == -1) { err_qqt(); return; } - qp = qmail_qp(&qqt); - out("354 go ahead\r\n"); - - received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,case_diffs(remotehost,helohost.s) ? helohost.s : 0); - blast(&ssin,&hops); - hops = (hops >= MAXHOPS); - if (hops) qmail_fail(&qqt); - qmail_from(&qqt,mailfrom.s); - qmail_put(&qqt,rcptto.s,rcptto.len); - - r = qmail_close(&qqt); - if (!r) { acceptmessage(qp); return; } - if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; } - switch(r) - { - case QMAIL_TOOLONG: out("554 address too long (#5.1.3)\r\n"); return; - case QMAIL_SYS: out("451 qq system error (#4.3.0)\r\n"); return; - case QMAIL_READ: out("451 qq read error (#4.3.0)\r\n"); return; - case QMAIL_WRITE: out("451 qq write error or disk full (#4.3.0)\r\n"); return; - case QMAIL_NOMEM: out("451 qq out of memory (#4.3.0)\r\n"); return; - case QMAIL_EXECSOFT: out("451 could not exec qq (#4.3.0)\r\n"); return; - case QMAIL_TIMEOUT: out("451 qq timeout (#4.3.0)\r\n"); return; - case QMAIL_WAITPID: out("451 qq waitpid surprise (#4.3.0)\r\n"); return; - case QMAIL_CRASHED: out("451 qq crashed (#4.3.0)\r\n"); return; - case QMAIL_USAGE: out("451 qq usage surprise (#4.3.0)\r\n"); return; - default: out("451 qq internal bug (#4.3.0)\r\n"); return; - } +char ssinbuf[1024]; +substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); + +struct qmail qqt; +unsigned int bytestooverflow = 0; + +void put(ch) +char *ch; +{ + if (bytestooverflow) + if (!--bytestooverflow) + qmail_fail(&qqt); + qmail_put(&qqt,ch,1); } -static struct { void (*fun)(); char *text; int flagflush; } smtpcmd[] = { - { smtp_rcpt, "rcpt", 0 } -, { smtp_mail, "mail", 0 } -, { smtp_data, "data", 1 } -, { smtp_quit, "quit", 1 } -, { smtp_helo, "helo", 1 } -, { smtp_helo, "ehlo", 1 } -, { smtp_rset, "rset", 0 } -, { smtp_help, "help", 1 } -, { err_noop, "noop", 1 } -, { err_vrfy, "vrfy", 1 } -, { 0, 0, 0 } -}; - -void doit(cmd) -char *cmd; +void blast(hops) +int *hops; { - int i; - int j; - char ch; - - for (i = 0;smtpcmd[i].fun;++i) - { - for (j = 0;ch = smtpcmd[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]) - smtpcmd[i].fun((char *) 0); - else - smtpcmd[i].fun(cmd + j); - if (smtpcmd[i].flagflush) flush(); - return; + char ch; + int state; + int flaginheader; + int pos; /* number of bytes since most recent \n, if fih */ + int flagmaybex; /* 1 if this line might match RECEIVED, if fih */ + int flagmaybey; /* 1 if this line might match \r\n, if fih */ + int flagmaybez; /* 1 if this line might match DELIVERED, if fih */ + + state = 1; + *hops = 0; + flaginheader = 1; + pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; + for (;;) { + substdio_get(&ssin,&ch,1); + if (flaginheader) { + if (pos < 9) { + if (ch != "delivered"[pos]) if (ch != "DELIVERED"[pos]) flagmaybez = 0; + if (flagmaybez) if (pos == 8) ++*hops; + if (pos < 8) + if (ch != "received"[pos]) if (ch != "RECEIVED"[pos]) flagmaybex = 0; + if (flagmaybex) if (pos == 7) ++*hops; + if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; + if (flagmaybey) if (pos == 1) flaginheader = 0; } + ++pos; + if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } + } + switch(state) { + case 0: + if (ch == '\n') straynewline(); + if (ch == '\r') { state = 4; continue; } + break; + case 1: /* \r\n */ + if (ch == '\n') straynewline(); + if (ch == '.') { state = 2; continue; } + if (ch == '\r') { state = 4; continue; } + state = 0; + break; + case 2: /* \r\n + . */ + if (ch == '\n') straynewline(); + if (ch == '\r') { state = 3; continue; } + state = 0; + break; + case 3: /* \r\n + .\r */ + if (ch == '\n') return; + put("."); + put("\r"); + if (ch == '\r') { state = 4; continue; } + state = 0; + break; + case 4: /* + \r */ + if (ch == '\n') { state = 1; break; } + if (ch != '\r') { put("\r"); state = 0; } + } + put(&ch); } - err_unimpl(); - flush(); } -void getcontrols() +char accept_buf[FMT_ULONG]; +void acceptmessage(qp) unsigned long qp; { - if (control_init() == -1) die(); - if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1) die(); - switch(control_rldef(&liphost,"control/localiphost",1,(char *) 0)) - { case -1: die(); case 1: liphostok = 1; } - if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die(); - if (timeout <= 0) timeout = 1; - switch(control_readfile(&rcpthosts,"control/rcpthosts",0)) - { - case -1: die(); - case 1: - rhok = 1; - if (!constmap_init(&maprcpthosts,rcpthosts.s,rcpthosts.len,0)) die(); - } - switch(control_readfile(&bmf,"control/badmailfrom",0)) - { - case -1: die(); - case 1: - bmfok = 1; - if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die(); - } + datetime_sec when; + when = now(); + out("250 ok "); + accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0; + out(accept_buf); + out(" qp "); + accept_buf[fmt_ulong(accept_buf,qp)] = 0; + out(accept_buf); + out("\r\n"); +} + +void smtp_data() { + int hops; + unsigned long qp; + char *qqx; + + if (!seenmail) { err_wantmail(); return; } + if (!rcptto.len) { err_wantrcpt(); return; } + seenmail = 0; + if (databytes) bytestooverflow = databytes + 1; + if (qmail_open(&qqt) == -1) { err_qqt(); return; } + qp = qmail_qp(&qqt); + out("354 go ahead\r\n"); + + received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo); + blast(&hops); + hops = (hops >= MAXHOPS); + if (hops) qmail_fail(&qqt); + qmail_from(&qqt,mailfrom.s); + qmail_put(&qqt,rcptto.s,rcptto.len); + + qqx = qmail_close(&qqt); + if (!*qqx) { acceptmessage(qp); return; } + if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; } + if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; } + if (*qqx == 'D') out("554 "); else out("451 "); + out(qqx + 1); + out("\r\n"); } +struct commands smtpcommands[] = { + { "rcpt", smtp_rcpt, 0 } +, { "mail", smtp_mail, 0 } +, { "data", smtp_data, flush } +, { "quit", smtp_quit, flush } +, { "helo", smtp_helo, flush } +, { "ehlo", smtp_ehlo, flush } +, { "rset", smtp_rset, 0 } +, { "help", smtp_help, flush } +, { "noop", err_noop, flush } +, { "vrfy", err_vrfy, flush } +, { 0, err_unimpl, flush } +} ; + void main() { - static stralloc cmd = {0}; - int match; - - sig_alarmcatch(sigalrm); - sig_pipeignore(); - - if (chdir(auto_qmail) == -1) die(); - getcontrols(); - getenvs(); - - if (ipme_init() != 1) die(); - - smtp_greet("220 "); - out(" ESMTP\r\n"); - - for (;;) - { - /* XXX: recipient can contain quoted lf. aargh. */ - 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); - } + sig_pipeignore(); + if (chdir(auto_qmail) == -1) die_control(); + setup(); + if (ipme_init() != 1) die_ipme(); + smtp_greet("220 "); + out(" ESMTP\r\n"); + if (commands(&ssin,&smtpcommands) == 0) die_read(); + die_nomem(); } diff --git a/qmail-start.9 b/qmail-start.9 index 95db54f..29876ec 100644 --- a/qmail-start.9 +++ b/qmail-start.9 @@ -4,7 +4,7 @@ qmail-start \- turn on mail delivery .SH SYNOPSIS .B qmail-start [ -.I aliasempty +.I defaultdelivery [ .I logger arg ... ] @@ -16,7 +16,8 @@ invokes .BR qmail-lspawn , .BR qmail-rspawn , and -.BR qmail-clean . +.BR qmail-clean , +under the proper uids and gids. These four daemons cooperate to deliver messages from the queue. .B qmail-start @@ -33,7 +34,7 @@ Other than this, does not print anything, even on failure. If -.I aliasempty +.I defaultdelivery is supplied, .B qmail-start passes it to @@ -67,8 +68,10 @@ manually: (all on one line) .EE +Resource limits, controlling ttys, et al. are also passed from .B qmail-start -sets the uid and gid of each daemon properly. +to +.BR qmail-local . Note that .B qmail-send diff --git a/qmail-tcpok.8 b/qmail-tcpok.8 new file mode 100644 index 0000000..ed2efcf --- /dev/null +++ b/qmail-tcpok.8 @@ -0,0 +1,24 @@ +.TH qmail-tcpok 8 +.SH NAME +qmail-tcpok \- clear TCP timeout table +.SH SYNOPSIS +.B qmail-tcpok +.SH DESCRIPTION +.B qmail-tcpok +erases +.BR qmail-remote 's +current list of timeouts, +so that +.B qmail-remote +does not make any assumptions about failing addresses. + +.B qmail-tcpok +must be run either as +.B root +or with user id +.B qmailr +and group id +.BR qmail . +.SH "SEE ALSO" +qmail-remote(8), +qmail-tcpto(8) diff --git a/qmail-tcpok.c b/qmail-tcpok.c new file mode 100644 index 0000000..a9b9652 --- /dev/null +++ b/qmail-tcpok.c @@ -0,0 +1,35 @@ +#include "strerr.h" +#include "substdio.h" +#include "lock.h" +#include "open.h" +#include "readwrite.h" +#include "auto_qmail.h" +#include "exit.h" + +#define FATAL "qmail-tcpok: fatal: " + +char buf[1024]; /* XXX: must match size in tcpto_clean.c, tcpto.c */ +substdio ss; + +void main() +{ + int fd; + int i; + + if (chdir(auto_qmail) == -1) + strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": "); + if (chdir("queue/lock") == -1) + strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,"/queue/lock: "); + + fd = open_write("tcpto"); + if (fd == -1) + strerr_die4sys(111,FATAL,"unable to write ",auto_qmail,"/queue/lock/tcpto: "); + if (lock_ex(fd) == -1) + strerr_die4sys(111,FATAL,"unable to lock ",auto_qmail,"/queue/lock/tcpto: "); + + substdio_fdbuf(&ss,write,fd,buf,sizeof buf); + for (i = 0;i < sizeof buf;++i) substdio_put(&ss,"",1); + if (substdio_flush(&ss) == -1) + strerr_die4sys(111,FATAL,"unable to clear ",auto_qmail,"/queue/lock/tcpto: "); + _exit(0); +} diff --git a/qmail-tcpto.8 b/qmail-tcpto.8 index f305181..cb4ddd6 100644 --- a/qmail-tcpto.8 +++ b/qmail-tcpto.8 @@ -26,4 +26,5 @@ and group id .BR qmail . .SH "SEE ALSO" qmail-qread(8), -qmail-remote(8) +qmail-remote(8), +qmail-tcpok(8) diff --git a/qmail-upgrade.9 b/qmail-upgrade.9 deleted file mode 100644 index 82ae6de..0000000 --- a/qmail-upgrade.9 +++ /dev/null @@ -1,201 +0,0 @@ -.TH qmail-upgrade 7 -.SH "NAME" -qmail-upgrade \- user-visible differences between qmail and sendmail -.SH "INTRODUCTION" -You will notice some differences -when the system switches from -.B sendmail -to -.BR qmail . -.TP 5 -1. -.B qmail-local -sends incoming mail to -.B ~\fIyou\fB/Mailbox -by default, -not -.BR /usr/spool/mail/\fIyou\fB . -Your system administrator has changed your -.B MAIL -environment variable so that your mail reader looks for -.BR ~\fIyou\fB/Mailbox . -.B \fR(\fB/usr/spool/mail -is a massive security problem.) -.TP 5 -2. -.B qmail-local -pays no attention to -.BR .forward . -It has a much better mechanism, -.BR .qmail , -so that you can handle not only forwarding -but even your own mailing lists. -See below for more details. -.TP 5 -3. -.B qmail-local -pays no attention to -.BR /etc/aliases . -Your system administrator -can use the -.B .qmail -mechanism instead. -See below. -.TP 5 -4. -.B qmail -does not support the -.B \e\fIyou\fB -mechanism -for ignoring aliases. -The -.B .qmail -mechanism is much more flexible; -see below. -.TP 5 -5. -.B qmail-inject -has a completely different philosophy from -.B sendmail -on interpreting non-fully-qualified host names. -It uses fixed rules, not DNS. -Some examples at UIC: - -.EX - russet -> russet.math.uic.edu -.br - newton -> newton.math.uic.edu -.br - ut.ee -> ut.ee (a host in Estonia) -.br - ut.ee+ -> ut.ee.uic.edu -.br - uicvm+ -> uicvm.uic.edu -.EE - -Here the -.I default domain name -(for hosts without dots) -is -.B math.uic.edu\fP, -and the -.I plus domain name -is -.B uic.edu\fP. -.TP 5 -6. -Unlike -.BR sendmail , -.B qmail-inject -doesn't replace host names with canonical names. -Example: -.B qmail-inject -won't change -.B postmaster@ftp.cs.berkeley.edu -in your header to -.BR postmaster@kohler.cs.berkeley.edu . -.TP 5 -7. -.B qmail-local -adds a new field, -.BR Delivered-To , -before every delivery. -It uses the contents of -.B Delivered-To -to prevent mail forwarding loops. -.TP 5 -8. -If you send a message with only -.B Bcc -recipients, -.B qmail-inject -will add -.B Cc: recipient list not shown:;\fR, -rather than -.BR sendmail 's -privacy-invading -.B Apparently-To -header field. -.SH "QMAIL MAILING LISTS" -.B sendmail -deals with aliases, forwarding, and mailing lists -at the very heart of the mail system. - -.B qmail -takes a radically different approach. -It gives you the power to set up your own mailing lists without -pestering your system administrator. - -Under -.BR qmail , -you are in charge of all addresses of the form -.B \fIyou\fBBREAK\fIanything\fR. -The delivery of -.B \fIyou\fBBREAK\fIanything -is controlled by -.B ~\fIyou\fB/.qmail-\fIanything\fR, -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 -.BR ~\fIyou\fB/.qmail-botmc . -Any mail to -.B \fIyou\fBBREAKbotmc -will be forwarded to all of those addresses. -Mail directly to -.B \fIyou\fB -is controlled by -.BR ~\fIyou\fB/.qmail . -You can even set up a catch-all, -.BR ~\fIyou\fB/.qmail-default , -to handle unknown -.B \fIyou\fBBREAK -addresses. - -Your -.B .qmail -files, like your old -.BR .forward , -may list files, -forwarding addresses, -or other programs to run. -(But beware that the syntax is a bit different; -see -.B dot-qmail(5) -for more details.) -.B qmail-local -automatically -detects forwarding loops the instant they occur, -even if they happen indirectly through other hosts. - -As a helpful special case, if a -.B .qmail -file is empty, it refers to -.BR ~\fIyou\fB/Mailbox . -For example, if you touch -.BR ~\fIyou\fB/.qmail-direct , -mail for -.B \fIyou\fBBREAKdirect -will act like -.B \e\fIyou\fB -did under -.BR sendmail . - -Addresses that don't contain a username are handled by the -.B alias -user. -For example, your system administrator has set up -.B ~alias/.qmail-postmaster -to handle mail for -.BR Postmaster . -(Note to administrators: -.B ~alias -doesn't apply to addresses that start with a user name, -with certain exceptions.) -.SH "SEE ALSO" -addresses(5), -dot-qmail(5), -envelopes(5), -qmail-header(8), -qmail-inject(8) diff --git a/qmail.7 b/qmail.7 index 3be2093..a59e8d0 100644 --- a/qmail.7 +++ b/qmail.7 @@ -12,10 +12,10 @@ Available commands for the .B .qmail file include .BR qbiff (1), -.BR qlist (1), .BR qreceipt (1), .BR forward (1), -and (for advanced users) +.BR bouncesaying (1), +and .BR condredirect (1). Other helpful commands include .BR maildirmake (1), @@ -51,13 +51,12 @@ and .BR forgeries (7). Miscellaneous documentation includes -.BR qmail-upgrade (7), -.BR qmail-limits (7), +.BR qmail-limits (7) and .BR qmail-pop3d (8). This documentation describes version -1.01 +1.03 of .BR qmail . See diff --git a/qmail.c b/qmail.c index 7484331..0fe0dfa 100644 --- a/qmail.c +++ b/qmail.c @@ -28,7 +28,7 @@ struct qmail *qq; close(pie[1]); if (fd_move(0,pim[0]) == -1) _exit(120); if (fd_move(1,pie[0]) == -1) _exit(120); - if (chdir(auto_qmail) == -1) _exit(120); + if (chdir(auto_qmail) == -1) _exit(61); execv(*binqqargs,binqqargs); _exit(120); } @@ -77,27 +77,49 @@ void qmail_to(qq,s) struct qmail *qq; char *s; qmail_put(qq,"",1); } -int qmail_close(qq) +char *qmail_close(qq) struct qmail *qq; { int wstat; + int exitcode; qmail_put(qq,"",1); if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1; close(qq->fde); - if (wait_pid(&wstat,qq->pid) != qq->pid) return QMAIL_WAITPID; - if (wait_crashed(wstat)) return QMAIL_CRASHED; - switch(wait_exitcode(wstat)) { - case 0: if (qq->flagerr) return QMAIL_BUG; return 0; - case 112: return QMAIL_USAGE; - case 115: return QMAIL_TOOLONG; - case 103: case 104: case 105: case 106: case 108: return QMAIL_SYS; - case 121: return QMAIL_READ; - case 122: return QMAIL_WRITE; - case 123: return QMAIL_NOMEM; - case 124: return QMAIL_TIMEOUT; - case 120: return QMAIL_EXECSOFT; - default: /* 101 or 102 */ return QMAIL_BUG; + if (wait_pid(&wstat,qq->pid) != qq->pid) + return "Zqq waitpid surprise (#4.3.0)"; + if (wait_crashed(wstat)) + return "Zqq crashed (#4.3.0)"; + exitcode = wait_exitcode(wstat); + + switch(exitcode) { + case 115: /* compatibility */ + case 11: return "Denvelope address too long for qq (#5.1.3)"; + case 31: return "Dmail server permanently rejected message (#5.3.0)"; + case 51: return "Zqq out of memory (#4.3.0)"; + case 52: return "Zqq timeout (#4.3.0)"; + case 53: return "Zqq write error or disk full (#4.3.0)"; + case 0: if (!qq->flagerr) return ""; /* fall through */ + case 54: return "Zqq read error (#4.3.0)"; + case 55: return "Zqq unable to read configuration (#4.3.0)"; + case 56: return "Zqq trouble making network connection (#4.3.0)"; + case 61: return "Zqq trouble in home directory (#4.3.0)"; + case 63: + case 64: + case 65: + case 66: + case 62: return "Zqq trouble creating files in queue (#4.3.0)"; + case 71: return "Zmail server temporarily rejected message (#4.3.0)"; + case 72: return "Zconnection to mail server timed out (#4.4.1)"; + case 73: return "Zconnection to mail server rejected (#4.4.1)"; + case 74: return "Zcommunication with mail server failed (#4.4.2)"; + case 91: /* fall through */ + case 81: return "Zqq internal bug (#4.3.0)"; + case 120: return "Zunable to exec qq (#4.3.0)"; + default: + if ((exitcode >= 11) && (exitcode <= 40)) + return "Dqq permanent problem (#5.3.0)"; + return "Zqq temporary problem (#4.3.0)"; } } diff --git a/qmail.h b/qmail.h index 7864ea1..7fa13e2 100644 --- a/qmail.h +++ b/qmail.h @@ -18,19 +18,7 @@ extern void qmail_puts(); extern void qmail_from(); extern void qmail_to(); extern void qmail_fail(); -extern int qmail_close(); +extern char *qmail_close(); extern unsigned long qmail_qp(); -#define QMAIL_WAITPID -2 -#define QMAIL_CRASHED -3 -#define QMAIL_USAGE -4 -#define QMAIL_BUG -5 -#define QMAIL_SYS -6 -#define QMAIL_READ -7 -#define QMAIL_WRITE -8 -#define QMAIL_NOMEM -9 -#define QMAIL_EXECSOFT -11 -#define QMAIL_TIMEOUT -13 -#define QMAIL_TOOLONG -14 - #endif diff --git a/qreceipt.c b/qreceipt.c index 9b51196..49b9807 100644 --- a/qreceipt.c +++ b/qreceipt.c @@ -60,6 +60,8 @@ stralloc quoted = {0}; void finishheader() { + char *qqx; + if (!flagreceipt) die_noreceipt(); if (str_equal(returnpath,"")) die_noreceipt(); if (str_equal(returnpath,"#@[]")) die_noreceipt(); @@ -88,13 +90,11 @@ following address: "); qmail_from(&qqt,""); qmail_to(&qqt,returnpath); + qqx = qmail_close(&qqt); - switch(qmail_close(&qqt)) - { - case 0: break; - case QMAIL_TOOLONG: die_qqperm(); - default: die_qqtemp(); - } + if (*qqx) + if (*qqx == 'D') die_qqperm(); + else die_qqtemp(); } stralloc hfbuf = {0}; diff --git a/quote.c b/quote.c index 9f97d93..659cfcd 100644 --- a/quote.c +++ b/quote.c @@ -45,7 +45,7 @@ unsigned int n; { unsigned char uch; int i; - if (!n) return 0; + if (!n) return 1; for (i = 0;i < n;++i) { uch = s[i]; @@ -73,6 +73,7 @@ stralloc *sa; char *s; { int j; + if (!*s) return stralloc_copys(sa,s); j = str_rchr(s,'@'); if (!stralloc_copys(&foo,s)) return 0; if (!s[j]) return quote(sa,&foo); diff --git a/rcpthosts.c b/rcpthosts.c new file mode 100644 index 0000000..1bc3018 --- /dev/null +++ b/rcpthosts.c @@ -0,0 +1,60 @@ +#include "cdb.h" +#include "byte.h" +#include "open.h" +#include "error.h" +#include "control.h" +#include "constmap.h" +#include "stralloc.h" +#include "rcpthosts.h" + +static int flagrh = 0; +static stralloc rh = {0}; +static struct constmap maprh; +static int fdmrh; + +int rcpthosts_init() +{ + flagrh = control_readfile(&rh,"control/rcpthosts",0); + if (flagrh != 1) return flagrh; + if (!constmap_init(&maprh,rh.s,rh.len,0)) return flagrh = -1; + fdmrh = open_read("control/morercpthosts.cdb"); + if (fdmrh == -1) if (errno != error_noent) return flagrh = -1; + return 0; +} + +static stralloc host = {0}; + +int rcpthosts(buf,len) +char *buf; +int len; +{ + int j; + + if (flagrh != 1) return 1; + + j = byte_rchr(buf,len,'@'); + if (j >= len) return 1; /* presumably envnoathost is acceptable */ + + ++j; buf += j; len -= j; + + if (!stralloc_copyb(&host,buf,len)) return -1; + buf = host.s; + case_lowerb(buf,len); + + for (j = 0;j < len;++j) + if (!j || (buf[j] == '.')) + if (constmap(&maprh,buf + j,len - j)) return 1; + + if (fdmrh != -1) { + uint32 dlen; + int r; + + for (j = 0;j < len;++j) + if (!j || (buf[j] == '.')) { + r = cdb_seek(fdmrh,buf + j,len - j,&dlen); + if (r) return r; + } + } + + return 0; +} diff --git a/rcpthosts.h b/rcpthosts.h new file mode 100644 index 0000000..5e7e6cc --- /dev/null +++ b/rcpthosts.h @@ -0,0 +1,7 @@ +#ifndef RCPTHOSTS_H +#define RCPTHOSTS_H + +extern int rcpthosts_init(); +extern int rcpthosts(); + +#endif diff --git a/remoteinfo.c b/remoteinfo.c index 195eef6..c7abd70 100644 --- a/remoteinfo.c +++ b/remoteinfo.c @@ -12,6 +12,16 @@ #include "remoteinfo.h" static char line[999]; +static int t; + +static int mywrite(fd,buf,len) int fd; char *buf; int len; +{ + return timeoutwrite(t,fd,buf,len); +} +static int myread(fd,buf,len) int fd; char *buf; int len; +{ + return timeoutread(t,fd,buf,len); +} char *remoteinfo_get(ipr,rp,ipl,lp,timeout) struct ip_address *ipr; @@ -28,6 +38,8 @@ int timeout; unsigned int len; int numcolons; char ch; + + t = timeout; s = socket(AF_INET,SOCK_STREAM,0); if (s == -1) return 0; @@ -46,10 +58,10 @@ int timeout; len += fmt_ulong(line + len,lp); len += fmt_str(line + len,"\r\n"); - substdio_fdbuf(&ss,timeoutwrite,TIMEOUTWRITE(timeout,s),buf,sizeof(buf)); + substdio_fdbuf(&ss,mywrite,s,buf,sizeof buf); if (substdio_putflush(&ss,line,len) == -1) { close(s); return 0; } - substdio_fdbuf(&ss,timeoutread,TIMEOUTREAD(timeout,s),buf,sizeof(buf)); + substdio_fdbuf(&ss,myread,s,buf,sizeof buf); x = line; numcolons = 0; for (;;) { diff --git a/scan_nbblong.c b/scan_nbblong.c deleted file mode 100644 index 5078053..0000000 --- a/scan_nbblong.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "scan.h" - -unsigned int scan_nbblong(s,n,base,bext,u) -char *s; unsigned int n; unsigned int base; unsigned int bext; unsigned long *u; -/* Note that n == 0 means scan forever. Hopefully this is a good choice. */ -{ - unsigned int pos; unsigned long result; unsigned long c; - pos = 0; result = 0; - while (((c = (unsigned long) (unsigned char) (s[pos] - '0')) < base) - ||(((c = (unsigned long) (unsigned char) (s[pos] - 'a')) < bext) - &&(c = c + base)) - ||(((c = (unsigned long) (unsigned char) (s[pos] - 'A')) < bext) - &&(c = c + base)) - ) /* this gets the job done */ - { result = result * (base + bext) + c; ++pos; if (pos == n) break; } - *u = result; return pos; -} - -unsigned int scan_nbbint(s,n,base,bext,u) -char *s; unsigned int n; unsigned int base; unsigned int bext; unsigned int *u; -{ - unsigned int pos; unsigned long result; - pos = scan_nbblong(s,n,base,bext,&result); - *u = result; return pos; -} - -unsigned int scan_nbbshort(s,n,base,bext,u) -char *s; unsigned int n; unsigned int base; unsigned int bext; unsigned short *u; -{ - unsigned int pos; unsigned long result; - pos = scan_nbblong(s,n,base,bext,&result); - *u = result; return pos; -} diff --git a/sendmail.c b/sendmail.c index f4205e1..46d0e4b 100644 --- a/sendmail.c +++ b/sendmail.c @@ -9,8 +9,40 @@ void nomem() { - substdio_putsflush(subfderr,"sendmail: fatal: out of memory\n"); - _exit(111); + substdio_putsflush(subfderr,"sendmail: fatal: out of memory\n"); + _exit(111); +} + +void die_usage() +{ + substdio_putsflush(subfderr,"sendmail: usage: sendmail [ -t ] [ -fsender ] [ -Fname ] [ -bp ] [ -bs ] [ arg ... ]\n"); + _exit(100); +} + +char *smtpdarg[] = { "bin/qmail-smtpd", 0 }; +void smtpd() +{ + if (!env_get("PROTO")) { + if (!env_put("RELAYCLIENT=")) nomem(); + if (!env_put("DATABYTES=0")) nomem(); + if (!env_put("PROTO=TCP")) nomem(); + if (!env_put("TCPLOCALIP=127.0.0.1")) nomem(); + if (!env_put("TCPLOCALHOST=localhost")) nomem(); + if (!env_put("TCPREMOTEIP=127.0.0.1")) nomem(); + if (!env_put("TCPREMOTEHOST=localhost")) nomem(); + if (!env_put("TCPREMOTEINFO=sendmail-bs")) nomem(); + } + execv(*smtpdarg,smtpdarg); + substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-smtpd\n"); + _exit(111); +} + +char *qreadarg[] = { "bin/qmail-qread", 0 }; +void mailq() +{ + execv(*qreadarg,qreadarg); + substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-qread\n"); + _exit(111); } int flagh; @@ -20,79 +52,78 @@ void main(argc,argv) int argc; char **argv; { - int opt; - char **qiargv; - char **arg; - int i; - - if (chdir(auto_qmail) == -1) - { - substdio_putsflush(subfderr,"sendmail: fatal: unable to switch to qmail home directory\n"); - _exit(111); + int opt; + char **qiargv; + char **arg; + int i; + + if (chdir(auto_qmail) == -1) { + substdio_putsflush(subfderr,"sendmail: fatal: unable to switch to qmail home directory\n"); + _exit(111); } - flagh = 0; - sender = 0; - while ((opt = getopt(argc,argv,"vimte:f:p:o:B:F:EJx")) != opteof) - switch(opt) - { - case 'B': break; - case 't': flagh = 1; break; - case 'f': sender = optarg; break; - case 'F': if (!env_put2("MAILNAME",optarg)) nomem(); break; - case 'p': break; /* could generate a Received line from optarg */ - case 'v': break; - case 'i': break; /* what an absurd concept */ - case 'x': break; /* SVR4 stupidity */ - case 'm': break; /* twisted-paper-path blindness, incompetent design */ - case 'e': break; /* qmail has only one error mode */ - case 'o': - switch(optarg[0]) - { - case 'd': break; /* qmail has only one delivery mode */ - case 'e': break; /* see 'e' above */ - case 'i': break; /* see 'i' above */ - case 'm': break; /* see 'm' above */ + flagh = 0; + sender = 0; + while ((opt = getopt(argc,argv,"vimte:f:p:o:B:F:EJxb:")) != opteof) + switch(opt) { + case 'B': break; + case 't': flagh = 1; break; + case 'f': sender = optarg; break; + case 'F': if (!env_put2("MAILNAME",optarg)) nomem(); break; + case 'p': break; /* could generate a Received line from optarg */ + case 'v': break; + case 'i': break; /* what an absurd concept */ + case 'x': break; /* SVR4 stupidity */ + case 'm': break; /* twisted-paper-path blindness, incompetent design */ + case 'e': break; /* qmail has only one error mode */ + case 'o': + switch(optarg[0]) { + case 'd': break; /* qmail has only one delivery mode */ + case 'e': break; /* see 'e' above */ + case 'i': break; /* see 'i' above */ + case 'm': break; /* see 'm' above */ + } + break; + case 'E': case 'J': /* Sony NEWS-OS */ + while (argv[optind][optpos]) ++optpos; /* skip optional argument */ + break; + case 'b': + switch(optarg[0]) { + case 'm': break; + case 'p': mailq(); + case 's': smtpd(); + default: die_usage(); } - break; - case 'E': case 'J': /* Sony NEWS-OS */ - while (argv[optind][optpos]) ++optpos; /* skip optional argument */ - break; - default: - _exit(100); + break; + default: + die_usage(); } - argc -= optind; - argv += optind; - - if (str_equal(optprogname,"mailq")) - { - substdio_putsflush(subfderr,"sendmail: fatal: please use qmail-qread instead\n"); - _exit(100); - } + argc -= optind; + argv += optind; + + if (str_equal(optprogname,"mailq")) + mailq(); - if (str_equal(optprogname,"newaliases")) - { - substdio_putsflush(subfderr,"sendmail: fatal: please use the qmsmac newaliases instead\n"); - _exit(100); + if (str_equal(optprogname,"newaliases")) { + substdio_putsflush(subfderr,"sendmail: fatal: please use fastforward/newaliases instead\n"); + _exit(100); } - qiargv = (char **) alloc((argc + 10) * sizeof(char *)); - if (!qiargv) nomem(); - - arg = qiargv; - *arg++ = "bin/qmail-inject"; - *arg++ = (flagh ? "-H" : "-a"); - if (sender) - { - *arg++ = "-f"; - *arg++ = sender; + qiargv = (char **) alloc((argc + 10) * sizeof(char *)); + if (!qiargv) nomem(); + + arg = qiargv; + *arg++ = "bin/qmail-inject"; + *arg++ = (flagh ? "-H" : "-a"); + if (sender) { + *arg++ = "-f"; + *arg++ = sender; } - *arg++ = "--"; - for (i = 0;i < argc;++i) *arg++ = argv[i]; - *arg = 0; - - execv(*qiargv,qiargv); + *arg++ = "--"; + for (i = 0;i < argc;++i) *arg++ = argv[i]; + *arg = 0; - substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-inject\n"); - _exit(111); + execv(*qiargv,qiargv); + substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-inject\n"); + _exit(111); } diff --git a/slurpclose.c b/slurpclose.c index 27be0ea..2fcef15 100644 --- a/slurpclose.c +++ b/slurpclose.c @@ -1,6 +1,7 @@ #include "stralloc.h" #include "readwrite.h" #include "slurpclose.h" +#include "error.h" int slurpclose(fd,sa,bufsize) int fd; @@ -11,6 +12,7 @@ int bufsize; for (;;) { if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } r = read(fd,sa->s + sa->len,bufsize); + if (r == -1) if (errno == error_intr) continue; if (r <= 0) { close(fd); return r; } sa->len += r; } diff --git a/substdio.h b/substdio.h index 7a0de6e..c3f7f7d 100644 --- a/substdio.h +++ b/substdio.h @@ -36,6 +36,12 @@ extern void substdio_seek(); #define substdio_PEEK(s) ( (s)->x + (s)->n ) #define substdio_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) +#define substdio_BPUTC(s,c) \ + ( ((s)->n != (s)->p) \ + ? ( (s)->x[(s)->p++] = (c), 0 ) \ + : substdio_bput((s),&(c),1) \ + ) + extern int substdio_copy(); #endif diff --git a/timeoutread.c b/timeoutread.c index 4cebf54..c75e29c 100644 --- a/timeoutread.c +++ b/timeoutread.c @@ -3,23 +3,20 @@ #include "error.h" #include "readwrite.h" -int timeoutread(fdt,buf,len) int fdt; char *buf; int len; +int timeoutread(t,fd,buf,len) int t; int fd; char *buf; int len; { fd_set rfds; struct timeval tv; - int fd; - tv.tv_sec = (fdt >> 10); + tv.tv_sec = t; tv.tv_usec = 0; - fd = (fdt & 1023); FD_ZERO(&rfds); FD_SET(fd,&rfds); if (select(fd + 1,&rfds,(fd_set *) 0,(fd_set *) 0,&tv) == -1) return -1; if (FD_ISSET(fd,&rfds)) return read(fd,buf,len); - shutdown(fd,0); errno = error_timeout; return -1; } diff --git a/timeoutread.h b/timeoutread.h index c1d19a0..20d3bfc 100644 --- a/timeoutread.h +++ b/timeoutread.h @@ -1,8 +1,6 @@ #ifndef TIMEOUTREAD_H #define TIMEOUTREAD_H -#define TIMEOUTREAD(s,fd) (((s) << 10) | (fd)) - extern int timeoutread(); #endif diff --git a/timeoutwrite.c b/timeoutwrite.c index 8a09c8a..516d283 100644 --- a/timeoutwrite.c +++ b/timeoutwrite.c @@ -3,23 +3,20 @@ #include "error.h" #include "readwrite.h" -int timeoutwrite(fdt,buf,len) int fdt; char *buf; int len; +int timeoutwrite(t,fd,buf,len) int t; int fd; char *buf; int len; { fd_set wfds; struct timeval tv; - int fd; - tv.tv_sec = (fdt >> 10); + tv.tv_sec = t; tv.tv_usec = 0; - fd = (fdt & 1023); FD_ZERO(&wfds); FD_SET(fd,&wfds); if (select(fd + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1; if (FD_ISSET(fd,&wfds)) return write(fd,buf,len); - shutdown(fd,1); errno = error_timeout; return -1; } diff --git a/timeoutwrite.h b/timeoutwrite.h index c93aa18..4725861 100644 --- a/timeoutwrite.h +++ b/timeoutwrite.h @@ -1,8 +1,6 @@ #ifndef TIMEOUTWRITE_H #define TIMEOUTWRITE_H -#define TIMEOUTWRITE(s,fd) (((s) << 10) | (fd)) - extern int timeoutwrite(); #endif diff --git a/token822.c b/token822.c index 7760159..48a4388 100644 --- a/token822.c +++ b/token822.c @@ -306,6 +306,7 @@ stralloc *buf; default: do { + if (sa->s[i] == '\\') if (++i >= salen) break; ++numchars; if (++i >= salen) break; @@ -384,6 +385,7 @@ stralloc *buf; t->type = TOKEN822_ATOM; t->s = cbuf; t->slen = 0; do { + if (sa->s[i] == '\\') if (++i >= salen) break; *cbuf++ = sa->s[i]; ++t->slen; if (++i >= salen) break; diff --git a/wait_pid.c b/wait_pid.c index 8dde830..d7a7e84 100644 --- a/wait_pid.c +++ b/wait_pid.c @@ -1,13 +1,39 @@ #include #include #include "error.h" +#include "haswaitp.h" + +#ifdef HASWAITPID -/* restriction: you must not care about any other child. */ int wait_pid(wstat,pid) int *wstat; int pid; { int r; + do + r = waitpid(pid,wstat,0); + while ((r == -1) && (errno == error_intr)); + return r; +} + +#else + +/* XXX untested */ +/* XXX breaks down with more than two children */ +static int oldpid = 0; +static int oldwstat; /* defined if(oldpid) */ + +int wait_pid(wstat,pid) int *wstat; int pid; +{ + int r; + + if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; } + + do { r = wait(wstat); - while ((r != pid) && ((r != -1) || (errno == error_intr))); + if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; } + } + while ((r == -1) && (errno == error_intr)); return r; } + +#endif -- 2.11.0