summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Denker <jsd@av8n.com>2012-06-02 01:58:45 (GMT)
committerJohn Denker <jsd@av8n.com>2012-06-02 01:58:45 (GMT)
commitb732a73bc773789894466b0e5320b2f1fe42c7e9 (patch)
tree385358983f064a1f10a5080b33a3ba13010886db
parent634d365a03cb0581a062cd3cf4db9ae69f1cde26 (diff)
original, as downloaded from http://www.qmail.org/netqmail-1.06.tar.gz
-rw-r--r--BIN.Makefile24
-rw-r--r--BIN.README19
-rw-r--r--BLURB43
-rw-r--r--BLURB226
-rw-r--r--BLURB393
-rw-r--r--BLURB444
-rw-r--r--CHANGES1484
-rw-r--r--COPYRIGHT33
-rw-r--r--FAQ709
-rw-r--r--FILES434
-rw-r--r--INSTALL1
-rw-r--r--INSTALL.alias40
-rw-r--r--INSTALL.ctl38
-rw-r--r--INSTALL.ids72
-rw-r--r--INSTALL.maildir59
-rw-r--r--INSTALL.mbox53
-rw-r--r--INSTALL.vsm50
-rw-r--r--INTERNALS156
-rw-r--r--Makefile2141
-rw-r--r--PIC.local2alias37
-rw-r--r--PIC.local2ext41
-rw-r--r--PIC.local2local40
-rw-r--r--PIC.local2rem38
-rw-r--r--PIC.local2virt44
-rw-r--r--PIC.nullclient38
-rw-r--r--PIC.relaybad8
-rw-r--r--PIC.relaygood33
-rw-r--r--PIC.rem2local36
-rw-r--r--README295
-rw-r--r--REMOVE.binmail16
-rw-r--r--REMOVE.sendmail28
-rw-r--r--SECURITY131
-rw-r--r--SENDMAIL76
-rw-r--r--SYSDEPS17
-rw-r--r--TARGETS387
-rw-r--r--TEST.deliver82
-rw-r--r--TEST.receive41
-rw-r--r--THANKS338
-rw-r--r--THOUGHTS418
-rw-r--r--TODO23
-rw-r--r--UPGRADE66
-rw-r--r--VERSION1
-rw-r--r--addresses.5260
-rw-r--r--alloc.362
-rw-r--r--alloc.c32
-rw-r--r--alloc.h8
-rw-r--r--alloc_re.c17
-rw-r--r--auto-gid.c51
-rw-r--r--auto-int.c40
-rw-r--r--auto-int8.c40
-rw-r--r--auto-str.c44
-rw-r--r--auto-uid.c51
-rw-r--r--auto_break.h6
-rw-r--r--auto_patrn.h6
-rw-r--r--auto_qmail.h6
-rw-r--r--auto_spawn.h6
-rw-r--r--auto_split.h6
-rw-r--r--auto_uids.h16
-rw-r--r--auto_usera.h6
-rw-r--r--binm1+df.sh11
-rw-r--r--binm1.sh10
-rw-r--r--binm2+df.sh11
-rw-r--r--binm2.sh10
-rw-r--r--binm3+df.sh11
-rw-r--r--binm3.sh10
-rw-r--r--bouncesaying.171
-rw-r--r--bouncesaying.c41
-rw-r--r--byte.h13
-rw-r--r--byte_chr.c20
-rw-r--r--byte_copy.c14
-rw-r--r--byte_cr.c16
-rw-r--r--byte_diff.c16
-rw-r--r--byte_rchr.c23
-rw-r--r--byte_zero.c13
-rw-r--r--case.3100
-rw-r--r--case.h13
-rw-r--r--case_diffb.c21
-rw-r--r--case_diffs.c19
-rw-r--r--case_lowerb.c14
-rw-r--r--case_lowers.c12
-rw-r--r--case_starts.c18
-rw-r--r--cdb.362
-rw-r--r--cdb.h12
-rw-r--r--cdb_hash.c16
-rw-r--r--cdb_seek.c94
-rw-r--r--cdb_unpack.c12
-rw-r--r--cdbmake.h35
-rw-r--r--cdbmake_add.c118
-rw-r--r--cdbmake_hash.c10
-rw-r--r--cdbmake_pack.c11
-rw-r--r--cdbmss.c65
-rw-r--r--cdbmss.h16
-rw-r--r--chkshsgr.c9
-rw-r--r--chkspawn.c48
-rw-r--r--coe.325
-rw-r--r--coe.c8
-rw-r--r--coe.h6
-rw-r--r--commands.c40
-rw-r--r--commands.h12
-rw-r--r--condredirect.163
-rw-r--r--condredirect.c85
-rw-r--r--conf-break9
-rw-r--r--conf-cc3
-rw-r--r--conf-groups6
-rw-r--r--conf-ld3
-rw-r--r--conf-patrn6
-rw-r--r--conf-qmail11
-rw-r--r--conf-spawn5
-rw-r--r--conf-split3
-rw-r--r--conf-users15
-rw-r--r--config-fast.sh30
-rw-r--r--config.sh64
-rw-r--r--constmap.c114
-rw-r--r--constmap.h20
-rw-r--r--control.c130
-rw-r--r--control.h10
-rw-r--r--date822fmt.c29
-rw-r--r--date822fmt.h7
-rw-r--r--datemail.sh1
-rw-r--r--datetime.373
-rw-r--r--datetime.c55
-rw-r--r--datetime.h20
-rw-r--r--datetime_un.c35
-rw-r--r--direntry.336
-rw-r--r--direntry.h18
-rw-r--r--direntry.h28
-rw-r--r--dns.c398
-rw-r--r--dns.h14
-rw-r--r--dnscname.c25
-rw-r--r--dnsdoe.c16
-rw-r--r--dnsdoe.h6
-rw-r--r--dnsfq.c32
-rw-r--r--dnsip.c34
-rw-r--r--dnsmxip.c40
-rw-r--r--dnsptr.c27
-rw-r--r--dot-qmail.9394
-rw-r--r--elq.sh1
-rw-r--r--env.331
-rw-r--r--env.c113
-rw-r--r--env.h17
-rw-r--r--envelopes.5231
-rw-r--r--envread.c30
-rw-r--r--error.345
-rw-r--r--error.c95
-rw-r--r--error.h23
-rw-r--r--error_str.319
-rw-r--r--error_str.c276
-rw-r--r--error_temp.327
-rw-r--r--error_temp.c80
-rw-r--r--except.133
-rw-r--r--except.c37
-rw-r--r--exit.h6
-rw-r--r--extra.h7
-rw-r--r--fd.h7
-rw-r--r--fd_copy.344
-rw-r--r--fd_copy.c13
-rw-r--r--fd_move.341
-rw-r--r--fd_move.c11
-rw-r--r--fifo.c10
-rw-r--r--fifo.h6
-rw-r--r--fifo_make.324
-rw-r--r--find-systype.sh144
-rw-r--r--fmt.h25
-rw-r--r--fmt_str.c12
-rw-r--r--fmt_strn.c12
-rw-r--r--fmt_uint.c6
-rw-r--r--fmt_uint0.c10
-rw-r--r--fmt_ulong.c13
-rw-r--r--fmtqfn.c24
-rw-r--r--fmtqfn.h8
-rw-r--r--forgeries.7104
-rw-r--r--fork.h17
-rw-r--r--fork.h27
-rw-r--r--forward.124
-rw-r--r--forward.c60
-rw-r--r--gen_alloc.h7
-rw-r--r--gen_allocdefs.h34
-rw-r--r--getln.351
-rw-r--r--getln.c20
-rw-r--r--getln.h7
-rw-r--r--getln2.364
-rw-r--r--getln2.c31
-rw-r--r--gfrom.c10
-rw-r--r--gfrom.h6
-rw-r--r--headerbody.c87
-rw-r--r--headerbody.h6
-rw-r--r--hfield.c125
-rw-r--r--hfield.h38
-rw-r--r--hier.c252
-rw-r--r--home+df.sh9
-rw-r--r--home.sh7
-rw-r--r--hostname.c17
-rw-r--r--idedit.c147
-rw-r--r--install-big.c285
-rw-r--r--install.c164
-rw-r--r--instcheck.c108
-rw-r--r--ip.c53
-rw-r--r--ip.h11
-rw-r--r--ipalloc.c7
-rw-r--r--ipalloc.h14
-rw-r--r--ipme.c100
-rw-r--r--ipme.h12
-rw-r--r--ipmeprint.c24
-rw-r--r--lock.h8
-rw-r--r--lock_ex.c11
-rw-r--r--lock_exnb.c11
-rw-r--r--lock_un.c11
-rw-r--r--maildir.5239
-rw-r--r--maildir.c108
-rw-r--r--maildir.h12
-rw-r--r--maildir2mbox.153
-rw-r--r--maildir2mbox.c162
-rw-r--r--maildirmake.115
-rw-r--r--maildirmake.c24
-rw-r--r--maildirwatch.123
-rw-r--r--maildirwatch.c125
-rw-r--r--mailsubj.138
-rw-r--r--mailsubj.sh7
-rw-r--r--make-compile.sh1
-rw-r--r--make-load.sh2
-rw-r--r--make-makelib.sh16
-rw-r--r--mbox.5235
-rw-r--r--myctime.c37
-rw-r--r--myctime.h6
-rw-r--r--ndelay.c13
-rw-r--r--ndelay.h7
-rw-r--r--ndelay_off.c13
-rw-r--r--newfield.c68
-rw-r--r--newfield.h12
-rw-r--r--now.314
-rw-r--r--now.c8
-rw-r--r--now.h8
-rw-r--r--old-patches/README3
-rw-r--r--old-patches/netqmail-1.04.patch414
-rw-r--r--old-patches/qmail-isoc.patch362
-rw-r--r--open.h10
-rw-r--r--open_append.c6
-rw-r--r--open_excl.c6
-rw-r--r--open_read.c6
-rw-r--r--open_trunc.c6
-rw-r--r--open_write.c6
-rw-r--r--other-patches/README51
-rw-r--r--other-patches/checkpassword-0.90.errno.patch12
-rw-r--r--other-patches/daemontools-0.76.errno.patch12
-rw-r--r--other-patches/djbdns-1.05.errno.patch12
-rw-r--r--other-patches/dot-forward-0.71.errno.patch12
-rw-r--r--other-patches/fastforward-0.51.errno.patch22
-rw-r--r--other-patches/mess822-0.58.errno.patch33
-rw-r--r--other-patches/qmailanalog-0.70.errno.patch87
-rw-r--r--other-patches/serialmail-0.75.errno.patch23
-rw-r--r--other-patches/ucspi-tcp-0.88.a_record.patch64
-rw-r--r--other-patches/ucspi-tcp-0.88.errno.patch12
-rw-r--r--other-patches/ucspi-tcp-0.88.nodefaultrbl.patch28
-rw-r--r--pinq.sh1
-rw-r--r--predate.c116
-rw-r--r--preline.157
-rw-r--r--preline.c90
-rw-r--r--prioq.c58
-rw-r--r--prioq.h15
-rw-r--r--proc+df.sh9
-rw-r--r--proc.sh7
-rw-r--r--prot.c21
-rw-r--r--prot.h7
-rw-r--r--qail.sh1
-rw-r--r--qbiff.131
-rw-r--r--qbiff.c113
-rw-r--r--qlx.h18
-rw-r--r--qmail-clean.813
-rw-r--r--qmail-clean.c98
-rw-r--r--qmail-command.8149
-rw-r--r--qmail-control.978
-rw-r--r--qmail-getpw.9114
-rw-r--r--qmail-getpw.c88
-rw-r--r--qmail-header.5332
-rw-r--r--qmail-inject.8309
-rw-r--r--qmail-inject.c773
-rw-r--r--qmail-limits.930
-rw-r--r--qmail-local.899
-rw-r--r--qmail-local.c698
-rw-r--r--qmail-log.5266
-rw-r--r--qmail-lspawn.846
-rw-r--r--qmail-lspawn.c234
-rw-r--r--qmail-newmrh.941
-rw-r--r--qmail-newmrh.c70
-rw-r--r--qmail-newu.943
-rw-r--r--qmail-newu.c137
-rw-r--r--qmail-pop3d.843
-rw-r--r--qmail-pop3d.c305
-rw-r--r--qmail-popup.865
-rw-r--r--qmail-popup.c183
-rw-r--r--qmail-pw2u.9241
-rw-r--r--qmail-pw2u.c312
-rw-r--r--qmail-qmqpc.829
-rw-r--r--qmail-qmqpc.c159
-rw-r--r--qmail-qmqpd.825
-rw-r--r--qmail-qmqpd.c174
-rw-r--r--qmail-qmtpd.832
-rw-r--r--qmail-qmtpd.c268
-rw-r--r--qmail-qread.824
-rw-r--r--qmail-qread.c175
-rw-r--r--qmail-qstat.818
-rw-r--r--qmail-qstat.sh7
-rw-r--r--qmail-queue.8161
-rw-r--r--qmail-queue.c254
-rw-r--r--qmail-remote.8205
-rw-r--r--qmail-remote.c427
-rw-r--r--qmail-rspawn.821
-rw-r--r--qmail-rspawn.c103
-rw-r--r--qmail-send.9246
-rw-r--r--qmail-send.c1612
-rw-r--r--qmail-showctl.812
-rw-r--r--qmail-showctl.c306
-rw-r--r--qmail-smtpd.8179
-rw-r--r--qmail-smtpd.c421
-rw-r--r--qmail-start.994
-rw-r--r--qmail-start.c120
-rw-r--r--qmail-tcpok.824
-rw-r--r--qmail-tcpok.c35
-rw-r--r--qmail-tcpto.830
-rw-r--r--qmail-tcpto.c85
-rw-r--r--qmail-upq.sh14
-rw-r--r--qmail-users.9113
-rw-r--r--qmail.768
-rw-r--r--qmail.c136
-rw-r--r--qmail.h24
-rw-r--r--qreceipt.133
-rw-r--r--qreceipt.c131
-rw-r--r--qsmhook.c137
-rw-r--r--qsutil.c46
-rw-r--r--qsutil.h12
-rw-r--r--quote.c83
-rw-r--r--quote.h8
-rw-r--r--rcpthosts.c60
-rw-r--r--rcpthosts.h7
-rw-r--r--readsubdir.c49
-rw-r--r--readsubdir.h20
-rw-r--r--readwrite.h7
-rw-r--r--received.c71
-rw-r--r--received.h6
-rw-r--r--remoteinfo.c77
-rw-r--r--remoteinfo.h6
-rw-r--r--scan.h27
-rw-r--r--scan_8long.c11
-rw-r--r--scan_ulong.c11
-rw-r--r--seek.h15
-rw-r--r--seek_cur.c7
-rw-r--r--seek_end.c7
-rw-r--r--seek_set.c7
-rw-r--r--seek_trunc.c5
-rw-r--r--select.h18
-rw-r--r--select.h29
-rw-r--r--sendmail.c162
-rw-r--r--sgetopt.328
-rw-r--r--sgetopt.c54
-rw-r--r--sgetopt.h21
-rw-r--r--sig.h43
-rw-r--r--sig_alarm.c7
-rw-r--r--sig_block.c40
-rw-r--r--sig_bug.c17
-rw-r--r--sig_catch.c18
-rw-r--r--sig_child.c7
-rw-r--r--sig_hup.c7
-rw-r--r--sig_misc.c17
-rw-r--r--sig_pause.c14
-rw-r--r--sig_pipe.c5
-rw-r--r--sig_term.c7
-rw-r--r--slurpclose.c19
-rw-r--r--slurpclose.h6
-rw-r--r--spawn.c260
-rw-r--r--splogger.860
-rw-r--r--splogger.c72
-rw-r--r--str.h14
-rw-r--r--str_chr.c19
-rw-r--r--str_cpy.c16
-rw-r--r--str_diff.c17
-rw-r--r--str_diffn.c18
-rw-r--r--str_len.c15
-rw-r--r--str_rchr.c22
-rw-r--r--str_start.c15
-rw-r--r--stralloc.3160
-rw-r--r--stralloc.h21
-rw-r--r--stralloc_arts.c12
-rw-r--r--stralloc_cat.c9
-rw-r--r--stralloc_catb.c15
-rw-r--r--stralloc_cats.c10
-rw-r--r--stralloc_copy.c9
-rw-r--r--stralloc_eady.c6
-rw-r--r--stralloc_opyb.c14
-rw-r--r--stralloc_opys.c10
-rw-r--r--stralloc_pend.c5
-rw-r--r--strerr.h80
-rw-r--r--strerr_die.c37
-rw-r--r--strerr_sys.c12
-rw-r--r--subfd.h15
-rw-r--r--subfderr.c7
-rw-r--r--subfdin.c13
-rw-r--r--subfdins.c13
-rw-r--r--subfdout.c7
-rw-r--r--subfdouts.c7
-rw-r--r--subgetopt.3357
-rw-r--r--subgetopt.c79
-rw-r--r--subgetopt.h24
-rw-r--r--substdi.c91
-rw-r--r--substdio.c15
-rw-r--r--substdio.h47
-rw-r--r--substdio_copy.c18
-rw-r--r--substdo.c108
-rw-r--r--tcp-env.167
-rw-r--r--tcp-env.c129
-rw-r--r--tcp-environ.562
-rw-r--r--tcpto.c165
-rw-r--r--tcpto.h8
-rw-r--r--tcpto_clean.c20
-rw-r--r--timeoutconn.c59
-rw-r--r--timeoutconn.h6
-rw-r--r--timeoutread.c22
-rw-r--r--timeoutread.h6
-rw-r--r--timeoutwrite.c22
-rw-r--r--timeoutwrite.h6
-rw-r--r--token822.c513
-rw-r--r--token822.h37
-rw-r--r--trigger.c41
-rw-r--r--trigger.h8
-rw-r--r--triggerpull.c16
-rw-r--r--triggerpull.h6
-rw-r--r--trycpp.c7
-rw-r--r--trydrent.c8
-rw-r--r--tryflock.c8
-rw-r--r--trylsock.c4
-rw-r--r--trymkffo.c7
-rw-r--r--trynpbg1.c26
-rw-r--r--tryrsolv.c4
-rw-r--r--trysalen.c11
-rw-r--r--trysgact.c10
-rw-r--r--trysgprm.c10
-rw-r--r--tryshsgr.c14
-rw-r--r--trysysel.c8
-rw-r--r--trysyslog.c9
-rw-r--r--tryulong32.c11
-rw-r--r--tryvfork.c4
-rw-r--r--trywaitp.c7
-rw-r--r--uint32.h16
-rw-r--r--uint32.h26
-rw-r--r--wait.393
-rw-r--r--wait.h14
-rw-r--r--wait_nohang.c12
-rw-r--r--wait_pid.c39
-rw-r--r--warn-auto.sh2
-rw-r--r--warn-shsgr3
449 files changed, 32673 insertions, 0 deletions
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/BLURB b/BLURB
new file mode 100644
index 0000000..7bcfb3f
--- /dev/null
+++ b/BLURB
@@ -0,0 +1,43 @@
+qmail is a secure, reliable, efficient, simple message transfer agent.
+It is meant as a replacement for the entire sendmail-binmail system on
+typical Internet-connected UNIX hosts.
+
+Secure: Security isn't just a goal, but an absolute requirement. Mail
+delivery is critical for users; it cannot be turned off, so it must be
+completely secure. (This is why I started writing qmail: I was sick of
+the security holes in sendmail and other MTAs.)
+
+Reliable: qmail's straight-paper-path philosophy guarantees that a
+message, once accepted into the system, will never be lost. qmail also
+supports maildir, a new, super-reliable user mailbox format. Maildirs,
+unlike mbox files and mh folders, won't be corrupted if the system
+crashes during delivery. Even better, not only can a user safely read
+his mail over NFS, but any number of NFS clients can deliver mail to him
+at the same time.
+
+Efficient: On a Pentium under BSD/OS, qmail can easily sustain 200000
+local messages per day---that's separate messages injected and delivered
+to mailboxes in a real test! Although remote deliveries are inherently
+limited by the slowness of DNS and SMTP, qmail overlaps 20 simultaneous
+deliveries by default, so it zooms quickly through mailing lists. (This
+is why I finished qmail: I had to get a big mailing list set up.)
+
+Simple: qmail is vastly smaller than any other Internet MTA. Some
+reasons why: (1) Other MTAs have separate forwarding, aliasing, and
+mailing list mechanisms. qmail has one simple forwarding mechanism that
+lets users handle their own mailing lists. (2) Other MTAs offer a
+spectrum of delivery modes, from fast+unsafe to slow+queued. qmail-send
+is instantly triggered by new items in the queue, so the qmail system
+has just one delivery mode: fast+queued. (3) Other MTAs include, in
+effect, a specialized version of inetd that watches the load average.
+qmail's design inherently limits the machine load, so qmail-smtpd can
+safely run from your system's inetd.
+
+Replacement for sendmail: qmail supports host and user masquerading,
+full host hiding, virtual domains, null clients, list-owner rewriting,
+relay control, double-bounce recording, arbitrary RFC 822 address lists,
+cross-host mailing list loop detection, per-recipient checkpointing,
+downed host backoffs, independent message retry schedules, etc. In
+short, it's up to speed on modern MTA features. qmail also includes a
+drop-in ``sendmail'' wrapper so that it will be used transparently by
+your current UAs.
diff --git a/BLURB2 b/BLURB2
new file mode 100644
index 0000000..1a98d0e
--- /dev/null
+++ b/BLURB2
@@ -0,0 +1,26 @@
+Mailing list management is one of qmail's strengths. Notable features:
+
+* qmail lets each user handle his own mailing lists. The delivery
+instructions for user-whatever go into ~user/.qmail-whatever.
+
+* qmail makes it really easy to set up mailing list owners. If the user
+touches ~user/.qmail-whatever-owner, all bounces will come back to him.
+
+* qmail supports VERPs, which permit completely reliable automated
+bounce handling for mailing lists of any size.
+
+* SPEED---qmail blasts through mailing lists an order of magnitude
+faster than sendmail. For example, one message was successfully
+delivered to 150 hosts around the world in just 70 seconds, with qmail's
+out-of-the-box configuration.
+
+* qmail automatically prevents mailing list loops, even across hosts.
+
+* 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
new file mode 100644
index 0000000..5f8af6d
--- /dev/null
+++ b/BLURB3
@@ -0,0 +1,93 @@
+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 (config, config-fast)
+* quick installation---no big list of decisions to make
+
+Security:
+* clear separation between addresses, files, and programs
+* minimization of setuid code (qmail-queue)
+* minimization of root code (qmail-start, qmail-lspawn)
+* five-way trust partitioning---security in depth
+* optional logging of one-way hashes, entire contents, etc. (QUEUE_EXTRA)
+
+Message construction (qmail-inject):
+* RFC 822, RFC 1123
+* full support for address groups
+* 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)
+* automatic Mail-Followup-To creation ($QMAILMFTFILE)
+
+SMTP service (qmail-smtpd):
+* RFC 821, RFC 1123, RFC 1651, RFC 1652, RFC 1854
+* 8-bit clean
+* 931/1413/ident/TAP callback (tcp-env)
+* relay control---stop unauthorized relaying by outsiders (control/rcpthosts)
+* no interference between relay control and forwarding
+* tcpd hook---reject SMTP connections from known abusers
+* automatic recognition of local IP addresses
+* per-buffer timeouts
+* hop counting
+
+Queue management (qmail-send):
+* instant handling of messages added to queue
+* parallelism limit (control/concurrencyremote, control/concurrencylocal)
+* split queue directory---no slowdown when queue gets big
+* quadratic retry schedule---old messages tried less often
+* independent message retry schedules
+* automatic safe queueing---no loss of mail if system crashes
+* automatic per-recipient checkpointing
+* automatic queue cleanups (qmail-clean)
+* queue viewing (qmail-qread)
+* detailed delivery statistics (qmailanalog, available separately)
+
+Bounces (qmail-send):
+* QSBMF bounce messages---both machine-readable and human-readable
+* HCMSSC support---language-independent RFC 1893 error codes
+* double bounces sent to postmaster
+
+Routing by domain (qmail-send):
+* any number of names for local host (control/locals)
+* any number of virtual domains (control/virtualdomains)
+* domain wildcards (control/virtualdomains)
+* configurable percent hack support (control/percenthack)
+* UUCP hook
+
+SMTP delivery (qmail-remote):
+* RFC 821, RFC 974, RFC 1123
+* 8-bit clean
+* automatic downed host backoffs
+* artificial routing---smarthost, localnet, mailertable (control/smtproutes)
+* per-buffer timeouts
+* passive SMTP queue---perfect for SLIP/PPP (serialmail, available separately)
+
+Forwarding and mailing lists (qmail-local):
+* address wildcards (.qmail-default, .qmail-foo-default, etc.)
+* 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 mailing list management (ezmlm, available separately)
+
+Local delivery (qmail-local):
+* user-controlled address hierarchy---fred controls fred-anything
+* mbox delivery
+* reliable NFS delivery (maildir)
+* user-controlled program delivery: procmail etc. (qmail-command)
+* optional new-mail notification (qbiff)
+* optional NRUDT return receipts (qreceipt)
+* conditional filtering (condredirect, bouncesaying)
+
+POP3 service (qmail-popup, qmail-pop3d):
+* RFC 1939
+* UIDL support
+* TOP support
+* APOP hook
+* modular password checking (checkpassword, available separately)
diff --git a/BLURB4 b/BLURB4
new file mode 100644
index 0000000..6c4eaac
--- /dev/null
+++ b/BLURB4
@@ -0,0 +1,44 @@
+qmail's modular, lightweight design and sensible queue management make
+it the fastest available message transfer agent. Here's how it stacks up
+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
+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
+accustamp and written to disk as usual.)
+
+* Local mailing lists: When qmail is delivering a message to a mailbox,
+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
+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
+per day on the SparcStation.
+
+* Mailing lists with remote recipients: qmail uses the same delivery
+strategy that makes LSOFT's LSMTP so fast for outgoing mailing lists---
+you choose how many parallel SMTP connections you want to run, and qmail
+runs exactly that many. Of course, performance varies depending on how
+far away your recipients are. The advantage of qmail over other packages
+is its smallness: for example, one Linux user is running 60 simultaneous
+connections, without swapping, on a machine with just 16MB of memory!
+
+* Separate local messages: What LSOFT doesn't tell you about LSMTP is
+how many _separate_ messages it can handle in a day. Does it get bogged
+down as the queue fills up? On my home machine, I disabled qmail's
+deliveries and then sent 5000 separate messages to one recipient. The
+messages were all safely written to the queue disk in 23 minutes, with
+no slowdown as the queue filled up. After I reenabled deliveries, all
+the messages were delivered to the recipient's mailbox in under 12
+minutes. End-to-end rate: more than 200000 individual messages a day!
+
+* Overall performance: What really matters is how well qmail performs
+with your mail load. Red Hat Software found one day that their mail hub,
+a 48MB Pentium running sendmail 8.7, was running out of steam at 70000
+messages a day. They shifted the load to qmail---on a _smaller_ machine,
+a 16MB 486/66---and now they're doing fine.
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..bb20670
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,1484 @@
+20071130 version: netqmail 1.06
+20071130 legal: qmail-1.03 is now in the public domain
+20051103 doc: dot-qmail.9 updated for changed (19980613) conf-patrn default, tnx ADM
+20040121 version: netqmail 1.05
+20040121 code: qmail-smtpd is protected from exceedingly long (eg 2GB)
+ header lines
+20040121 code: qmail_lspawn, qmail-newmrh, qmail-newu, and qmail-rspawn
+ are protected from misbehaving on hosts where the size of an
+ integer is not the same as the size of a character pointer
+ (eg 64 bit hosts with 32 bit ints)
+20031027 version: netqmail 1.04.
+20031027 doc: INSTALL points to http://lifewithqmail.org/lwq.html
+20031027 doc: qmail.7 identifies installation as netqmail and points to
+ http://qmail.org/
+20031027 doc: qmail-queue.8 adds explanation of $QMAILQUEUE
+20031027 doc: qmail-log.5 adds reference to errors from $QMAILQUEUE script
+20031027 doc: FAQ also points to http://cr.yp.to/qmail/faq.html and
+ http://qmail.org/
+20031027 code: qmail-smtpd identifies itself as netqmail
+20031027 code: if $QMAILQUEUE is set, it's invoked instead of qmail-queue
+20031024 code: changed errno from int to #include.
+20031024 code: fixed .qmail parsing bug.
+20031024 code: recognize 0.0.0.0 as a local address.
+20031024 code: sendmail's -f flag now overrides environment variables.
+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().
+19970414 code: implemented recipientmap. suggested by RDM.
+19970414 doc: auto-configured qmail home directory in qmail-control.5,
+ qmail-newu.8, qmail-pw2u.8, qmail-start.8, qmail-users.5.
+19970414 port: Solaris needs socket libs for gethostname. impact: can't
+ compile under Solaris. fix: use socket.lib for qmail-local.
+19970412 code: introduced stralloc_starts.
+19970412 code: introduced str_equal.
+19970412 code: introduced str_start.
+19970412 code: introduced byte_equal.
+19970412 code: made an optional aliasempty arg for qmail-start.
+19970412 code: made an aliasempty arg for qmail-lspawn.
+19970412 code: changed ALIAS_EMPTY to an arg for qmail-local.
+19970412 port: UnixWare returns >0 for SIOCGIFCONF. impact: ipme fails
+ under UnixWare. fix: check for >=0, not =0. tnx JD.
+19970412 port: DGUX does not have ranlib. impact: can't compile under
+ DGUX. fix: added dgux line to make-makelib. tnx HWM.
+19970412 code: changed maildir library to skip any filename beginning
+ with dot. tnx SP.
+19970412 doc: added FAQ entry about aliases with dots.
+19970412 doc: clarified in qmail-inject.8 that default envelope sender
+ is the same as _default_ From address.
+19970411 code: renamed qmail-makectl as qmail-config.
+19970411 code: renamed qmail-alias as qmail-local.
+19970411 code: switched from signal library to sig library.
+19970411 code: switched from qqtalk library to qmail library.
+19970411 code: switched from getline library to getln library.
+19970411 code: massive library cleanups.
+19970411 code: revamped autoconfiguration system.
+19970411 code: revamped configuration interface.
+19970411 code: eliminated qmail-home.
+19970411 code: eliminated tokenize.
+19970220 qmail 1.00.
+19970219 change: various documentation tweaks.
+19970218 change: updated THOUGHTS.
+19970218 change: talked about SPAWN_NUMD in FAQ. tnx EC.
+19970210 change: noted in maildir.5 that readers should skip any name
+ starting with a dot. tnx SP.
+19970209 change: added note to splogger.8 about reliability. tnx BT.
+19970209 change: added section to FAQ on slow sendmail switch. tnx BT.
+19970206 change: added section to FAQ about dtcm. tnx PJG.
+19970206 change: tweaked maildir.5.
+19970201 change: added MH spost note to FAQ. tnx TU.
+19970131 change: reorganized FAQ.
+19970131 change: added web references to FAQ.
+19970124 change: tweaked qmail-upgrade man page.
+19970120 qmail 0.96, gamma.
+19970120 change: removed various try* in auto-configuration.
+19970120 bug: qmail-inject fails to quote argument addresses. impact:
+ addresses containing special characters could be misinterpreted
+ or rejected. tnx C2F. fix: use quote2().
+19970120 portability problem: ESIX puts syslog() and openlog() into
+ -lgen. impact: can't compile under ESIX. fix: put -lgen into
+ LIBS for unix_sv. tnx RN.
+19961221 qmail 0.95, gamma.
+19961218 change: added various try* to TARGETS. tnx SA.
+19961216 change: clarified in qmail-send.8 that virtualdomains does not
+ apply to domains listed in locals.
+19961216 change: slurpclose() now closes fd on out-of-memory. makes it
+ more widely applicable.
+19961215 change: replaced elm instructions in INSTALL.mbox with an
+ explanation of what source change to make. tnx AB.
+19961212 portability problem: under NEWS-OS, time_t needs sys/types.h.
+ impact: couldn't compile under NEWS-OS. fix: include
+ sys/types.h in predate.c. tnx TU.
+19961211 change: used timeoutread, timeoutwrite in remoteinfo(). tnx
+ REB.
+19961210 portability problem: apparently some SGIs produce a systype of
+ irix64. impact: couldn't compile on those systems. fix: handle
+ irix64 in make-cmds. tnx M3S.
+19961208 change: added note to maildir2mbox.1 about mbox locking.
+19961208 qmail 0.94, gamma.
+19961207 change: added QMAILDEFAULTDOMAIN, QMAILDEFAULTHOST,
+ QMAILIDHOST, QMAILPLUSDOMAIN. tnx BTW.
+19961206 cleanup: readsubdir() protects itself against name overflow,
+ rather than depending on caller.
+19961204 change: changed FAQ 7.3 to prohibit fixup relaying.
+19961203 change: added note to FAQ about possibly having to put a space
+ before "$SENDER" for uux. tnx FW.
+19961202 change: added FAQ entry on QUEUE_EXTRA.
+19961202 change: added FAQ entry on backups. tnx DP.
+19961202 change: added note to INSTALL.mbox about qpopper. tnx VV.
+19961201 change: replaced logger with splogger in FAQ 5.1. tnx FPL.
+19961201 change: used netmask example for tcpcontrol in FAQ. tnx FPL.
+19961201 change: added note to README about the mailing list. tnx FPL.
+19961201 change: documented rcpthosts wildcards. tnx RN.
+19961201 change: added note to FAQ about making mailx use datemail.
+19961201 change: added datemail. function requested by several people;
+ approach suggested by TG.
+19961201 change: added predate.
+19961129 change: added QUEUE_EXTRA, QUEUE_EXTRALEN.
+19961129 change: qmail-remote bounces messages with partial final lines.
+19961129 change: added atomcheck() to quote crappy atoms.
+19961129 change: revised atomok() to let atoms deal with more crap.
+19961127 change: qmail-send adds note to deferral if flagdying. tnx TG.
+19961127 change: split off maildirbounce, maildir2qmtp, and maildir2smtp
+ into a separate serialmail package.
+19961126 change: eliminated beta success reports from README.
+19961124 change: forced res_query() return value to fit inside incoming
+ buffer size. allegedly there are buggy versions of res_query()
+ that don't guarantee this.
+19961122 qmail 0.93, gamma.
+19961122 change: allowed empty arg list in forward.
+19961121 change: qmail-smtpd now uses unknown (like qmail-qmtpd) rather
+ than dying if environment variables are not set.
+19961121 cleanup: reorganized helo handling in qmail-smtpd.c.
+19961121 cleanup: eliminated newfield_rec.
+19961121 cleanup: introduced DATE822FMT. used it in received.c.
+19961121 cleanup: introduced received.c. used it in qmail-qmtpd.c,
+ qmail-smtpd.c.
+19961121 change: qmail-smtpd now generates a new timestamp for each
+ message. tnx PJG.
+19961121 cleanup: used stralloc in newfield.
+19961121 cleanup: eliminated newfield_cc.
+19961121 change: eliminated hfield_mort().
+19961119 change: added 2-minute damper on tcpto.
+19961118 change: wrote defaults for readfile controls in showctl.
+19961117 change: control_readfile() now allows comments and blank lines.
+ tnx LW.
+19961117 change: qmail-start sets logger gid to GID_NOFILES.
+19961117 bug: ipme_init() uses a fixed-length buffer for SIOCGIFCONF.
+ impact: qmail-smtpd and qmail-remote will die if there are too
+ many local IP addresses. tnx MD. fix: ipme_init() now
+ dynamically allocates space, up to 200000 bytes, as long as
+ SIOCGIFCONF keeps failing. note that this is a very widespread
+ bug; it's in amd, exim, mrouted, named, nntpd, rarpd, sendmail,
+ tcpdump, timed, xntpd, and probably dozens more programs.
+19961117 portability problem: on BSD 4.4 and various other systems,
+ SIOCGIFCONF will truncate long lists and return success.
+ impact: on those systems, qmail-smtpd and qmail-remote will
+ miss some local IP addresses if there are too many. fix:
+ ipme_init() now checks whether there is enough space left in
+ the buffer for another ifreq, plus 64 bytes JIC. yuck.
+19961117 change: ipmeprint now flushes only at end.
+19961117 cleanup: introduced subfdinsmall. used it in qmail-clean.c,
+ qmail-qmtpd.c.
+19961117 cleanup: introduced subfdoutsmall. used it in hostname.c,
+ printbreak.c, printnumd.c, printsplit.c, qmail-alias.c,
+ qmail-clean.c, qmail-getpw.c, qmail-qmtpd.c, maildir2smtp.c,
+ maildir2qmtp.c.
+19961117 change: moved subfderr buf up to 256 characters.
+19961117 change: added maildirbounce. tnx MD, TG.
+19961116 change: maildir2smtp and maildir2qmtp now print filenames for
+ permanent bounces. tnx MD.
+19961116 change: in SECURITY, ``eleven most recent sendmail security
+ holes, five'' -> ``twelve most recent sendmail security holes,
+ six.''
+19961116 change: rewrote qmail-showctl more professionally.
+19961115 change: added several tests to find-systype.sh. this will
+ affect many systypes.
+19961115 change: qmail-alias now treats most exit codes as soft errors.
+19961115 change: revamped exit codes everywhere for 0, 100, 111.
+19961114 change: added splogger.
+19961114 portability problem: Sun's cc recognizes sqrt() as a builtin,
+ even if math.h is not included and sqrt is defined statically.
+ yuck. impact: when qmail is compiled with Sun's cc, next-retry
+ times are all screwed up. tnx PJG. fix: my sqrt() is now called
+ squareroot().
+19961114 change: dns_ip() now recognizes [1.2.3.4]. tnx DS.
+19961112 change: enabled x option in sendmail. tnx DS.
+19961111 change: added SIGHUP handling to qmail-send. suggested by many
+ people.
+19961111 bug: control routines returned incorrect codes for some
+ out-of-memory conditions. impact: none; conditions cannot
+ happen with sane control files. fix: return -1.
+19961111 change: added SIGALRM handling to qmail-send. suggested by many
+ people.
+19961111 change: eliminated flagnobreak (-b/-B) from qmail-pw2u.
+19961111 change: qmail-getpw now allows hyphens inside usernames.
+19961111 change: added users/append to qmail-pw2u. tnx G2A.
+19961111 change: added badmailfrom to qmail-smtpd. requested by several
+ people.
+19961110 change: replaced elm instructions in INSTALL.mbox with a simple
+ note to set incomingfolders in elm.rc. tnx AB.
+19961110 change: replaced ``owner hack'' with ``variable envelope
+ return paths'' throughout the documentation. tnx DS.
+19961110 change: qmail-setup installs man pages as well as cat pages.
+19961110 change: renamed qmail-newuser as qmail-newu. tnx G2A.
+19961110 change: renamed qmail-pw2user as qmail-pw2u. tnx G2A.
+19961105 change: set path in INSTALL.boot. tnx TJH.
+19961105 change: noted in qmail-smtpd.8 that addresses without @ are
+ always allowed through.
+19961105 change: indicated at various spots in FAQ that rcpthosts has to
+ be updated. suggested by various people.
+19961105 change: indicated at various spots in FAQ that qmail has to be
+ restarted. suggested by various people.
+19961029 change: fixed typo in maildir2qmtp.1. tnx BG.
+19961026 qmail 0.92, gamma.
+19961026 bug: qmail-getpw did not 0-terminate usernames. tnx CF. impact:
+ qmail-getpw would crash on some systems, deferring local
+ deliveries. fix: 0-terminate.
+19961025 cleanup: renamed auto-hassgprm.h to hassgprm.h.
+19961025 cleanup: renamed auto-hassgact.h to hassgact.h.
+19961024 change: replaced qmail-alias.0 with dot-qmail.0 in
+ INSTALL.alias. tnx MW.
+19961022 change: switched uids as early as possible in qmail-start.c.
+19961022 change: in SECURITY, ``ten most recent sendmail security
+ holes, five'' -> ``eleven most recent sendmail security holes,
+ five.''
+19961022 change: quote_need() now treats non-ASCII characters the same
+ way as control characters.
+19961022 change: added version and home page to qmail.7.
+19961022 cleanup: introduced slurpclose.c. used it in qmail-alias.c,
+ qmail-lspawn.c.
+19961021 portability problem: AT&T NCR boxes need stdio.h before
+ arpa/nameser.h. impact: dns.c would not compile. fix: include
+ stdio.h. tnx HS.
+19961021 change: added AIX section to INSTALL.ids. tnx SSB.
+19961021 change: added qmail-pw2user.
+19961020 change: added qmail-pw2user.8.
+19961020 change: qmail-alias now dies soft on EACCES/EPERM for .qmail.
+19961020 change: eliminated root comments from INSTALL.qsmhook.
+19961020 change: various improvements in FAQ.
+19961017 change: added QLX_ROOT.
+19961017 change: renamed hosts in FAQ. tnx SLB.
+19961017 change: in dot-qmail.5, documented envnoathost effects. tnx RN.
+19961017 change: revamped addresses.5.
+19961017 change: added stripvdomprepend() for better bounces. tnx PT.
+19961012 portability problem: under HP-UX 9, can't setgroups() to 65537.
+ impact: couldn't compile under HP-UX 9. fix: use 0 instead of
+ 65537 in chkshsgr.c. tnx HHO.
+19961008 change: added several qlx codes.
+19961008 cleanup: eliminated qlx from qmail-alias.
+19961008 change: qmail-lspawn runs qmail-getpw as UID_PW.
+19961008 change: added qmail-newuser.
+19961008 change: added cdb support to qmail-lspawn.
+19961008 change: integrated cdb.
+19961007 change: added qmail-users.5.
+19961007 change: eliminated usermap.
+19961007 cleanup: switched execvp to execv in sendmail, qmail-lspawn.
+19961007 change: used qmail-getpw in qmail-lspawn.
+19961007 change: renamed LSPAWN_USERLEN as GETPW_USERLEN.
+19961007 change: added qmail-getpw.
+19961007 change: created users subdirectory of CONF_HOME.
+19961007 change: fixed typo in FAQ. tnx J1B.
+19961006 change: replaced subfdout with a small ss in qmail-alias.
+19961006 change: reduced qmail-alias buffer sizes to 1024.
+19961003 change: added note to maildir2smtp.0 about maildirmake. tnx SM.
+19961003 bug: if ipme_init() returned -1, qmail-remote would continue,
+ blindly assuming that all addresses are local. impact: on
+ systems with too many aliases, all remote deliveries fail. tnx
+ MD. fix: qmail-remote now dies with temp_oserr() on any result
+ other than 1.
+19961003 portability problem: all pre-4.9.4 versions of bind barf,
+ badly, on CNAME queries to lame servers. what a crappy system.
+ even if the resolver doesn't barf, the next name server down
+ the line may barf. impact: qmail can't get mail through to
+ domains that are (1) lame and (2) running old versions of bind.
+ fix: never, ever, do a CNAME query. dns_cname() now does an ANY
+ query instead. this, like sendmail's analogous procedure, is
+ unreliable when a CNAME is mixed with other records.
+19961001 cleanup: switched to libfd in qmail-start.c.
+19960929 cleanup: renamed auto-hasmkffo.h to hasmkffo.h.
+19960928 cleanup: reorganized qmail-start.c.
+19960928 cleanup: used libfd in preline.c, qmail-lspawn.c,
+ qmail-popup.c, qmail-rspawn.c, qmail-start.c, qqtalk.c,
+ qsmhook.c.
+19960928 cleanup: added libfd.
+19960927 change: in SECURITY, ``nine most recent sendmail security
+ holes, four'' -> ``ten most recent sendmail security holes,
+ five.''
+19960926 change: added tcpcontrol notes to FAQ.
+19960926 change: qmail-smtpd now immediately closes connection, with a
+ warning message dedicated to Solaris, if stray newlines show up
+ in the incoming data.
+19960926 change: added INSTALL.boot.
+19960926 portability problem: on systems that can handle IP interface
+ aliases (i.e., on sa_len systems), SIOCGIFADDR returns the
+ primary address for an alias. impact: ipme_init() did not
+ include alias addresses. fix: ipme_init() avoids SIOCGIFADDR on
+ sa_len systems; on these systems, the address we want is
+ already in ifr. tnx DM.
+19960926 change: qmail-alias kills itself if locking takes longer than
+ 30 seconds.
+19960926 change: qmail-pop3d no longer moves messages. tnx RS.
+19960924 change: added note to FAQ about descriptors limit. tnx RD.
+19960922 change: open_trunc() now uses 644.
+19960922 change: qmail-setup now does umask(077).
+19960922 change: maildir2mbox now does umask(077).
+19960922 change: moved subfderr buf up to 64 characters.
+19960920 change: in SECURITY, ``eight most recent sendmail security
+ holes, three'' -> ``nine most recent sendmail security holes,
+ four.''
+19960920 portability problem: init run commands are subject to job
+ control signals under more systems than HP-UX. impact: on some
+ systems (e.g., Solaris), qmail daemons would be killed. fix:
+ INSTALL now tells everybody to use csh -cf.
+19960920 change: added queue-run section to FAQ.
+19960920 change: in pine-crashing question in FAQ, added -oem and -oi,
+ so that change will work with the real sendmail too.
+19960919 change: added CNAME section to FAQ. tnx to various people.
+19960919 change: eliminated QQX_EXECHARD and QQT_EXECHARD. this means
+ that all qmail-queue invocation failures are now soft, even
+ things like EPERM.
+19960919 change: replaced ``No such address'' with ``Sorry, no mailbox
+ here by that name.'' tnx G2A.
+19960919 change: qmail-remote now includes host name in no-such-host
+ messages. tnx G2A.
+19960919 change: replaced ``Temporarily unable to canonicalize address''
+ with ``CNAME lookup failed temporarily.''
+19960918 change: improved an error message in qmail-alias.c. tnx TG.
+19960918 change: added SHELL=/bin/sh to Makefile. tnx JL.
+19960916 change: reorganized INSTALL.ids a bit.
+19960916 change: ``from smtpd'' is now ``from network''.
+19960916 change: SMTPD is now DAEMON.
+19960916 change: qmail-start sets logger uid to UID_LOG. tnx JLH.
+19960916 change: added CONF_USERL.
+19960916 change: iaafmt() now puts a dot on in-addr.arpa.
+19960915 change: added UPGRADE. suggested by several people.
+19960915 change: added qsutil error messages to qmail-log.5.
+19960915 change: qsutil error messages are now alerts.
+19960915 portability problem: on some systems, logger appears to use
+ syslog(pri,buf) instead of syslog(pri,"%s",buf). tnx JC.
+ impact: logger could barf or crash if fed messages containing
+ %. an attacker could easily cause a crash, eliminating qmail's
+ logs. fix: % is no longer considered safe for logs.
+19960912 cleanup: split seek.c into seek_*.c.
+19960912 cleanup: replaced seek_to() with seek_set().
+19960912 cleanup: introduced libseek.a.
+19960907 cleanup: split case.c into case_*.c.
+19960907 cleanup: introduced libcase.a.
+19960907 cleanup: split wait.c into wait_*.c.
+19960907 cleanup: introduced libwait.a.
+19960907 cleanup: renamed auto-haswaitp.h to haswaitp.h.
+19960907 cleanup: split open.c into open_*.c.
+19960907 cleanup: introduced libopen.a.
+19960904 change: added generic pointer to qmail-control.5. tnx HW.
+19960904 change: rewrote rcpthosts section in FAQ. tnx HW.
+19960904 change: added organization section to FAQ. tnx HW.
+19960902 qmail 0.91, gamma.
+19960902 change: control_readfile() can now handle partial lines. tnx
+ JDHB.
+19960902 change: eliminated non-fqdn note from FAQ. next version of
+ tcpserver will use DNS directly.
+19960902 change: qlist now uses NEWSENDER, not SENDER.
+19960902 change: qmail-pop3d no longer obtains a lock. tnx RS.
+19960902 change: put }g on all seds in Makefile.
+19960831 change: noted in qmail-control.5 that comments are not allowed
+ in control files. tnx J2B.
+19960829 change: used double union in alloc.c. tnx ME.
+19960829 change: replaced semicolon with colon for smtproutes port.
+19960829 change: in INSTALL, put make man just before make setup.
+19960829 change: changed a few qmail messages into alerts.
+19960829 cleanup: renamed datetime_gmt as datetime_tai.
+19960829 change: added note to UUCP question that some UUCP software
+ doesn't want preline -f. tnx SB.
+19960829 change: added question 2.4 to FAQ on SLIP/PPP.
+19960828 change: replaced owner- with owner-@host-@[] in qmail-inject.
+19690828 change: replaced owner- with owner-@host-@[] in qmail-alias.
+19960828 change: replaced owner- with owner-@host-@[] in injectbounce().
+19960828 change: replaced owner- with owner-@host-@[] in senderadd() for
+ owner hack.
+19960828 change: qmail-inject -n now prints Return-Path.
+19960825 cleanup: revised ending code in token_addrlist().
+19960825 change: tokenize now uses linelen 0 for unparse.
+19960825 change: if linelen is 0 in token822_unparse, no length limit.
+19960825 change: added LINELEN macro to qmail-inject for unparse.
+19960825 change: token822_unparse now takes linelen argument. (leaving
+ two spaces on the right before linelen.)
+19960824 cleanup: renamed token as token822.
+19960822 portability problem: under NEWS-OS, /bin/mail and /usr/ucb/mail
+ invoke sendmail with -E and -J options. tnx TU. impact:
+ couldn't send mail with those programs. fix: accept opts,
+ including _optional_ args. ugh.
+19960821 change: sendmail now quits if invoked as newaliases. tnx TU.
+19960821 portability problem: under NEWS-OS, dirent.h needs sys/types.h.
+ tnx TU. this POSIX violation also appears in some versions of
+ FreeBSD. impact: couldn't compile under NEWS-OS. fix: include
+ sys/types.h in direntry.h* and trydrent.c. [sigh]
+19960821 change: added concurrencyremote question to FAQ.
+19960821 change: added chkspawn.
+19960821 change: moved default SPAWN_NUMD up to 120.
+19960818 change: allowed ;port in smtproutes. tnx AL.
+19960818 change: introduced port in qmail-remote.c.
+19960818 change: qmail-queue records qp in Received lines. 2 lines of
+ code. tnx ME.
+19960818 change: in SECURITY, ``seven most recent sendmail security
+ holes'' -> ``eight most recent sendmail security holes.''
+19960818 change: qmail-pop3d now appends an extra blank line to every
+ message, for compatibility with popper. some clients can't
+ deal with the right thing, unfortunately. tnx FPL.
+19960818 change: added qmail-tcpto.
+19960818 change: eliminated cc -posix for NeXTs. tnx SA.
+19960818 change: eliminated loadfifo. tnx SA.
+19960818 change: integrated auto-configured fifo.c code from SA.
+19960817 change: put SYSDEPS into a more reasonable order.
+19960813 change: indicated possibility of duplication when qmail-remote
+ gets a dead connection after DATA. tnx ME.
+19960813 change: documented qmail-inject environment variables.
+19960813 change: supported per-recipient owner hack in qmail-inject.
+19960813 change: supported per-message owner hack in qmail-inject.
+19960813 change: introduced hackedruser into qmail-inject.
+19960813 change: introduced QMAILRUSER, QMAILRHOST.
+19960812 change: added QMAILINJECT option to allow address-comment form.
+19960812 change: made name-address form the default in qmail-inject.
+19960812 change: added QMAILINJECT options f and m to delete From and
+ Message-ID on input. tnx LL.
+19960812 change: added QMAILINJECT environment variable.
+19960812 change: added QMAILHOST, QMAILUSER, QMAILNAME to override
+ MAILHOST, MAILUSER, MAILNAME. tnx MG.
+19960812 change: added qmail-showctl.
+19960812 portability problem: under Solaris 2.4 and possibly other
+ systems, the linker does not give generic alignment to an array
+ of 4096 chars. tnx JP. impact: some subset of the programs
+ would (reliably) die with a bus error; in the Solaris case,
+ maildir2mbox. fix: redefine space in alloc.c to be aligned.
+19960812 change: qmail-remote no longer does CNAME lookups if there's an
+ artificial SMTP route. tnx ME.
+19960812 change: added flagcname arg to addrmangle() in qmail-remote.
+19960812 cleanup: moved host/relayhost processing earlier in
+ qmail-remote.
+19960812 change: qmail-remote stops before DATA if no RCPTs were
+ successful. tnx JLH.
+19960812 change: rewrote rcpthosts explanation in FAQ.
+19960811 change: added qmail-log.5.
+19960811 change: introduced ALIAS_PATERNALISM. configurability requested
+ by several people.
+19960811 change: eliminated go-writability test for qmeox(). the alleged
+ value of paternalism is nonexistent if nobody even notices
+ you're doing it.
+19960811 change: in qbiff, changed no-/-allowed to no-/-at-beginning,
+ no-dots-allowed, must-be-nonempty. tnx MD.
+19960811 change: in mbox.5, discouraged mail readers from looking for
+ From_ lines only after blank lines. too much crap in the world.
+19960811 change: added subject line to qreceipt success notices.
+19960811 change: added subject line to qmail-send bounce messages.
+19960811 change: qmail-alias now expects dash arg. this finally gives
+ lspawn complete control over the local -> ~user/.qmail-ext map.
+19960811 change: qmail-lspawn passes dash arg to qmail-alias.
+19960811 change: reorganized qlist acknowledgment format. again.
+19960811 change: documented EXT, EXT2, EXT3, EXT4. tnx BB.
+19960810 change: qmail-makectl now copies locals to rcpthosts. should be
+ a better default. suggested by TK.
+19960805 portability problem: new makefile generator put in tabs again.
+ sigh. impact: couldn't compile under some systems. fix: same as
+ before. tnx TG.
+19960804 change: added tcpserver instructions to FAQ.
+19960804 change: reorganized FAQ server instructions into a new section.
+19960801 qmail 0.90, gamma.
+19960801 change: qmail-qmtpd now supports rcpthosts, RELAYCLIENT.
+19960731 change: default NUMD is now 29. this prepares for weird systems
+ where getpwnam() needs more than one descriptor (but the
+ descriptor limit is still 64! ... you never know), and for
+ possible future getpwnam() replacements.
+19960731 change: popped subfderr buffer up to 32 characters. made sure
+ that everybody flushed subfderr as necessary.
+19960731 change: maildir2qmtp now prints filenames and responses.
+19960731 change: maildir2smtp now prints filenames it's trying and
+ relevant portion of SMTP responses.
+19960731 change: used succwrite() in maildir2smtp, maildir2qmtp.
+ simplifies code quite a bit.
+19960731 change: qmail-remote's blast() checks sooner for write errors.
+19960731 change: added better -e option to sendmail. tnx TG.
+19960731 change: added maildir2qmtp.
+19960730 cleanup: eliminated die_nomem() in maildir2smtp.c.
+19960730 change: dns_cname now pretends that "foo." is a CNAME for "foo"
+ to give the desired behavior for people who misuse DNS and
+ violate RFC 822. tnx RN.
+19960730 change: dns_cname now tests for empty names and ] on every
+ loop.
+19960730 change: used LSPAWN_BREAK in qmail-send.c for usermap.
+19960730 change: updated header example in qmail-header.5.
+19960730 change: added printbreak. auto-configured BREAK in dot-qmail.5,
+ qmail-lspawn.7, qmail-send.8, qmail-upgrade.7, qlist2.
+19960730 change: added printnumd. auto-configured NUMD in qmail-send.8,
+ qmail-limits.8.
+19960730 change: added printsplit. auto-configured split in qmail-upq.
+19960730 change: added dot-qmail.5.
+19960730 change: qmail-smtpd now treats HELO as including RSET.
+19960730 change: added moreinfo to qlist usage message.
+19960729 change: improved an error message in qmail-alias.
+19960729 cleanup: merged qmeox(), qmeodx().
+19960729 bug: failure to stat .qmail-owner was not an error. impact: if
+ stat failed temporarily (e.g., because of NFS), .qmail-owner
+ would be incorrectly ignored, so outgoing message would have
+ wrong envelope sender. fix: qmail-alias does temp_nfsqmail() if
+ stat() returns a temporary error.
+19960729 change: added RFCOWNER.
+19960729 change: added qmtpd setup question to FAQ.
+19960729 change: added qmail-qmtpd.
+19960728 change: revamped maildir2smtp error messages.
+19960728 change: revamped maildirwatch error messages.
+19960728 change: revamped maildir2mbox error messages.
+19960728 change: used strerr in maildir_scan().
+19960728 change: used strerr in maildir_chdir().
+19960728 change: introduced strerr.
+19960728 bug: the new tcp-env tried to read from an ndelay socket.
+ impact: TCPREMOTEINFO would always be empty. fix: unset ndelay
+ in remoteinfo.c.
+19960728 bug: if maildir2smtp saw a permanent failure after MAIL, it
+ failed to do RSET. impact: all further messages would be
+ rejected at the MAIL stage. fix: maildir2smtp now always does
+ RSET. tnx JW.
+19960728 cleanup: qmail-alias now applies lowercase and dot-to-colon
+ conversion directly to dashext, leaving everything else alone.
+ this works since all .qmail access is factored through dashext.
+19960727 portability problem: under NeXTStep, -posix is almost entirely
+ broken. impact: qmail daemons would dump core under NeXTStep.
+ fix: turn off -posix, except for loading qmail-setup, which
+ needs mkfifo(); NeXT, bless them, didn't put mkfifo() into the
+ C library where it belongs. this requires a new make command,
+ namely loadfifo.
+19960727 change: all characters 33-126 are now considered safe for logs.
+ tnx MD.
+19960727 cleanup: eliminated qp variable from mailforward().
+19960727 cleanup: maildirwatch.c includes headerbody.h.
+19960727 cleanup: eliminated match from maildirwatch.c.
+19960727 cleanup: eliminated code variable from maildir2smtp.c:doit().
+19960727 cleanup: maildir2smtp.c includes scan.h.
+19960727 cleanup: maildir.c includes str.h.
+19960727 cleanup: qmail-popup.c now includes exit.h.
+19960727 cleanup: qmail-pop3d.c now includes exit.h.
+19960727 cleanup: eliminated path from qmail-start.c.
+19960727 cleanup: eliminated birthplusnn from nextretry().
+19960727 cleanup: eliminated r from timeoutconn().
+19960727 cleanup: tcpto.c now includes byte.h.
+19960727 cleanup: spawn.c now declares initialize().
+19960727 cleanup: qmail-lspawn.c now includes str.h, byte.h.
+19960727 cleanup: qmail-inject.c now includes quote.h.
+19960727 change: qmail-check now checks separately for group
+ readability and other readability.
+19960727 bug: maildir2smtp didn't check flagehlo in PIPELINING parsing.
+ impact: a server that said PIPELINING at any point, not just
+ EHLO, would receive pipelined data. fix: check flagehlo.
+19960727 bug: readsubdir was calling pause(). impact: if a subdirectory
+ was removed, qmail-send would hang. fix: use rs->pause().
+19960727 change: used error_str in qmail-qread.
+19960727 change: qmail-qread now looks for local/remote open errors.
+19960727 cleanup: added warn() in qmail-qread.c.
+19960727 change: qmail-qread now exits 111 for temporary errors.
+19960727 change: used error_str in qmail-setup.
+19960727 change: introduced error_str.
+19960727 change: replaced qmail-check with make check in INSTALL.
+19960727 change: added check target to Makefile.
+19960727 change: replaced qmail-setup with make setup in INSTALL.
+19960727 change: indirected fake targets through do- targets.
+19960727 change: added setup target to Makefile.
+19960727 change: qmail-makectl now makes sure that defaultdomain has
+ at least one dot. e.g., enteract.com -> enteract.com, not com.
+19960726 bug: quote() failed to quote commas. impact: addresses
+ containing commas would not have been quoted correctly for
+ Return-Path or for SMTP MAIL FROM. fix: quote commas.
+19960726 change: sendmail now mentions qmail-qread, not qmail-mailq.
+19960726 change: qmail-alias now expects ext arg. this eliminates
+ LSPAWN_BREAK from qmail-alias and gives lspawn almost complete
+ control over the local -> ~user/.qmail-ext transformation. the
+ exception is that qmail-alias always uses ~user/.qmail,
+ ignoring ext, if local is the same as user.
+19960726 change: qmail-lspawn passes ext to qmail-alias.
+19960726 change: alloc() now uses up a 4K space before calling malloc().
+19960726 change: ipalloc allocation base is now 10. 100 was silly.
+19960726 change: stralloc allocation base is now 30.
+19960726 change: injectbounce() now supports the owner hack.
+19960726 change: qmail-smtpd no longer requires HELO. tnx K1J.
+19960726 cleanup: replaced makereceived() with dohelo().
+19960726 change: qmail-smtpd is back to 555 for syntax errors.
+19960725 change: qmail-alias now supports the owner hack. tnx to RN for
+ prodding me to look at this problem.
+19960725 change: senderadd() now supports the owner hack.
+19960725 cleanup: split off senderadd().
+19960725 change: added pine-crashing note to FAQ.
+19960725 change: added procmail config.h note to INSTALL.mbox.
+19960725 change: added elm TMPDIR note to INSTALL.mbox.
+19960725 change: added pine.conf note to INSTALL.mbox.
+19960724 change: added fixup note to FAQ.
+19960724 change: qmail-inject now exits 111 for temporary errors.
+19960724 change: qmail-smtpd now appends RELAYCLIENT to incoming
+ recipient domain names.
+19960724 cleanup: moved relayclient out of qmail-smtpd's addrallowed()
+ into caller.
+19960724 change: added rcpthosts wildcards.
+19960724 change: added clean target to Makefile.
+19960723 change: added virtualdomains exceptions.
+19960722 change: added BLURB4.
+19960722 change: added BLURB3.
+19960722 change: eliminated smarthost and localnet.
+19960722 change: incorporated relaymap, contributed by LW. renamed it
+ as smtproutes.
+19960722 change: qmail-popup now supports APOP. suggested by BG, who
+ distributed similar changes.
+19960722 change: qmail-popup now sends APOP timestamp to checkpassword.
+19960722 cleanup: in qmail-popup, split off doanddie().
+19960722 change: qmail-popup now prints APOP timestamp in banner.
+19960722 change: added hostname argument to qmail-popup.
+19960722 cleanup: in qmail-popup, split out() into out(), outflush().
+19960722 cleanup: in qmail-popup, introduced pop3_greet().
+19960721 portability problem: under Unisys SVR4, hostname is not in the
+ usual path. impact: qmail-makectl fails. fix: added hostname
+ command here, used it in qmail-makectl.
+19960721 portability problem: on some sysctl-based systems, apparently
+ gethostname() doesn't write anything if the output buffer is
+ too small. it should write a truncated name. impact: if anyone
+ has a hostname longer than 64 characters, maildirs could get up
+ to 64 characters of garbage, rather than a truncated hostname.
+ fix: qmail-alias now does *host = 0 before calling gethostname.
+19960721 change: updated FAQ examples from qsmhook to preline.
+19960721 change: added preline.
+19960721 change: qsmhook now uses signal_init, signal_uninit.
+19960721 change: qsmhook now checks specifically for empty args.
+19960721 change: documented mbox.
+19960721 change: added EXT, EXT2, EXT3, EXT4.
+19960721 change: added LAST response to qmail-pop3d, always returning
+ OK 0. tnx RN.
+19960721 change: added qmail home page to README.
+19960721 change: added HELP response to qmail-smtpd. tnx RN.
+19960720 change: expanded, vertically, the qmail-inject error message
+ for unparseable header fields.
+19960720 change: logo is now dolphin. tnx CEJ.
+19960719 qmail 0.76, beta.
+19960719 change: used LSPAWN_BREAK in qmail-alias for deciding how to
+ handle extensions. this should produce better behavior in the
+ (unsupported) case that LSPAWN_BREAK is not a hyphen.
+19960719 bug: qmail-smtpd didn't check for null arg on MAIL, RCPT.
+ impact: qmail-smtpd would deref 0 and crash. fix: qmail-smtpd
+ now gives syntax error on null arg.
+19960719 change: documented UFLINE in qmail-command.8. tnx TG.
+19960718 change: added maildir2smtp.
+19960718 cleanup: introduced maildir.c. used it in maildir2mbox.c,
+ maildirwatch.c.
+19960718 change: added maildirwatch.
+19960718 cleanup: maildir2mbox now sets up pq2 as it is deleting from
+ pq, rather than simultaneously with pq.
+19960718 change: added H_DELIVEREDTO.
+19960718 portability problem: Unisys requires -lsocket -lnsl. impact:
+ couldn't compile under Unisys. fix: added unix_sv section to
+ make-cmds.sh. tnx TVP.
+19960718 change: added unix_sv section in find-systype. tnx TVP.
+19960717 change: qmail-alias now appends newline if .qmail does not end
+ with a newline. tnx MC.
+19960717 change: qmail-alias now defers delivery for a blank line only
+ if it is the first line of the file. handles user behavior
+ described by MC of putting many newlines at end of file.
+19960717 bug: qmail-inject looked for dots in user part, not just host
+ part, when deciding whether to use defaultdomain. impact: the
+ address joe.bloggs@here didn't have defaultdomain added. fix:
+ qmail-inject now stops at the @.
+19960717 change: updated INSTALL.alias to mention qmsmac.
+19960717 change: syntax error code for SMTP is now 501.
+19960717 change: added -e option to sendmail. tnx TG.
+19960716 change: changed ~alias files to .qmail-local, not .qmaillocal.
+ suggested by many people.
+19960716 change: redid qmail-alias/qmail-lspawn interface.
+19960716 change: replaced EXTENSION, USEREXT with LOCAL.
+19960716 change: qmail-queue now removes intd, mess upon error, as long
+ as it doesn't time out. suggested by BB et al.
+19960716 change: added flagmademess, flagmadeintd to qmail-queue.c.
+19960716 cleanup: changed todofd to intdfd in qmail-queue.c.
+19960716 cleanup: added cleanup() to qmail-queue.c.
+19960716 change: added timeout to tcp-env.c, default 30 seconds.
+19960716 change: remoteinfo_get() now uses timeoutconn().
+19960715 change: added procmail config.h note to FAQ.
+19960704 change: qmail-upgrade.7 now warns administrators that ~alias
+ generally doesn't apply to addresses starting with a user name.
+19960703 change: added echo \c note to FAQ. tnx PJG.
+19960702 change: qmail-smtpd now accepts HELO without an argument.
+ tnx K1J, J1B.
+19960627 change: qmail-lspawn.8 now mentions that qmail-lspawn doesn't
+ set up supplementary groups. tnx TG.
+19960625 portability problem: under Linux, read(,,0) doesn't do proper
+ error slippage. impact: timeoutconn() would always report
+ success; if a connection failed, qmail-remote would report a
+ greeting failure and skip all further MX records. tnx ME. fix:
+ timeoutconn() now uses getpeername() to check for success.
+19960625 change: qmail-smtpd now mentions disk full for QQT_WRITE.
+19960625 change: qmail-inject now mentions disk full for QQT_WRITE.
+19960622 change: if RELAYCLIENT is set, qmail-smtpd skips rcpthosts.
+19960609 change: updated INSTALL for current SMTP responses.
+19960607 change: clarified INSTALL.qsmhook examples. tnx S1R.
+19960607 change: added subject parsing to qlist.c. tnx RN.
+19960607 cleanup: used case_diffb in qlist.c.
+19960607 change: added extra log information to INSTALL examples.
+19960606 change: added -Pn to uucp line in FAQ. tnx DWS.
+19960605 portability problem: under Solaris, /usr/bin/groups incorrectly
+ reports your groups in /etc/group, rather than the results of
+ getgroups(). tnx MD, PJG. impact: test #19 in INSTALL fails.
+ fix: added special note to test #19 (sigh) about Solaris.
+19960605 change: improved maildir setup commands in INSTALL.mbox.
+19960605 change: on success, qmail-alias logs forwarding qp. 9 lines
+ extra code.
+19960605 change: qmail-send logs qp for bounce. 6 lines extra code.
+19960605 change: qmail-smtpd includes qp in its response when it accepts
+ a message. 7 lines extra code. requested by MD and others.
+19960605 change: added qqtalk_qp.
+19960605 change: qmail-send now logs uid and qp from todo file. 14 lines
+ extra code.
+19960605 change: qmail-queue now records uid and qp in u and p lines
+ in todo file. 7 lines extra code.
+19960605 change: improved qmail-alias x-bit error messages.
+19960605 change: newline in log is now converted to /, not underscore.
+19960604 change: when it accepts a message, qmail-smtpd includes the
+ local time in its 250 response.
+19960604 change: on success, qmail-alias prints delivery counts,
+ file+forward+program.
+19960603 change: qmail-remote now reports IP address on success. tnx MD.
+19960603 change: qmail-send now logs success and failure reports, not
+ just deferral reports.
+19960603 change: added netbsd section in find-systype, same as bsd.os
+ section. this will affect netbsd-* systypes. tnx MBS.
+19960530 qmail 0.75, beta.
+19960528 change: added qmail.7. tnx MD.
+19960525 change: added qmail-pop3d. tnx RN.
+19960525 change: added qmail-popup. tnx RN.
+19960525 change: added elm filter section to FAQ. tnx GB.
+19960502 portability problem: on many systems, select() on an
+ almost-full pipe incorrectly says writable. tnx ME for running
+ into this and helping track it down. impact: if qmail-send
+ writes a pipeful to qmail-lspawn or qmail-rspawn before they
+ can react (because of high concurrency, high load, or long
+ addresses), it will receive an incorrect -1/EAGAIN, and will
+ conclude that spawn died. sysadmin will have to restart qmail,
+ and messages will be duplicated. fix: in qmail-send.c,
+ busy-loop if write() to spawn returns any error other than
+ EPIPE.
+19960501 bug: qmail-alias treated NAMETOOLONG and NOTDIR as temporary
+ errors. impact: qmail-alias never looked for -default; even if
+ mail was destined to bounce, it would have to time out first.
+ fix: qmail-alias now uses error_temp().
+19960430 bug: qmail-smtpd treated qq crash as permanent error. impact:
+ if somebody actively kills qq, mail will be incorrectly
+ bounced. tnx SS. fix: qmail-smtpd now treats only TOOLONG and
+ EXECHARD as permanent errors.
+19960430 cleanup: eliminated QQT_TTY from qqtalk.h.
+19960428 change: added ``warning: '' before trouble-marking message.
+19960428 change: added percenthack. requested by GB.
+19960428 cleanup: switched to auto-generated Makefile.
+19960428 cleanup: switched to auto-generated .o dependencies.
+19960428 cleanup: eliminated fmt.o, scan.o from Makefile.
+19960428 portability problem: under HP-UX 10, the rc pgrp is sent HUP
+ when rc finishes. tnx BG. impact: the qmail daemons are killed
+ when rc finishes. fix: added special note in INSTALL (sigh) to
+ use csh -cf.
+19960427 cleanup: added PORT_SMTP in qmail-remote.c.
+19960427 cleanup: introduced timeoutwrite.c. used it in qmail-remote.c.
+19960427 cleanup: introduced timeoutread.c. used it in qmail-remote.c.
+19960427 cleanup: introduced timeoutconn.c. used it in qmail-remote.c.
+19960427 change: added timeoutconnect. default: 60 seconds.
+19960427 change: added pop3d instructions to FAQ. tnx RN.
+19960427 change: eliminated env manipulation from qmail-start. tnx BG.
+19960427 change: headerbody now ends header, inserting blank line, if
+ first line of a header field doesn't pass hfield_valid. tnx TG.
+19960427 change: headerbody now prepends MBOX-Line: to any header line
+ starting From_. this lets qmail-inject work with elm's bounce.
+ tnx OR, K1J, et al.
+19960426 change: added moreinfo arg to qlist and qlist2.
+19960426 change: added signal_uncatchchild() to qmail-send.c. tnx BG.
+ now, if sysadmin sets SIGCHLD to SIG_IGN before invoking
+ qmail-send [sigh], qmail-send won't screw up bounce messages.
+19960426 change: dns_cname now checks whether last character is ],
+ rather than whether first character is [, for quick return.
+19960426 cleanup: glue is now global in dns.c.
+19960426 cleanup: qmail-remote no longer does stralloc_0 for host and
+ canonhost.
+19960426 change: dns_mxip no longer rejects [foo].bar.
+19960426 change: dns_mxip no longer requires for bracket that input
+ be 0-terminated.
+19960426 change: qmail-start can now take logger as an argument.
+19960426 change: qmail-start now invokes qmail-send in foreground (as
+ parent of other processes).
+19960426 change: added mailsubj. tnx GAW.
+19960426 portability problem: under some systems, can't lock read-only
+ file. impact: maildir2mbox would always fail on those systems.
+ fix: maildir2mbox now opens a separate lock fd. tnx BG.
+19960426 cleanup: removed unnecessary #!/bin/sh and # AUTO from mctl.sh.
+19960426 change: added qmail-qstat.
+19960426 change: added qmail-qread.8.
+19960426 change: renamed qmail-mailq as qmail-qread.
+19960419 change: qmail-alias now defers delivery rather than skipping
+ blank lines in .qmail.
+19960419 change: in qmail-lspawn.c, lowercased name before getpwnam().
+ really getpwnam() should do this, but oh well.
+19960419 change: added username to qmail-lspawn.c, with LSPAWN_USERLEN
+ in conf-unusual.h. names longer than LSPAWN_USERLEN will skip
+ getpwnam().
+19960419 change: if qlist doesn't see any cmds, it presumes that you
+ meant to subscribe.
+19960419 change: reorganized qlist acknowledgment format.
+19960415 change: reorganized and rewrote FAQ.
+19960415 change: renamed HOWTO as FAQ.
+19960414 change: in qmail-alias, converted extension to lowercase just
+ before qmeopen(), qmeox() calls. thus EXTENSION and USEREXT and
+ RECIPIENT will preserve case passed by qmail-lspawn, while
+ .qmailext lookups will not.
+19960414 change: removed case_lowers(r) from qmail-lspawn.c. tnx JLH.
+19960414 change: moved extension . -> : conversion to just before
+ qmeopen(), qmeox() calls in qmail-alias.c. thus EXTENSION and
+ USEREXT and RECIPIENT will preserve dots.
+19960414 change: qsmhook -x now does case-independent comparison.
+19960413 change: added procmail instructions to HOWTO.
+19960409 bug: qmail-alias does not check for newlines when it generates
+ Return-Path. impact: resulting Return-Path header field will be
+ illegal, if sender address contains newline followed by
+ something other than whitespace. fix: qmail-alias now replaces
+ newline with underscore in rpline.
+19960409 change: added leaf UUCP description to HOWTO. tnx J2K.
+19960409 change: added -B option to sendmail. tnx OR.
+19960409 change: qlist now makes lists unwritable (after renaming from
+ .qtemp to .qmail). tnx MLH.
+19960409 change: added flagdtline to qsmhook.c, based on -l option.
+19960409 change: added PIPELINING declaration to qmail-smtpd. tnx JGM.
+19960409 change: qmail-smtpd now flushes output instantly after DATA,
+ QUIT, HELO, EHLO, NOOP, VRFY, or any 502.
+19960409 change: qmail-smtpd now flushes output upon read() and death.
+19960409 change: qmail-smtpd no longer flushes output in out().
+19960409 change: increased qmail-smtpd outbuf size from 128 to 512.
+19960409 cleanup: in qmail-smtpd, eliminated ssinit() in favor of FDBUF.
+19960409 bug: qmail-alias produced aliasfoo-owner rather than foo-owner
+ as envelope sender for ~alias/.qmailfoo. tnx DS. impact: wrong
+ envelope sender whenever ~alias/.qmailfoo-owner existed. fix:
+ qmail-alias now checks for hyphen at beginning of extension.
+19960409 change: added _ESMTP to end of 220. tnx JLH.
+19960409 change: moved out("\r\n") out of smtp_greet() into callers.
+ this improves the flushing behavior on 221.
+19960328 qmail 0.74, beta.
+19960326 change: changed subdirectory split from 32 to 23.
+19960326 portability problem: some versions of make don't understand
+ that a line with just a tab is blank. impact: couldn't compile
+ under those systems. fix: eliminated extra tab from Makefile.
+ tnx TG.
+19960325 change: added qmail-mailq.
+19960325 change: introduced readsubdir.
+19960325 change: qmail-setup makes split; qmail-check checks split.
+19960325 change: used split in qmail-send, qmail-clean, qmail-queue
+ for mess, info, local, remote.
+19960325 change: fmtqfn now supports split queue subdirectories.
+19960325 cleanup: eliminated cat2s().
+19960325 cleanup: introduced fmtqfn.c. used it in qmail-queue.c,
+ qmail-send.c, qmail-clean.c.
+19960325 change: in protocol between qmail-clean and qmail-send, now
+ using intd/ instead of mess/.
+19960325 change: qmail-queue.c and triggerpull.c now work inside queue
+ subdirectory.
+19960325 change: spawn.c now checks whether message is a regular file.
+19960325 change: spawn.c now allows slashes in messid except at
+ beginning.
+19960325 cleanup: introduced fnmake_split in qmail-send.c.
+19960325 cleanup: eliminated strnum in qmail-send.c in favor of
+ fnmake_{info,todo,mess,chanaddr} and fnmake2_bounce.
+19960325 cleanup: introduced strnum3 in qmail-send.c for the logging
+ uses of strnum.
+19960325 cleanup: in qmail-send.c, getinfo() now takes id argument.
+19960325 cleanup: qmail-send.c now preallocates space for fn, fn2.
+19960325 change: time zone is now -0000 instead of +0000. encouraging
+ DRUMS to use this as an i-don't-know-the-local-time indicator.
+19960324 change: qmail-rspawn.c now calls tcpto_clean().
+19960324 cleanup: spawn.c now calls initialize().
+19960324 change: qmail-setup makes lock/tcpto; qmail-check checks it.
+19960324 change: qmail-remote now quickly skips connect() to a host that
+ seems to be down. tnx BP for pressuring me to get this done.
+19960323 change: in qmail-alias.8, renamed mboxg as mboxrd. tnx RD.
+ idea was popularized by RD in June 1995.
+19960322 cleanup: eliminated subfd_init().
+19960322 change: qbiff now removes the word Subject.
+19960322 change: now /bin/true instead of /dev/null in the generic
+ INSTALL.ids instructions. tnx JPR.
+19960322 change: added hfield_skipname(). tnx RN.
+19960322 bug: qmail-inject did not check whether USER needed quoting.
+ impact: if USER had weird characters, the From address would
+ generally be wrong, unless the user manually set up MAILUSER
+ with proper quoting. fix: qmail-inject sets up a quoted-string
+ if necessary.
+19960322 cleanup: separated out quote_need() in quote.c.
+19960322 cleanup: added stralloc_catb.c. used it in qmail-alias.c,
+ qmail-send.c.
+19960322 change: qmail-send now uses a quadratic retry schedule from
+ birth of each message. this also eliminates clustering.
+19960322 cleanup: separated out nextretry() in qmail-send.c.
+19960322 change: qmail-remote now passes all non-@ addresses through
+ without comment, not just <> and <#>.
+19960322 change: replaced # test with anything@[] test in qmail-inject.
+19960322 change: replaced # with #@[] in qlist.c, qmail-alias.c,
+ qmail-send.c, qreceipt.c.
+19960322 change: qmail-lspawn no longer discards messages to <#>.
+19960322 cleanup: in qlist, used str_diff for <> and <#> tests.
+19960322 change: qmail-alias is now back to testing envelope sender for
+ <> and <#>, rather than things without an @.
+19960321 change: added 8BITMIME support to qmail-smtpd.
+19960321 change: added ESMTP support to qmail-smtpd.
+19960318 change: used NEWSENDER in place of SENDER for |forward.
+19960318 change: added NEWSENDER.
+19960318 change: added HCMSSC support to qmail-alias.c.
+19960318 change: added HCMSSC support to spawn.c.
+19960318 change: added HCMSSC support to qmail-remote.c.
+19960318 change: added HCMSSC support to qmail-smtpd.c.
+19960317 portability problem: SCO requires -lsocket -lnsl. impact:
+ couldn't compile under SCO. fix: added SCO section in
+ make-cmds.sh. tnx JPR. note that this is for OSR 5; 3.2v4.2
+ will need more fixes, and old 3.2 is basically hopeless.
+19960317 bug: newfield_datemake would leave newfield_date alone if it
+ was already initialized, even though qmail-send calls
+ newfield_datemake anew for each bounce. impact: bounce messages
+ would usually have an incorrect Date field. fix: redid
+ newfield_datemake to update newfield_date each time.
+19960317 change: allowed . and @ in 822 phrases; 822 doesn't allow them,
+ but they do show up. tnx to the DRUMS group.
+19960317 change: replaced GMT with +0000 in date822fmt.c. this confuses
+ a few versions of getdate(), but the DRUMS group is going to
+ outlaw GMT, not just recommend against it as in 1123.
+19960317 change: redefined ALIAS_EMPTY to take advantage of . for file
+ deliveries. tnx RN.
+19960317 change: qmail-alias now allows . as well as / to start file
+ deliveries. tnx RN.
+19960317 change: qmail-alias now dies (soft) if .qmail is writable to
+ others, rather than silently ignoring it.
+19960317 change: qmail-alias now dies (soft) if flagforwardonly is
+ violated, rather than silently ignoring the bad instructions.
+19960317 change: qmail-alias now ignores x bit on empty .qmail files.
+19960317 bug: if RCPT gave 4xx and DATA gave 5xx, qmail-rspawn would
+ incorrectly assign a permanent failure to that recipient.
+ impact: in that case, mail would be incorrectly bounced. fix:
+ remove orr > 0 test from qmail-rspawn.c.
+19960310 change: tcp-env now uses signal_uninit(). [sigh]
+19960310 change: tcp-env now specifically unsets HOST and INFO if they
+ are not applicable. just trying to make it more widely usable.
+19960310 cleanup: used byte_* in remoteinfo.c, ipme.c, tcp-env.c.
+19960310 cleanup: added readwrite.h, eliminated sys.h.
+19960310 cleanup: included byte.h in qmail-send.c.
+19960310 cleanup: eliminated i and j from forward.c's main().
+19960310 cleanup: eliminated wstat from qlist.c.
+19960310 cleanup: eliminated die_nomem() parameter in qmail-setup.c.
+19960310 cleanup: eliminated i from qmail-remote's addrmangle().
+19960310 cleanup: added exit.h.
+19960310 cleanup: split ipalloc.c off of ip.c.
+19960310 cleanup: added fmt_strn.c, eliminated fmt_strncpy.c.
+19960310 change: reorganized INSTALL to do some pre-upgrade tests.
+ tnx RN.
+19960310 change: reordered steps in upgrade procedure in INSTALL.
+19960308 change: eliminated ownership test in qmail-alias.c. tnx DS.
+19960304 change: in SECURITY, ``six most recent sendmail security
+ holes'' -> ``seven most recent sendmail security holes.''
+19960303 qmail 0.73, beta.
+19960303 change: added SYSDEPS.
+19960303 cleanup: revamped select.h autoconfiguration.
+19960303 cleanup: revamped fork.h autoconfiguration.
+19960303 cleanup: revamped direntry.h autoconfiguration. target is now
+ direntry.h; auto-hasdrent.h is gone.
+19960303 change: tryflock.c now includes <sys/types.h>, for consistency
+ with lock.c. may affect portability.
+19960302 portability problem: under BSDI, can't set sticky on normal
+ files. dorks. impact: the new qlist doesn't work under BSDI;
+ be glad I test things before release. fix: qmail-alias and
+ qlist now use executable instead of sticky.
+19960302 change: gfrom now quotes >From and >>From etc. as well as From;
+ in other words, I'm switching from mbox format to mboxg format.
+19960302 cleanup: added gfrom.c. used it in qmail-alias.c, maildir2mbox.c.
+19960302 change: addbounce() now substitutes \n\n -> \n/ in reports,
+ and \n -> _ in recips. thus bounces can now be reliably parsed.
+19960302 change: if qmail-send had trouble reading the original message
+ or the list of addresses for a bounce, it used to give up and
+ send a bounce with "Oh no! I had trouble reading the rest of
+ your message" or some such. now it aborts the bounce attempt
+ and tries again later.
+19960302 cleanup: added qqtalk_fail(). used it in qmail-alias.c,
+ qmail-smtpd.c.
+19960302 bug: if mailforward() had trouble reading message (e.g.,
+ because of an I/O error), it marked an error but kept reading.
+ impact: could loop forever. fix: upon error, break.
+19960302 change: maildir2mbox now scans (restrictively) for return-path.
+19960302 change: qbiff now prints subject and body, up to 74 chars.
+19960302 change: added H_SUBJECT to hfield.
+19960302 change: qbiff now puts TO before FROM.
+19960301 cleanup: added fmt_str.c. used it in many places.
+19960301 change: qmail-send now says something if you've told it to exit
+ but it's waiting for some deliveries. tnx RN.
+19960301 change: qmail-alias -n now continues (with warning) if home
+ directory is sticky. tnx RN.
+19960301 change: improved usage messages in qmail-alias.c. tnx RN.
+19960301 change: put limit on length of addresses in qlist.
+19960301 change: added exit 99 support to qmail-alias. tnx RN.
+19960301 change: qmail-alias now exits immediately on temporary or
+ permanent error. rewrote section in qmail-alias.8 accordingly.
+19960301 cleanup: eliminated flagsuccesses from qmail-alias.c.
+19960301 change: added usermap.
+19960301 bug: failure to append to mbox was a permanent error. impact:
+ if mbox was temporarily unopenable (e.g., because fds were
+ low), mail would be incorrectly bounced. fix: failure is now
+ temporary. tnx DS.
+19960229 change: qmail-alias now preserves any envelope sender that
+ doesn't contain an @, not just <> and <#>.
+19960229 cleanup: revamped byte_* interface.
+19960229 cleanup: renamed str_cpy as str_copy.
+19960229 cleanup: added str_chr.c. used it in qbiff.c, qmail-smtpd.c.
+19960229 cleanup: added str_rchr.c. used it in qmail-send.c, quote.c,
+ qmail-remote.c.
+19960229 cleanup: added byte_rchr.c. used it in qmail-smtpd.c, spawn.c.
+19960229 cleanup: used USEREXT instead of RECIPIENT in qsmhook.c.
+19960229 cleanup: used USEREXT instead of RECIPIENT in qbiff.c.
+19960229 cleanup: removed j and k from rewrite() in qmail-send.c.
+19960229 portability problem: under HP-UX 10 and Solaris 2.5, can't
+ setgroups()/setgid() to the system's nogroup/nobody gid. dorks.
+ impact: inetd chokes, so all SMTP connections are rejected; and
+ ``alias'' mail, including postmaster, bounces. fix: in
+ INSTALL.ids, set up a separate powerless gid (tentatively
+ ``nofiles'') for qmaild and alias. tnx DS and PJG.
+19960229 change: qreceipt now uses qqtalk rather than qmail-inject.
+19960229 change: qlist now uses qqtalk rather than qmail-inject.
+19960229 change: incorporated qmail-setup patch from RN for better
+ error messages.
+19960228 change: added LSPAWN_BREAK in conf-unusual.h; used it in
+ lspawn.c. configurability requested by PJG.
+19960228 portability problem: on several systems, including everything
+ from DEC, select() on a pipe reader returns 1 if there aren't
+ any writers yet. pointed out by DS. impact: qmail-send chewed
+ up lots of CPU time. fix: trigger_set() now opens the pipe for
+ writing after opening it for reading. also added trynpbg1; on
+ working systems, no point in wasting the extra fd.
+19960228 change: qmail-alias uses .qmail sticky bit for forwardonly.
+19960228 change: qlist now sets sticky bit on .qmail file.
+19960228 change: un-documented +list.
+19960228 portability problem: on HP-UX and possibly other systems, the
+ supplementary group list does not include the gid. pointed out
+ by DS. impact: on those systems, tryshsgr could incorrectly set
+ hasshsgr; this would prevent qmail-send from running. fix: if
+ tryshsgr sees that getgroups() returns 0, now it actively sets
+ up a supplementary group list. added chkshsgr to make sure the
+ setgroups() will work.
+19960227 cleanup: eliminated GETSHORT in dns.c in favor of getshort().
+19960227 cleanup: deleted h->len < 3 test from qlist.c:dobody. tnx RN.
+19960227 change: replaced ~ with $HOME in INSTALL.mbox.
+19960227 change: added note about setgid-mail bits to INSTALL.mbox.
+19960227 change: added forward.1.
+19960227 change: modified forward to allow multiple addresses.
+19960227 change: modified forward to take an entire address, not just a
+ hostname.
+19960227 change: renamed qrelay as forward.
+19960227 change: added USEREXT support to qmail-alias.
+19960227 change: added -F to sendmail. the need for this was pointed
+ out by RN.
+19960227 change: added 2 bytes of slop in alloc().
+19960227 bug: received_setup() was not allowing space for the final \0.
+ impact: none; the line length is always between 65 and 75
+ characters, which gives at least 45 characters of slop with
+ existing malloc() implementations. fix: leave space. tnx NH.
+ note that the bug here is really in fmt_strncpy, which was
+ written before i was truly free of the curse of libc.a.
+19960227 change: added ALIAS_EMPTY in conf-unusual.h; used it in
+ qmail-alias.c. tnx PJG.
+19960227 change: added SPAWN_NUMD in conf-unusual.h; used it in spawn.c.
+19960227 change: added conf-unusual.h.
+19960227 cleanup: replaced sizeof(short) with 2 in dns.c.
+19960227 portability problem: on an Alpha, long is 64 bits. pointed out
+ by DS. impact: address lookups produced incorrect results on an
+ Alpha; qmail-makectl and qmail-remote failed. fix: replaced
+ sizeof(long) with 4 in dns.c.
+19960227 portability problem: on an Alpha, bzero() is declared properly
+ via sys/time.h. impact: couldn't compile on an Alpha. fix:
+ removed bzero() declaration from select.h. tnx DS.
+19960227 portability problem: under SCO, sys/file.h is not protected.
+ impact: couldn't compile under SCO. fix: include sys/types.h in
+ lock.c. tnx RN.
+19960219 change: added some .qmail-list hints to qlist.1.
+19960219 change: added +list support to qmail-alias.
+19960215 change: added THANKS.
+19960212 bug: foo was not initialized in qrelay.c. impact: depends on
+ the machine; on some machines, no effect; on other machines,
+ guaranteed core dump. fix: initialized foo. tnx DS.
+19960209 qmail 0.72, beta.
+19960209 change: qmail-alias now replaces dot, not slash, with colon.
+ also, qmeopen() makes sure that .qmail file is S_IFREG; I hope
+ this doesn't cause portability problems.
+19960209 change: added success-reporting procedure to INSTALL.
+19960208 change: added VERSION.
+19960208 change: added qlist2.
+19960208 change: revamped qlist interface. tnx RN.
+19960208 change: improved an error message in qlist.c.
+19960208 change: added qrelay. added relay section to HOWTO. tnx DS.
+19960208 cleanup: included substdio.h in qqtalk.h.
+19960207 bug: prioq_delmin() wasn't guaranteeing heap structure on the
+ last element. impact: scheduled passes could have been delayed,
+ conceivably as long as half an hour. fix: prioq_delmin() now
+ checks when it can safely move the last element.
+19960207 change: added maildirmake.1, maildir2mbox.1.
+19960206 change: revised logo paragraph in THOUGHTS.
+19960206 change: replaced nowhere.org with nowhere.mil in examples.
+ nowhere.org is a real domain... [sigh]
+19960206 change: added qreceipt.1.
+19960206 portability problem: IRIX doesn't have vfork. pointed out by
+ DS. impact: couldn't compile under IRIX. fix: added fork.h,
+ tryvfork.c.
+19960206 portability problem: IRIX doesn't have ranlib. pointed out by
+ DS. impact: couldn't compile under IRIX. fix: added IRIX
+ section in make-cmds.sh.
+19960205 cleanup: removed warning from substdio_copy() documentation; in
+ fact, substdio_copy() can be used safely on a fed substdio.
+19960205 change: added qbiff.1.
+19960204 change: implemented localnet. removed relevant paragraph from
+ THOUGHTS. tnx IS.
+19960204 change: in qmail-remote.8, explained the dangers of smarthost.
+ tnx IS.
+19960204 change: implemented virtualdomains wildcards. tnx JLH.
+19960203 change: qmail-send now handles virtualdomains _after_ locals.
+ updated INSTALL.qsmhook appropriately.
+19960203 change: added note to INSTALL.alias about ~ftp, ~www, ~uucp
+ being owned by root.
+19960130 cleanup: in qlist.c, renamed flagremoved as flagwasthere.
+19960130 bug: qmail-send did not pay attention to flagexitasap in
+ pass_dochan(). impact: qmail-send would happily start new
+ deliveries even if it wanted to exit. fix: qmail-send now
+ returns immediately in pass_selprep() and pass_dochan() if
+ flagexitasap.
+19960130 change: in qlist.c and qlist.1, renamed ext as list.
+19960130 change: in qlist.c and qlist.1, renamed manager as owner.
+19960129 qmail 0.71, beta.
+19960129 change: mentioned djb-qmailbeta in README. tnx MWE.
+19960129 change: added a note to INSTALL.mbox making clear that
+ Mailbox is in mbox format. tnx MWE.
+19960129 change: qlist now warns you if it didn't see any cmds. tnx RN.
+19960129 change: incorporated qlist patch from RN to refuse double subs.
+19960129 change: added qlist.1, contributed by RN. mangled it a bit.
+19960129 bug: comment was not allowed in ``phrase (comment) <route>'';
+ pointed out by RN. impact: some correct address lists could be
+ mis-parsed by qmail-inject or qlist. fix: token.c now allows
+ TOKEN_COMMENT in the appropriate scan.
+19960128 change: added a logo paragraph to THOUGHTS.
+19960127 change: implemented rcpthosts.
+19960127 change: split up some uses of putflush in qmail-remote,
+ qmail-smtpd, spawn.c. eliminated NODELAY and corresponding
+ paragraph in THOUGHTS.
+19960127 change: added quote2(). used it in qmail-alias, qmail-send,
+ qreceipt. now addresses are properly quoted in the From, To,
+ and internal Return-Path of bounces; the From and To of
+ receipts; and the Return-Path/RPLINE of delivered messages.
+ removed relevant paragraph from THOUGHTS.
+19960127 change: in RFCLOOPS, documented fact that Delivered-To address
+ is conventionally not quoted.
+19960127 change: knocked default SMTP timeouts down to 20 minutes.
+19960127 change: added INSTALL.ids. tnx RN.
+19960127 change: in INSTALL, noted that nogroup should already exist.
+19960127 bug: pass_selprep checked pqchan[c] even if pass[c].id. impact:
+ qmail-send wasted CPU time whenever more than one message was
+ waiting on a blocked channel. fix: pass_selprep now checks
+ !pass[c].id.
+19960127 bug: programs invoked from qmail-alias were immune to SIGPIPE.
+ impact: a delivery pipeline such as |yes|head -1000 would loop
+ forever, since yes does not check for write errors. fix: added
+ signal_uninit(). used it before execvp in qmail-alias. [sigh]
+19960127 cleanup: added date822fmt.c. used it in newfield.c, qmail-queue.
+19960127 cleanup: added fmt_uint0.c. used it in myctime.c, newfield.c,
+ qmail-queue.
+19960127 cleanup: added dnsdoe.c. used it in dnscname, dnsfq, dnsip,
+ dnsmxip, dnsptr.
+19960127 cleanup: eliminated temp from dnsfq.c.
+19960127 bug: gen_allocdefs was making assumptions incompatible with the
+ alloc_re interface. impact: qmail-send would dump core if you
+ ran out of memory. fix: changed alloc_re interface.
+19960126 portability problem: some versions of Linux don't have
+ net/route.h. pointed out by RN. impact: couldn't compile under
+ those versions. fix: ipme.c no longer includes net/route.h;
+ hopefully this won't cause new portability problems.
+19960126 change: added chmod instructions to INSTALL and INSTALL.alias.
+ tnx RN.
+19960126 change: INSTALL now refers to the traditional sendmail spot
+ (/usr/lib), not the BSD 4.4 spot (/usr/sbin). tnx RN.
+19960126 change: make auto-uids.h now creates auto-uids.h.tmp first.
+ thus, if someone disobeys the installation instructions, and
+ his make fails to remove targets upon error, he'll still be
+ okay. tnx RN.
+19960126 change: added forgeries.7.
+19960125 cleanup: eliminated flagverbose, flagmetoo in sendmail.
+19960125 cleanup: added substdio_copy.c. used it at several spots.
+19960125 cleanup: added constmap.c. qmail-send now uses constmap for
+ locals and virtualdomains. this will speed things up: no
+ problem now to have thousands of virtual domains. removed
+ relevant paragraph from THOUGHTS.
+19960125 change: added linux section in find-systype. this will affect
+ linux-* systypes. tnx RN for relevant info.
+19960124 change: added -od, -oe, -p, -f to sendmail. the need for
+ these was pointed out by TN.
+19960124 bug: qmail-smtpd was reading from descriptor 1. impact: none;
+ in normal use, both 0 and 1 point to the network. fix: changed
+ 1 to 0.
+19960124 bug: qmail-alias treated any .qmail open failure as permanent.
+ impact: if a .qmail file was temporarily unopenable (e.g.,
+ because of NFS), it was incorrectly ignored. fix: qmail-alias
+ now dies QLX_SOFT on any open failure other than ENOENT.
+19960124 change: added freebsd section in find-systype, same as bsd.os
+ section. this will affect freebsd-* systypes.
+19960124 cleanup: find-systype now immediately converts sys to lowercase.
+19960124 change: qmail-setup now copies man pages into /var/qmail/man;
+ qmail-check checks /var/qmail/man. using .0 style, which might
+ cause trouble on various machines, but better than not trying.
+19960124 change: in qmail-remote.c, changed perm_control to temp_control
+ (and D to Z, thanks); thus failure to read control files (e.g.,
+ because of permissions) is now a temporary error.
+19960124 bug: in qmail-remote.c, temp_chdir() used D, not Z. impact: if
+ chdir() to CONF_HOME failed (e.g., because of NFS), message
+ would be bounced. fix: changed D to Z.
+19960124 change: reorganized README.
+19960124 portability problem: Linux has the fifo kernel bug that I had
+ hoped I'd never run into. impact: messages under Linux (and any
+ other systems with this bug) were picked up only in sweeps, not
+ instantly. fix: triggerpull.c now writes a byte (non-blocking)
+ to the fifo. updated INTERNALS accordingly.
+19960124 bug: in qmail-remote.c, if quit() saw a remote write error, it
+ would call writeerr() even though a message report had already
+ been produced. impact: the mess report would include an extra
+ ``ZConnected but communications failed,'' which was confusing
+ to humans. fix: quit() now simply skips the wait-for-QUIT
+ smtpcode() upon write error.
+19960124 portability problem: Linux does not have SIGSYS or SIGEMT.
+ impact: couldn't compile under Linux. fix: added appropriate
+ ifdefs in signal.c.
+19960124 qmail 0.70, beta.
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
index 0000000..3f36a91
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,33 @@
+netqmail-1.04
+-------------
+No copyright is claimed by the distributors of netqmail for changes from
+qmail 1.03 to netqmail 1.04.
+NOTE: netqmail 1.04 is a community-assembled distribution of qmail from
+the official qmail-1.03.tar.gz and patches approved by the community.
+D. J. Bernstein did not participate in, nor has he been asked to approve
+of this distribution.
+
+netqmail-1.05
+-------------
+James Craig Burley claims copyright on the qmail-isoc patch. See the file
+
+ old-patches/qmail-isoc.patch
+
+for details on James' copyright claim and distribution license.
+
+James' patch has been combined with the original netqmail-1.04 patch
+and the result incorporated into a unified netqmail-1.05 patch.
+
+Apart from James' copyrights, no other copyright is claimed by the
+distributors of netqmail for changes from qmail 1.03 to netqmail 1.05.
+
+NOTE: netqmail 1.05 is a community-assembled distribution of qmail from
+the official qmail-1.03.tar.gz and patches approved by the community.
+D. J. Bernstein did not participate in, nor has he been asked to approve
+of this distribution.
+
+netqmail-1.06
+-------------
+The same copyright information as netqmail-1.05 applies to netqmail-1.06
+with the addition of D. J. Bernstein's dedication of qmail to the public
+domain.
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..ab24b64
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,709 @@
+See http://cr.yp.to/qmail/faq.html for newer FAQs not included in this
+document, and http://qmail.org/ for qmail community contributions.
+
+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?
+2.2. How do I set up a null client?
+2.3. How do I send outgoing mail through UUCP?
+2.4. How do I set up a separate queue for a SLIP/PPP link?
+2.5. How do I deal with ``CNAME lookup failed temporarily''?
+
+3. Routing incoming messages by host
+3.1. How do I receive mail for another host name?
+3.2. How do I set up a virtual domain?
+3.3. How do I set up several virtual domains for one user?
+
+4. Routing incoming messages by user
+4.1. How do I forward unrecognized usernames to another host?
+4.2. How do I set up a mailing list?
+4.3. How do I use majordomo with qmail?
+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?
+5.2. How do I set up qmail-qmtpd?
+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 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?
+
+7. Managing the mail system
+7.1. How do I safely stop qmail-send?
+7.2. How do I manually run the queue?
+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?
+8.2. How do I keep a copy of all incoming and outgoing mail messages?
+8.3. How do I switch slowly from sendmail to qmail?
+
+
+
+1. Controlling the appearance of outgoing messages
+
+
+1.1. How do I set up host masquerading? All the users on this host,
+zippy.af.mil, are users on af.mil. When joe sends a message to fred, the
+message should say ``From: joe@af.mil'' and ``To: fred@af.mil'', without
+``zippy'' anywhere.
+
+Answer: echo af.mil > /var/qmail/control/defaulthost; chmod 644
+/var/qmail/control/defaulthost.
+
+
+1.2. How do I set up user masquerading? I'd like my own From lines to
+show boss@af.mil rather than god@heaven.af.mil.
+
+Answer: Add MAILHOST=af.mil and MAILUSER=boss to your environment. To
+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
+
+
+2.1. How do I send local messages to another host? All the mail for
+af.mil should be delivered to our disk server, pokey.af.mil. I've set up
+an MX from af.mil to pokey.af.mil, but when a user on the af.mil host
+sends a message to boss@af.mil, af.mil tries to deliver it locally. How
+do I stop that?
+
+Answer: Remove af.mil from /var/qmail/control/locals. If qmail-send is
+running, give it a HUP. Make sure the MX is set up properly before you
+do this. Also make sure that pokey can receive mail for af.mil---see
+question 3.1.
+
+
+2.2. How do I set up a null client? I'd like zippy.af.mil to
+send all mail to bigbang.af.mil.
+
+Answer: echo :bigbang.af.mil > /var/qmail/control/smtproutes;
+chmod 644 /var/qmail/control/smtproutes. Disable local delivery as in
+question 2.1. Turn off qmail-smtpd in /etc/inetd.conf.
+
+
+2.3. How do I send outgoing mail through UUCP? I need qmail to send all
+outgoing mail via UUCP to my upstream UUCP site, gonzo.
+
+Answer: Put
+
+ :alias-uucp
+
+into control/virtualdomains and
+
+ |preline -df /usr/bin/uux - -r -gC
+ -a"${SENDER:-MAILER-DAEMON}" gonzo!rmail "($DEFAULT@$HOST)"
+
+(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.
+
+
+2.4. How do I set up a separate queue for a SLIP/PPP link?
+
+Answer: Use serialmail (http://pobox.com/~djb/serialmail.html).
+
+
+2.5. How do I deal with ``CNAME lookup failed temporarily''? The log
+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 recipient host. If the
+relevant DNS server is down, qmail defers the message. It will try again
+soon.
+
+
+
+3. Routing incoming messages by host
+
+
+3.1. How do I receive mail for another host name? I'd like our disk
+server, pokey.af.mil, to receive mail addressed to af.mil. I've set up
+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
+(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
+nowhere.mil, including root@nowhere.mil and postmaster@nowhere.mil and
+so on, to be delivered to Bob. I've set up the MX already.
+
+Answer: Put
+
+ nowhere.mil:bob
+
+into control/virtualdomains. Add nowhere.mil to control/rcpthosts. If
+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
+possible addresses, ~bob/.qmail-info to catch info@nowhere.mil, etc.
+
+
+3.3. How do I set up several virtual domains for one user? Bob wants
+another virtual domain, everywhere.org, but he wants to handle
+nowhere.mil users and everywhere.org users differently. How can we do
+that without setting up a second account?
+
+Answer: Put two lines into control/virtualdomains:
+
+ nowhere.mil:bob-nowhere
+ everywhere.org:bob-everywhere
+
+Add nowhere.mil and everywhere.org to control/rcpthosts. If qmail-send
+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.
+
+
+
+4. Routing incoming messages by user
+
+
+4.1. How do I forward unrecognized usernames to another host? I'd like
+to set up a LUSER_RELAY pointing at bigbang.af.mil.
+
+Answer: Put
+
+ | forward "$LOCAL"@bigbang.af.mil
+
+into ~alias/.qmail-default.
+
+
+4.2. How do I set up a mailing list? I'd like me-sos@my.host.name to be
+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.
+
+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: 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?
+
+Answer: Put
+
+ | preline procmail
+
+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 /var/spool/mail/$USER by default; to change this, see
+INSTALL.mbox.
+
+
+4.5. How do I use elm's filter with qmail?
+
+Answer: Put
+
+ | preline filter
+
+into ~/.qmail. You'll have to use a full path for filter unless filter
+is in the system's startup PATH.
+
+
+4.6. How do I create aliases with dots? I tried setting up
+~alias/.qmail-P.D.Q.Bach, but it doesn't do anything.
+
+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
+
+
+5.1. How do I run qmail-smtpd under tcpserver? inetd is barfing at high
+loads, cutting off service for ten-minute stretches. I'd also like
+better connection logging.
+
+Answer: First, install the tcpserver program, part of the ucspi-tcp
+package (http://pobox.com/~djb/ucspi-tcp.html). Second, remove the smtp
+line from /etc/inetd.conf, and put the line
+
+ tcpserver -u 7770 -g 2108 0 smtp /var/qmail/bin/qmail-smtpd &
+
+into your system startup files. Replace 7770 with your qmaild uid, and
+replace 2108 with your nofiles gid. Don't forget the &. The change will
+take effect at your next reboot.
+
+By default, tcpserver allows at most 40 simultaneous qmail-smtpd
+processes. To raise this limit to 400, use tcpserver -c 400. To keep
+track of who's connecting and for how long, run (on two lines)
+
+ tcpserver -v -u 7770 -g 2108 0 smtp /var/qmail/bin/qmail-smtpd \
+ 2>&1 | /var/qmail/bin/splogger smtpd 3 &
+
+
+5.2. How do I set up qmail-qmtpd?
+
+Answer: Two steps. First, put a
+
+ qmtp 209/tcp
+
+line into /etc/services. Second, put (all on one line)
+
+ qmtp stream tcp nowait qmaild
+ /var/qmail/bin/tcp-env tcp-env /var/qmail/bin/qmail-qmtpd
+
+into /etc/inetd.conf, and give inetd a HUP.
+
+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 on tcpserver.
+
+
+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, 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
+
+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
+any user who wants to read mail via POP.
+
+If you have tcpserver installed, skip the inetd step, and set up (on two
+lines)
+
+ tcpserver 0 pop3 /var/qmail/bin/qmail-popup YOURHOST \
+ /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 on tcpserver.
+
+Security note: pop3d should be used only within a secure network;
+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.
+
+Answer: Three steps. First, install tcp-wrappers, available separately,
+including hosts_options. Second, change your qmail-smtpd line in
+inetd.conf to
+
+ smtp stream tcp nowait qmaild /usr/local/bin/tcpd
+ /var/qmail/bin/tcp-env /var/qmail/bin/qmail-smtpd
+
+(all on one line) and give inetd a HUP. Third, in tcpd's hosts.allow,
+make a line setting the environment variable RELAYCLIENT to the empty
+string for the selected clients:
+
+ tcp-env: 1.2.3.4, 1.2.3.5: setenv = RELAYCLIENT
+
+Here 1.2.3.4 and 1.2.3.5 are the clients' IP addresses. qmail-smtpd
+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 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
+
+ tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
+
+Finally, insert
+
+ -x /etc/tcp.smtp.cdb
+
+after tcpserver in your qmail-smtpd invocation.
+
+
+5.5. How do I fix up messages from broken SMTP clients?
+
+Answer: Three steps. First, put
+
+ | bouncesaying 'Permission denied' [ "@$HOST" != "@fixme" ]
+ | qmail-inject -f "$SENDER" -- "$DEFAULT"
+
+into ~alias/.qmail-fixup-default. Second, put
+
+ fixme:fixup
+
+into /var/qmail/control/virtualdomains, and give qmail-send a HUP.
+Third, follow the procedure in question 5.4, but set RELAYCLIENT to the
+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 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 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.
+
+
+
+6. Configuring MUAs to work with qmail
+
+
+6.1. How do I make BSD mail generate a Date with the local time zone?
+When I send mail, I'd rather use the local time zone than GMT, since
+some MUAs don't know how to display Date in the receiver's time zone.
+
+Answer: Put
+
+ set sendmail=/var/qmail/bin/datemail
+
+into your .mailrc or your system-wide Mail.rc. Beware that BSD mail is
+neither secure nor reliable.
+
+
+6.2. How do I make pine work with qmail?
+
+Answer: Put
+
+ sendmail-path=/usr/lib/sendmail -oem -oi -t
+
+into /usr/local/lib/pine.conf. (This will work with sendmail too.)
+Beware that pine is neither secure nor reliable.
+
+
+6.3. How do I make MH work with qmail?
+
+Answer: Put
+
+ postproc: /usr/mh/lib/spost
+
+into each user's .mh_profile. (This will work with sendmail too.) Beware
+that MH is neither secure nor reliable.
+
+
+6.4. How do I stop Sun's dtcm from hanging?
+
+Answer: There is a novice programming error in dtcm, known as ``failure
+to close the output side of the pipe in the child.'' Sun has, at the
+time of this writing, not yet provided a patch. Sorry.
+
+
+
+7. Managing the mail system
+
+
+7.1. How do I safely stop qmail-send? Back when we were running
+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 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. (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
+again; it's going to be down for at least another two days. I know Eric
+has been expecting an important message---in fact, I see it sitting here
+in /var/qmail/queue/mess/15/26902. It's been in the queue for six days;
+how can I make sure it isn't bounced tomorrow?
+
+Answer: Just touch /var/qmail/queue/info/15/26902. (This is the only
+form of queue modification that's safe while qmail is running.)
+
+
+7.4. How do I organize a big network? I have a lot of machines, and I
+don't know where to start.
+
+Answer: First, choose the domain name where your users will receive
+mail. This is normally the shortest domain name you control. If you are
+in charge of *.movie.edu, you can use addresses like joe@movie.edu.
+
+Second, choose the machine that will know what to do with different
+users at movie.edu. Set up a host name in DNS for this machine:
+
+ mailhost.movie.edu IN A 1.2.3.4
+ 4.3.2.1.in-addr.arpa IN PTR mailhost.movie.edu
+
+Here 1.2.3.4 is the IP address of that machine.
+
+Third, make a list of machines where mail should end up. For example, if
+mail for Bob should end up on Bob's workstation, put Bob's workstation
+onto the list. For each of these machines, set up a host name in DNS:
+
+ bobshost.movie.edu IN A 1.2.3.7
+ 7.3.2.1.in-addr.arpa IN PTR bobshost.movie.edu
+
+Fourth, install qmail on bobshost.movie.edu. qmail will automatically
+configure itself to accept messages for bob@bobshost.movie.edu and
+deliver them to ~bob/Mailbox on bobshost. Do the same for the other
+machines where mail should end up.
+
+Fifth, install qmail on mailhost.movie.edu. Put
+
+ movie.edu:alias-movie
+
+into control/virtualdomains on mailhost. Then forward bob@movie.edu to
+bob@bobshost.movie.edu, by putting
+
+ bob@bobshost.movie.edu
+
+into ~alias/.qmail-movie-bob. Do the same for other users.
+
+Sixth, put movie.edu into control/rcpthosts on mailhost.movie.edu, so
+that mailhost.movie.edu will accept messages for users at movie.edu.
+
+Seventh, set up an MX record in DNS to deliver movie.edu messages to
+mailhost:
+
+ movie.edu IN MX 10 mailhost.movie.edu
+
+Eighth, on all your machines, put movie.edu into control/defaulthost.
+
+
+7.5. How do I back up and restore the queue disk?
+
+Answer: You can't.
+
+One difficulty is that you can't get a consistent snapshot of the queue
+while qmail-send is running. Another difficulty is that messages in the
+queue must have filenames that match their inode numbers.
+
+However, the big problem is that backups---even twice-daily backups---
+are far too unreliable for mail. If your disk dies, there will be very
+little overlap between the messages saved in the last backup and the
+messages that were lost.
+
+There are several ways to add real reliability to a mail server. Battery
+backups will keep your server alive, letting you park the disk to avoid
+a head crash, when the power goes out. Solid-state disks have their own
+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
+
+
+8.1. How do I tell qmail to do more deliveries at once? It's running
+only 20 parallel qmail-remote processes.
+
+Answer: Decide how many deliveries you want to allow at once. Put that
+number into control/concurrencyremote. Restart qmail-send as in question
+7.1. If your system has resource limits, make sure you set the
+descriptors limit to at least double the concurrency plus 5; otherwise
+you'll get lots of unnecessary deferrals whenever a big burst of mail
+shows up. Note that qmail also imposes a compile-time concurrency limit,
+120 by default; this is set in conf-spawn.
+
+
+8.2. How do I keep a copy of all incoming and outgoing mail messages?
+
+Answer: Set QUEUE_EXTRA to "Tlog\0" and QUEUE_EXTRALEN to 5 in extra.h.
+Recompile qmail. Put ./msg-log into ~alias/.qmail-log.
+
+You can also use QUEUE_EXTRA to, e.g., record the Message-ID of every
+message: run
+
+ | awk '/^$/ { exit } /^[mM][eE][sS][sS][aA][gG][eE]-/ { print }'
+
+from ~alias/.qmail-log.
+
+
+8.3. How do I switch slowly from sendmail to qmail? I'm thinking of
+moving the heaven.af.mil network over to qmail, but first I'd like to
+give my users a chance to try out qmail without affecting current
+sendmail deliveries. We're using NFS.
+
+Answer: Find a host in your network, say pc.heaven.af.mil, that isn't
+running an SMTP server. (If addresses at pc.heaven.af.mil are used, you
+should already have an MX pointing pc.heaven.af.mil to your mail hub.)
+
+Set up a new MX record pointing lists.heaven.af.mil to pc.heaven.af.mil.
+Install qmail on pc.heaven.af.mil. Replace pc with lists in the control
+files. Make the qmail man pages available on all your machines.
+
+Now tell your users about qmail. A user can forward joe@heaven.af.mil to
+joe@lists.heaven.af.mil to get ~/Mailbox delivery; he can set up .qmail
+files; he can start running his own mailing lists @lists.heaven.af.mil.
+
+When you're ready to turn sendmail off, you can set up pc.heaven.af.mil
+as your new mail hub. Add heaven.af.mil to control/locals, and change
+the heaven.af.mil MX to point to pc.heaven.af.mil. Make sure you leave
+lists.heaven.af.mil in control/locals so that transition addresses will
+continue to work.
diff --git a/FILES b/FILES
new file mode 100644
index 0000000..0f70971
--- /dev/null
+++ b/FILES
@@ -0,0 +1,434 @@
+BLURB
+BLURB2
+BLURB3
+BLURB4
+README
+FAQ
+INSTALL
+INSTALL.alias
+INSTALL.ctl
+INSTALL.ids
+INSTALL.maildir
+INSTALL.mbox
+INSTALL-1.03
+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
+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
+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
+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
+coe.h
+coe.c
+fd.h
+fd_copy.3
+fd_copy.c
+fd_move.3
+fd_move.c
+fifo_make.3
+fifo.h
+fifo.c
+trymkffo.c
+fork.h1
+fork.h2
+tryvfork.c
+now.3
+now.h
+now.c
+open.h
+open_append.c
+open_excl.c
+open_read.c
+open_trunc.c
+open_write.c
+seek.h
+seek_cur.c
+seek_end.c
+seek_set.c
+seek_trunc.c
+conf-qmail
+auto_qmail.h
+qmail.h
+qmail.c
+gen_alloc.h
+gen_allocdefs.h
+stralloc.3
+stralloc.h
+stralloc_eady.c
+stralloc_pend.c
+stralloc_copy.c
+stralloc_opyb.c
+stralloc_opys.c
+stralloc_cat.c
+stralloc_catb.c
+stralloc_cats.c
+stralloc_arts.c
+strerr.h
+strerr_sys.c
+strerr_die.c
+substdio.h
+substdio.c
+substdi.c
+substdo.c
+substdio_copy.c
+subfd.h
+subfderr.c
+subfdouts.c
+subfdout.c
+subfdins.c
+subfdin.c
+readwrite.h
+exit.h
+timeoutconn.h
+timeoutconn.c
+timeoutread.h
+timeoutread.c
+timeoutwrite.h
+timeoutwrite.c
+remoteinfo.h
+remoteinfo.c
+uint32.h1
+uint32.h2
+tryulong32.c
+wait.3
+wait.h
+wait_pid.c
+wait_nohang.c
+trywaitp.c
+sig.h
+sig_alarm.c
+sig_block.c
+sig_catch.c
+sig_pause.c
+sig_pipe.c
+sig_child.c
+sig_term.c
+sig_hup.c
+sig_misc.c
+sig_bug.c
+trysgact.c
+trysgprm.c
+env.3
+env.h
+env.c
+envread.c
+byte.h
+byte_chr.c
+byte_copy.c
+byte_cr.c
+byte_diff.c
+byte_rchr.c
+byte_zero.c
+str.h
+str_chr.c
+str_cpy.c
+str_diff.c
+str_diffn.c
+str_len.c
+str_rchr.c
+str_start.c
+lock.h
+lock_ex.c
+lock_exnb.c
+lock_un.c
+tryflock.c
+getln.3
+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
+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
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..b2da6b1
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1 @@
+See http://lifewithqmail.org/lwq.html
diff --git a/INSTALL.alias b/INSTALL.alias
new file mode 100644
index 0000000..672365a
--- /dev/null
+++ b/INSTALL.alias
@@ -0,0 +1,40 @@
+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
+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 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
+set up right now.
+
+* Postmaster. You're not an Internet citizen if this address doesn't
+work. Simply touch (and chmod 644) ~alias/.qmail-postmaster; any mail
+for Postmaster will be delivered to ~alias/Mailbox.
+
+* MAILER-DAEMON. Not required, but users sometimes respond to bounce
+messages. Touch (and chmod 644) ~alias/.qmail-mailer-daemon.
+
+* root. Under qmail, root never receives mail. Your system may generate
+mail messages to root every night; if you don't have an alias for root,
+those messages will bounce. (They'll end up double-bouncing to the
+postmaster.) Set up an alias for root in ~alias/.qmail-root. .qmail
+files are similar to .forward files, but beware that they are strictly
+line-oriented---see dot-qmail.0 for details.
+
+* Other non-user accounts. Under qmail, non-user accounts don't get
+mail; ``user'' means a non-root account that owns ~account. Set up
+aliases for any non-user accounts that normally receive mail.
+
+Note that special accounts such as ftp, www, and uucp should always have
+home directories owned by root.
+
+* Default. If you want, you can touch ~alias/.qmail-default to catch
+everything else. Beware: this will also catch typos and other addresses
+that should probably be bounced instead. It won't catch addresses that
+start with a user name---the user can set up his own ~/.qmail-default.
diff --git a/INSTALL.ctl b/INSTALL.ctl
new file mode 100644
index 0000000..00ce689
--- /dev/null
+++ b/INSTALL.ctl
@@ -0,0 +1,38 @@
+As you've seen, qmail has essentially no pre-compilation configuration.
+You should never have to recompile it unless you want to change the
+qmail home directory, usernames, or uids.
+
+qmail does allow quite a bit of easy post-installation configuration. If
+you care how your machine greets other machines via SMTP, for example,
+you can put an appropriate line into /var/qmail/control/smtpgreeting.
+
+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. Just run
+the config-fast script:
+
+ # ./config-fast your.full.host.name
+
+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,
+checking if a recipient is local, etc.---without talking to the network.
+The point is that qmail can continue accepting and delivering local mail
+even if your network connection goes down.)
+
+Next, read through FAQ for information on setting up optional features
+like masquerading. If you really want to learn right now what all the
+configuration possibilities are, see qmail-control.0.
diff --git a/INSTALL.ids b/INSTALL.ids
new file mode 100644
index 0000000..a50e10d
--- /dev/null
+++ b/INSTALL.ids
@@ -0,0 +1,72 @@
+Here's how to set up the qmail groups and the qmail users.
+
+On some systems there are commands that make this easy. Solaris and
+Linux:
+
+ # groupadd nofiles
+ # useradd -g nofiles -d /var/qmail/alias alias
+ # useradd -g nofiles -d /var/qmail qmaild
+ # useradd -g nofiles -d /var/qmail qmaill
+ # useradd -g nofiles -d /var/qmail qmailp
+ # groupadd qmail
+ # useradd -g qmail -d /var/qmail qmailq
+ # 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
+ # adduser -g nofiles -H/var/qmail/alias -G,,, -s/dev/null -P'*' alias
+ # adduser -g nofiles -H/var/qmail -G,,, -s/dev/null -P'*' qmaild
+ # adduser -g nofiles -H/var/qmail -G,,, -s/dev/null -P'*' qmaill
+ # adduser -g nofiles -H/var/qmail -G,,, -s/dev/null -P'*' qmailp
+ # addgroup qmail
+ # adduser -g qmail -H/var/qmail -G,,, -s/dev/null -P'*' qmailq
+ # adduser -g qmail -H/var/qmail -G,,, -s/dev/null -P'*' qmailr
+ # adduser -g qmail -H/var/qmail -G,,, -s/dev/null -P'*' qmails
+
+AIX:
+
+ # mkgroup -A nofiles
+ # mkuser pgrp=nofiles home=/var/qmail/alias shell=/bin/true alias
+ # mkuser pgrp=nofiles home=/var/qmail shell=/bin/true qmaild
+ # mkuser pgrp=nofiles home=/var/qmail shell=/bin/true qmaill
+ # mkuser pgrp=nofiles home=/var/qmail shell=/bin/true qmailp
+ # mkgroup -A qmail
+ # mkuser pgrp=qmail home=/var/qmail shell=/bin/true qmailq
+ # mkuser pgrp=qmail home=/var/qmail shell=/bin/true qmailr
+ # mkuser pgrp=qmail home=/var/qmail shell=/bin/true qmails
+
+On other systems, you will have to edit /etc/group and /etc/passwd
+manually. First add two new lines to /etc/group, something like
+
+ qmail:*:2107:
+ nofiles:*:2108:
+
+where 2107 and 2108 are different from the other gids in /etc/group.
+Next (using vipw) add six new lines to /etc/passwd, something like
+
+ alias:*:7790:2108::/var/qmail/alias:/bin/true
+ qmaild:*:7791:2108::/var/qmail:/bin/true
+ qmaill:*:7792:2108::/var/qmail:/bin/true
+ qmailp:*:7793:2108::/var/qmail:/bin/true
+ qmailq:*:7794:2107::/var/qmail:/bin/true
+ qmailr:*:7795:2107::/var/qmail:/bin/true
+ qmails:*:7796:2107::/var/qmail:/bin/true
+
+where 7790 through 7796 are _new_ uids, 2107 is the qmail gid, and 2108
+is the nofiles gid. Make sure you use the nofiles gid for qmaild,
+qmaill, qmailp, and alias, and the qmail gid for qmailq, qmailr, and
+qmails.
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
new file mode 100644
index 0000000..93ca16c
--- /dev/null
+++ b/INSTALL.mbox
@@ -0,0 +1,53 @@
+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 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 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.
+
+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.
+
+ * 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:
+
+ * procmail: Change SYSTEM_MBOX in config.h and recompile; or, with
+ recent versions, define MAILSPOOLHOME in src/authenticate.c.
+
+An alternative to symbolic links is hlfsd. Consult the documentation for
+hlfsd if it is included in your operating system.
+
+If /var/spool/mail is large, you can gain extra speed by configuring
+all your mail software to look at ~user/Mailbox directly:
+
+ * Most MUAs: Put ``setenv MAIL $HOME/Mailbox'' in your system-wide
+ .cshrc and ``MAIL=$HOME/Mailbox; export MAIL'' in your system-wide
+ .profile.
+
+ * 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.)
+
+ * pine: Put ``inbox-path=Mailbox'' in your system-wide pine.conf.
+ (For pine versions more recent than 3.91, see also FAQ 6.2.)
+
+ * qpopper 2.2: Change /.mail to /Mailbox in pop_dropcopy.c and
+ recompile with -DHOMEDIRMAIL in CFLAGS.
+
+Some vendors, in a misguided attempt to solve the security problems of
+/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.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
new file mode 100644
index 0000000..e668ae8
--- /dev/null
+++ b/INTERNALS
@@ -0,0 +1,156 @@
+1. Overview
+
+Here's the data flow in the qmail suite:
+
+ qmail-smtpd --- qmail-queue --- qmail-send --- qmail-rspawn --- qmail-remote
+ / | \
+qmail-inject _/ qmail-clean \_ qmail-lspawn --- qmail-local
+
+Every message is added to a central queue directory by qmail-queue.
+qmail-queue is invoked as needed, usually by qmail-inject for locally
+generated messages, qmail-smtpd for messages received through SMTP,
+qmail-local for forwarded messages, or qmail-send for bounce messages.
+
+Every message is then delivered by qmail-send, in cooperation with
+qmail-lspawn and qmail-rspawn, and cleaned up by qmail-clean. These four
+programs are long-running daemons.
+
+The queue is designed to be crashproof, provided that the underlying
+filesystem is crashproof. All cleanups are handled by qmail-send and
+qmail-clean without human intervention. See section 6 for more details.
+
+
+2. Queue structure
+
+Each message in the queue is identified by a unique number, let's say
+457. The queue is organized into several directories, each of which may
+contain files related to message 457:
+
+ mess/457: the message
+ todo/457: the envelope: where the message came from, where it's going
+ intd/457: the envelope, under construction by qmail-queue
+ info/457: the envelope sender address, after preprocessing
+ local/457: local envelope recipient addresses, after preprocessing
+ remote/457: remote envelope recipient addresses, after preprocessing
+ bounce/457: permanent delivery errors
+
+Here are all possible states for a message. + means a file exists; -
+means it does not exist; ? means it may or may not exist.
+
+ S1. -mess -intd -todo -info -local -remote -bounce
+ S2. +mess -intd -todo -info -local -remote -bounce
+ S3. +mess +intd -todo -info -local -remote -bounce
+ S4. +mess ?intd +todo ?info ?local ?remote -bounce (queued)
+ S5. +mess -intd -todo +info ?local ?remote ?bounce (preprocessed)
+
+Guarantee: If mess/457 exists, it has inode number 457.
+
+
+3. How messages enter the queue
+
+To add a message to the queue, qmail-queue first creates a file in a
+separate directory, pid/, with a unique name. The filesystem assigns
+that file a unique inode number. qmail-queue looks at that number, say
+457. By the guarantee above, message 457 must be in state S1.
+
+qmail-queue renames pid/whatever as mess/457, moving to S2. It writes
+the message to mess/457. It then creates intd/457, moving to S3, and
+writes the envelope information to intd/457.
+
+Finally qmail-queue creates a new link, todo/457, for intd/457, moving
+to S4. At that instant the message has been successfully queued, and
+qmail-queue leaves it for further handling by qmail-send.
+
+qmail-queue starts a 24-hour timer before touching any files, and
+commits suicide if the timer expires.
+
+
+4. How queued messages are preprocessed
+
+Once a message has been queued, qmail-send must decide which recipients
+are local and which recipients are remote. It may also rewrite some
+recipient addresses.
+
+When qmail-send notices todo/457, it knows that message 457 is in S4. It
+removes info/457, local/457, and remote/457 if they exist. Then it reads
+through todo/457. It creates info/457, possibly local/457, and possibly
+remote/457. When it is done, it removes intd/457. The message is still
+in S4 at this point. Finally qmail-send removes todo/457, moving to S5.
+At that instant the message has been successfully preprocessed.
+
+
+5. How preprocessed messages are delivered
+
+Messages at S5 are handled as follows. Each address in local/457 and
+remote/457 is marked either NOT DONE or DONE.
+
+ DONE: The message was successfully delivered, or the last delivery
+ attempt met with permanent failure. Either way, qmail-send
+ should not attempt further delivery to this address.
+
+ NOT DONE: If there have been any delivery attempts, they have all
+ met with temporary failure. Either way, qmail-send should
+ try delivery in the future.
+
+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. 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
+bounce/457.
+
+When all addresses in local/457 are DONE, qmail-send deletes local/457.
+Same for remote/457.
+
+When local/457 and remote/457 are gone, qmail-send eliminates the
+message, as follows. First, if bounce/457 exists, qmail-send handles it
+as described above. Once bounce/457 is definitely gone, qmail-send
+deletes info/457, moving to S2, and finally mess/457, moving to S1.
+
+
+6. Cleanups
+
+If the computer crashes while qmail-queue is trying to queue a message,
+or while qmail-send is eliminating a message, the message may be left in
+state S2 or S3.
+
+When qmail-send sees a message in state S2 or S3---other than one
+it is currently eliminating!---where mess/457 is more than 36 hours old,
+it deletes intd/457 if that exists, then deletes mess/457. Note that any
+qmail-queue handling the message must be dead.
+
+Similarly, when qmail-send sees a file in the pid/ directory that is
+more than 36 hours old, it deletes it.
+
+Cleanups are not necessary if the computer crashes while qmail-send is
+delivering a message. At worst a message may be delivered twice. (There
+is no way for a distributed mail system to eliminate the possibility of
+duplication. What if an SMTP connection is broken just before the server
+acknowledges successful receipt of the message? The client must assume
+the worst and send the message again. Similarly, if the computer crashes
+just before qmail-send marks a message as DONE, the new qmail-send must
+assume the worst and send the message again. The usual solutions in the
+database literature---e.g., keeping log files---amount to saying that
+it's the recipient's computer's job to discard duplicate messages.)
+
+
+7. Further notes
+
+Currently info/457 serves two purposes: first, it records the envelope
+sender; second, its modification time is used to decide when a message
+has been in the queue too long. In the future info/457 may store more
+information. Any non-backwards-compatible changes will be identified by
+version numbers.
+
+When qmail-queue has successfully placed a message into the queue, it
+pulls a trigger offered by qmail-send. Here is the current triggering
+mechanism: lock/trigger is a named pipe. Before scanning todo/,
+qmail-send opens lock/trigger O_NDELAY for reading. It then selects for
+readability on lock/trigger. qmail-queue pulls the trigger by writing a
+byte O_NDELAY to lock/trigger. This makes lock/trigger readable and
+wakes up qmail-send. Before scanning todo/ again, qmail-send closes and
+reopens lock/trigger.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0f0e31a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,2141 @@
+# Don't edit Makefile! Use conf-* for configuration.
+
+SHELL=/bin/sh
+
+default: it
+
+addresses.0: \
+addresses.5
+ nroff -man addresses.5 > addresses.0
+
+alloc.a: \
+makelib alloc.o alloc_re.o
+ ./makelib alloc.a alloc.o alloc_re.o
+
+alloc.o: \
+compile alloc.c alloc.h error.h
+ ./compile alloc.c
+
+alloc_re.o: \
+compile alloc_re.c alloc.h byte.h
+ ./compile alloc_re.c
+
+auto-ccld.sh: \
+conf-cc conf-ld warn-auto.sh
+ ( cat warn-auto.sh; \
+ echo CC=\'`head -1 conf-cc`\'; \
+ echo LD=\'`head -1 conf-ld`\' \
+ ) > auto-ccld.sh
+
+auto-gid: \
+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 subfd.h substdio.h substdio.h readwrite.h exit.h \
+scan.h fmt.h
+ ./compile auto-gid.c
+
+auto-int: \
+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 readwrite.h exit.h scan.h fmt.h
+ ./compile auto-int.c
+
+auto-int8: \
+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 readwrite.h exit.h scan.h fmt.h
+ ./compile auto-int8.c
+
+auto-str: \
+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 readwrite.h exit.h
+ ./compile auto-str.c
+
+auto-uid: \
+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 subfd.h substdio.h substdio.h readwrite.h exit.h \
+scan.h fmt.h
+ ./compile auto-uid.c
+
+auto_break.c: \
+auto-str conf-break
+ ./auto-str auto_break \
+ "`head -1 conf-break`" > auto_break.c
+
+auto_break.o: \
+compile auto_break.c
+ ./compile auto_break.c
+
+auto_patrn.c: \
+auto-int8 conf-patrn
+ ./auto-int8 auto_patrn `head -1 conf-patrn` > auto_patrn.c
+
+auto_patrn.o: \
+compile auto_patrn.c
+ ./compile auto_patrn.c
+
+auto_qmail.c: \
+auto-str conf-qmail
+ ./auto-str auto_qmail `head -1 conf-qmail` > auto_qmail.c
+
+auto_qmail.o: \
+compile auto_qmail.c
+ ./compile auto_qmail.c
+
+auto_spawn.c: \
+auto-int conf-spawn
+ ./auto-int auto_spawn `head -1 conf-spawn` > auto_spawn.c
+
+auto_spawn.o: \
+compile auto_spawn.c
+ ./compile auto_spawn.c
+
+auto_split.c: \
+auto-int conf-split
+ ./auto-int auto_split `head -1 conf-split` > auto_split.c
+
+auto_split.o: \
+compile auto_split.c
+ ./compile auto_split.c
+
+auto_uids.c: \
+auto-uid auto-gid conf-users conf-groups
+ ( ./auto-uid auto_uida `head -1 conf-users` \
+ &&./auto-uid auto_uidd `head -2 conf-users | tail -1` \
+ &&./auto-uid auto_uidl `head -3 conf-users | tail -1` \
+ &&./auto-uid auto_uido `head -4 conf-users | tail -1` \
+ &&./auto-uid auto_uidp `head -5 conf-users | tail -1` \
+ &&./auto-uid auto_uidq `head -6 conf-users | tail -1` \
+ &&./auto-uid auto_uidr `head -7 conf-users | tail -1` \
+ &&./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.tmp && mv auto_uids.c.tmp auto_uids.c
+
+auto_uids.o: \
+compile auto_uids.c
+ ./compile auto_uids.c
+
+auto_usera.c: \
+auto-str conf-users
+ ./auto-str auto_usera `head -1 conf-users` > auto_usera.c
+
+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
+ ./compile byte_chr.c
+
+byte_copy.o: \
+compile byte_copy.c byte.h
+ ./compile byte_copy.c
+
+byte_cr.o: \
+compile byte_cr.c byte.h
+ ./compile byte_cr.c
+
+byte_diff.o: \
+compile byte_diff.c byte.h
+ ./compile byte_diff.c
+
+byte_rchr.o: \
+compile byte_rchr.c byte.h
+ ./compile byte_rchr.c
+
+byte_zero.o: \
+compile byte_zero.c byte.h
+ ./compile byte_zero.c
+
+case.a: \
+makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
+case_starts.o
+ ./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
+ case_lowers.o case_starts.o
+
+case_diffb.o: \
+compile case_diffb.c case.h
+ ./compile case_diffb.c
+
+case_diffs.o: \
+compile case_diffs.c case.h
+ ./compile case_diffs.c
+
+case_lowerb.o: \
+compile case_lowerb.c case.h
+ ./compile case_lowerb.c
+
+case_lowers.o: \
+compile case_lowers.c case.h
+ ./compile case_lowers.c
+
+case_starts.o: \
+compile case_starts.c case.h
+ ./compile case_starts.c
+
+cdb.a: \
+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
+ ./compile cdb_hash.c
+
+cdb_seek.o: \
+compile cdb_seek.c cdb.h uint32.h
+ ./compile cdb_seek.c
+
+cdb_unpack.o: \
+compile cdb_unpack.c cdb.h uint32.h
+ ./compile cdb_unpack.c
+
+cdbmake.a: \
+makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o
+ ./makelib cdbmake.a cdbmake_pack.o cdbmake_hash.o \
+ cdbmake_add.o
+
+cdbmake_add.o: \
+compile cdbmake_add.c cdbmake.h alloc.h uint32.h
+ ./compile cdbmake_add.c
+
+cdbmake_hash.o: \
+compile cdbmake_hash.c cdbmake.h uint32.h
+ ./compile cdbmake_hash.c
+
+cdbmake_pack.o: \
+compile cdbmake_pack.c cdbmake.h uint32.h
+ ./compile cdbmake_pack.c
+
+cdbmss.o: \
+compile cdbmss.c readwrite.h seek.h alloc.h cdbmss.h cdbmake.h \
+uint32.h substdio.h
+ ./compile cdbmss.c
+
+check: \
+it man
+ ./instcheck
+
+chkshsgr: \
+load chkshsgr.o
+ ./load chkshsgr
+
+chkshsgr.o: \
+compile chkshsgr.c exit.h
+ ./compile chkshsgr.c
+
+chkspawn: \
+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 subfd.h substdio.h fmt.h select.h \
+exit.h auto_spawn.h
+ ./compile chkspawn.c
+
+clean: \
+TARGETS
+ rm -f `cat TARGETS`
+
+coe.o: \
+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`" ) > \
+ compile
+ chmod 755 compile
+
+condredirect: \
+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 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 alloc.h case.h
+ ./compile constmap.c
+
+control.o: \
+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 fmt.h date822fmt.h
+ ./compile date822fmt.c
+
+datemail: \
+warn-auto.sh datemail.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh datemail.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 \
+ > datemail
+ chmod 755 datemail
+
+datetime.a: \
+makelib datetime.o datetime_un.o
+ ./makelib datetime.a datetime.o datetime_un.o
+
+datetime.o: \
+compile datetime.c datetime.h
+ ./compile datetime.c
+
+datetime_un.o: \
+compile datetime_un.c datetime.h
+ ./compile datetime_un.c
+
+direntry.h: \
+compile trydrent.c direntry.h1 direntry.h2
+ ( ./compile trydrent.c >/dev/null 2>&1 \
+ && cat direntry.h2 || cat direntry.h1 ) > direntry.h
+ rm -f trydrent.o
+
+dns.lib: \
+tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \
+alloc.a error.a fs.a str.a
+ ( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \
+ ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \
+ -lresolv `cat socket.lib` ) >/dev/null 2>&1 \
+ && echo -lresolv || exit 0 ) > dns.lib
+ rm -f tryrsolv.o tryrsolv
+
+dns.o: \
+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: \
+load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnscname dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnscname.o: \
+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 subfd.h substdio.h exit.h dns.h dnsdoe.h
+ ./compile dnsdoe.c
+
+dnsfq: \
+load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnsfq.o: \
+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: \
+load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnsip dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnsip.o: \
+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: \
+load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o now.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o now.o \
+ stralloc.a alloc.a substdio.a error.a str.a fs.a `cat \
+ dns.lib` `cat socket.lib`
+
+dnsmxip.o: \
+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: \
+load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnsptr.o: \
+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: \
+dot-qmail.5
+ nroff -man dot-qmail.5 > dot-qmail.0
+
+dot-qmail.5: \
+dot-qmail.9 conf-break conf-spawn
+ cat dot-qmail.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 \
+ > dot-qmail.5
+
+elq: \
+warn-auto.sh elq.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh elq.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 \
+ > elq
+ chmod 755 elq
+
+env.a: \
+makelib env.o envread.o
+ ./makelib env.a env.o envread.o
+
+env.o: \
+compile env.c str.h alloc.h env.h
+ ./compile env.c
+
+envelopes.0: \
+envelopes.5
+ nroff -man envelopes.5 > envelopes.0
+
+envread.o: \
+compile envread.c env.h str.h
+ ./compile envread.c
+
+error.a: \
+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.h
+ ./compile error.c
+
+error_str.o: \
+compile error_str.c error.h
+ ./compile error_str.c
+
+error_temp.o: \
+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.h
+ ./compile fd_copy.c
+
+fd_move.o: \
+compile fd_move.c fd.h
+ ./compile fd_move.c
+
+fifo.o: \
+compile fifo.c hasmkffo.h fifo.h
+ ./compile fifo.c
+
+find-systype: \
+find-systype.sh auto-ccld.sh
+ cat auto-ccld.sh find-systype.sh > find-systype
+ chmod 755 find-systype
+
+fmt_str.o: \
+compile fmt_str.c fmt.h
+ ./compile fmt_str.c
+
+fmt_strn.o: \
+compile fmt_strn.c fmt.h
+ ./compile fmt_strn.c
+
+fmt_uint.o: \
+compile fmt_uint.c fmt.h
+ ./compile fmt_uint.c
+
+fmt_uint0.o: \
+compile fmt_uint0.c fmt.h
+ ./compile fmt_uint0.c
+
+fmt_ulong.o: \
+compile fmt_ulong.c fmt.h
+ ./compile fmt_ulong.c
+
+fmtqfn.o: \
+compile fmtqfn.c fmtqfn.h fmt.h auto_split.h
+ ./compile fmtqfn.c
+
+forgeries.0: \
+forgeries.7
+ nroff -man forgeries.7 > forgeries.0
+
+fork.h: \
+compile load tryvfork.c fork.h1 fork.h2
+ ( ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null \
+ 2>&1 \
+ && cat fork.h2 || cat fork.h1 ) > fork.h
+ rm -f tryvfork.o tryvfork
+
+forward: \
+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 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
+ ./makelib fs.a fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.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 byte.h stralloc.h gen_alloc.h getln.h
+ ./compile getln.c
+
+getln2.o: \
+compile getln2.c substdio.h stralloc.h gen_alloc.h byte.h getln.h
+ ./compile getln2.c
+
+getopt.a: \
+makelib subgetopt.o sgetopt.o
+ ./makelib getopt.a subgetopt.o sgetopt.o
+
+gfrom.o: \
+compile gfrom.c str.h gfrom.h
+ ./compile gfrom.c
+
+hasflock.h: \
+tryflock.c compile load
+ ( ( ./compile tryflock.c && ./load tryflock ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASFLOCK 1 || exit 0 ) > hasflock.h
+ rm -f tryflock.o tryflock
+
+hasmkffo.h: \
+trymkffo.c compile load
+ ( ( ./compile trymkffo.c && ./load trymkffo ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASMKFIFO 1 || exit 0 ) > hasmkffo.h
+ rm -f trymkffo.o trymkffo
+
+hasnpbg1.h: \
+trynpbg1.c compile load open.h open.a fifo.h fifo.o select.h
+ ( ( ./compile trynpbg1.c \
+ && ./load trynpbg1 fifo.o open.a && ./trynpbg1 ) \
+ >/dev/null 2>&1 \
+ && echo \#define HASNAMEDPIPEBUG1 1 || exit 0 ) > \
+ hasnpbg1.h
+ rm -f trynpbg1.o trynpbg1
+
+hassalen.h: \
+trysalen.c compile
+ ( ./compile trysalen.c >/dev/null 2>&1 \
+ && echo \#define HASSALEN 1 || exit 0 ) > hassalen.h
+ rm -f trysalen.o
+
+hassgact.h: \
+trysgact.c compile load
+ ( ( ./compile trysgact.c && ./load trysgact ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h
+ rm -f trysgact.o trysgact
+
+hassgprm.h: \
+trysgprm.c compile load
+ ( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h
+ rm -f trysgprm.o trysgprm
+
+hasshsgr.h: \
+chkshsgr warn-shsgr tryshsgr.c compile load
+ ./chkshsgr || ( cat warn-shsgr; exit 1 )
+ ( ( ./compile tryshsgr.c \
+ && ./load tryshsgr && ./tryshsgr ) >/dev/null 2>&1 \
+ && echo \#define HASSHORTSETGROUPS 1 || exit 0 ) > \
+ hasshsgr.h
+ rm -f tryshsgr.o tryshsgr
+
+haswaitp.h: \
+trywaitp.c compile load
+ ( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASWAITPID 1 || exit 0 ) > haswaitp.h
+ rm -f trywaitp.o trywaitp
+
+headerbody.o: \
+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
+ ./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 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 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 strerr.h error.h open.h readwrite.h \
+exit.h
+ ./compile install.c
+
+instcheck: \
+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 strerr.h error.h readwrite.h exit.h
+ ./compile instcheck.c
+
+ip.o: \
+compile ip.c fmt.h scan.h ip.h
+ ./compile ip.c
+
+ipalloc.o: \
+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 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: \
+load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \
+error.a str.a fs.a socket.lib
+ ./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \
+ substdio.a error.a str.a fs.a `cat socket.lib`
+
+ipmeprint.o: \
+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-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
+ ( cat warn-auto.sh; ./make-load "`cat systype`" ) > load
+ chmod 755 load
+
+lock.a: \
+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 hasflock.h lock.h
+ ./compile lock_ex.c
+
+lock_exnb.o: \
+compile lock_exnb.c hasflock.h lock.h
+ ./compile lock_exnb.c
+
+lock_un.o: \
+compile lock_un.c hasflock.h lock.h
+ ./compile lock_un.c
+
+maildir.0: \
+maildir.5
+ nroff -man maildir.5 > maildir.0
+
+maildir.o: \
+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: \
+load maildir2mbox.o maildir.o prioq.o now.o myctime.o gfrom.o lock.a \
+getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \
+str.a fs.a datetime.a
+ ./load maildir2mbox maildir.o prioq.o now.o myctime.o \
+ gfrom.o lock.a getln.a env.a open.a strerr.a stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a datetime.a
+
+maildir2mbox.0: \
+maildir2mbox.1
+ nroff -man maildir2mbox.1 > maildir2mbox.0
+
+maildir2mbox.o: \
+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 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 strerr.h exit.h
+ ./compile maildirmake.c
+
+maildirwatch: \
+load maildirwatch.o hfield.o headerbody.o maildir.o prioq.o now.o \
+getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \
+str.a
+ ./load maildirwatch hfield.o headerbody.o maildir.o \
+ prioq.o now.o getln.a env.a open.a strerr.a stralloc.a \
+ alloc.a substdio.a error.a str.a
+
+maildirwatch.0: \
+maildirwatch.1
+ nroff -man maildirwatch.1 > maildirwatch.0
+
+maildirwatch.o: \
+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: \
+warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh mailsubj.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 \
+ > mailsubj
+ chmod 755 mailsubj
+
+mailsubj.0: \
+mailsubj.1
+ nroff -man mailsubj.1 > mailsubj.0
+
+make-compile: \
+make-compile.sh auto-ccld.sh
+ cat auto-ccld.sh make-compile.sh > make-compile
+ chmod 755 make-compile
+
+make-load: \
+make-load.sh auto-ccld.sh
+ cat auto-ccld.sh make-load.sh > make-load
+ chmod 755 make-load
+
+make-makelib: \
+make-makelib.sh auto-ccld.sh
+ cat auto-ccld.sh make-makelib.sh > make-makelib
+ chmod 755 make-makelib
+
+makelib: \
+make-makelib warn-auto.sh systype
+ ( cat warn-auto.sh; ./make-makelib "`cat systype`" ) > \
+ makelib
+ chmod 755 makelib
+
+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-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
+
+mbox.0: \
+mbox.5
+ nroff -man mbox.5 > mbox.0
+
+myctime.o: \
+compile myctime.c datetime.h fmt.h myctime.h
+ ./compile myctime.c
+
+ndelay.a: \
+makelib ndelay.o ndelay_off.o
+ ./makelib ndelay.a ndelay.o ndelay_off.o
+
+ndelay.o: \
+compile ndelay.c ndelay.h
+ ./compile ndelay.c
+
+ndelay_off.o: \
+compile ndelay_off.c ndelay.h
+ ./compile ndelay_off.c
+
+newfield.o: \
+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 datetime.h now.h datetime.h
+ ./compile now.c
+
+open.a: \
+makelib open_append.o open_excl.o open_read.o open_trunc.o \
+open_write.o
+ ./makelib open.a open_append.o open_excl.o open_read.o \
+ open_trunc.o open_write.o
+
+open_append.o: \
+compile open_append.c open.h
+ ./compile open_append.c
+
+open_excl.o: \
+compile open_excl.c open.h
+ ./compile open_excl.c
+
+open_read.o: \
+compile open_read.c open.h
+ ./compile open_read.c
+
+open_trunc.o: \
+compile open_trunc.c open.h
+ ./compile open_trunc.c
+
+open_write.o: \
+compile open_write.c open.h
+ ./compile open_write.c
+
+pinq: \
+warn-auto.sh pinq.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh pinq.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 \
+ > pinq
+ chmod 755 pinq
+
+predate: \
+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 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 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 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 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.h
+ ./compile prot.c
+
+qail: \
+warn-auto.sh qail.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh qail.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 \
+ > qail
+ chmod 755 qail
+
+qbiff: \
+load qbiff.o headerbody.o hfield.o getln.a env.a open.a stralloc.a \
+alloc.a substdio.a error.a str.a
+ ./load qbiff headerbody.o hfield.o getln.a env.a open.a \
+ stralloc.a alloc.a substdio.a error.a str.a
+
+qbiff.0: \
+qbiff.1
+ nroff -man qbiff.1 > qbiff.0
+
+qbiff.o: \
+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
+
+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
+ ./load qmail-clean 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
+
+qmail-clean.0: \
+qmail-clean.8
+ nroff -man qmail-clean.8 > qmail-clean.0
+
+qmail-clean.o: \
+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-control.0: \
+qmail-control.5
+ nroff -man qmail-control.5 > qmail-control.0
+
+qmail-control.5: \
+qmail-control.9 conf-break conf-spawn
+ cat qmail-control.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-control.5
+
+qmail-getpw: \
+load qmail-getpw.o case.a substdio.a error.a str.a fs.a auto_break.o \
+auto_usera.o
+ ./load qmail-getpw case.a substdio.a error.a str.a fs.a \
+ auto_break.o auto_usera.o
+
+qmail-getpw.0: \
+qmail-getpw.8
+ nroff -man qmail-getpw.8 > qmail-getpw.0
+
+qmail-getpw.8: \
+qmail-getpw.9 conf-break conf-spawn
+ cat qmail-getpw.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-getpw.8
+
+qmail-getpw.o: \
+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-inject: \
+load qmail-inject.o headerbody.o hfield.o newfield.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
+ ./load qmail-inject headerbody.o hfield.o newfield.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 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: \
+qmail-limits.7
+ nroff -man qmail-limits.7 > qmail-limits.0
+
+qmail-limits.7: \
+qmail-limits.9 conf-break conf-spawn
+ cat qmail-limits.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-limits.7
+
+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 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 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 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: \
+qmail-log.5
+ nroff -man qmail-log.5 > qmail-log.0
+
+qmail-lspawn: \
+load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o sig.a wait.a \
+case.a cdb.a fd.a open.a stralloc.a alloc.a substdio.a error.a str.a \
+fs.a auto_qmail.o auto_uids.o auto_spawn.o
+ ./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o \
+ sig.a wait.a case.a cdb.a fd.a open.a stralloc.a alloc.a \
+ substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \
+ auto_spawn.o
+
+qmail-lspawn.0: \
+qmail-lspawn.8
+ nroff -man qmail-lspawn.8 > qmail-lspawn.0
+
+qmail-lspawn.o: \
+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
+ ./load qmail-newu 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
+
+qmail-newu.0: \
+qmail-newu.8
+ nroff -man qmail-newu.8 > qmail-newu.0
+
+qmail-newu.8: \
+qmail-newu.9 conf-break conf-spawn
+ cat qmail-newu.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-newu.8
+
+qmail-newu.o: \
+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 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 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 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 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: \
+load qmail-pw2u.o constmap.o control.o open.a getln.a case.a getopt.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a auto_usera.o \
+auto_break.o auto_qmail.o
+ ./load qmail-pw2u constmap.o control.o open.a getln.a \
+ case.a getopt.a stralloc.a alloc.a substdio.a error.a str.a \
+ fs.a auto_usera.o auto_break.o auto_qmail.o
+
+qmail-pw2u.0: \
+qmail-pw2u.8
+ nroff -man qmail-pw2u.8 > qmail-pw2u.0
+
+qmail-pw2u.8: \
+qmail-pw2u.9 conf-break conf-spawn
+ cat qmail-pw2u.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-pw2u.8
+
+qmail-pw2u.o: \
+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 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 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: \
+load qmail-qread.o fmtqfn.o readsubdir.o date822fmt.o datetime.a \
+open.a getln.a stralloc.a alloc.a substdio.a error.a str.a fs.a \
+auto_qmail.o auto_split.o
+ ./load qmail-qread fmtqfn.o readsubdir.o date822fmt.o \
+ datetime.a open.a getln.a stralloc.a alloc.a substdio.a \
+ error.a str.a fs.a auto_qmail.o auto_split.o
+
+qmail-qread.0: \
+qmail-qread.8
+ nroff -man qmail-qread.8 > qmail-qread.0
+
+qmail-qread.o: \
+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: \
+warn-auto.sh qmail-qstat.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh qmail-qstat.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-qstat
+ chmod 755 qmail-qstat
+
+qmail-qstat.0: \
+qmail-qstat.8
+ nroff -man qmail-qstat.8 > qmail-qstat.0
+
+qmail-queue: \
+load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \
+datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \
+str.a fs.a auto_qmail.o auto_split.o auto_uids.o
+ ./load qmail-queue triggerpull.o fmtqfn.o now.o \
+ date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
+ alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+ auto_split.o auto_uids.o
+
+qmail-queue.0: \
+qmail-queue.8
+ nroff -man qmail-queue.8 > qmail-queue.0
+
+qmail-queue.o: \
+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: \
+load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
+timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
+ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
+substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
+ ./load qmail-remote control.o constmap.o timeoutread.o \
+ timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
+ ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
+ lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
+ str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib`
+
+qmail-remote.0: \
+qmail-remote.8
+ nroff -man qmail-remote.8 > qmail-remote.0
+
+qmail-remote.o: \
+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: \
+load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \
+seek.a lock.a wait.a fd.a stralloc.a alloc.a substdio.a error.a str.a \
+auto_qmail.o auto_uids.o auto_spawn.o
+ ./load qmail-rspawn spawn.o tcpto_clean.o now.o coe.o \
+ sig.a open.a seek.a lock.a wait.a fd.a stralloc.a alloc.a \
+ substdio.a error.a str.a auto_qmail.o auto_uids.o \
+ auto_spawn.o
+
+qmail-rspawn.0: \
+qmail-rspawn.8
+ nroff -man qmail-rspawn.8 > qmail-rspawn.0
+
+qmail-rspawn.o: \
+compile qmail-rspawn.c fd.h wait.h substdio.h exit.h fork.h error.h \
+tcpto.h
+ ./compile qmail-rspawn.c
+
+qmail-send: \
+load qmail-send.o qsutil.o control.o constmap.o newfield.o prioq.o \
+trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
+datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
+lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+auto_split.o env.a
+ ./load qmail-send qsutil.o control.o constmap.o newfield.o \
+ prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
+ qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
+ wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
+ substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
+
+qmail-send.0: \
+qmail-send.8
+ nroff -man qmail-send.8 > qmail-send.0
+
+qmail-send.8: \
+qmail-send.9 conf-break conf-spawn
+ cat qmail-send.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-send.8
+
+qmail-send.o: \
+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 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 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 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 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: \
+load qmail-start.o prot.o fd.a auto_uids.o
+ ./load qmail-start prot.o fd.a auto_uids.o
+
+qmail-start.0: \
+qmail-start.8
+ nroff -man qmail-start.8 > qmail-start.0
+
+qmail-start.8: \
+qmail-start.9 conf-break conf-spawn
+ cat qmail-start.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-start.8
+
+qmail-start.o: \
+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
+ ./load qmail-tcpto ip.o now.o open.a lock.a substdio.a \
+ error.a str.a fs.a auto_qmail.o
+
+qmail-tcpto.0: \
+qmail-tcpto.8
+ nroff -man qmail-tcpto.8 > qmail-tcpto.0
+
+qmail-tcpto.o: \
+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-upq: \
+warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh qmail-upq.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-upq
+ chmod 755 qmail-upq
+
+qmail-users.0: \
+qmail-users.5
+ nroff -man qmail-users.5 > qmail-users.0
+
+qmail-users.5: \
+qmail-users.9 conf-break conf-spawn
+ cat qmail-users.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-users.5
+
+qmail.0: \
+qmail.7
+ nroff -man qmail.7 > qmail.0
+
+qmail.o: \
+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: \
+load qreceipt.o headerbody.o hfield.o quote.o token822.o qmail.o \
+getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a substdio.a error.a \
+str.a auto_qmail.o
+ ./load qreceipt headerbody.o hfield.o quote.o token822.o \
+ qmail.o getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a \
+ substdio.a error.a str.a auto_qmail.o
+
+qreceipt.0: \
+qreceipt.1
+ nroff -man qreceipt.1 > qreceipt.0
+
+qreceipt.o: \
+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: \
+load qsmhook.o sig.a case.a fd.a wait.a getopt.a env.a stralloc.a \
+alloc.a substdio.a error.a str.a
+ ./load qsmhook sig.a case.a fd.a wait.a getopt.a env.a \
+ stralloc.a alloc.a substdio.a error.a str.a
+
+qsmhook.o: \
+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 readwrite.h substdio.h \
+qsutil.h
+ ./compile qsutil.c
+
+quote.o: \
+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 fmt.h scan.h str.h \
+auto_split.h
+ ./compile readsubdir.c
+
+received.o: \
+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 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
+ ./compile scan_8long.c
+
+scan_ulong.o: \
+compile scan_ulong.c scan.h
+ ./compile scan_ulong.c
+
+seek.a: \
+makelib seek_cur.o seek_end.o seek_set.o seek_trunc.o
+ ./makelib seek.a seek_cur.o seek_end.o seek_set.o \
+ seek_trunc.o
+
+seek_cur.o: \
+compile seek_cur.c seek.h
+ ./compile seek_cur.c
+
+seek_end.o: \
+compile seek_end.c seek.h
+ ./compile seek_end.c
+
+seek_set.o: \
+compile seek_set.c seek.h
+ ./compile seek_set.c
+
+seek_trunc.o: \
+compile seek_trunc.c seek.h
+ ./compile seek_trunc.c
+
+select.h: \
+compile trysysel.c select.h1 select.h2
+ ( ./compile trysysel.c >/dev/null 2>&1 \
+ && cat select.h2 || cat select.h1 ) > select.h
+ rm -f trysysel.o trysysel
+
+sendmail: \
+load sendmail.o env.a getopt.a alloc.a substdio.a error.a str.a \
+auto_qmail.o
+ ./load sendmail env.a getopt.a alloc.a substdio.a error.a \
+ str.a auto_qmail.o
+
+sendmail.o: \
+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
+ ./install
+
+sgetopt.o: \
+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.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 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 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 \
+coe.h coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \
+fifo.h fifo.c trymkffo.c fork.h1 fork.h2 tryvfork.c now.3 now.h now.c \
+open.h open_append.c open_excl.c open_read.c open_trunc.c \
+open_write.c seek.h seek_cur.c seek_end.c seek_set.c seek_trunc.c \
+conf-qmail auto_qmail.h qmail.h qmail.c gen_alloc.h gen_allocdefs.h \
+stralloc.3 stralloc.h stralloc_eady.c stralloc_pend.c stralloc_copy.c \
+stralloc_opyb.c stralloc_opys.c stralloc_cat.c stralloc_catb.c \
+stralloc_cats.c stralloc_arts.c strerr.h strerr_sys.c strerr_die.c \
+substdio.h substdio.c substdi.c substdo.c substdio_copy.c subfd.h \
+subfderr.c subfdouts.c subfdout.c subfdins.c subfdin.c readwrite.h \
+exit.h timeoutconn.h timeoutconn.c timeoutread.h timeoutread.c \
+timeoutwrite.h timeoutwrite.c remoteinfo.h remoteinfo.c uint32.h1 \
+uint32.h2 tryulong32.c wait.3 wait.h wait_pid.c wait_nohang.c \
+trywaitp.c sig.h sig_alarm.c sig_block.c sig_catch.c sig_pause.c \
+sig_pipe.c sig_child.c sig_term.c sig_hup.c sig_misc.c sig_bug.c \
+trysgact.c trysgprm.c env.3 env.h env.c envread.c byte.h byte_chr.c \
+byte_copy.c byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h \
+str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c \
+str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c getln.3 \
+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 \
+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
+
+sig.a: \
+makelib sig_alarm.o sig_block.o sig_catch.o sig_pause.o sig_pipe.o \
+sig_child.o sig_hup.o sig_term.o sig_bug.o sig_misc.o
+ ./makelib sig.a sig_alarm.o sig_block.o sig_catch.o \
+ sig_pause.o sig_pipe.o sig_child.o sig_hup.o sig_term.o \
+ sig_bug.o sig_misc.o
+
+sig_alarm.o: \
+compile sig_alarm.c sig.h
+ ./compile sig_alarm.c
+
+sig_block.o: \
+compile sig_block.c sig.h hassgprm.h
+ ./compile sig_block.c
+
+sig_bug.o: \
+compile sig_bug.c sig.h
+ ./compile sig_bug.c
+
+sig_catch.o: \
+compile sig_catch.c sig.h hassgact.h
+ ./compile sig_catch.c
+
+sig_child.o: \
+compile sig_child.c sig.h
+ ./compile sig_child.c
+
+sig_hup.o: \
+compile sig_hup.c sig.h
+ ./compile sig_hup.c
+
+sig_misc.o: \
+compile sig_misc.c sig.h
+ ./compile sig_misc.c
+
+sig_pause.o: \
+compile sig_pause.c sig.h hassgprm.h
+ ./compile sig_pause.c
+
+sig_pipe.o: \
+compile sig_pipe.c sig.h
+ ./compile sig_pipe.c
+
+sig_term.o: \
+compile sig_term.c sig.h
+ ./compile sig_term.c
+
+slurpclose.o: \
+compile slurpclose.c stralloc.h gen_alloc.h readwrite.h slurpclose.h \
+error.h
+ ./compile slurpclose.c
+
+socket.lib: \
+trylsock.c compile load
+ ( ( ./compile trylsock.c && \
+ ./load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \
+ && echo -lsocket -lnsl || exit 0 ) > socket.lib
+ rm -f trylsock.o trylsock
+
+spawn.o: \
+compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \
+stralloc.h gen_alloc.h select.h exit.h alloc.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 socket.lib
+ ./load splogger substdio.a error.a str.a fs.a `cat \
+ syslog.lib` `cat socket.lib`
+
+splogger.0: \
+splogger.8
+ nroff -man splogger.8 > splogger.0
+
+splogger.o: \
+compile splogger.c error.h substdio.h subfd.h substdio.h exit.h str.h \
+scan.h fmt.h
+ ./compile splogger.c
+
+str.a: \
+makelib 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
+ ./makelib str.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_chr.o: \
+compile str_chr.c str.h
+ ./compile str_chr.c
+
+str_cpy.o: \
+compile str_cpy.c str.h
+ ./compile str_cpy.c
+
+str_diff.o: \
+compile str_diff.c str.h
+ ./compile str_diff.c
+
+str_diffn.o: \
+compile str_diffn.c str.h
+ ./compile str_diffn.c
+
+str_len.o: \
+compile str_len.c str.h
+ ./compile str_len.c
+
+str_rchr.o: \
+compile str_rchr.c str.h
+ ./compile str_rchr.c
+
+str_start.o: \
+compile str_start.c str.h
+ ./compile str_start.c
+
+stralloc.a: \
+makelib stralloc_eady.o stralloc_pend.o stralloc_copy.o \
+stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o \
+stralloc_catb.o stralloc_arts.o
+ ./makelib stralloc.a stralloc_eady.o stralloc_pend.o \
+ stralloc_copy.o stralloc_opys.o stralloc_opyb.o \
+ stralloc_cat.o stralloc_cats.o stralloc_catb.o \
+ stralloc_arts.o
+
+stralloc_arts.o: \
+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.h gen_alloc.h
+ ./compile stralloc_cat.c
+
+stralloc_catb.o: \
+compile stralloc_catb.c stralloc.h gen_alloc.h byte.h
+ ./compile stralloc_catb.c
+
+stralloc_cats.o: \
+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.h gen_alloc.h
+ ./compile stralloc_copy.c
+
+stralloc_eady.o: \
+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 byte.h
+ ./compile stralloc_opyb.c
+
+stralloc_opys.o: \
+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.h gen_alloc.h \
+gen_allocdefs.h
+ ./compile stralloc_pend.c
+
+strerr.a: \
+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 subfd.h substdio.h exit.h strerr.h
+ ./compile strerr_die.c
+
+strerr_sys.o: \
+compile strerr_sys.c error.h strerr.h
+ ./compile strerr_sys.c
+
+subfderr.o: \
+compile subfderr.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfderr.c
+
+subfdin.o: \
+compile subfdin.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfdin.c
+
+subfdins.o: \
+compile subfdins.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfdins.c
+
+subfdout.o: \
+compile subfdout.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfdout.c
+
+subfdouts.o: \
+compile subfdouts.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfdouts.c
+
+subgetopt.o: \
+compile subgetopt.c subgetopt.h
+ ./compile subgetopt.c
+
+substdi.o: \
+compile substdi.c substdio.h byte.h error.h
+ ./compile substdi.c
+
+substdio.a: \
+makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \
+subfdouts.o subfdin.o subfdins.o substdio_copy.o
+ ./makelib substdio.a substdio.o substdi.o substdo.o \
+ subfderr.o subfdout.o subfdouts.o subfdin.o subfdins.o \
+ substdio_copy.o
+
+substdio.o: \
+compile substdio.c substdio.h
+ ./compile substdio.c
+
+substdio_copy.o: \
+compile substdio_copy.c substdio.h
+ ./compile substdio_copy.c
+
+substdo.o: \
+compile substdo.c substdio.h str.h byte.h error.h
+ ./compile substdo.c
+
+syslog.lib: \
+trysyslog.c compile load
+ ( ( ./compile trysyslog.c && \
+ ./load trysyslog -lgen ) >/dev/null 2>&1 \
+ && echo -lgen || exit 0 ) > syslog.lib
+ rm -f trysyslog.o trysyslog
+
+systype: \
+find-systype trycpp.c
+ ./find-systype > systype
+
+tcp-env: \
+load tcp-env.o dns.o remoteinfo.o timeoutread.o timeoutwrite.o \
+timeoutconn.o ip.o ipalloc.o case.a ndelay.a sig.a env.a getopt.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load tcp-env dns.o remoteinfo.o timeoutread.o \
+ timeoutwrite.o timeoutconn.o ip.o ipalloc.o case.a ndelay.a \
+ sig.a env.a getopt.a stralloc.a alloc.a substdio.a error.a \
+ str.a fs.a `cat dns.lib` `cat socket.lib`
+
+tcp-env.0: \
+tcp-env.1
+ nroff -man tcp-env.1 > tcp-env.0
+
+tcp-env.o: \
+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: \
+tcp-environ.5
+ nroff -man tcp-environ.5 > tcp-environ.0
+
+tcpto.o: \
+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 open.h substdio.h readwrite.h
+ ./compile tcpto_clean.c
+
+timeoutconn.o: \
+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 select.h error.h readwrite.h
+ ./compile timeoutread.c
+
+timeoutwrite.o: \
+compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
+ ./compile timeoutwrite.c
+
+token822.o: \
+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 open.h trigger.h hasnpbg1.h
+ ./compile trigger.c
+
+triggerpull.o: \
+compile triggerpull.c ndelay.h open.h triggerpull.h
+ ./compile triggerpull.c
+
+uint32.h: \
+tryulong32.c compile load uint32.h1 uint32.h2
+ ( ( ./compile tryulong32.c && ./load tryulong32 && \
+ ./tryulong32 ) >/dev/null 2>&1 \
+ && cat uint32.h2 || cat uint32.h1 ) > uint32.h
+ rm -f tryulong32.o tryulong32
+
+wait.a: \
+makelib wait_pid.o wait_nohang.o
+ ./makelib wait.a wait_pid.o wait_nohang.o
+
+wait_nohang.o: \
+compile wait_nohang.c haswaitp.h
+ ./compile wait_nohang.c
+
+wait_pid.o: \
+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:<joe@heaven.af.mil>
+ RCPT TO:<bill@irs.gov>
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:<joe@heaven.af.mil>
+ RCPT TO:<bill@irs.gov>
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:<spammer@aol.com>
+ RCPT TO:<bill@irs.gov>
+
+ 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:<joe@heaven.af.mil>
+ | RCPT TO:<bill@irs.gov>
+ |
+ | Is $RELAYCLIENT set? Yes: "".
+ | Accept RCPT.
+ V
+
+qmail-queue Store message safely on disk.
+ Trigger qmail-send.
+ |
+ V
+
+qmail-send Look at envelope recipient, bill@irs.gov.
+ | Is irs.gov in locals? No.
+ | Is bill@irs.gov in virtualdomains? No.
+ | Is irs.gov in virtualdomains? No.
+ | Is .gov in virtualdomains? No.
+ | Deliver remotely to bill@irs.gov.
+ V
+
+qmail-rspawn Run qmail-remote.
+
+ |
+ V
+
+qmail-remote Look at host name, irs.gov.
+ Is irs.gov listed in smtproutes? No.
+ Look up DNS MX/A for irs.gov and connect to it by SMTP:
+
+ MAIL FROM:<joe@heaven.af.mil>
+ RCPT TO:<bill@irs.gov>
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:<bill@irs.gov>
+ | RCPT TO:<joe@heaven.af.mil>
+ |
+ | Is $RELAYCLIENT set? No.
+ | Is heaven.af.mil in rcpthosts? Yes.
+ | Accept RCPT.
+ V
+
+qmail-queue Store message safely on disk.
+ Trigger qmail-send.
+ |
+ V
+
+qmail-send Look at envelope recipient, joe@heaven.af.mil.
+ | Is heaven.af.mil in locals? Yes.
+ | Deliver locally to joe@heaven.af.mil.
+ V
+
+qmail-lspawn ./Mailbox
+
+ | Look at mailbox name, joe.
+ | Is joe listed in qmail-users? No.
+ | Is there a joe account? Yes.
+ | Is joe's uid nonzero? Yes.
+ | Is ~joe visible to the qmailp user? Yes.
+ | Is ~joe owned by joe? Yes.
+ | Give control of the message to joe.
+ | Run qmail-local.
+ V
+
+qmail-local joe ~joe joe '' '' heaven.af.mil bill@irs.gov ./Mailbox
+
+ Does ~joe/.qmail exist? No.
+ Write message to ./Mailbox in mbox format.
diff --git a/README b/README
new file mode 100644
index 0000000..e282597
--- /dev/null
+++ b/README
@@ -0,0 +1,295 @@
+netqmail 1.06
+20071130
+James Craig Burley claims copyright on the qmail-isoc patch. For
+more details, see COPYRIGHT.
+
+Apart from James' copyrights, no other copyright is claimed by the
+distributors of netqmail for changes from qmail 1.03 to netqmail 1.05.
+Daniel J. Bernstein has abandoned copyright for qmail 1.03.
+D. J. Bernstein did not participate in, nor has he been asked to
+approve of this distribution.
+
+With this distribution, we thank Daniel Bernstein for his dedication
+of qmail to the public domain. We have taken advantage of this event
+to remove the need to apply a patch. We will distribute a Netqmail 1.07
+shortly which includes enhancements.
+
+Netqmail 1.06 is produced by this motley krewe:
+
+Russ Nelson <nelson@qmail.org>
+Charles Cazabon <charlesc-software-netqmail@pyropus.ca>
+Dave Sill <de5@sws5.ornl.gov>
+Peter Samuel <Peter.Samuel@gormand.com.au>
+Henning Brauer <henning@bsws.de>
+Andrew Richards <ar-nq@acrconsulting.co.uk>
+Richard Lyons <rick-netqmail@frob.com.au>
+John Levine <netqmail@johnlevine.com>
+Scott Gifford <sgifford@suspectclass.com>
+Kyle Wheeler <kyle-netqmail@memoryhole.net>
+Wayne Marshall
+
+qmail is a secure, reliable, efficient, simple message transfer agent.
+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 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: 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.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)
+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 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)
+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)
+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)
+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.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)
+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)
+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)
+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)
+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.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-:-: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.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)
+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.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)
+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)
+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)
+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-:- (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)
+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)
+1.00: sunos-5.4-generic_101945-34-:sparc-:sun4-:sun4m-:sun4m- (tnx ACB)
+0.96: sunos-5.4-generic_101946-35-:i386-:i86pc-:i86pc-:i86pc- (tnx CK)
+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)
+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)
+1.00: sunos-5.5.1-generic_103640-03-:sparc-:sun4-:sun4u-:sun4u- (tnx EG)
+1.00: sunos-5.5.1-generic_103640-05-:sparc-:sun4-:sun4m-:sun4m- (tnx L2L)
+1.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/SECURITY b/SECURITY
new file mode 100644
index 0000000..098f124
--- /dev/null
+++ b/SECURITY
@@ -0,0 +1,131 @@
+Background: Every few months CERT announces Yet Another Security Hole In
+Sendmail---something that lets local or even remote users take complete
+control of the machine. I'm sure there are many more holes waiting to be
+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.
+
+
+1. Programs and files are not addresses. Don't treat them as addresses.
+
+sendmail treats programs and files as addresses. Obviously random people
+can't be allowed to execute arbitrary programs or write to arbitrary
+files, so sendmail goes through horrendous contortions trying to keep
+track of whether a local user was ``responsible'' for an address. This
+has proven to be an unmitigated disaster.
+
+In qmail, programs and files are not addresses. The local delivery
+agent, qmail-local, can run programs or write to files as directed by
+~user/.qmail, but it's always running as that user. (The notion of
+``user'' is configurable, but root is never a user. To prevent silly
+mistakes, qmail-local makes sure that neither ~user nor ~user/.qmail is
+group-writable or world-writable.)
+
+Security impact: .qmail, like .cshrc and .exrc and various other files,
+means that anyone who can write arbitrary files as a user can execute
+arbitrary programs as that user. That's it.
+
+
+2. Do as little as possible in setuid programs.
+
+A setuid program must operate in a very dangerous environment: a user is
+under complete control of its fds, args, environ, cwd, tty, rlimits,
+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 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
+add a new mail message to the outgoing queue.
+
+
+3. Do as little as possible as root.
+
+The entire sendmail system runs as root, so there's no way that its
+mistakes can be caught by the operating system's built-in protections.
+In contrast, only two qmail programs, qmail-start and qmail-lspawn,
+run as root.
+
+
+4. Move separate functions into mutually untrusting programs.
+
+Five of the qmail programs---qmail-smtpd, qmail-send, qmail-rspawn,
+qmail-remote, and tcp-env---are not security-critical. Even if all of
+these programs are completely compromised, so that an intruder has
+control over the qmaild, qmails, and qmailr accounts and the mail queue,
+he still can't take over your system. None of the other programs trust
+the results from these five.
+
+In fact, these programs don't even trust each other. They are in three
+groups: tcp-env and qmail-smtpd, which run as qmaild; qmail-rspawn and
+qmail-remote, which run as qmailr; and qmail-send, the queue manager,
+which runs as qmails. Each group is immune from attacks by the others.
+
+(From root's point of view, as long as root doesn't send any mail, only
+qmail-start and qmail-lspawn are security-critical. They don't write any
+files or start any other programs as root.)
+
+
+5. Don't parse.
+
+I have discovered that there are two types of command interfaces in the
+world of computing: good interfaces and user interfaces.
+
+The essence of user interfaces is _parsing_---converting an unstructured
+sequence of commands, in a format usually determined more by psychology
+than by solid engineering, into structured data.
+
+When another programmer wants to talk to a user interface, he has to
+_quote_: convert his structured data into an unstructured sequence of
+commands that the parser will, he hopes, convert back into the original
+structured data.
+
+This situation is a recipe for disaster. The parser often has bugs: it
+fails to handle some inputs according to the documented interface. The
+quoter often has bugs: it produces outputs that do not have the right
+meaning. Only on rare joyous occasions does it happen that the parser
+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
+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
+lines beginning with single-character commands. (text0 format means that
+lines are separated by a 0 byte instead of line feed.) The program-level
+interfaces don't take options.
+
+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.
+
+
+6. Keep it simple, stupid.
+
+See BLURB for some of the reasons that qmail is so much smaller than
+sendmail. There's nothing inherently complicated about writing a mailer.
+(Except RFC 822 support; but that's only in qmail-inject.) Security
+holes can't show up in features that don't exist.
+
+
+7. Write bug-free code.
+
+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
+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/SYSDEPS b/SYSDEPS
new file mode 100644
index 0000000..0bb01ec
--- /dev/null
+++ b/SYSDEPS
@@ -0,0 +1,17 @@
+VERSION
+systype
+hasshsgr.h
+hasnpbg1.h
+select.h
+hasflock.h
+hassalen.h
+fork.h
+hassgact.h
+direntry.h
+hassgprm.h
+haswaitp.h
+hasmkffo.h
+uint32.h
+dns.lib
+socket.lib
+syslog.lib
diff --git a/TARGETS b/TARGETS
new file mode 100644
index 0000000..facdad7
--- /dev/null
+++ b/TARGETS
@@ -0,0 +1,387 @@
+auto-ccld.sh
+make-load
+find-systype
+systype
+load
+make-compile
+compile
+fork.h
+qmail-local.o
+qmail.o
+quote.o
+now.o
+gfrom.o
+myctime.o
+slurpclose.o
+make-makelib
+makelib
+case_diffb.o
+case_diffs.o
+case_lowerb.o
+case_lowers.o
+case_starts.o
+case.a
+getln.o
+getln2.o
+getln.a
+subgetopt.o
+sgetopt.o
+getopt.a
+sig_alarm.o
+hassgprm.h
+sig_block.o
+hassgact.h
+sig_catch.o
+sig_pause.o
+sig_pipe.o
+sig_child.o
+sig_hup.o
+sig_term.o
+sig_bug.o
+sig_misc.o
+sig.a
+open_append.o
+open_excl.o
+open_read.o
+open_trunc.o
+open_write.o
+open.a
+seek_cur.o
+seek_end.o
+seek_set.o
+seek_trunc.o
+seek.a
+hasflock.h
+lock_ex.o
+lock_exnb.o
+lock_un.o
+lock.a
+fd_copy.o
+fd_move.o
+fd.a
+haswaitp.h
+wait_pid.o
+wait_nohang.o
+wait.a
+env.o
+envread.o
+env.a
+stralloc_eady.o
+stralloc_pend.o
+stralloc_copy.o
+stralloc_opys.o
+stralloc_opyb.o
+stralloc_cat.o
+stralloc_cats.o
+stralloc_catb.o
+stralloc_arts.o
+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
+select.h
+chkspawn.o
+auto-int.o
+auto-int
+auto_spawn.c
+auto_spawn.o
+chkspawn
+spawn.o
+chkshsgr.o
+chkshsgr
+hasshsgr.h
+prot.o
+coe.o
+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
+auto_break.o
+auto_usera.c
+auto_usera.o
+qmail-getpw
+qmail-remote.o
+control.o
+constmap.o
+timeoutread.o
+timeoutwrite.o
+timeoutconn.o
+tcpto.o
+dns.o
+ip.o
+ipalloc.o
+hassalen.h
+ipme.o
+ndelay.o
+ndelay_off.o
+ndelay.a
+dns.lib
+qmail-remote
+qmail-rspawn.o
+tcpto_clean.o
+qmail-rspawn
+direntry.h
+qmail-clean.o
+fmtqfn.o
+auto_split.c
+auto_split.o
+qmail-clean
+qmail-send.o
+qsutil.o
+newfield.o
+prioq.o
+hasmkffo.h
+fifo.o
+hasnpbg1.h
+trigger.o
+readsubdir.o
+date822fmt.o
+qmail-send
+qmail-start.o
+qmail-start
+splogger.o
+syslog.lib
+splogger
+qmail-queue.o
+triggerpull.o
+qmail-queue
+qmail-inject.o
+headerbody.o
+hfield.o
+token822.o
+qmail-inject
+predate.o
+predate
+datemail
+mailsubj
+qmail-upq
+qmail-showctl.o
+qmail-showctl
+qmail-newu.o
+cdbmss.o
+cdbmake_pack.o
+cdbmake_hash.o
+cdbmake_add.o
+cdbmake.a
+qmail-newu
+qmail-pw2u.o
+qmail-pw2u
+qmail-qread.o
+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-qmqpc.o
+qmail-qmqpc
+qmail-qmqpd.o
+received.o
+qmail-qmqpd
+qmail-qmtpd.o
+rcpthosts.o
+qmail-qmtpd
+qmail-smtpd.o
+qmail-smtpd
+sendmail.o
+sendmail
+tcp-env.o
+remoteinfo.o
+tcp-env
+qmail-newmrh.o
+qmail-newmrh
+config
+config-fast
+dnscname.o
+dnsdoe.o
+dnscname
+dnsptr.o
+dnsptr
+dnsip.o
+dnsip
+dnsmxip.o
+dnsmxip
+dnsfq.o
+dnsfq
+hostname.o
+hostname
+ipmeprint.o
+ipmeprint
+qreceipt.o
+qreceipt
+qsmhook.o
+qsmhook
+qbiff.o
+qbiff
+forward.o
+forward
+preline.o
+preline
+condredirect.o
+condredirect
+bouncesaying.o
+bouncesaying
+except.o
+except
+maildirmake.o
+maildirmake
+maildir2mbox.o
+maildir2mbox
+maildirwatch.o
+maildirwatch
+qail
+elq
+pinq
+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
+qmail-getpw.8
+qmail-getpw.0
+qmail-remote.0
+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
+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-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
+qmail-command.0
+tcp-environ.0
+maildir.0
+mbox.0
+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 <me@domain> 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 <me@domain> 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 <me@domain> 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 <me@domain>
+ 250 ok
+ rcpt <me@domain>
+ 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
new file mode 100644
index 0000000..76996f8
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,338 @@
+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.
+
+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
+ADM = Adam D. Morley
+AF = Andreas Faerber
+AG = Armin Gruner
+AGB = Andre Grosse Bley
+AH = Amos Hayes
+AI = Akihiro Iijima
+AJ = Alan Jaffray
+AJK = Antti-Juhani Kaijanaho
+AKB = Allen K. Briggs
+AL = Andreas Lamprecht
+ALB = Allan L. Bazinet
+ANR = Adriano Nagelschmidt Rodrigues
+AP = Andrew Pam
+AS = Akos Szalkai
+AV = Alex Vostrikov
+AWB = Andy W. Barclay
+AY = Araki Yasuhiro
+B1F = Bo Fussing
+B2F = Brad Forschinger
+B2H = Buck Huppmann
+B2L = Brent Laminack
+B2W = Bil Wendling
+B3W = Boris Wedl
+BB = Bruce Bodger
+BC = Bob Collie
+BCK = Benjamin C. Kite
+BCM = Bill C. Miller
+BDB = Boris D. Beletsky
+BDM = Byron D. Miller
+BEO = Bruce E. O'Neel
+BET = Bennett E. Todd
+BG = Bert Gijsbers
+BH = Brad Howes
+BJ = Brian Jackson
+BJM = Barry J. Miller
+BL = Brian Litzinger
+BMF = Brian M. Fisk
+BN = Bill Nugent
+BP = Bruce Perens
+BR = Brian J. Reichert
+BS = Bjoern Stabell
+BT = Brad Templeton
+BTW = Brian T. Wightman
+BW = Bill Weinman
+BZ = Blaz Zupan
+C2F = Chuck Foster
+C2H = Christoph Heidermanns
+C2S = Craig Shrimpton
+CEJ = Colin Eric Johnson
+CF = C. Ferree
+CG = Chris Garrigues
+CH = Chael Hall
+CHR = Craig H. Rowland
+CK = Christoph Kaesling
+CL = Carsten Leonhardt
+CLS = Christopher L. Seawood
+CM = Charles Mattair
+CMP = Chase M. Phillips
+CR = Christian Riede
+CS = Cloyce Spradling
+CSH = Clayton S. Haapala
+D1H = Dieter Heidner
+D2H = Dan Hollis
+D2K = Dax Kelson
+D2S = Dan Senie
+D3S = Don Samek
+DA = Dave Arcuri
+DAR = Daniel A. Reish
+DB = David Buscher
+DBK = Douglas B. Kerry
+DC = Dan Cross
+DCC = Daniel C. Cotey
+DE = Daniel Egnor
+DEH = Daniel E. Harris
+DF = Dale Farnsworth
+DG = David Guntner
+DK = Dave Kopper
+DL = Daniel Lawrence
+DM = David Mazieres
+DML = David M. Lew
+DP = Dave Platt
+DS = Dave Sill
+DST = Daniel S. Thibadeau
+DWS = David Wayne Summers
+EC = Evan Champion
+ECG = Eric C. Garrison
+EG = Eivind Gjelseth
+EK = Eric Krohn
+EP = Emanuele Pucciarelli
+ERH = Eric R. Hankins
+ES = Eric Smith
+ESM = Edward S. Marshall
+ET = Eivind Tagseth
+ETT = Emmanuel T. Tardieu
+F2T = Frank Thieme
+FE = Frank Ederveen
+FN = Faried Nawaz
+FPL = Frederik P. Lindberg
+FT = Frank Tegtmeyer
+FW = Frank Wagner
+G1A = Graham Adams
+G2A = Greg Andrews
+GAW = Greg A. Woods
+GB = Glenn Barry
+GH = Gene Hightower
+GL = Giles Lean
+GLM = Grant L. Miller
+H2S = Harley Silver
+HCJ = Helio Coelho Jr.
+HDG = Hans de Graaff
+HG = Howard Goldstein
+HHO = Harald Hanche-Olsen
+HJB = Herbert J. Bernstein
+HM = Hirokazu Morikawa
+HS = Harlan Stenn
+HT = Henry Timmerman
+HW = Hal Wine
+HWM = Henry W. Miller
+IH = Ingmar Hupp
+IK = Ivan Kohler
+IKW = Ian Keith Wynne
+IS = Icarus Sparry
+IW = Ian Westcott
+J1B = John Banghart
+J1K = Jost Krieger
+J2B = Jos Backus
+J2K = Johannes Kroeger
+J2M = Joel Maslak
+J2P = John Parker
+J2W = Jim Whitby
+JAB = Jeremy A. Bussard
+JAK = Johan A. Kullstam
+JB = Joshua Buysse
+JBB = Jason B. Brown
+JBF = John B. Fleming
+JC = Jim Clausing
+JCD = Jeffrey C. Dege
+JD = Joe Doupnik
+JDHB = Johannes D. H. Beekhuizen
+JDJ = Joshua D. Juran
+JF = Janos Farkas
+JFK = James F. Kane III
+JGM = John G. Myers
+JJB = J. J. Bailey
+JJMK = Jonathan J. M. Katz
+JJR = Jaron J. Rubenstein
+JK = Jari Kirma
+JL = Jim Littlefield
+JLB = Julie L. Baumler
+JLH = Jason L. Haar
+JLW = Jason L. Wright
+JM = Jim Meehan
+JMS = Jason M. Stokes
+JMT = John M. Twilley
+JP = John Palkovic
+JPB = Joe Block
+JPH = Justin P. Hannah
+JPR = Jean-Pierre Radley
+JRL = John R. Levine
+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
+OS = Oliver Seiler
+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
+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
+S3T = Steffen Thorsen
+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
+TV = Tommi Virtanen
+TVP = Tom van Peer
+UO = Uwe Ohse
+VBM = Vladimir B. Machulsky
+VR = Vincenzo Romano
+VU = Viriya Upatising
+VV = Vince Vielhaber
+W2K = Wolfram Kahl
+WEB = William E. Baxter
+WK = Werner Koch
+WS = Wilbur Sims
+WW = Wei Wu
+YC = Yuji Chikahiro
+YF = Yaroslav Faybishenko
+ZU = Zin Uda
diff --git a/THOUGHTS b/THOUGHTS
new file mode 100644
index 0000000..d6910da
--- /dev/null
+++ b/THOUGHTS
@@ -0,0 +1,418 @@
+Please note that this file is not called ``Internet Mail For Dummies.''
+It _records_ my thoughts on various issues. It does not _explain_ them.
+Paragraphs are not organized except by section. The required background
+varies wildly from one paragraph to the next.
+
+In this file, ``sendmail'' means Allman's creation; ``sendmail-clone''
+means the program in this package.
+
+
+1. Security
+
+There are lots of interesting remote denial-of-service attacks on any
+mail system. A long-term solution is to insist on prepayment for
+unauthorized resource use. The tricky technical problem is to make the
+prepayment enforcement mechanism cheaper than the expected cost of the
+attacks. (For local denial-of-service attacks it's enough to be able to
+figure out which user is responsible.)
+
+qmail-send's log was originally designed for profiling. It subsequently
+sprouted some tracing features. However, there's no way to verify
+securely that a particular message came from a particular local user;
+how do you know the recipient is telling you the truth about the
+contents of the message? With QUEUE_EXTRA it'd be possible to record a
+one-way hash of each outgoing message, but a user who wants to send
+``bad'' mail can avoid qmail entirely.
+
+I originally decided on security grounds not to put qmail advertisements
+into SMTP responses: advertisements often act as version identifiers.
+But this problem went away when I found a stable qmail URL.
+
+As qmail grows in popularity, the mere knowledge that rcpthosts is so
+easily available will deter people from setting up unauthorized MXs.
+(I've never seen an unauthorized MX, but I can imagine that it would be
+rather annoying.) Note that, unlike the bat book checkcompat() kludge,
+rcpthosts doesn't interfere with mailing lists.
+
+qmail-start doesn't bother with tty dissociation. On some old machines
+this means that random people can send tty signals to the qmail daemons.
+That's a security flaw in the job control subsystem, not in qmail.
+
+The resolver library isn't too bloated (before 4.9.4, at least), but it
+uses stdio, which _is_ bloated. Reading /etc/resolv.conf costs lots of
+memory in each qmail-remote process. So it's tempting to incorporate a
+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. 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
+tried to hide that fact by disallowing root access over NFS. Intruders
+nevertheless broke into system after system, first obtaining bin access
+and then obtaining root access. Various people thus decided to compound
+Sun's error and build a wall between root and all other users: if all
+system files are owned by root, and if there are no security holes other
+than NFS, someone who breaks in via NFS won't be able to wipe out the
+operating system---he'll merely be able to wipe out all user files. This
+clueless policy means that, for example, all the qmail users have to be
+replaced by root. See what I mean by ``enemy''? ... Basic NFS comments:
+Aside from the cryptographic problem of having hosts communicate
+securely, it's obvious that there's an administrative problem of mapping
+client uids to server uids. If a host is secure and under your control,
+you shouldn't have to map anything. If a host is under someone else's
+control, you'll want to map his uids to one local account; it's his
+client's job to decide which of his users get to talk NFS in the first
+place. Sun's original map---root to nobody, everyone else left alone---
+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, 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
+sendmail will append a host name. This wasn't fixed until sendmail 8.7.
+How many years has it been since RFC 822 came out?
+
+sendmail discards duplicate addresses. This has probably resulted in
+more lost and stolen mail over the years than the entire Chicago branch
+of the United States Postal Service. The qmail system delivers messages
+exactly as it's told to do. Along the same lines: qmail-inject is both
+unable and unwilling to support anything like sendmail's (default)
+nometoo option. Of course, a list manager could support nometoo.
+
+There should be a mechanism in qmail-inject that does for envelope
+recipients what Return-Path does for the envelope sender. Then
+qmail-inject -n could print the recipients.
+
+Should qmail-inject bounce messages with no recipients? Should there be
+an option for this? If it stays as is (accept the message), qmail-inject
+could at least avoid invoking qmail-queue.
+
+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 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 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)
+
+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 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
+incapable of handling an address that contains a 0 byte. I can't imagine
+that this will be a problem.
+
+Should qmail-queue not bother queueing a message with no recipients?
+
+
+5. Handling queued mail (qmail-send, qmail-clean)
+
+The queue directory must be local. Mounting it over NFS is extremely
+dangerous---not that this stops people from running sendmail that way!
+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
+filesystem such as LFS.
+
+qmail-send uses 8 bytes of memory per queued message. Double that for
+reallocation. (Fix: use a small forest of heaps; i.e., keep several
+prioqs.) Double again for buddy malloc()s. (Fix: be clever about the
+heap sizes.) 32 bytes is worrisome, but not devastating. Even on my
+disk-heavy memory-light machine, I'd run out of inodes long before
+running out of memory.
+
+Some mail systems organize the queue by host. This is pointless as a
+means of splitting up the queue directory. The real issue is what to do
+when you suddenly find out that a host is up. For local SLIP/PPP links
+you know in advance which hosts need this treatment, so you can handle
+them with virtualdomains and serialmail.
+
+For the old queue structure I implemented recipient list compression:
+if mail goes out to a giant mailing list, and most of the recipients are
+delivered, make a new, compressed, todo list. But this really isn't
+worth the effort: it saves only a tiny bit of CPU time.
+
+qmail-send doesn't have any notions of precedence, priority, fairness,
+importance, etc. It handles the queue in first-seen-first-served order.
+One could put a lot of work into doing something different, but that
+work would be a waste: given the triggering mechanism and qmail's
+deferral strategy, it is exceedingly rare for the queue to contain more
+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. 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
+next pass will be delayed. I implemented the opposite strategy for the
+old queue structure. Some hassles: mark() had to understand how job
+input was buffered; every new delivery had to check whether the same
+mpos in the same message was already being done.
+
+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.
+(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
+to do about this. Of course, a hard I/O error means that mail is toast,
+but a soft I/O error shouldn't cause any trouble.
+
+job_open() or pass_dochan() could be paranoid about the same id,channel
+already being open; but, since messdone() is so paranoid, the worst
+possible effect of a bug along these lines would be double delivery.
+
+Mathematical amusement: The optimal retry schedule is essentially,
+though not exactly, independent of the actual distribution of message
+delay times. What really matters is how much cost you assign to retries
+and to particular increases in latency. qmail's current quadratic retry
+schedule says that an hour-long delay in a day-old message is worth the
+same as a ten-minute delay in an hour-old message; this doesn't seem so
+unreasonable.
+
+Insider information: AOL retries their messages every five minutes for
+three days straight. Hmmm.
+
+
+6. Sending mail through the network (qmail-rspawn, qmail-remote)
+
+Are there any hosts, anywhere, whose mailers are bogged down by huge
+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.
+
+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. (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.)
+Automatically treating ambiguous MXs as local is incompatible with my
+design decision to keep local delivery working when the network goes
+down. It puts more faith in DNS than DNS deserves. Much better: Have
+your MX records generated automatically from control/locals.
+
+If I successfully connect to an MX host but it temporarily refuses to
+accept the message, I give up and put the message back into the queue.
+But several documents seem to suggest that I should try further MX
+records. What are they thinking? My approach deals properly with downed
+hosts, hosts that are unreachable through a firewall, and load
+balancing; what else do people use multiple MX records for?
+
+Currently qmail-remote sends data in 1024-byte buffers. Perhaps it
+should try to take account of the MTU.
+
+Perhaps qmail-remote should allocate a fixed amount of DNS/connect()
+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)
+
+qmail-local doesn't support comsat. comsat is a pointless abomination.
+Use qbiff if you want that kind of notification.
+
+The getpwnam() interface hides I/O errors. Solution: qmail-pw2u.
+
+
+8. sendmail V8's new features
+
+sendmail-8.8.0/doc/op/op.me includes a list of big improvements of
+sendmail 8.8.0 over sendmail 5.67. Here's how qmail stacks up against
+each of those improvements. (Of course, qmail has its own improvements,
+but that's not the point of this list.)
+
+Connection caching, MX piggybacking: Nope. (Profile. Don't speculate.)
+
+Response to RCPT command is fast: Yup.
+
+IP addresses show up in Received lines: Yup.
+
+Self domain literal is properly handled: Yup.
+
+Different timeouts for QUIT, RCPT, etc.: No, just a single timeout.
+
+Proper <> handling, route-address pruning: Yes, but not configurable.
+
+ESMTP support: Yup. (Server-side, including PIPELINING.)
+
+8-bit clean: Yup. (Including server-side 8BITMIME support; same as
+sendmail with the 8 option.)
+
+Configurable user database: Yup.
+
+BIND support: Yup.
+
+Keyed files: Yes, in fastforward.
+
+931/1413/Ident/TAP: Yup.
+
+Correct 822 address list parsing: Yup. (Note that sendmail still has
+some major problems with quoting.)
+
+List-owner handling: Yup.
+
+Dynamic header allocation: Yup.
+
+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.
+
+Error message configuration: Nope.
+
+GECOS matching: Not directly, but easy to hook in.
+
+Hop limit configuration: No. (qmail's limit is 100 hops. qmail offers
+automatic loop protection much more advanced than hop counting.)
+
+MIME error messages: No. (qmail uses QSBMF error messages, which are
+much easier to parse.)
+
+Forward file path: Yes, via /etc/passwd.
+
+Incoming SMTP configuration: Yes, via inetd or tcpserver.
+
+Privacy options: Yes, but they're not options.
+
+Best-MX mangling: Nope. See section 6 for further discussion.
+
+7-bit mangling: Nope. qmail always uses 8 bits.
+
+Support for up to 20 MX records: Yes, and more. qmail has no limits
+other than memory.
+
+Correct quoting of name-and-address headers: Yup.
+
+VRFY and EXPN now different: Nope. qmail always hides this information.
+
+Multi-word classes, deferred macro expansion, separate envelope/header
+$g processing, separate per-mailer envelope and header processing, new
+command line flags, new configuration lines, new mailer flags, new
+macros: These are sendmail-specific; they wouldn't even make sense for
+qmail. For example, _of course_ qmail handles envelopes and headers
+separately; they're almost entirely different objects!
+
+
+9. Miscellany
+
+sendmail-clone and qsmhook are too bletcherous to be documented. (The
+official replacement for qsmhook is preline, together with the
+qmail-command environment variables.)
+
+I've considered making install atomic, but this is very difficult to do
+right, and pointless if it isn't done right.
+
+RN suggests automatically putting together a reasonable set of lines for
+/etc/passwd. I perceive this as getting into the adduser business, which
+is worrisome: I'll be lynched the first time I screw up somebody's
+passwd file. This should be left to OS-specific installation scripts.
+
+The BSD 4.2 inetd didn't allow a username. I think I can safely forget
+about this. (DS notes that the username works under Ultrix even though
+it's undocumented.)
+
+I should clean up the bput/put choices.
+
+Some of the stralloc_0()s indicate that certain lower-level routines
+should grok stralloc.
+
+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?
+
+The bat book justifies sendmail's insane line-splitting mechanism by
+pointing out that it might be useful for ``a 40-character braille
+print-driving program.'' C'mon, guys, is that your best excuse?
+
+qmail's mascot is a dolphin.
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..5841c0a
--- /dev/null
+++ b/TODO
@@ -0,0 +1,23 @@
+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
diff --git a/UPGRADE b/UPGRADE
new file mode 100644
index 0000000..959120d
--- /dev/null
+++ b/UPGRADE
@@ -0,0 +1,66 @@
+SAVE COPIES OF YOUR OUTGOING MAIL! Like any other piece of software (and
+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 to netqmail 1.05. 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 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. You can copy conf* from 1.02 or 1.03.
+
+
+How to install:
+
+ 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.
+
+ 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. 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.)
+
+10. Read TEST.receive.
+
+
+That's it! To report success:
+ % ( 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
new file mode 100644
index 0000000..5ac3967
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+netqmail 1.06
diff --git a/addresses.5 b/addresses.5
new file mode 100644
index 0000000..1fd4c5b
--- /dev/null
+++ b/addresses.5
@@ -0,0 +1,260 @@
+.TH addresses 5
+.SH "NAME"
+addresses \- formats for Internet mail addresses
+.SH "INTRODUCTION"
+A
+.B mail address
+is a string of characters containing @.
+
+Every mail address has a
+.B local part
+and a
+.B domain part\fR.
+The domain part is everything after the final @.
+The local part is everything before.
+
+For example, the mail addresses
+
+.EX
+ God@heaven.af.mil
+ @heaven.af.mil
+ @at@@heaven.af.mil
+.EE
+
+all have domain part
+.BR heaven.af.mil .
+The local parts are
+.BR God ,
+empty,
+and
+.BR @at@ .
+
+Some domains have owners.
+It is up to the owner of
+.B heaven.af.mil
+to say how mail messages will be delivered to addresses with domain part
+.BR heaven.af.mil .
+
+The domain part of an address is interpreted without regard to case, so
+
+.EX
+ God@heaven.af.mil
+.br
+ God@HEAVEN.AF.MIL
+.br
+ God@Heaven.AF.Mil
+.EE
+
+all refer to the same domain.
+
+There is one exceptional address that does not contain an @:
+namely, the empty string.
+The empty string cannot be used as a recipient address.
+It can be used as a sender address so that
+the real sender doesn't receive bounces.
+.SH "QMAIL EXTENSIONS"
+The
+.B qmail
+system allows several further types of addresses in mail envelopes.
+
+First, an envelope recipient address without an @ is interpreted as being at
+.IR envnoathost .
+For example, if
+.I envnoathost
+is
+.BR heaven.af.mil ,
+the address
+.B God
+will be rewritten as
+.BR God@heaven.af.mil .
+
+Second, the address
+.B #@[]
+is used as an envelope sender address for double bounces.
+
+Third, envelope sender addresses of the form
+.I pre\fB@\fIhost\fB-@[]
+are used to support variable envelope return paths (VERPs).
+.B qmail-send
+will rewrite
+.I pre\fB@\fIhost\fB-@[]
+as
+.I prerecip\fB=\fIdomain\fB@\fIhost
+for deliveries to
+.IR recip\fB@\fIdomain .
+Bounces directly from
+.B qmail-send
+will come back to
+.IR pre\fB@\fIhost .
+.SH "CHOOSING MAIL ADDRESSES"
+Here are some suggestions on choosing mail addresses for the Internet.
+
+Do not use non-ASCII characters.
+Under RFC 822 and RFC 821,
+these characters cannot be used in mail headers or in SMTP commands.
+In practice, they are regularly corrupted.
+
+Do not use ASCII control characters.
+NUL is regularly corrupted.
+CR and LF cannot be used in some combinations
+and are corrupted in all.
+None of these characters are usable on business cards.
+
+Avoid spaces and the characters
+
+.EX
+ \\"<>()[],;:
+.EE
+
+These all require quoting in mail headers and in SMTP.
+Many existing mail programs do not handle quoting properly.
+
+Do not use @ in a local part.
+@ requires quoting in mail headers and in SMTP.
+Many programs incorrectly look for the first @,
+rather than the last @,
+to find the domain part of an address.
+
+In a local part,
+do not use two consecutive dots, a dot at the beginning, or a dot at the end.
+Any of these would require quoting in mail headers.
+
+Do not use an empty local part; it cannot appear in SMTP commands.
+
+Avoid local parts longer than 64 characters.
+
+Be wary of uppercase letters in local parts.
+Some mail programs (and users!) will incorrectly convert
+.B God@heaven.af.mil
+to
+.BR god@heaven.af.mil .
+
+Be wary of the following characters:
+
+.EX
+ $&!#~`'^*|{}
+.EE
+
+Some users will not know
+how to feed these characters safely to their mail programs.
+
+In domain names, stick to letters, digits, dash, and dot.
+One popular DNS resolver has,
+under the banner of security,
+recently begun destroying domain names
+that contain certain other characters,
+including underscore.
+Exception: A dotted-decimal IP address in brackets,
+such as
+.BR [127.0.0.1] ,
+identifies a domain owned by whoever owns the host at that IP address,
+and can be used safely.
+
+In a domain name,
+do not use two consecutive dots,
+a dot at the beginning,
+or a dot at the end.
+This means that,
+when a domain name is broken down into components separated by dots,
+there are no empty components.
+
+Always use at least one dot in a domain name.
+If you own the
+.B mil
+domain,
+don't bother using the address
+.BR root@mil ;
+most users will be unable to send messages to that address.
+Same for the root domain.
+
+Avoid domain names longer than 64 characters.
+.SH "ENCODED ADDRESSES IN SMTP COMMANDS"
+RFC 821 defines an encoding of mail addresses in SMTP.
+For example, the addresses
+
+.EX
+ God@heaven.af.mil
+.br
+ a"quote@heaven.af.mil
+.br
+ The Almighty.One@heaven.af.mil
+.EE
+
+could be encoded in RCPT commands as
+
+.EX
+ RCPT TO:<God@heaven.af.mil>
+.br
+ RCPT TO:<a\\"quote@heaven.af.mil>
+.br
+ RCPT TO:<The\\ Almighty.One@heaven.af.mil>
+.EE
+
+There are several restrictions in RFC 821
+on the mail addresses that can be used over SMTP.
+Non-ASCII characters are prohibited.
+The local part must not be empty.
+The domain part must be a sequence of elements separated by dots,
+where each element is either a component,
+a sequence of digits preceded by #,
+or a dotted-decimal IP address surrounded by brackets.
+The only allowable characters in components are
+letters, digits, and dashes.
+Every component must (believe it or not)
+have at least three characters;
+the first character must be a letter;
+the last character must not be a hyphen.
+.SH "ENCODED ADDRESSES IN MAIL HEADERS"
+RFC 822 defines an encoding of mail addresses
+in certain header fields in a mail message.
+For example, the addresses
+
+.EX
+ God@heaven.af.mil
+.br
+ a"quote@heaven.af.mil
+.br
+ The Almighty.One@heaven.af.mil
+.EE
+
+could be encoded in a
+.B To
+field as
+
+.EX
+ To: God@heaven.af.mil,
+.br
+ <@brl.mil:"a\\"quote"@heaven.af.mil>,
+.br
+ "The Almighty".One@heaven.af.mil
+.EE
+
+or perhaps
+
+.EX
+ To: < "God"@heaven .af.mil>,
+.br
+ "a\\"quote" (Who?) @ heaven . af. mil
+.br
+ , God<"The Almighty.One"@heaven.af.mil>
+.EE
+
+There are several restrictions on the mail addresses that can
+be used in these header fields.
+Non-ASCII characters are prohibited.
+The domain part must be a sequence of elements separated by dots,
+where each element either (1) begins with [ and ends with ]
+or (2) is a nonempty string of printable ASCII characters
+not including any of
+
+.EX
+ \\".<>()[],;:
+.EE
+
+and not including space.
+.SH "SEE ALSO"
+envelopes(5),
+qmail-header(5),
+qmail-inject(8),
+qmail-remote(8),
+qmail-smtpd(8)
diff --git a/alloc.3 b/alloc.3
new file mode 100644
index 0000000..58b4432
--- /dev/null
+++ b/alloc.3
@@ -0,0 +1,62 @@
+.TH alloc 3
+.SH NAME
+alloc \- allocate memory
+.SH SYNTAX
+.B #include <alloc.h>
+
+char *\fBalloc\fP(\fInew\fR);
+
+void \fBalloc_free\fP(\fIx\fR);
+
+void \fBalloc_re\fP(&\fIx\fR,\fIold\fR,\fInew\fR);
+
+char *\fIx\fR;
+.br
+unsigned int \fIold\fR;
+.br
+unsigned int \fInew\fR;
+.SH DESCRIPTION
+.B alloc
+allocates enough space from the heap for
+.I new
+bytes of data,
+adequately aligned for any data type.
+.I new
+may be 0.
+.B alloc
+returns a pointer to the space.
+If space is not available,
+.B alloc
+returns 0,
+setting
+.B errno
+appropriately.
+
+.B alloc_free
+returns space to the heap.
+
+.B alloc_re
+expands the space allocated to
+.I x
+from
+.I old
+bytes to
+.I new
+bytes.
+It allocates new space,
+copies
+.I old
+bytes from the old space to the new space,
+returns the old space to the heap,
+and changes
+.I x
+to point to the new space.
+It then returns 1.
+If space is not available,
+.B alloc_re
+returns 0,
+leaving the old space alone.
+.SH "SEE ALSO"
+sbrk(2),
+malloc(3),
+error(3)
diff --git a/alloc.c b/alloc.c
new file mode 100644
index 0000000..c661453
--- /dev/null
+++ b/alloc.c
@@ -0,0 +1,32 @@
+#include "alloc.h"
+#include "error.h"
+extern char *malloc();
+extern void free();
+
+#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */
+#define SPACE 4096 /* must be multiple of ALIGNMENT */
+
+typedef union { char irrelevant[ALIGNMENT]; double d; } aligned;
+static aligned realspace[SPACE / ALIGNMENT];
+#define space ((char *) realspace)
+static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */
+
+/*@null@*//*@out@*/char *alloc(n)
+unsigned int n;
+{
+ char *x;
+ n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */
+ if (n <= avail) { avail -= n; return space + avail; }
+ x = malloc(n);
+ if (!x) errno = error_nomem;
+ return x;
+}
+
+void alloc_free(x)
+char *x;
+{
+ if (x >= space)
+ if (x < space + SPACE)
+ return; /* XXX: assuming that pointers are flat */
+ free(x);
+}
diff --git a/alloc.h b/alloc.h
new file mode 100644
index 0000000..1b1d893
--- /dev/null
+++ b/alloc.h
@@ -0,0 +1,8 @@
+#ifndef ALLOC_H
+#define ALLOC_H
+
+extern /*@null@*//*@out@*/char *alloc();
+extern void alloc_free();
+extern int alloc_re();
+
+#endif
diff --git a/alloc_re.c b/alloc_re.c
new file mode 100644
index 0000000..feb8b49
--- /dev/null
+++ b/alloc_re.c
@@ -0,0 +1,17 @@
+#include "alloc.h"
+#include "byte.h"
+
+int alloc_re(x,m,n)
+char **x;
+unsigned int m;
+unsigned int n;
+{
+ char *y;
+
+ y = alloc(n);
+ if (!y) return 0;
+ byte_copy(y,m,*x);
+ alloc_free(*x);
+ *x = y;
+ return 1;
+}
diff --git a/auto-gid.c b/auto-gid.c
new file mode 100644
index 0000000..774a8c1
--- /dev/null
+++ b/auto-gid.c
@@ -0,0 +1,51 @@
+#include <sys/types.h>
+#include <grp.h>
+#include "subfd.h"
+#include "substdio.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "scan.h"
+#include "fmt.h"
+
+char buf1[256];
+substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+
+void outs(s)
+char *s;
+{
+ if (substdio_puts(&ss1,s) == -1) _exit(111);
+}
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ char *name;
+ char *value;
+ struct group *gr;
+ char strnum[FMT_ULONG];
+
+ name = argv[1];
+ if (!name) _exit(100);
+ value = argv[2];
+ if (!value) _exit(100);
+
+ gr = getgrnam(value);
+ if (!gr) {
+ substdio_puts(subfderr,"fatal: unable to find group ");
+ substdio_puts(subfderr,value);
+ substdio_puts(subfderr,"\n");
+ substdio_flush(subfderr);
+ _exit(111);
+ }
+
+ strnum[fmt_ulong(strnum,(unsigned long) gr->gr_gid)] = 0;
+
+ outs("int ");
+ outs(name);
+ outs(" = ");
+ outs(strnum);
+ outs(";\n");
+ if (substdio_flush(&ss1) == -1) _exit(111);
+ _exit(0);
+}
diff --git a/auto-int.c b/auto-int.c
new file mode 100644
index 0000000..c138869
--- /dev/null
+++ b/auto-int.c
@@ -0,0 +1,40 @@
+#include "substdio.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "scan.h"
+#include "fmt.h"
+
+char buf1[256];
+substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+
+void puts(s)
+char *s;
+{
+ if (substdio_puts(&ss1,s) == -1) _exit(111);
+}
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ char *name;
+ char *value;
+ unsigned long num;
+ char strnum[FMT_ULONG];
+
+ name = argv[1];
+ if (!name) _exit(100);
+ value = argv[2];
+ if (!value) _exit(100);
+
+ scan_ulong(value,&num);
+ strnum[fmt_ulong(strnum,num)] = 0;
+
+ puts("int ");
+ puts(name);
+ puts(" = ");
+ puts(strnum);
+ puts(";\n");
+ if (substdio_flush(&ss1) == -1) _exit(111);
+ _exit(0);
+}
diff --git a/auto-int8.c b/auto-int8.c
new file mode 100644
index 0000000..091978f
--- /dev/null
+++ b/auto-int8.c
@@ -0,0 +1,40 @@
+#include "substdio.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "scan.h"
+#include "fmt.h"
+
+char buf1[256];
+substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+
+void puts(s)
+char *s;
+{
+ if (substdio_puts(&ss1,s) == -1) _exit(111);
+}
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ char *name;
+ char *value;
+ unsigned long num;
+ char strnum[FMT_ULONG];
+
+ name = argv[1];
+ if (!name) _exit(100);
+ value = argv[2];
+ if (!value) _exit(100);
+
+ scan_8long(value,&num);
+ strnum[fmt_ulong(strnum,num)] = 0;
+
+ puts("int ");
+ puts(name);
+ puts(" = ");
+ puts(strnum);
+ puts(";\n");
+ if (substdio_flush(&ss1) == -1) _exit(111);
+ _exit(0);
+}
diff --git a/auto-str.c b/auto-str.c
new file mode 100644
index 0000000..acc3d60
--- /dev/null
+++ b/auto-str.c
@@ -0,0 +1,44 @@
+#include "substdio.h"
+#include "readwrite.h"
+#include "exit.h"
+
+char buf1[256];
+substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+
+void puts(s)
+char *s;
+{
+ if (substdio_puts(&ss1,s) == -1) _exit(111);
+}
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ char *name;
+ char *value;
+ unsigned char ch;
+ char octal[4];
+
+ name = argv[1];
+ if (!name) _exit(100);
+ value = argv[2];
+ if (!value) _exit(100);
+
+ puts("char ");
+ puts(name);
+ puts("[] = \"\\\n");
+
+ while (ch = *value++) {
+ puts("\\");
+ octal[3] = 0;
+ octal[2] = '0' + (ch & 7); ch >>= 3;
+ octal[1] = '0' + (ch & 7); ch >>= 3;
+ octal[0] = '0' + (ch & 7);
+ puts(octal);
+ }
+
+ puts("\\\n\";\n");
+ if (substdio_flush(&ss1) == -1) _exit(111);
+ _exit(0);
+}
diff --git a/auto-uid.c b/auto-uid.c
new file mode 100644
index 0000000..326051c
--- /dev/null
+++ b/auto-uid.c
@@ -0,0 +1,51 @@
+#include <sys/types.h>
+#include <pwd.h>
+#include "subfd.h"
+#include "substdio.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "scan.h"
+#include "fmt.h"
+
+char buf1[256];
+substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1));
+
+void outs(s) /* was named puts, but Solaris pwd.h includes stdio.h. dorks. */
+char *s;
+{
+ if (substdio_puts(&ss1,s) == -1) _exit(111);
+}
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ char *name;
+ char *value;
+ struct passwd *pw;
+ char strnum[FMT_ULONG];
+
+ name = argv[1];
+ if (!name) _exit(100);
+ value = argv[2];
+ if (!value) _exit(100);
+
+ pw = getpwnam(value);
+ if (!pw) {
+ substdio_puts(subfderr,"fatal: unable to find user ");
+ substdio_puts(subfderr,value);
+ substdio_puts(subfderr,"\n");
+ substdio_flush(subfderr);
+ _exit(111);
+ }
+
+ strnum[fmt_ulong(strnum,(unsigned long) pw->pw_uid)] = 0;
+
+ outs("int ");
+ outs(name);
+ outs(" = ");
+ outs(strnum);
+ outs(";\n");
+ if (substdio_flush(&ss1) == -1) _exit(111);
+ _exit(0);
+}
diff --git a/auto_break.h b/auto_break.h
new file mode 100644
index 0000000..b7f3a63
--- /dev/null
+++ b/auto_break.h
@@ -0,0 +1,6 @@
+#ifndef AUTO_BREAK_H
+#define AUTO_BREAK_H
+
+extern char auto_break[];
+
+#endif
diff --git a/auto_patrn.h b/auto_patrn.h
new file mode 100644
index 0000000..77cdf1f
--- /dev/null
+++ b/auto_patrn.h
@@ -0,0 +1,6 @@
+#ifndef AUTO_PATRN_H
+#define AUTO_PATRN_H
+
+extern int auto_patrn;
+
+#endif
diff --git a/auto_qmail.h b/auto_qmail.h
new file mode 100644
index 0000000..0c56001
--- /dev/null
+++ b/auto_qmail.h
@@ -0,0 +1,6 @@
+#ifndef AUTO_QMAIL_H
+#define AUTO_QMAIL_H
+
+extern char auto_qmail[];
+
+#endif
diff --git a/auto_spawn.h b/auto_spawn.h
new file mode 100644
index 0000000..165d988
--- /dev/null
+++ b/auto_spawn.h
@@ -0,0 +1,6 @@
+#ifndef AUTO_SPAWN_H
+#define AUTO_SPAWN_H
+
+extern int auto_spawn;
+
+#endif
diff --git a/auto_split.h b/auto_split.h
new file mode 100644
index 0000000..3754129
--- /dev/null
+++ b/auto_split.h
@@ -0,0 +1,6 @@
+#ifndef AUTO_SPLIT_H
+#define AUTO_SPLIT_H
+
+extern int auto_split;
+
+#endif
diff --git a/auto_uids.h b/auto_uids.h
new file mode 100644
index 0000000..1252ecb
--- /dev/null
+++ b/auto_uids.h
@@ -0,0 +1,16 @@
+#ifndef AUTO_UIDS_H
+#define AUTO_UIDS_H
+
+extern int auto_uida;
+extern int auto_uidd;
+extern int auto_uidl;
+extern int auto_uido;
+extern int auto_uidp;
+extern int auto_uidq;
+extern int auto_uidr;
+extern int auto_uids;
+
+extern int auto_gidn;
+extern int auto_gidq;
+
+#endif
diff --git a/auto_usera.h b/auto_usera.h
new file mode 100644
index 0000000..49d7755
--- /dev/null
+++ b/auto_usera.h
@@ -0,0 +1,6 @@
+#ifndef AUTO_USERA_H
+#define AUTO_USERA_H
+
+extern char auto_usera[];
+
+#endif
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/byte.h b/byte.h
new file mode 100644
index 0000000..de06c69
--- /dev/null
+++ b/byte.h
@@ -0,0 +1,13 @@
+#ifndef BYTE_H
+#define BYTE_H
+
+extern unsigned int byte_chr();
+extern unsigned int byte_rchr();
+extern void byte_copy();
+extern void byte_copyr();
+extern int byte_diff();
+extern void byte_zero();
+
+#define byte_equal(s,n,t) (!byte_diff((s),(n),(t)))
+
+#endif
diff --git a/byte_chr.c b/byte_chr.c
new file mode 100644
index 0000000..f81dde8
--- /dev/null
+++ b/byte_chr.c
@@ -0,0 +1,20 @@
+#include "byte.h"
+
+unsigned int byte_chr(s,n,c)
+char *s;
+register unsigned int n;
+int c;
+{
+ register char ch;
+ register char *t;
+
+ ch = c;
+ t = s;
+ for (;;) {
+ if (!n) break; if (*t == ch) break; ++t; --n;
+ if (!n) break; if (*t == ch) break; ++t; --n;
+ if (!n) break; if (*t == ch) break; ++t; --n;
+ if (!n) break; if (*t == ch) break; ++t; --n;
+ }
+ return t - s;
+}
diff --git a/byte_copy.c b/byte_copy.c
new file mode 100644
index 0000000..eaad11b
--- /dev/null
+++ b/byte_copy.c
@@ -0,0 +1,14 @@
+#include "byte.h"
+
+void byte_copy(to,n,from)
+register char *to;
+register unsigned int n;
+register char *from;
+{
+ for (;;) {
+ if (!n) return; *to++ = *from++; --n;
+ if (!n) return; *to++ = *from++; --n;
+ if (!n) return; *to++ = *from++; --n;
+ if (!n) return; *to++ = *from++; --n;
+ }
+}
diff --git a/byte_cr.c b/byte_cr.c
new file mode 100644
index 0000000..3e7a1d5
--- /dev/null
+++ b/byte_cr.c
@@ -0,0 +1,16 @@
+#include "byte.h"
+
+void byte_copyr(to,n,from)
+register char *to;
+register unsigned int n;
+register char *from;
+{
+ to += n;
+ from += n;
+ for (;;) {
+ if (!n) return; *--to = *--from; --n;
+ if (!n) return; *--to = *--from; --n;
+ if (!n) return; *--to = *--from; --n;
+ if (!n) return; *--to = *--from; --n;
+ }
+}
diff --git a/byte_diff.c b/byte_diff.c
new file mode 100644
index 0000000..cdbd760
--- /dev/null
+++ b/byte_diff.c
@@ -0,0 +1,16 @@
+#include "byte.h"
+
+int byte_diff(s,n,t)
+register char *s;
+register unsigned int n;
+register char *t;
+{
+ for (;;) {
+ if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+ if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+ if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+ if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+ }
+ return ((int)(unsigned int)(unsigned char) *s)
+ - ((int)(unsigned int)(unsigned char) *t);
+}
diff --git a/byte_rchr.c b/byte_rchr.c
new file mode 100644
index 0000000..476bc22
--- /dev/null
+++ b/byte_rchr.c
@@ -0,0 +1,23 @@
+#include "byte.h"
+
+unsigned int byte_rchr(s,n,c)
+char *s;
+register unsigned int n;
+int c;
+{
+ register char ch;
+ register char *t;
+ register char *u;
+
+ ch = c;
+ t = s;
+ u = 0;
+ for (;;) {
+ if (!n) break; if (*t == ch) u = t; ++t; --n;
+ if (!n) break; if (*t == ch) u = t; ++t; --n;
+ if (!n) break; if (*t == ch) u = t; ++t; --n;
+ if (!n) break; if (*t == ch) u = t; ++t; --n;
+ }
+ if (!u) u = t;
+ return u - s;
+}
diff --git a/byte_zero.c b/byte_zero.c
new file mode 100644
index 0000000..92009ba
--- /dev/null
+++ b/byte_zero.c
@@ -0,0 +1,13 @@
+#include "byte.h"
+
+void byte_zero(s,n)
+char *s;
+register unsigned int n;
+{
+ for (;;) {
+ if (!n) break; *s++ = 0; --n;
+ if (!n) break; *s++ = 0; --n;
+ if (!n) break; *s++ = 0; --n;
+ if (!n) break; *s++ = 0; --n;
+ }
+}
diff --git a/case.3 b/case.3
new file mode 100644
index 0000000..58bd724
--- /dev/null
+++ b/case.3
@@ -0,0 +1,100 @@
+.TH case 3
+.SH NAME
+case \- convert ASCII uppercase bytes to lowercase
+.SH SYNTAX
+.B #include <case.h>
+
+void \fBcase_lowers\fP(\fIs\fR);
+.br
+void \fBcase_lowerb\fP(\fIs\fR,\fIlen\fR);
+
+int \fBcase_diffs\fP(\fIs\fR,\fIt\fR);
+.br
+int \fBcase_equals\fP(\fIs\fR,\fIt\fR);
+.br
+int \fBcase_starts\fP(\fIs\fR,\fIt\fR);
+
+int \fBcase_diffb\fP(\fIs\fR,\fIlen\fR,\fIt\fR);
+.br
+int \fBcase_startb\fP(\fIs\fR,\fIlen\fR,\fIt\fR);
+
+char *\fIs\fR;
+.br
+char *\fIt\fR;
+.br
+unsigned int \fIlen\fR;
+.SH DESCRIPTION
+.B case_lowers
+converts each uppercase byte in the string
+.I s
+to lowercase.
+.I s
+must be 0-terminated.
+
+.B case_lowerb
+converts each uppercase byte in the buffer
+.IR s ,
+of length
+.IR len ,
+to lowercase.
+
+.B case_diffs
+lexicographically compares lowercase versions of the strings
+.I s
+and
+.IR t .
+It returns something positive, negative, or zero
+when the first is larger than, smaller than, or equal to the second.
+.I s
+and
+.I t
+must be 0-terminated.
+
+.B case_equals
+means
+.BR !case_diffs .
+
+.B case_starts
+returns 1 if a lowercase version of
+.I s
+starts with a lowercase version of
+.IR t .
+.I s
+and
+.I t
+must be 0-terminated.
+
+.B case_diffb
+lexicographically compares lowercase versions of the buffers
+.I s
+and
+.IR t ,
+each of length
+.IR len .
+It returns something positive, negative, or zero
+when the first is larger than, smaller than, or equal to the second.
+
+.B case_startb
+returns 1 if a lowercase version of the buffer
+.IR s ,
+of length
+.IR len ,
+starts with a lowercase version of the string
+.IR t .
+.I t
+must be 0-terminated.
+
+The
+.B case
+routines
+are ASCII-specific.
+They are suitable for programs that handle
+case-independent networking protocols.
+
+All comparisons are performed on unsigned bytes.
+.SH "SEE ALSO"
+byte_diff(3),
+byte_equal(3),
+str_diff(3),
+str_equal(3),
+str_start(3)
diff --git a/case.h b/case.h
new file mode 100644
index 0000000..35a2434
--- /dev/null
+++ b/case.h
@@ -0,0 +1,13 @@
+#ifndef CASE_H
+#define CASE_H
+
+extern void case_lowers();
+extern void case_lowerb();
+extern int case_diffs();
+extern int case_diffb();
+extern int case_starts();
+extern int case_startb();
+
+#define case_equals(s,t) (!case_diffs((s),(t)))
+
+#endif
diff --git a/case_diffb.c b/case_diffb.c
new file mode 100644
index 0000000..9064b8a
--- /dev/null
+++ b/case_diffb.c
@@ -0,0 +1,21 @@
+#include "case.h"
+
+int case_diffb(s,len,t)
+register char *s;
+unsigned int len;
+register char *t;
+{
+ register unsigned char x;
+ register unsigned char y;
+
+ while (len > 0) {
+ --len;
+ x = *s++ - 'A';
+ if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+ y = *t++ - 'A';
+ if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+ if (x != y)
+ return ((int)(unsigned int) x) - ((int)(unsigned int) y);
+ }
+ return 0;
+}
diff --git a/case_diffs.c b/case_diffs.c
new file mode 100644
index 0000000..212c645
--- /dev/null
+++ b/case_diffs.c
@@ -0,0 +1,19 @@
+#include "case.h"
+
+int case_diffs(s,t)
+register char *s;
+register char *t;
+{
+ register unsigned char x;
+ register unsigned char y;
+
+ for (;;) {
+ x = *s++ - 'A';
+ if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+ y = *t++ - 'A';
+ if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+ if (x != y) break;
+ if (!x) break;
+ }
+ return ((int)(unsigned int) x) - ((int)(unsigned int) y);
+}
diff --git a/case_lowerb.c b/case_lowerb.c
new file mode 100644
index 0000000..4034c14
--- /dev/null
+++ b/case_lowerb.c
@@ -0,0 +1,14 @@
+#include "case.h"
+
+void case_lowerb(s,len)
+char *s;
+unsigned int len;
+{
+ unsigned char x;
+ while (len > 0) {
+ --len;
+ x = *s - 'A';
+ if (x <= 'Z' - 'A') *s = x + 'a';
+ ++s;
+ }
+}
diff --git a/case_lowers.c b/case_lowers.c
new file mode 100644
index 0000000..208b3f5
--- /dev/null
+++ b/case_lowers.c
@@ -0,0 +1,12 @@
+#include "case.h"
+
+void case_lowers(s)
+char *s;
+{
+ unsigned char x;
+ while (x = *s) {
+ x -= 'A';
+ if (x <= 'Z' - 'A') *s = x + 'a';
+ ++s;
+ }
+}
diff --git a/case_starts.c b/case_starts.c
new file mode 100644
index 0000000..2278a0a
--- /dev/null
+++ b/case_starts.c
@@ -0,0 +1,18 @@
+#include "case.h"
+
+int case_starts(s,t)
+register char *s;
+register char *t;
+{
+ register unsigned char x;
+ register unsigned char y;
+
+ for (;;) {
+ x = *s++ - 'A';
+ if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+ y = *t++ - 'A';
+ if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+ if (!y) return 1;
+ if (x != y) return 0;
+ }
+}
diff --git a/cdb.3 b/cdb.3
new file mode 100644
index 0000000..a85b34c
--- /dev/null
+++ b/cdb.3
@@ -0,0 +1,62 @@
+.TH cdb 3
+.SH NAME
+cdb \- read from a constant database
+.SH SYNTAX
+.B #include <cdb.h>
+
+int \fBcdb_seek(\fP\fIfd,key,len,dlen\fR\fB)\fP;
+
+int \fIfd\fR;
+.br
+char *\fIkey\fR;
+.br
+unsigned int \fIlen\fR;
+.br
+uint32 *\fIdlen\fR;
+.SH DESCRIPTION
+.B cdb_seek
+looks up
+.I key
+in a constant database.
+It returns 1 if
+.I key
+is present,
+0 if
+.I key
+is not present,
+or \-1 if there was a read error.
+.I key
+is an array of
+.I len
+characters.
+
+.B cdb_seek
+needs an open file descriptor,
+.IR fd ,
+pointing to the database.
+If
+.B cdb_seek
+returns 1,
+it points
+.I fd
+at the beginning of the data portion of the first record
+indexed by
+.IR key ,
+and it stores the data length in
+.IR dlen.
+.B cdb_seek
+does not provide a way to read subsequent records with the same key.
+
+It's fine to do several
+.B cdb_seek
+lookups with the same open file descriptor.
+Beware, however, that two simultaneous
+.B cdb_seek
+lookups can fail horribly;
+separate processes should not share the same database descriptor.
+Furthermore, any updates after the database was opened
+will be invisible.
+It's rarely a good idea for a long-running program
+to hold a database open.
+.SH "SEE ALSO"
+cdbget(1)
diff --git a/cdb.h b/cdb.h
new file mode 100644
index 0000000..571e5d6
--- /dev/null
+++ b/cdb.h
@@ -0,0 +1,12 @@
+#ifndef CDB_H
+#define CDB_H
+
+#include "uint32.h"
+
+extern uint32 cdb_hash();
+extern uint32 cdb_unpack();
+
+extern int cdb_bread();
+extern int cdb_seek();
+
+#endif
diff --git a/cdb_hash.c b/cdb_hash.c
new file mode 100644
index 0000000..8238020
--- /dev/null
+++ b/cdb_hash.c
@@ -0,0 +1,16 @@
+#include "cdb.h"
+
+uint32 cdb_hash(buf,len)
+unsigned char *buf;
+unsigned int len;
+{
+ uint32 h;
+
+ h = 5381;
+ while (len) {
+ --len;
+ h += (h << 5);
+ h ^= (uint32) *buf++;
+ }
+ return h;
+}
diff --git a/cdb_seek.c b/cdb_seek.c
new file mode 100644
index 0000000..f31b87d
--- /dev/null
+++ b/cdb_seek.c
@@ -0,0 +1,94 @@
+#include <sys/types.h>
+#include <errno.h>
+#include "cdb.h"
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+int cdb_bread(fd,buf,len)
+int fd;
+char *buf;
+int len;
+{
+ int r;
+ while (len > 0) {
+ do
+ r = read(fd,buf,len);
+ while ((r == -1) && (errno == EINTR));
+ if (r == -1) return -1;
+ if (r == 0) { errno = EIO; return -1; }
+ buf += r;
+ len -= r;
+ }
+ return 0;
+}
+
+static int match(fd,key,len)
+int fd;
+char *key;
+unsigned int len;
+{
+ char buf[32];
+ int n;
+ int i;
+
+ while (len > 0) {
+ n = sizeof(buf);
+ if (n > len) n = len;
+ if (cdb_bread(fd,buf,n) == -1) return -1;
+ for (i = 0;i < n;++i) if (buf[i] != key[i]) return 0;
+ key += n;
+ len -= n;
+ }
+ return 1;
+}
+
+int cdb_seek(fd,key,len,dlen)
+int fd;
+char *key;
+unsigned int len;
+uint32 *dlen;
+{
+ char packbuf[8];
+ uint32 pos;
+ uint32 h;
+ uint32 lenhash;
+ uint32 h2;
+ uint32 loop;
+ uint32 poskd;
+
+ h = cdb_hash(key,len);
+
+ pos = 8 * (h & 255);
+ if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1;
+
+ if (cdb_bread(fd,packbuf,8) == -1) return -1;
+
+ pos = cdb_unpack(packbuf);
+ lenhash = cdb_unpack(packbuf + 4);
+
+ if (!lenhash) return 0;
+ h2 = (h >> 8) % lenhash;
+
+ for (loop = 0;loop < lenhash;++loop) {
+ if (lseek(fd,(off_t) (pos + 8 * h2),SEEK_SET) == -1) return -1;
+ if (cdb_bread(fd,packbuf,8) == -1) return -1;
+ poskd = cdb_unpack(packbuf + 4);
+ if (!poskd) return 0;
+ if (cdb_unpack(packbuf) == h) {
+ if (lseek(fd,(off_t) poskd,SEEK_SET) == -1) return -1;
+ if (cdb_bread(fd,packbuf,8) == -1) return -1;
+ if (cdb_unpack(packbuf) == len)
+ switch(match(fd,key,len)) {
+ case -1:
+ return -1;
+ case 1:
+ *dlen = cdb_unpack(packbuf + 4);
+ return 1;
+ }
+ }
+ if (++h2 == lenhash) h2 = 0;
+ }
+ return 0;
+}
diff --git a/cdb_unpack.c b/cdb_unpack.c
new file mode 100644
index 0000000..c882202
--- /dev/null
+++ b/cdb_unpack.c
@@ -0,0 +1,12 @@
+#include "cdb.h"
+
+uint32 cdb_unpack(buf)
+unsigned char *buf;
+{
+ uint32 num;
+ num = buf[3]; num <<= 8;
+ num += buf[2]; num <<= 8;
+ num += buf[1]; num <<= 8;
+ num += buf[0];
+ return num;
+}
diff --git a/cdbmake.h b/cdbmake.h
new file mode 100644
index 0000000..883a231
--- /dev/null
+++ b/cdbmake.h
@@ -0,0 +1,35 @@
+#ifndef CDBMAKE_H
+#define CDBMAKE_H
+
+#include "uint32.h"
+
+#define CDBMAKE_HPLIST 1000
+
+struct cdbmake_hp { uint32 h; uint32 p; } ;
+
+struct cdbmake_hplist {
+ struct cdbmake_hp hp[CDBMAKE_HPLIST];
+ struct cdbmake_hplist *next;
+ int num;
+} ;
+
+struct cdbmake {
+ char final[2048];
+ uint32 count[256];
+ uint32 start[256];
+ struct cdbmake_hplist *head;
+ struct cdbmake_hp *split; /* includes space for hash */
+ struct cdbmake_hp *hash;
+ uint32 numentries;
+} ;
+
+extern void cdbmake_pack();
+#define CDBMAKE_HASHSTART ((uint32) 5381)
+extern uint32 cdbmake_hashadd();
+
+extern void cdbmake_init();
+extern int cdbmake_add();
+extern int cdbmake_split();
+extern uint32 cdbmake_throw();
+
+#endif
diff --git a/cdbmake_add.c b/cdbmake_add.c
new file mode 100644
index 0000000..83a03ff
--- /dev/null
+++ b/cdbmake_add.c
@@ -0,0 +1,118 @@
+#include "alloc.h"
+#include "cdbmake.h"
+
+void cdbmake_init(cdbm)
+struct cdbmake *cdbm;
+{
+ cdbm->head = 0;
+ cdbm->split = 0;
+ cdbm->hash = 0;
+ cdbm->numentries = 0;
+}
+
+int cdbmake_add(cdbm,h,p,alloc)
+struct cdbmake *cdbm;
+uint32 h;
+uint32 p;
+char *(*alloc)();
+{
+ struct cdbmake_hplist *head;
+
+ head = cdbm->head;
+ if (!head || (head->num >= CDBMAKE_HPLIST)) {
+ head = (struct cdbmake_hplist *) alloc(sizeof(struct cdbmake_hplist));
+ if (!head) return 0;
+ head->num = 0;
+ head->next = cdbm->head;
+ cdbm->head = head;
+ }
+ head->hp[head->num].h = h;
+ head->hp[head->num].p = p;
+ ++head->num;
+ ++cdbm->numentries;
+ return 1;
+}
+
+int cdbmake_split(cdbm,alloc)
+struct cdbmake *cdbm;
+char *(*alloc)();
+{
+ int i;
+ uint32 u;
+ uint32 memsize;
+ struct cdbmake_hplist *x;
+
+ for (i = 0;i < 256;++i)
+ cdbm->count[i] = 0;
+
+ for (x = cdbm->head;x;x = x->next) {
+ i = x->num;
+ while (i--)
+ ++cdbm->count[255 & x->hp[i].h];
+ }
+
+ memsize = 1;
+ for (i = 0;i < 256;++i) {
+ u = cdbm->count[i] * 2;
+ if (u > memsize)
+ memsize = u;
+ }
+
+ memsize += cdbm->numentries; /* no overflow possible up to now */
+ u = (uint32) 0 - (uint32) 1;
+ u /= sizeof(struct cdbmake_hp);
+ if (memsize > u) return 0;
+
+ cdbm->split = (struct cdbmake_hp *) alloc(memsize * sizeof(struct cdbmake_hp));
+ if (!cdbm->split) return 0;
+
+ cdbm->hash = cdbm->split + cdbm->numentries;
+
+ u = 0;
+ for (i = 0;i < 256;++i) {
+ u += cdbm->count[i]; /* bounded by numentries, so no overflow */
+ cdbm->start[i] = u;
+ }
+
+ for (x = cdbm->head;x;x = x->next) {
+ i = x->num;
+ while (i--)
+ cdbm->split[--cdbm->start[255 & x->hp[i].h]] = x->hp[i];
+ }
+
+ return 1;
+}
+
+uint32 cdbmake_throw(cdbm,pos,b)
+struct cdbmake *cdbm;
+uint32 pos;
+int b;
+{
+ uint32 len;
+ uint32 j;
+ uint32 count;
+ struct cdbmake_hp *hp;
+ uint32 where;
+
+ count = cdbm->count[b];
+
+ len = count + count; /* no overflow possible */
+ cdbmake_pack(cdbm->final + 8 * b,pos);
+ cdbmake_pack(cdbm->final + 8 * b + 4,len);
+
+ if (len) {
+ for (j = 0;j < len;++j)
+ cdbm->hash[j].h = cdbm->hash[j].p = 0;
+
+ hp = cdbm->split + cdbm->start[b];
+ for (j = 0;j < count;++j) {
+ where = (hp->h >> 8) % len;
+ while (cdbm->hash[where].p)
+ if (++where == len)
+ where = 0;
+ cdbm->hash[where] = *hp++;
+ }
+ }
+
+ return len;
+}
diff --git a/cdbmake_hash.c b/cdbmake_hash.c
new file mode 100644
index 0000000..f9dc3e5
--- /dev/null
+++ b/cdbmake_hash.c
@@ -0,0 +1,10 @@
+#include "cdbmake.h"
+
+uint32 cdbmake_hashadd(h,c)
+uint32 h;
+unsigned int c;
+{
+ h += (h << 5);
+ h ^= (uint32) (unsigned char) c;
+ return h;
+}
diff --git a/cdbmake_pack.c b/cdbmake_pack.c
new file mode 100644
index 0000000..04b5f5b
--- /dev/null
+++ b/cdbmake_pack.c
@@ -0,0 +1,11 @@
+#include "cdbmake.h"
+
+void cdbmake_pack(buf,num)
+unsigned char *buf;
+uint32 num;
+{
+ *buf++ = num; num >>= 8;
+ *buf++ = num; num >>= 8;
+ *buf++ = num; num >>= 8;
+ *buf = num;
+}
diff --git a/cdbmss.c b/cdbmss.c
new file mode 100644
index 0000000..2d8f367
--- /dev/null
+++ b/cdbmss.c
@@ -0,0 +1,65 @@
+#include "readwrite.h"
+#include "seek.h"
+#include "alloc.h"
+#include "cdbmss.h"
+
+int cdbmss_start(c,fd)
+struct cdbmss *c;
+int fd;
+{
+ cdbmake_init(&c->cdbm);
+ c->fd = fd;
+ c->pos = sizeof(c->cdbm.final);
+ substdio_fdbuf(&c->ss,write,fd,c->ssbuf,sizeof(c->ssbuf));
+ return seek_set(fd,(seek_pos) c->pos);
+}
+
+int cdbmss_add(c,key,keylen,data,datalen)
+struct cdbmss *c;
+unsigned char *key;
+unsigned int keylen;
+unsigned char *data;
+unsigned int datalen;
+{
+ uint32 h;
+ int i;
+
+ cdbmake_pack(c->packbuf,(uint32) keylen);
+ cdbmake_pack(c->packbuf + 4,(uint32) datalen);
+ if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1;
+ if (substdio_put(&c->ss,key,keylen) == -1) return -1;
+ if (substdio_put(&c->ss,data,datalen) == -1) return -1;
+
+ h = CDBMAKE_HASHSTART;
+ for (i = 0;i < keylen;++i)
+ h = cdbmake_hashadd(h,(unsigned int) key[i]);
+
+ if (!cdbmake_add(&c->cdbm,h,c->pos,alloc)) return -1;
+
+ c->pos += 8 + keylen + datalen; /* XXX: overflow? */
+ return 0;
+}
+
+int cdbmss_finish(c)
+struct cdbmss *c;
+{
+ int i;
+ uint32 len;
+ uint32 u;
+
+ if (!cdbmake_split(&c->cdbm,alloc)) return -1;
+
+ for (i = 0;i < 256;++i) {
+ len = cdbmake_throw(&c->cdbm,c->pos,i);
+ for (u = 0;u < len;++u) {
+ cdbmake_pack(c->packbuf,c->cdbm.hash[u].h);
+ cdbmake_pack(c->packbuf + 4,c->cdbm.hash[u].p);
+ if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1;
+ c->pos += 8; /* XXX: overflow? */
+ }
+ }
+
+ if (substdio_flush(&c->ss) == -1) return -1;
+ if (seek_begin(c->fd) == -1) return -1;
+ return substdio_putflush(&c->ss,c->cdbm.final,sizeof(c->cdbm.final));
+}
diff --git a/cdbmss.h b/cdbmss.h
new file mode 100644
index 0000000..5e6bdf4
--- /dev/null
+++ b/cdbmss.h
@@ -0,0 +1,16 @@
+#ifndef CDBMSS_H
+#define CDBMSS_H
+
+#include "cdbmake.h"
+#include "substdio.h"
+
+struct cdbmss {
+ char ssbuf[1024];
+ struct cdbmake cdbm;
+ substdio ss;
+ char packbuf[8];
+ uint32 pos;
+ int fd;
+} ;
+
+#endif
diff --git a/chkshsgr.c b/chkshsgr.c
new file mode 100644
index 0000000..2bcdade
--- /dev/null
+++ b/chkshsgr.c
@@ -0,0 +1,9 @@
+#include "exit.h"
+void main()
+{
+ short x[4];
+
+ x[0] = x[1] = 0;
+ if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1);
+ _exit(0);
+}
diff --git a/chkspawn.c b/chkspawn.c
new file mode 100644
index 0000000..d19259e
--- /dev/null
+++ b/chkspawn.c
@@ -0,0 +1,48 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "fmt.h"
+#include "select.h"
+#include "exit.h"
+#include "auto_spawn.h"
+
+char num[FMT_ULONG];
+fd_set fds;
+
+void main()
+{
+ unsigned long hiddenlimit;
+ unsigned long maxnumd;
+
+ hiddenlimit = sizeof(fds) * 8;
+ maxnumd = (hiddenlimit - 5) / 2;
+
+ if (auto_spawn < 1) {
+ substdio_puts(subfderr,"Oops. You have set conf-spawn lower than 1.\n");
+ substdio_flush(subfderr);
+ _exit(1);
+ }
+
+ if (auto_spawn > 255) {
+ substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 255.\n");
+ substdio_flush(subfderr);
+ _exit(1);
+ }
+
+ if (auto_spawn > maxnumd) {
+ substdio_puts(subfderr,"Oops. Your system's FD_SET() has a hidden limit of ");
+ substdio_put(subfderr,num,fmt_ulong(num,hiddenlimit));
+ substdio_puts(subfderr," descriptors.\n\
+This means that the qmail daemons could crash if you set the run-time\n\
+concurrency higher than ");
+ substdio_put(subfderr,num,fmt_ulong(num,maxnumd));
+ substdio_puts(subfderr,". So I'm going to insist that the concurrency\n\
+limit in conf-spawn be at most ");
+ substdio_put(subfderr,num,fmt_ulong(num,maxnumd));
+ substdio_puts(subfderr,". Right now it's ");
+ substdio_put(subfderr,num,fmt_ulong(num,(unsigned long) auto_spawn));
+ substdio_puts(subfderr,".\n");
+ substdio_flush(subfderr);
+ _exit(1);
+ }
+ _exit(0);
+}
diff --git a/coe.3 b/coe.3
new file mode 100644
index 0000000..06591b6
--- /dev/null
+++ b/coe.3
@@ -0,0 +1,25 @@
+.TH coe 3
+.SH NAME
+coe \- set close-on-exec flag for a descriptor
+.SH SYNTAX
+.B #include <coe.h>
+
+int \fBcoe\fP(\fIfd\fR);
+
+int \fIfd\fR;
+.SH DESCRIPTION
+.B coe
+sets the close-on-exec flag for
+file descriptor
+.IR fd ,
+returning 0 if it was successful
+or -1 on error.
+If
+.B coe
+is successful,
+.I fd
+will be closed when the process calls
+.BR execve .
+.SH "SEE ALSO"
+execve(2),
+fcntl(2)
diff --git a/coe.c b/coe.c
new file mode 100644
index 0000000..d855158
--- /dev/null
+++ b/coe.c
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include "coe.h"
+
+int coe(fd)
+int fd;
+{
+ return fcntl(fd,F_SETFD,1);
+}
diff --git a/coe.h b/coe.h
new file mode 100644
index 0000000..1559bc1
--- /dev/null
+++ b/coe.h
@@ -0,0 +1,6 @@
+#ifndef COE_H
+#define COE_H
+
+extern int coe();
+
+#endif
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
new file mode 100644
index 0000000..9f9d3c4
--- /dev/null
+++ b/condredirect.1
@@ -0,0 +1,63 @@
+.TH condredirect 1
+.SH NAME
+condredirect \- perhaps redirect mail to another address
+.SH SYNOPSIS
+in
+.BR .qmail :
+.B |condredirect
+.I newaddress
+.I program
+[
+.I arg ...
+]
+.SH DESCRIPTION
+.B condredirect
+feeds each new mail message to
+.I program
+with the given arguments.
+If
+.I program
+exits 0,
+.B condredirect
+forwards the mail message to
+.IR newaddress ,
+and then exits 99,
+so further commands in
+.B .qmail
+are ignored.
+
+If
+.I program
+exits 111,
+.B condredirect
+exits 111,
+so delivery will be retried later.
+
+If
+.I program
+exits anything else
+(or does not exist),
+.B condredirect
+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.
+
+.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
new file mode 100644
index 0000000..593d2f5
--- /dev/null
+++ b/condredirect.c
@@ -0,0 +1,85 @@
+#include "sig.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "env.h"
+#include "error.h"
+#include "fork.h"
+#include "wait.h"
+#include "seek.h"
+#include "qmail.h"
+#include "strerr.h"
+#include "substdio.h"
+#include "fmt.h"
+
+#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;
+}
+
+char inbuf[SUBSTDIO_INSIZE];
+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;
+ 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) == -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)
+ 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;
+
+ 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-break b/conf-break
new file mode 100644
index 0000000..28fd977
--- /dev/null
+++ b/conf-break
@@ -0,0 +1,9 @@
+-
+
+This character is the user-ext delimiter. The default delimiter is -,
+meaning that user joe controls joe-anything. Some system administrators
+prefer + or =.
+
+You can override this choice at run time with the qmail-users mechanism.
+
+Multicharacter delimiters are not permitted.
diff --git a/conf-cc b/conf-cc
new file mode 100644
index 0000000..e58fb9b
--- /dev/null
+++ b/conf-cc
@@ -0,0 +1,3 @@
+cc -O2
+
+This will be used to compile .c files.
diff --git a/conf-groups b/conf-groups
new file mode 100644
index 0000000..cec0845
--- /dev/null
+++ b/conf-groups
@@ -0,0 +1,6 @@
+qmail
+nofiles
+
+These are the qmail groups. The second group should not have access to
+any files, but it must be usable for processes; this requirement
+excludes the ``nogroup'' and ``nobody'' groups on many systems.
diff --git a/conf-ld b/conf-ld
new file mode 100644
index 0000000..a9e796a
--- /dev/null
+++ b/conf-ld
@@ -0,0 +1,3 @@
+cc -s
+
+This will be used to link .o files into an executable.
diff --git a/conf-patrn b/conf-patrn
new file mode 100644
index 0000000..70c72af
--- /dev/null
+++ b/conf-patrn
@@ -0,0 +1,6 @@
+002
+
+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
new file mode 100644
index 0000000..0267f30
--- /dev/null
+++ b/conf-qmail
@@ -0,0 +1,11 @@
+/var/qmail
+
+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/conf-spawn b/conf-spawn
new file mode 100644
index 0000000..d6a4256
--- /dev/null
+++ b/conf-spawn
@@ -0,0 +1,5 @@
+120
+
+This is a silent concurrency limit. You can't set it above 255. On some
+systems you can't set it above 125. qmail will refuse to compile if the
+limit is too high.
diff --git a/conf-split b/conf-split
new file mode 100644
index 0000000..dc6aaf1
--- /dev/null
+++ b/conf-split
@@ -0,0 +1,3 @@
+23
+
+This is the queue subdirectory split.
diff --git a/conf-users b/conf-users
new file mode 100644
index 0000000..9bb35df
--- /dev/null
+++ b/conf-users
@@ -0,0 +1,15 @@
+alias
+qmaild
+qmaill
+root
+qmailp
+qmailq
+qmailr
+qmails
+
+The qmail system is heavily partitioned for security; it does almost
+nothing as root.
+
+The first eight lines of this file are the alias user, the daemon user,
+the log user, the owner of miscellaneous files such as binaries, the
+passwd user, the queue user, the remote user, and the send user.
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/config.sh b/config.sh
new file mode 100644
index 0000000..8450070
--- /dev/null
+++ b/config.sh
@@ -0,0 +1,64 @@
+./hostname | tr '[A-Z]' '[a-z]' | (
+ if read host
+ then
+ echo Your hostname is "$host".
+ ./dnsfq "$host" | tr '[A-Z]' '[a-z]' | (
+ if read fqdn
+ then
+ echo Your host\'s fully qualified name in DNS 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 ' '
+ echo Checking local IP addresses:
+ : > QMAIL/control/locals
+ chmod 644 QMAIL/control/locals
+ ( ./dnsip "$fqdn"
+ ./ipmeprint ) | sort -u | \
+ (
+ while read localip
+ do
+ echo "$localip: " | tr -d '\012'
+ ./dnsptr "$localip" 2>/dev/null | (
+ if read local
+ then
+ echo Adding "$local" to control/locals...
+ echo "$local" >> QMAIL/control/locals
+ else
+ echo PTR lookup failed. I assume this address has no DNS name.
+ fi
+ )
+ done
+ )
+ echo ' '
+ echo If there are any other domain names that point to you,
+ echo you will have to add them to QMAIL/control/locals.
+ echo You don\'t have to worry about aliases, i.e., domains with CNAME records.
+ echo ' '
+ echo Copying QMAIL/control/locals to QMAIL/control/rcpthosts...
+ cp QMAIL/control/locals QMAIL/control/rcpthosts
+ chmod 644 QMAIL/control/rcpthosts
+ echo 'Now qmail will refuse to accept SMTP messages except to those hosts.'
+ echo 'Make sure to change rcpthosts if you add hosts to locals or virtualdomains!'
+ else
+ echo Sorry, I couldn\'t find your host\'s canonical name in DNS.
+ echo You will have to set up control/me yourself.
+ fi
+ )
+ else
+ echo Sorry, I couldn\'t find your hostname.
+ echo You will have to set up control/me yourself.
+ fi
+)
diff --git a/constmap.c b/constmap.c
new file mode 100644
index 0000000..722e3b8
--- /dev/null
+++ b/constmap.c
@@ -0,0 +1,114 @@
+#include "constmap.h"
+#include "alloc.h"
+#include "case.h"
+
+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;
+ }
+ return h;
+}
+
+char *constmap(cm,s,len)
+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];
+ }
+ return 0;
+}
+
+int constmap_init(cm,s,len,flagcolon)
+struct constmap *cm;
+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;
+ }
+ 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;
+ }
+ alloc_free(cm->hash);
+ }
+ alloc_free(cm->inputlen);
+ }
+ alloc_free(cm->input);
+ }
+ alloc_free(cm->first);
+ }
+ 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);
+}
diff --git a/constmap.h b/constmap.h
new file mode 100644
index 0000000..3f29179
--- /dev/null
+++ b/constmap.h
@@ -0,0 +1,20 @@
+#ifndef CONSTMAP_H
+#define CONSTMAP_H
+
+typedef unsigned long constmap_hash;
+
+struct constmap {
+ int num;
+ constmap_hash mask;
+ constmap_hash *hash;
+ int *first;
+ int *next;
+ char **input;
+ int *inputlen;
+} ;
+
+extern int constmap_init();
+extern void constmap_free();
+extern char *constmap();
+
+#endif
diff --git a/control.c b/control.c
new file mode 100644
index 0000000..b655352
--- /dev/null
+++ b/control.c
@@ -0,0 +1,130 @@
+#include "readwrite.h"
+#include "open.h"
+#include "getln.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "error.h"
+#include "control.h"
+#include "alloc.h"
+#include "scan.h"
+
+static char inbuf[64];
+static stralloc line = {0};
+static stralloc me = {0};
+static int meok = 0;
+
+static void striptrailingwhitespace(sa)
+stralloc *sa;
+{
+ while (sa->len > 0)
+ switch(sa->s[sa->len - 1])
+ {
+ case '\n': case ' ': case '\t':
+ --sa->len;
+ break;
+ default:
+ return;
+ }
+}
+
+int control_init()
+{
+ int r;
+ r = control_readline(&me,"control/me");
+ if (r == 1) meok = 1;
+ return r;
+}
+
+int control_rldef(sa,fn,flagme,def)
+stralloc *sa;
+char *fn;
+int flagme;
+char *def;
+{
+ int r;
+ r = control_readline(sa,fn);
+ if (r) return r;
+ if (flagme) if (meok) return stralloc_copy(sa,&me) ? 1 : -1;
+ if (def) return stralloc_copys(sa,def) ? 1 : -1;
+ return r;
+}
+
+int control_readline(sa,fn)
+stralloc *sa;
+char *fn;
+{
+ substdio ss;
+ int fd;
+ int match;
+
+ fd = open_read(fn);
+ if (fd == -1) { if (errno == error_noent) return 0; return -1; }
+
+ substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf));
+
+ if (getln(&ss,sa,&match,'\n') == -1) { close(fd); return -1; }
+
+ striptrailingwhitespace(sa);
+ close(fd);
+ return 1;
+}
+
+int control_readint(i,fn)
+int *i;
+char *fn;
+{
+ unsigned long u;
+ switch(control_readline(&line,fn))
+ {
+ case 0: return 0;
+ case -1: return -1;
+ }
+ if (!stralloc_0(&line)) return -1;
+ if (!scan_ulong(line.s,&u)) return 0;
+ *i = u;
+ return 1;
+}
+
+int control_readfile(sa,fn,flagme)
+stralloc *sa;
+char *fn;
+int flagme;
+{
+ substdio ss;
+ int fd;
+ int match;
+
+ if (!stralloc_copys(sa,"")) return -1;
+
+ fd = open_read(fn);
+ if (fd == -1)
+ {
+ if (errno == error_noent)
+ {
+ if (flagme && meok)
+ {
+ if (!stralloc_copy(sa,&me)) return -1;
+ if (!stralloc_0(sa)) return -1;
+ return 1;
+ }
+ return 0;
+ }
+ return -1;
+ }
+
+ substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf));
+
+ for (;;)
+ {
+ if (getln(&ss,&line,&match,'\n') == -1) break;
+ if (!match && !line.len) { close(fd); return 1; }
+ striptrailingwhitespace(&line);
+ if (!stralloc_0(&line)) break;
+ if (line.s[0])
+ if (line.s[0] != '#')
+ if (!stralloc_cat(sa,&line)) break;
+ if (!match) { close(fd); return 1; }
+ }
+ close(fd);
+ return -1;
+}
diff --git a/control.h b/control.h
new file mode 100644
index 0000000..7cba89b
--- /dev/null
+++ b/control.h
@@ -0,0 +1,10 @@
+#ifndef CONTROL_H
+#define CONTROL_H
+
+extern int control_init();
+extern int control_readline();
+extern int control_rldef();
+extern int control_readint();
+extern int control_readfile();
+
+#endif
diff --git a/date822fmt.c b/date822fmt.c
new file mode 100644
index 0000000..7674bd1
--- /dev/null
+++ b/date822fmt.c
@@ -0,0 +1,29 @@
+#include "datetime.h"
+#include "fmt.h"
+#include "date822fmt.h"
+
+static char *montab[12] = {
+"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+unsigned int date822fmt(s,dt)
+char *s;
+struct datetime *dt;
+{
+ unsigned int i;
+ unsigned int len;
+ len = 0;
+ i = fmt_uint(s,dt->mday); len += i; if (s) s += i;
+ i = fmt_str(s," "); len += i; if (s) s += i;
+ i = fmt_str(s,montab[dt->mon]); len += i; if (s) s += i;
+ i = fmt_str(s," "); len += i; if (s) s += i;
+ i = fmt_uint(s,dt->year + 1900); len += i; if (s) s += i;
+ i = fmt_str(s," "); len += i; if (s) s += i;
+ i = fmt_uint0(s,dt->hour,2); len += i; if (s) s += i;
+ i = fmt_str(s,":"); len += i; if (s) s += i;
+ i = fmt_uint0(s,dt->min,2); len += i; if (s) s += i;
+ i = fmt_str(s,":"); len += i; if (s) s += i;
+ i = fmt_uint0(s,dt->sec,2); len += i; if (s) s += i;
+ i = fmt_str(s," -0000\n"); len += i; if (s) s += i;
+ return len;
+}
diff --git a/date822fmt.h b/date822fmt.h
new file mode 100644
index 0000000..1848e5a
--- /dev/null
+++ b/date822fmt.h
@@ -0,0 +1,7 @@
+#ifndef DATE822FMT_H
+#define DATE822FMT_H
+
+extern unsigned int date822fmt();
+#define DATE822FMT 60
+
+#endif
diff --git a/datemail.sh b/datemail.sh
new file mode 100644
index 0000000..fd28f46
--- /dev/null
+++ b/datemail.sh
@@ -0,0 +1 @@
+exec QMAIL/bin/predate QMAIL/bin/sendmail ${1+"$@"}
diff --git a/datetime.3 b/datetime.3
new file mode 100644
index 0000000..33a623f
--- /dev/null
+++ b/datetime.3
@@ -0,0 +1,73 @@
+.TH datetime 3
+.SH NAME
+datetime \- convert between TAI labels and seconds
+.SH SYNTAX
+.B #include <datetime.h>
+
+void \fBdatetime_tai\fP(&\fIdt\fR,\fIt\fR);
+
+datetime_sec \fBdatetime_untai\fP(&\fIdt\fR);
+
+struct datetime \fIdt\fR;
+.br
+datetime_sec \fIt\fR;
+.SH DESCRIPTION
+International Atomic Time, TAI,
+is the fundamental unit for time measurements.
+TAI has one label for every second of real time,
+without complications such as leap seconds.
+
+A
+struct datetime
+variable,
+such as
+.IR dt ,
+stores a TAI label.
+.I dt\fB.year
+is the year number minus 1900;
+.I dt\fB.mon
+is the month number, from 0 (January) through 11 (December);
+.I dt\fB.mday
+is the day of the month, from 1 through 31;
+.I dt\fB.hour
+is the hour, from 0 through 23;
+.I dt\fB.min
+is the minute, from 0 through 59;
+.I dt\fB.sec
+is the second, from 0 through 59;
+.I dt\fB.wday
+is the day of the week, from 0 (Sunday) through 6 (Saturday);
+.I dt\fB.yday
+is the day of the year, from 0 through 365.
+
+The
+.B datetime
+library supports more convenient TAI manipulation with
+the datetime_sec type.
+A datetime_sec value, such as
+.IR t ,
+is an integer referring to the
+.IR t th
+second after the beginning of 1970 TAI.
+The first second of 1970 TAI was 0;
+the next second was 1;
+the last second of 1969 TAI was -1.
+The difference between two datetime_sec values is a number
+of real-time seconds.
+
+.B datetime_tai
+converts a datetime_sec to a TAI label.
+
+.B datetime_untai
+reads a TAI label
+(specifically
+.IR dt\fB.year ,
+.IR dt\fB.mon ,
+.IR dt\fB.mday ,
+.IR dt\fB.hour ,
+.IR dt\fB.min ,
+and
+.IR dt\fB.sec )
+and returns a datetime_sec.
+.SH "SEE ALSO"
+now(3)
diff --git a/datetime.c b/datetime.c
new file mode 100644
index 0000000..7b8a803
--- /dev/null
+++ b/datetime.c
@@ -0,0 +1,55 @@
+/* 19950925 */
+#include "datetime.h"
+
+void datetime_tai(dt,t)
+struct datetime *dt;
+datetime_sec t;
+{
+ int day;
+ int tod;
+ int year;
+ int yday;
+ int wday;
+ int mon;
+
+ tod = t % 86400;
+ day = t / 86400;
+ if (tod < 0) { tod += 86400; --day; }
+
+ dt->hour = tod / 3600;
+ tod %= 3600;
+ dt->min = tod / 60;
+ dt->sec = tod % 60;
+
+ wday = (day + 4) % 7; if (wday < 0) wday += 7;
+ dt->wday = wday;
+
+ day -= 11017;
+ /* day 0 is march 1, 2000 */
+ year = 5 + day / 146097;
+ day = day % 146097; if (day < 0) { day += 146097; --year; }
+ /* from now on, day is nonnegative */
+ year *= 4;
+ if (day == 146096) { year += 3; day = 36524; }
+ else { year += day / 36524; day %= 36524; }
+ year *= 25;
+ year += day / 1461;
+ day %= 1461;
+ year *= 4;
+ yday = (day < 306);
+ if (day == 1460) { year += 3; day = 365; }
+ else { year += day / 365; day %= 365; }
+ yday += day;
+
+ day *= 10;
+ mon = (day + 5) / 306;
+ day = day + 5 - 306 * mon;
+ day /= 10;
+ if (mon >= 10) { yday -= 306; ++year; mon -= 10; }
+ else { yday += 59; mon += 2; }
+
+ dt->yday = yday;
+ dt->year = year - 1900;
+ dt->mon = mon;
+ dt->mday = day + 1;
+}
diff --git a/datetime.h b/datetime.h
new file mode 100644
index 0000000..cde2a9b
--- /dev/null
+++ b/datetime.h
@@ -0,0 +1,20 @@
+#ifndef DATETIME_H
+#define DATETIME_H
+
+struct datetime {
+ int hour;
+ int min;
+ int sec;
+ int wday;
+ int mday;
+ int yday;
+ int mon;
+ int year;
+} ;
+
+typedef long datetime_sec;
+
+extern void datetime_tai();
+extern datetime_sec datetime_untai();
+
+#endif
diff --git a/datetime_un.c b/datetime_un.c
new file mode 100644
index 0000000..b5048f8
--- /dev/null
+++ b/datetime_un.c
@@ -0,0 +1,35 @@
+#include "datetime.h"
+
+/* roughly 100x faster than mktime() */
+datetime_sec datetime_untai(dt)
+struct datetime *dt;
+{
+ int year;
+ int day;
+ int mon;
+
+ year = dt->year + 1900;
+
+ mon = dt->mon;
+ if (mon >= 2) { mon -= 2; }
+ else { mon += 10; --year; }
+
+ day = (dt->mday - 1) * 10 + 5 + 306 * mon;
+ day /= 10;
+
+ if (day == 365) { year -= 3; day = 1460; }
+ else { day += 365 * (year % 4); }
+ year /= 4;
+
+ day += 1461 * (year % 25);
+ year /= 25;
+
+ if (day == 36524) { year -= 3; day = 146096; }
+ else { day += 36524 * (year % 4); }
+ year /= 4;
+
+ day += 146097 * (year - 5);
+ day += 11017;
+
+ return ((day * 24 + dt->hour) * 60 + dt->min) * 60 + dt->sec;
+}
diff --git a/direntry.3 b/direntry.3
new file mode 100644
index 0000000..8928fbb
--- /dev/null
+++ b/direntry.3
@@ -0,0 +1,36 @@
+.TH direntry 3
+.SH NAME
+direntry \- read directory entries
+.SH SYNTAX
+.B #include <direntry.h>
+
+DIR *\fBopendir\fP(\fIfn\fR);
+
+struct direntry *\fBreaddir\fP(\fIdir\fP);
+
+void \fBclosedir\fP(\fIdir\fP);
+
+DIR *\fIdir\fR;
+.br
+char *\fIfn\fR;
+.SH DESCRIPTION
+The point of
+.B direntry.h
+is to provide a uniform interface to BSD's
+.B sys/dir.h
+and POSIX's
+.BR dirent.h .
+
+The
+.B readdir
+interface is highly unsatisfactory.
+It does not distinguish between I/O errors and end-of-directory.
+It uses
+.BR malloc .
+The return type for
+.B closedir
+varies: some implementations return the
+.B close
+return value.
+.SH "SEE ALSO"
+readdir(3)
diff --git a/direntry.h1 b/direntry.h1
new file mode 100644
index 0000000..f737676
--- /dev/null
+++ b/direntry.h1
@@ -0,0 +1,8 @@
+#ifndef DIRENTRY_H
+#define DIRENTRY_H
+
+#include <sys/types.h>
+#include <sys/dir.h>
+#define direntry struct direct
+
+#endif
diff --git a/direntry.h2 b/direntry.h2
new file mode 100644
index 0000000..0302ebe
--- /dev/null
+++ b/direntry.h2
@@ -0,0 +1,8 @@
+#ifndef DIRENTRY_H
+#define DIRENTRY_H
+
+#include <sys/types.h>
+#include <dirent.h>
+#define direntry struct dirent
+
+#endif
diff --git a/dns.c b/dns.c
new file mode 100644
index 0000000..e9faad7
--- /dev/null
+++ b/dns.c
@@ -0,0 +1,398 @@
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <errno.h>
+extern int res_query();
+extern int res_search();
+#include "ip.h"
+#include "ipalloc.h"
+#include "fmt.h"
+#include "alloc.h"
+#include "str.h"
+#include "stralloc.h"
+#include "dns.h"
+#include "case.h"
+
+static unsigned short getshort(c) unsigned char *c;
+{ unsigned short u; u = c[0]; return (u << 8) + c[1]; }
+
+static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response;
+static int responselen;
+static unsigned char *responseend;
+static unsigned char *responsepos;
+
+static int numanswers;
+static char name[MAXDNAME];
+static struct ip_address ip;
+unsigned short pref;
+
+static stralloc glue = {0};
+
+static int (*lookup)() = res_query;
+
+static int resolve(domain,type)
+stralloc *domain;
+int type;
+{
+ int n;
+ int i;
+
+ errno = 0;
+ if (!stralloc_copy(&glue,domain)) return DNS_MEM;
+ if (!stralloc_0(&glue)) return DNS_MEM;
+ responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response));
+ if (responselen <= 0)
+ {
+ if (errno == ECONNREFUSED) return DNS_SOFT;
+ if (h_errno == TRY_AGAIN) return DNS_SOFT;
+ return DNS_HARD;
+ }
+ if (responselen >= sizeof(response))
+ responselen = sizeof(response);
+ responseend = response.buf + responselen;
+ responsepos = response.buf + sizeof(HEADER);
+ n = ntohs(response.hdr.qdcount);
+ while (n-- > 0)
+ {
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+ i = responseend - responsepos;
+ if (i < QFIXEDSZ) return DNS_SOFT;
+ responsepos += QFIXEDSZ;
+ }
+ numanswers = ntohs(response.hdr.ancount);
+ return 0;
+}
+
+static int findname(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+ {
+ if (dn_expand(response.buf,responseend,responsepos,name,MAXDNAME) < 0)
+ return DNS_SOFT;
+ responsepos += rrdlen;
+ return 1;
+ }
+
+ responsepos += rrdlen;
+ return 0;
+}
+
+static int findip(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+ {
+ if (rrdlen < 4)
+ return DNS_SOFT;
+ ip.d[0] = responsepos[0];
+ ip.d[1] = responsepos[1];
+ ip.d[2] = responsepos[2];
+ ip.d[3] = responsepos[3];
+ responsepos += rrdlen;
+ return 1;
+ }
+
+ responsepos += rrdlen;
+ return 0;
+}
+
+static int findmx(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+ {
+ if (rrdlen < 3)
+ return DNS_SOFT;
+ pref = (responsepos[0] << 8) + responsepos[1];
+ if (dn_expand(response.buf,responseend,responsepos + 2,name,MAXDNAME) < 0)
+ return DNS_SOFT;
+ responsepos += rrdlen;
+ return 1;
+ }
+
+ responsepos += rrdlen;
+ return 0;
+}
+
+void dns_init(flagsearch)
+int flagsearch;
+{
+ res_init();
+ if (flagsearch) lookup = res_search;
+}
+
+int dns_cname(sa)
+stralloc *sa;
+{
+ int r;
+ int loop;
+ for (loop = 0;loop < 10;++loop)
+ {
+ if (!sa->len) return loop;
+ if (sa->s[sa->len - 1] == ']') return loop;
+ if (sa->s[sa->len - 1] == '.') { --sa->len; continue; }
+ switch(resolve(sa,T_ANY))
+ {
+ case DNS_MEM: return DNS_MEM;
+ case DNS_SOFT: return DNS_SOFT;
+ case DNS_HARD: return loop;
+ default:
+ while ((r = findname(T_CNAME)) != 2)
+ {
+ if (r == DNS_SOFT) return DNS_SOFT;
+ if (r == 1)
+ {
+ if (!stralloc_copys(sa,name)) return DNS_MEM;
+ break;
+ }
+ }
+ if (r == 2) return loop;
+ }
+ }
+ return DNS_HARD; /* alias loop */
+}
+
+#define FMT_IAA 40
+
+static int iaafmt(s,ip)
+char *s;
+struct ip_address *ip;
+{
+ unsigned int i;
+ unsigned int len;
+ len = 0;
+ i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i;
+ i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i;
+ return len;
+}
+
+int dns_ptr(sa,ip)
+stralloc *sa;
+struct ip_address *ip;
+{
+ int r;
+
+ if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM;
+ sa->len = iaafmt(sa->s,ip);
+ switch(resolve(sa,T_PTR))
+ {
+ case DNS_MEM: return DNS_MEM;
+ case DNS_SOFT: return DNS_SOFT;
+ case DNS_HARD: return DNS_HARD;
+ }
+ while ((r = findname(T_PTR)) != 2)
+ {
+ if (r == DNS_SOFT) return DNS_SOFT;
+ if (r == 1)
+ {
+ if (!stralloc_copys(sa,name)) return DNS_MEM;
+ return 0;
+ }
+ }
+ return DNS_HARD;
+}
+
+static int dns_ipplus(ia,sa,pref)
+ipalloc *ia;
+stralloc *sa;
+int pref;
+{
+ int r;
+ struct ip_mx ix;
+
+ 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_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))
+ {
+ case DNS_MEM: return DNS_MEM;
+ case DNS_SOFT: return DNS_SOFT;
+ case DNS_HARD: return DNS_HARD;
+ }
+ while ((r = findip(T_A)) != 2)
+ {
+ ix.ip = ip;
+ ix.pref = pref;
+ if (r == DNS_SOFT) return DNS_SOFT;
+ if (r == 1)
+ if (!ipalloc_append(ia,&ix)) return DNS_MEM;
+ }
+ return 0;
+}
+
+int dns_ip(ia,sa)
+ipalloc *ia;
+stralloc *sa;
+{
+ if (!ipalloc_readyplus(ia,0)) return DNS_MEM;
+ ia->len = 0;
+ return dns_ipplus(ia,sa,0);
+}
+
+int dns_mxip(ia,sa,random)
+ipalloc *ia;
+stralloc *sa;
+unsigned long random;
+{
+ int r;
+ struct mx { stralloc sa; unsigned short p; } *mx;
+ struct ip_mx ix;
+ int nummx;
+ int i;
+ int j;
+ int flagsoft;
+
+ if (!ipalloc_readyplus(ia,0)) return DNS_MEM;
+ ia->len = 0;
+
+ 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_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))
+ {
+ case DNS_MEM: return DNS_MEM;
+ case DNS_SOFT: return DNS_SOFT;
+ case DNS_HARD: return dns_ip(ia,sa);
+ }
+
+ mx = (struct mx *) alloc(numanswers * sizeof(struct mx));
+ if (!mx) return DNS_MEM;
+ nummx = 0;
+
+ while ((r = findmx(T_MX)) != 2)
+ {
+ if (r == DNS_SOFT) { alloc_free(mx); return DNS_SOFT; }
+ if (r == 1)
+ {
+ mx[nummx].p = pref;
+ mx[nummx].sa.s = 0;
+ if (!stralloc_copys(&mx[nummx].sa,name))
+ {
+ while (nummx > 0) alloc_free(mx[--nummx].sa.s);
+ alloc_free(mx); return DNS_MEM;
+ }
+ ++nummx;
+ }
+ }
+
+ if (!nummx) return dns_ip(ia,sa); /* e.g., CNAME -> A */
+
+ flagsoft = 0;
+ while (nummx > 0)
+ {
+ unsigned long numsame;
+
+ i = 0;
+ numsame = 1;
+ for (j = 1;j < nummx;++j)
+ if (mx[j].p < mx[i].p)
+ {
+ i = j;
+ numsame = 1;
+ }
+ else if (mx[j].p == mx[i].p)
+ {
+ ++numsame;
+ random = random * 69069 + 1;
+ if ((random / 2) < (2147483647 / numsame))
+ i = j;
+ }
+
+ switch(dns_ipplus(ia,&mx[i].sa,mx[i].p))
+ {
+ case DNS_MEM: case DNS_SOFT:
+ flagsoft = 1; break;
+ }
+
+ alloc_free(mx[i].sa.s);
+ mx[i] = mx[--nummx];
+ }
+
+ alloc_free(mx);
+ return flagsoft;
+}
diff --git a/dns.h b/dns.h
new file mode 100644
index 0000000..bca9490
--- /dev/null
+++ b/dns.h
@@ -0,0 +1,14 @@
+#ifndef DNS_H
+#define DNS_H
+
+#define DNS_SOFT -1
+#define DNS_HARD -2
+#define DNS_MEM -3
+
+void dns_init();
+int dns_cname();
+int dns_mxip();
+int dns_ip();
+int dns_ptr();
+
+#endif
diff --git a/dnscname.c b/dnscname.c
new file mode 100644
index 0000000..b3cd6f1
--- /dev/null
+++ b/dnscname.c
@@ -0,0 +1,25 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "dns.h"
+#include "dnsdoe.h"
+#include "readwrite.h"
+#include "exit.h"
+
+stralloc sa = {0};
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ if (!argv[1]) _exit(100);
+
+ if (!stralloc_copys(&sa,argv[1]))
+ { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); }
+
+ dns_init(0);
+ dnsdoe(dns_cname(&sa));
+ substdio_putflush(subfdout,sa.s,sa.len);
+ substdio_putsflush(subfdout,"\n");
+ _exit(0);
+}
diff --git a/dnsdoe.c b/dnsdoe.c
new file mode 100644
index 0000000..806ca53
--- /dev/null
+++ b/dnsdoe.c
@@ -0,0 +1,16 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "exit.h"
+#include "dns.h"
+#include "dnsdoe.h"
+
+void dnsdoe(r)
+int r;
+{
+ switch (r)
+ {
+ case DNS_HARD: substdio_putsflush(subfderr,"hard error\n"); _exit(100);
+ case DNS_SOFT: substdio_putsflush(subfderr,"soft error\n"); _exit(111);
+ case DNS_MEM: substdio_putsflush(subfderr,"out of memory\n"); _exit(111);
+ }
+}
diff --git a/dnsdoe.h b/dnsdoe.h
new file mode 100644
index 0000000..0e47bf6
--- /dev/null
+++ b/dnsdoe.h
@@ -0,0 +1,6 @@
+#ifndef DNSDOE_H
+#define DNSDOE_H
+
+extern void dnsdoe();
+
+#endif
diff --git a/dnsfq.c b/dnsfq.c
new file mode 100644
index 0000000..b7619b9
--- /dev/null
+++ b/dnsfq.c
@@ -0,0 +1,32 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "dns.h"
+#include "dnsdoe.h"
+#include "ip.h"
+#include "ipalloc.h"
+#include "exit.h"
+
+stralloc sa = {0};
+ipalloc ia = {0};
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ if (!argv[1]) _exit(100);
+
+ if (!stralloc_copys(&sa,argv[1]))
+ { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); }
+
+ dns_init(1);
+ dnsdoe(dns_ip(&ia,&sa));
+ if (ia.len <= 0)
+ {
+ substdio_putsflush(subfderr,"no IP addresses\n"); _exit(100);
+ }
+ dnsdoe(dns_ptr(&sa,&ia.ix[0].ip));
+ substdio_putflush(subfdout,sa.s,sa.len);
+ substdio_putsflush(subfdout,"\n");
+ _exit(0);
+}
diff --git a/dnsip.c b/dnsip.c
new file mode 100644
index 0000000..e7b671c
--- /dev/null
+++ b/dnsip.c
@@ -0,0 +1,34 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "dns.h"
+#include "dnsdoe.h"
+#include "ip.h"
+#include "ipalloc.h"
+#include "exit.h"
+
+char temp[IPFMT];
+
+stralloc sa = {0};
+ipalloc ia = {0};
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ int j;
+
+ if (!argv[1]) _exit(100);
+
+ if (!stralloc_copys(&sa,argv[1]))
+ { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); }
+
+ dns_init(0);
+ dnsdoe(dns_ip(&ia,&sa));
+ for (j = 0;j < ia.len;++j)
+ {
+ substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip));
+ substdio_putsflush(subfdout,"\n");
+ }
+ _exit(0);
+}
diff --git a/dnsmxip.c b/dnsmxip.c
new file mode 100644
index 0000000..6d8e137
--- /dev/null
+++ b/dnsmxip.c
@@ -0,0 +1,40 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "fmt.h"
+#include "dns.h"
+#include "dnsdoe.h"
+#include "ip.h"
+#include "ipalloc.h"
+#include "now.h"
+#include "exit.h"
+
+char temp[IPFMT + FMT_ULONG];
+
+stralloc sa = {0};
+ipalloc ia = {0};
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ int j;
+ unsigned long r;
+
+ if (!argv[1]) _exit(100);
+
+ if (!stralloc_copys(&sa,argv[1]))
+ { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); }
+
+ r = now() + getpid();
+ dns_init(0);
+ dnsdoe(dns_mxip(&ia,&sa,r));
+ for (j = 0;j < ia.len;++j)
+ {
+ substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip));
+ substdio_puts(subfdout," ");
+ substdio_put(subfdout,temp,fmt_ulong(temp,(unsigned long) ia.ix[j].pref));
+ substdio_putsflush(subfdout,"\n");
+ }
+ _exit(0);
+}
diff --git a/dnsptr.c b/dnsptr.c
new file mode 100644
index 0000000..6a92fe0
--- /dev/null
+++ b/dnsptr.c
@@ -0,0 +1,27 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "str.h"
+#include "scan.h"
+#include "dns.h"
+#include "dnsdoe.h"
+#include "ip.h"
+#include "exit.h"
+
+stralloc sa = {0};
+struct ip_address ip;
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ if (!argv[1]) _exit(100);
+
+ ip_scan(argv[1],&ip);
+
+ dns_init(0);
+ dnsdoe(dns_ptr(&sa,&ip));
+ substdio_putflush(subfdout,sa.s,sa.len);
+ substdio_putsflush(subfdout,"\n");
+ _exit(0);
+}
diff --git a/dot-qmail.9 b/dot-qmail.9
new file mode 100644
index 0000000..52d4626
--- /dev/null
+++ b/dot-qmail.9
@@ -0,0 +1,394 @@
+.TH dot-qmail 5
+.SH NAME
+dot-qmail \- control the delivery of mail messages
+.SH DESCRIPTION
+Normally the
+.B qmail-local
+program delivers each incoming message to your system mailbox,
+.IR homedir\fB/Mailbox ,
+where
+.I homedir
+is your home directory.
+
+It can instead
+write the mail to a different file or directory,
+forward it to another address,
+distribute it to a mailing list,
+or even execute programs,
+all under your control.
+.SH "THE QMAIL FILE"
+To change
+.BR qmail-local 's
+behavior, set up a
+.B .qmail
+file in your home directory.
+
+.B .qmail
+contains one or more lines.
+Each line is a delivery instruction.
+.B qmail-local
+follows each instruction in turn.
+There are five types of delivery instructions:
+(1) comment; (2) program; (3) forward; (4) mbox; (5) maildir.
+.TP 5
+(1)
+A comment line begins with a number sign:
+
+.EX
+ # this is a comment
+.EE
+
+.B qmail-local
+ignores the line.
+.TP 5
+(2)
+A program line begins with a vertical bar:
+
+.EX
+ |preline /usr/ucb/vacation djb
+.EE
+
+.B qmail-local
+takes the rest of the line as a command to supply to
+.BR sh .
+See
+.B qmail-command(8)
+for further information.
+.TP 5
+(3)
+A forward line begins with an ampersand:
+
+.EX
+ &me@new.job.com
+.EE
+
+.B qmail-local
+takes the rest of the line as a mail address;
+it uses
+.B qmail-queue
+to forward the message to that address.
+The address must contain a fully qualified domain name;
+it must not contain extra spaces, angle brackets, or comments:
+
+.EX
+ # the following examples are WRONG
+.br
+ &me@new
+.br
+ &<me@new.job.com>
+.br
+ & me@new.job.com
+.br
+ &me@new.job.com (New Address)
+.EE
+
+If the address begins with a letter or number,
+you may leave out the ampersand:
+
+.EX
+ me@new.job.com
+.EE
+
+Note that
+.B qmail-local
+omits its new
+.B Return-Path
+line when forwarding messages.
+.TP 5
+(4)
+An
+.I mbox
+line begins with a slash or dot,
+and does not end with a slash:
+
+.EX
+ /home/djb/Mailbox.sos
+.EE
+
+.B qmail-local
+takes the entire line as a filename.
+It appends the mail message to that file,
+using
+.BR flock -style
+file locking if possible.
+.B qmail-local
+stores the mail message in
+.I mbox
+format, as described in
+.BR mbox(5) .
+
+.B WARNING:
+On many systems,
+anyone who can read a file can
+.B flock
+it, and thus hold up
+.BR qmail-local 's
+delivery forever.
+Do not deliver mail to a publicly accessible file!
+
+If
+.B qmail-local
+is able to lock the file, but has trouble writing to it
+(because, for example, the disk is full),
+it will truncate the file back to its original length.
+However, it cannot prevent mailbox corruption if the system
+crashes during delivery.
+.TP 5
+(5)
+A
+.I maildir
+line begins with a slash or dot,
+and ends with a slash:
+
+.EX
+ /home/djb/Maildir/
+.EE
+
+.B qmail-local
+takes the entire line as the name of a directory in
+.I maildir
+format.
+It reliably stores the incoming message in that directory.
+See
+.B maildir(5)
+for more details.
+.PP
+If
+.B .qmail
+has the execute bit set,
+it must not contain any
+program lines,
+.I mbox
+lines,
+or
+.I maildir
+lines.
+If
+.B qmail-local
+sees any such lines,
+it will stop and indicate a temporary failure.
+
+If
+.B .qmail
+is completely empty (0 bytes long), or does not exist,
+.B qmail-local
+follows the
+.I defaultdelivery
+instructions set by your system administrator;
+normally
+.I defaultdelivery
+is
+.BR ./Mailbox ,
+so
+.B qmail-local
+appends the mail message to
+.B Mailbox
+in
+.I mbox
+format.
+
+.B .qmail
+may contain extra spaces and tabs at the end of a line.
+Blank lines are allowed, but not for the first line of
+.BR .qmail .
+
+If
+.B .qmail
+is world-writable,
+.B qmail-local
+stops and indicates a temporary failure.
+.SH "SAFE QMAIL EDITING"
+Incoming messages can arrive at any moment.
+If you want to safely edit your
+.B .qmail
+file, first set the sticky bit on your home directory:
+
+.EX
+ chmod +t $HOME
+.EE
+
+.B qmail-local
+will temporarily defer delivery of any message to you
+if your home directory is sticky
+(or group-writable or other-writable,
+which should never happen).
+Make sure to
+
+.EX
+ chmod -t $HOME
+.EE
+
+when you are done!
+It's a good idea to test your new
+.B .qmail
+file as follows:
+
+.EX
+ qmail-local -n $USER ~ $USER '' '' '' '' ./Mailbox
+.EE
+.SH "EXTENSION ADDRESSES"
+In the
+.B qmail
+system,
+you control all local addresses of the form
+.IR user\fBBREAK\fIanything ,
+as well as the address
+.I user
+itself,
+where
+.I user
+is your account name.
+Delivery to
+.I user\fBBREAK\fIanything
+is controlled by the file
+.IR homedir/\fB.qmail\-\fIanything .
+(These rules may be changed by the system administrator;
+see
+.BR qmail-users (5).)
+
+The
+.B alias
+user controls all other addresses.
+Delivery to
+.I local
+is controlled by the file
+.IR homedir/\fB.qmail\-\fIlocal ,
+where
+.I homedir
+is
+.BR alias 's
+home directory.
+
+In the following description,
+.B qmail-local
+is handling a message addressed to
+.IR local@domain ,
+where
+.I local
+is controlled by
+.BR .qmail\-\fIext .
+Here is what it does.
+
+If
+.B .qmail\-\fIext
+is completely empty,
+.B qmail-local
+follows the
+.I defaultdelivery
+instructions set by your system administrator.
+
+If
+.B .qmail\-\fIext
+doesn't exist,
+.B qmail-local
+will try some default
+.B .qmail
+files.
+For example,
+if
+.I ext
+is
+.BR foo-bar ,
+.B qmail-local
+will try first
+.BR .qmail-foo-bar ,
+then
+.BR .qmail-foo-default ,
+and finally
+.BR .qmail-default .
+If none of these exist,
+.B qmail-local
+will bounce the message.
+(Exception: for the basic
+.I user
+address,
+.B qmail-local
+treats a nonexistent
+.B .qmail
+the same as an empty
+.BR .qmail .)
+
+.B WARNING:
+For security,
+.B qmail-local
+replaces any dots in
+.I ext
+with colons before checking
+.BR .qmail\-\fIext .
+For convenience,
+.B qmail-local
+converts any uppercase letters in
+.I ext
+to lowercase.
+
+When
+.B qmail-local
+forwards a message as instructed in
+.B .qmail\-\fIext
+(or
+.BR .qmail-default ),
+it checks whether
+.B .qmail\-\fIext\fB-owner\fP
+exists.
+If so,
+it uses
+.I local\fB-owner@\fIdomain
+as the envelope sender for the forwarded message.
+Otherwise it retains the envelope sender of the original message.
+Exception:
+.B qmail-local
+always retains the original envelope sender
+if it is the empty address or
+.BR #@[] ,
+i.e., if this is a bounce message.
+
+.B qmail-local
+also supports
+.B variable envelope return paths
+(VERPs):
+if
+.B .qmail\-\fIext\fB-owner\fP
+and
+.B .qmail\-\fIext\fB-owner-default\fP
+both exist, it uses
+.I local\fB\-owner\-@\fIdomain\fB-@[]
+as the envelope sender.
+This will cause a recipient
+.I recip\fB@\fIreciphost
+to see an envelope sender of
+.IR local\fB\-owner\-\fIrecip\fB=\fIreciphost\fB@\fIdomain .
+.SH "ERROR HANDLING"
+If a delivery instruction fails,
+.B qmail-local
+stops immediately and reports failure.
+.B qmail-local
+handles forwarding after all other instructions,
+so any error in another type of delivery will prevent all forwarding.
+
+If a program returns exit code 99,
+.B qmail-local
+ignores all succeeding lines in
+.BR .qmail ,
+but it still pays attention to previous forward lines.
+
+To set up independent instructions,
+where a temporary or permanent failure in one instruction
+does not affect the others,
+move each instruction into a separate
+.B .qmail\-\fIext
+file, and set up a central
+.B .qmail
+file that forwards to all of the
+.BR .qmail\-\fIext s.
+Note that
+.B qmail-local
+can handle any number of forward lines simultaneously.
+.SH "SEE ALSO"
+envelopes(5),
+maildir(5),
+mbox(5),
+qmail-users(5),
+qmail-local(8),
+qmail-command(8),
+qmail-queue(8),
+qmail-lspawn(8)
diff --git a/elq.sh b/elq.sh
new file mode 100644
index 0000000..7e20262
--- /dev/null
+++ b/elq.sh
@@ -0,0 +1 @@
+QMAIL/bin/maildir2mbox && exec elm ${1+"$@"}
diff --git a/env.3 b/env.3
new file mode 100644
index 0000000..53a5f89
--- /dev/null
+++ b/env.3
@@ -0,0 +1,31 @@
+.TH env 3
+.SH NAME
+env \- manage the environment
+.SH SYNTAX
+.B #include <env.h>
+
+char **\fBenviron\fP;
+
+char *\fBenv_get\fP(\fIname\fR);
+.br
+char *\fBenv_pick\fP();
+
+char *\fIname\fR;
+.SH DESCRIPTION
+The environment,
+.BR environ ,
+is a 0-terminated array of 0-terminated strings,
+called environment variables.
+Each environment variable is of the form
+.IR name\fB=\fIvalue .
+
+.B env_get
+returns the value of the first variable whose name is
+.IR name ,
+or 0 if there is no such variable.
+
+.B env_pick
+returns any variable in the environment,
+or 0 if the environment is empty.
+.SH "SEE ALSO"
+environ(7)
diff --git a/env.c b/env.c
new file mode 100644
index 0000000..05d527b
--- /dev/null
+++ b/env.c
@@ -0,0 +1,113 @@
+/* env.c, envread.c, env.h: environ library
+Daniel J. Bernstein, djb@silverton.berkeley.edu.
+Depends on str.h, alloc.h.
+Requires environ.
+19960113: rewrite. warning: interface is different.
+No known patent problems.
+*/
+
+#include "str.h"
+#include "alloc.h"
+#include "env.h"
+
+int env_isinit = 0; /* if env_isinit: */
+static int ea; /* environ is a pointer to ea+1 char*'s. */
+static int en; /* the first en of those are ALLOCATED. environ[en] is 0. */
+
+static void env_goodbye(i) int i;
+{
+ alloc_free(environ[i]);
+ environ[i] = environ[--en];
+ environ[en] = 0;
+}
+
+static char *null = 0;
+
+void env_clear()
+{
+ if (env_isinit) while (en) env_goodbye(0);
+ else environ = &null;
+}
+
+static void env_unsetlen(s,len) char *s; int len;
+{
+ int i;
+ for (i = en - 1;i >= 0;--i)
+ if (!str_diffn(s,environ[i],len))
+ if (environ[i][len] == '=')
+ env_goodbye(i);
+}
+
+int env_unset(s) char *s;
+{
+ if (!env_isinit) if (!env_init()) return 0;
+ env_unsetlen(s,str_len(s));
+ return 1;
+}
+
+static int env_add(s) char *s;
+{
+ char *t;
+ t = env_findeq(s);
+ if (t) env_unsetlen(s,t - s);
+ if (en == ea)
+ {
+ ea += 30;
+ if (!alloc_re(&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *)))
+ { ea = en; return 0; }
+ }
+ environ[en++] = s;
+ environ[en] = 0;
+ return 1;
+}
+
+int env_put(s) char *s;
+{
+ char *u;
+ if (!env_isinit) if (!env_init()) return 0;
+ u = alloc(str_len(s) + 1);
+ if (!u) return 0;
+ str_copy(u,s);
+ if (!env_add(u)) { alloc_free(u); return 0; }
+ return 1;
+}
+
+int env_put2(s,t) char *s; char *t;
+{
+ char *u;
+ int slen;
+ if (!env_isinit) if (!env_init()) return 0;
+ slen = str_len(s);
+ u = alloc(slen + str_len(t) + 2);
+ if (!u) return 0;
+ str_copy(u,s);
+ u[slen] = '=';
+ str_copy(u + slen + 1,t);
+ if (!env_add(u)) { alloc_free(u); return 0; }
+ return 1;
+}
+
+int env_init()
+{
+ char **newenviron;
+ int i;
+ for (en = 0;environ[en];++en) ;
+ ea = en + 10;
+ newenviron = (char **) alloc((ea + 1) * sizeof(char *));
+ if (!newenviron) return 0;
+ for (en = 0;environ[en];++en)
+ {
+ newenviron[en] = alloc(str_len(environ[en]) + 1);
+ if (!newenviron[en])
+ {
+ for (i = 0;i < en;++i) alloc_free(newenviron[i]);
+ alloc_free(newenviron);
+ return 0;
+ }
+ str_copy(newenviron[en],environ[en]);
+ }
+ newenviron[en] = 0;
+ environ = newenviron;
+ env_isinit = 1;
+ return 1;
+}
diff --git a/env.h b/env.h
new file mode 100644
index 0000000..9befc79
--- /dev/null
+++ b/env.h
@@ -0,0 +1,17 @@
+#ifndef ENV_H
+#define ENV_H
+
+extern int env_isinit;
+
+extern int env_init();
+extern int env_put();
+extern int env_put2();
+extern int env_unset();
+extern /*@null@*/char *env_get();
+extern char *env_pick();
+extern void env_clear();
+extern char *env_findeq();
+
+extern char **environ;
+
+#endif
diff --git a/envelopes.5 b/envelopes.5
new file mode 100644
index 0000000..5f7084a
--- /dev/null
+++ b/envelopes.5
@@ -0,0 +1,231 @@
+.TH envelopes 5
+.SH "NAME"
+envelopes \- sender/recipient lists attached to messages
+.SH "INTRODUCTION"
+Electronic mail messages are delivered in
+.IR envelopes .
+
+An envelope lists a
+.I sender
+and one or more
+.IR recipients .
+Usually these
+envelope addresses are the same
+as the addresses listed in the message header:
+
+.EX
+ (envelope) from djb to root
+.br
+ From: djb
+.br
+ To: root
+.EE
+
+In more complicated situations, though,
+the envelope addresses may differ from the header addresses.
+.SH "ENVELOPE EXAMPLES"
+When a message is delivered to
+several people at different locations,
+it is first photocopied
+and placed into several envelopes:
+
+.EX
+ (envelope) from djb to root
+.br
+ From: djb Copy #1 of message
+.br
+ To: root, god@brl.mil
+.EE
+
+.EX
+ (envelope) from djb to god@brl.mil
+.br
+ From: djb Copy #2 of message
+.br
+ To: root, god@brl.mil
+.EE
+
+When a message is delivered
+to several people at the same location,
+the sender doesn't have to photocopy it.
+He can instead stuff it into
+one envelope with several addresses;
+the recipients will make the photocopy:
+
+.EX
+ (envelope) from djb to god@brl.mil, angel@brl.mil
+.br
+ From: djb
+.br
+ To: god@brl.mil, angel@brl.mil, joe, frde
+.EE
+
+Bounced mail is sent back to the envelope sender address.
+The bounced mail doesn't list an envelope sender,
+so bounce loops are impossible:
+
+.EX
+ (envelope) from <> to djb
+.br
+ From: MAILER-DAEMON
+.br
+ To: djb
+.br
+ Subject: unknown user frde
+.EE
+
+The recipient of a message may make another copy
+and forward it in a new envelope:
+
+.EX
+ (envelope) from djb to joe
+.br
+ From: djb Original message
+.br
+ To: joe
+.EE
+
+.EX
+ (envelope) from joe to fred
+.br
+ From: djb Forwarded message
+.br
+ To: joe
+.EE
+
+A mailing list works almost the same way:
+
+.EX
+ (envelope) from djb to sos-list
+.br
+ From: djb Original message
+.br
+ To: sos-list
+.EE
+
+.EX
+ (envelope) from sos-owner to god@brl.mil
+.br
+ From: djb Forwarded message
+.br
+ To: sos-list to recipient #1
+.EE
+
+.EX
+ (envelope) from sos-owner to frde
+.br
+ From: djb Forwarded message
+.br
+ To: sos-list to recipient #2
+.EE
+
+Notice that the mailing list is set up
+to replace the envelope sender with something new,
+.BR sos-owner .
+So bounces will come back to
+.BR sos-owner :
+
+.EX
+ (envelope) from <> to sos-owner
+.br
+ From: MAILER-DAEMON
+.br
+ To: sos-owner
+.br
+ Subject: unknown user frde
+.EE
+
+It's a good idea to set up an extra address,
+.BR sos-owner ,
+like this:
+the original envelope sender (\fBdjb\fP)
+has no way to fix bad
+.B sos-list
+addresses,
+and of course bounces must not be sent to
+.B sos-list
+itself.
+.SH "HOW ENVELOPE ADDRESSES ARE STORED"
+Envelope sender and envelope recipient addresses
+are transmitted and recorded in several ways.
+
+When a user injects mail through
+.BR qmail-inject ,
+he can supply a
+.B Return-Path
+line or a
+.B \-f
+option for the envelope sender;
+by default the envelope sender is his login name.
+The envelope recipient addresses can be taken
+from the command line or from various header fields,
+depending on the options to
+.BR qmail-inject .
+Similar comments apply to
+.BR sendmail .
+
+When a message is transferred from one machine to another through SMTP,
+the envelope sender is given in a
+.B MAIL FROM
+command,
+the envelope recipients are given in
+.B RCPT TO
+commands,
+and the message is supplied separately by a
+.B DATA
+command.
+
+When a message is delivered by
+.B qmail
+to a single local recipient,
+.B qmail-local
+records the recipient in
+.B Delivered-To
+and the envelope sender in
+.BR Return-Path .
+It uses
+.B Delivered-To
+to detect mail forwarding loops.
+
+.B sendmail
+normally records the envelope sender in
+.BR Return-Path .
+It does not record envelope recipient addresses,
+on the theory that they are redundant:
+you received the mail,
+so you must have been one of the envelope recipients.
+
+Note that,
+if the header doesn't have any recipient addresses,
+.B sendmail
+will move envelope recipient addresses back into the header.
+This situation occurs if all addresses were originally listed as
+.BR Bcc ,
+since
+.B Bcc
+is automatically removed.
+When
+.B sendmail
+sees this, it creates a new
+.B Apparently-To
+header field with the envelope recipient addresses.
+This has the strange effect that each blind-carbon-copy recipient will see
+a list of all recipients on the same machine.
+
+When a message is stored in
+.B mbox
+format,
+the envelope sender is recorded at the top of the message
+as a UUCP-style
+.B From
+(no colon) line.
+Note that this line is less reliable than the
+.B Return-Path
+line added by
+.B qmail-local
+or
+.B sendmail\fP.
+.SH "SEE ALSO"
+qmail-header(5),
+qmail-local(8),
+qmail-inject(8)
diff --git a/envread.c b/envread.c
new file mode 100644
index 0000000..80185de
--- /dev/null
+++ b/envread.c
@@ -0,0 +1,30 @@
+#include "env.h"
+#include "str.h"
+
+extern /*@null@*/char *env_get(s)
+char *s;
+{
+ int i;
+ unsigned int slen;
+ char *envi;
+
+ slen = str_len(s);
+ for (i = 0;envi = environ[i];++i)
+ if ((!str_diffn(s,envi,slen)) && (envi[slen] == '='))
+ return envi + slen + 1;
+ return 0;
+}
+
+extern char *env_pick()
+{
+ return environ[0];
+}
+
+extern char *env_findeq(s)
+char *s;
+{
+ for (;*s;++s)
+ if (*s == '=')
+ return s;
+ return 0;
+}
diff --git a/error.3 b/error.3
new file mode 100644
index 0000000..308e43c
--- /dev/null
+++ b/error.3
@@ -0,0 +1,45 @@
+.TH error 3
+.SH NAME
+error \- syscall error codes
+.SH SYNTAX
+.B #include <error.h>
+.br
+.B #include <errno.h>
+
+extern int \fBerror_intr\fP;
+.br
+extern int \fBerror_nomem\fP;
+.br
+extern int \fBerror_noent\fP;
+.br
+extern int \fBerror_txtbsy\fP;
+.br
+extern int \fBerror_io\fP;
+.br
+extern int \fBerror_exist\fP;
+.br
+extern int \fBerror_timeout\fP;
+.br
+extern int \fBerror_inprogress\fP;
+.br
+extern int \fBerror_wouldblock\fP;
+.br
+extern int \fBerror_again\fP;
+.br
+extern int \fBerror_pipe\fP;
+.br
+extern int \fBerror_perm\fP;
+.br
+extern int \fBerror_acces\fP;
+.SH DESCRIPTION
+UNIX syscalls provide detailed error codes in the
+.B errno
+variable.
+The
+.B error
+library provides portable names for a variety of possible
+.B errno
+values.
+.SH "SEE ALSO"
+error_str(3),
+error_temp(3)
diff --git a/error.c b/error.c
new file mode 100644
index 0000000..d51304f
--- /dev/null
+++ b/error.c
@@ -0,0 +1,95 @@
+#include <errno.h>
+#include "error.h"
+
+/* warning: as coverage improves here, should update error_{str,temp} */
+
+int error_intr =
+#ifdef EINTR
+EINTR;
+#else
+-1;
+#endif
+
+int error_nomem =
+#ifdef ENOMEM
+ENOMEM;
+#else
+-2;
+#endif
+
+int error_noent =
+#ifdef ENOENT
+ENOENT;
+#else
+-3;
+#endif
+
+int error_txtbsy =
+#ifdef ETXTBSY
+ETXTBSY;
+#else
+-4;
+#endif
+
+int error_io =
+#ifdef EIO
+EIO;
+#else
+-5;
+#endif
+
+int error_exist =
+#ifdef EEXIST
+EEXIST;
+#else
+-6;
+#endif
+
+int error_timeout =
+#ifdef ETIMEDOUT
+ETIMEDOUT;
+#else
+-7;
+#endif
+
+int error_inprogress =
+#ifdef EINPROGRESS
+EINPROGRESS;
+#else
+-8;
+#endif
+
+int error_wouldblock =
+#ifdef EWOULDBLOCK
+EWOULDBLOCK;
+#else
+-9;
+#endif
+
+int error_again =
+#ifdef EAGAIN
+EAGAIN;
+#else
+-10;
+#endif
+
+int error_pipe =
+#ifdef EPIPE
+EPIPE;
+#else
+-11;
+#endif
+
+int error_perm =
+#ifdef EPERM
+EPERM;
+#else
+-12;
+#endif
+
+int error_acces =
+#ifdef EACCES
+EACCES;
+#else
+-13;
+#endif
diff --git a/error.h b/error.h
new file mode 100644
index 0000000..5d98c6b
--- /dev/null
+++ b/error.h
@@ -0,0 +1,23 @@
+#ifndef ERROR_H
+#define ERROR_H
+
+#include <errno.h>
+
+extern int error_intr;
+extern int error_nomem;
+extern int error_noent;
+extern int error_txtbsy;
+extern int error_io;
+extern int error_exist;
+extern int error_timeout;
+extern int error_inprogress;
+extern int error_wouldblock;
+extern int error_again;
+extern int error_pipe;
+extern int error_perm;
+extern int error_acces;
+
+extern char *error_str();
+extern int error_temp();
+
+#endif
diff --git a/error_str.3 b/error_str.3
new file mode 100644
index 0000000..62043c4
--- /dev/null
+++ b/error_str.3
@@ -0,0 +1,19 @@
+.TH error_str 3
+.SH NAME
+error_str \- names for syscall error codes
+.SH SYNTAX
+.B #include <error.h>
+
+char *\fBerror_str\fP(\fIe\fR);
+
+int \fIe\fR;
+.SH DESCRIPTION
+.B error_str
+returns a printable string describing syscall error code
+.IR e .
+Normally
+.I e
+is
+.BR errno .
+.SH "SEE ALSO"
+error(3)
diff --git a/error_str.c b/error_str.c
new file mode 100644
index 0000000..804d1fa
--- /dev/null
+++ b/error_str.c
@@ -0,0 +1,276 @@
+#include <errno.h>
+#include "error.h"
+
+#define X(e,s) if (i == e) return s;
+
+char *error_str(i)
+int i;
+{
+ X(0,"no error")
+ X(error_intr,"interrupted system call")
+ X(error_nomem,"out of memory")
+ X(error_noent,"file does not exist")
+ X(error_txtbsy,"text busy")
+ X(error_io,"input/output error")
+ X(error_exist,"file already exists")
+ X(error_timeout,"timed out")
+ X(error_inprogress,"operation in progress")
+ X(error_again,"temporary failure")
+ X(error_wouldblock,"input/output would block")
+ X(error_pipe,"broken pipe")
+ X(error_perm,"permission denied")
+ X(error_acces,"access denied")
+#ifdef ESRCH
+ X(ESRCH,"no such process")
+#endif
+#ifdef ENXIO
+ X(ENXIO,"device not configured")
+#endif
+#ifdef E2BIG
+ X(E2BIG,"argument list too long")
+#endif
+#ifdef ENOEXEC
+ X(ENOEXEC,"exec format error")
+#endif
+#ifdef EBADF
+ X(EBADF,"file descriptor not open")
+#endif
+#ifdef ECHILD
+ X(ECHILD,"no child processes")
+#endif
+#ifdef EDEADLK
+ X(EDEADLK,"operation would cause deadlock")
+#endif
+#ifdef EFAULT
+ X(EFAULT,"bad address")
+#endif
+#ifdef ENOTBLK
+ X(ENOTBLK,"not a block device")
+#endif
+#ifdef EBUSY
+ X(EBUSY,"device busy")
+#endif
+#ifdef EXDEV
+ X(EXDEV,"cross-device link")
+#endif
+#ifdef ENODEV
+ X(ENODEV,"device does not support operation")
+#endif
+#ifdef ENOTDIR
+ X(ENOTDIR,"not a directory")
+#endif
+#ifdef EISDIR
+ X(EISDIR,"is a directory")
+#endif
+#ifdef EINVAL
+ X(EINVAL,"invalid argument")
+#endif
+#ifdef ENFILE
+ X(ENFILE,"system cannot open more files")
+#endif
+#ifdef EMFILE
+ X(EMFILE,"process cannot open more files")
+#endif
+#ifdef ENOTTY
+ X(ENOTTY,"not a tty")
+#endif
+#ifdef EFBIG
+ X(EFBIG,"file too big")
+#endif
+#ifdef ENOSPC
+ X(ENOSPC,"out of disk space")
+#endif
+#ifdef ESPIPE
+ X(ESPIPE,"unseekable descriptor")
+#endif
+#ifdef EROFS
+ X(EROFS,"read-only file system")
+#endif
+#ifdef EMLINK
+ X(EMLINK,"too many links")
+#endif
+#ifdef EDOM
+ X(EDOM,"input out of range")
+#endif
+#ifdef ERANGE
+ X(ERANGE,"output out of range")
+#endif
+#ifdef EALREADY
+ X(EALREADY,"operation already in progress")
+#endif
+#ifdef ENOTSOCK
+ X(ENOTSOCK,"not a socket")
+#endif
+#ifdef EDESTADDRREQ
+ X(EDESTADDRREQ,"destination address required")
+#endif
+#ifdef EMSGSIZE
+ X(EMSGSIZE,"message too long")
+#endif
+#ifdef EPROTOTYPE
+ X(EPROTOTYPE,"incorrect protocol type")
+#endif
+#ifdef ENOPROTOOPT
+ X(ENOPROTOOPT,"protocol not available")
+#endif
+#ifdef EPROTONOSUPPORT
+ X(EPROTONOSUPPORT,"protocol not supported")
+#endif
+#ifdef ESOCKTNOSUPPORT
+ X(ESOCKTNOSUPPORT,"socket type not supported")
+#endif
+#ifdef EOPNOTSUPP
+ X(EOPNOTSUPP,"operation not supported")
+#endif
+#ifdef EPFNOSUPPORT
+ X(EPFNOSUPPORT,"protocol family not supported")
+#endif
+#ifdef EAFNOSUPPORT
+ X(EAFNOSUPPORT,"address family not supported")
+#endif
+#ifdef EADDRINUSE
+ X(EADDRINUSE,"address already used")
+#endif
+#ifdef EADDRNOTAVAIL
+ X(EADDRNOTAVAIL,"address not available")
+#endif
+#ifdef ENETDOWN
+ X(ENETDOWN,"network down")
+#endif
+#ifdef ENETUNREACH
+ X(ENETUNREACH,"network unreachable")
+#endif
+#ifdef ENETRESET
+ X(ENETRESET,"network reset")
+#endif
+#ifdef ECONNABORTED
+ X(ECONNABORTED,"connection aborted")
+#endif
+#ifdef ECONNRESET
+ X(ECONNRESET,"connection reset")
+#endif
+#ifdef ENOBUFS
+ X(ENOBUFS,"out of buffer space")
+#endif
+#ifdef EISCONN
+ X(EISCONN,"already connected")
+#endif
+#ifdef ENOTCONN
+ X(ENOTCONN,"not connected")
+#endif
+#ifdef ESHUTDOWN
+ X(ESHUTDOWN,"socket shut down")
+#endif
+#ifdef ETOOMANYREFS
+ X(ETOOMANYREFS,"too many references")
+#endif
+#ifdef ECONNREFUSED
+ X(ECONNREFUSED,"connection refused")
+#endif
+#ifdef ELOOP
+ X(ELOOP,"symbolic link loop")
+#endif
+#ifdef ENAMETOOLONG
+ X(ENAMETOOLONG,"file name too long")
+#endif
+#ifdef EHOSTDOWN
+ X(EHOSTDOWN,"host down")
+#endif
+#ifdef EHOSTUNREACH
+ X(EHOSTUNREACH,"host unreachable")
+#endif
+#ifdef ENOTEMPTY
+ X(ENOTEMPTY,"directory not empty")
+#endif
+#ifdef EPROCLIM
+ X(EPROCLIM,"too many processes")
+#endif
+#ifdef EUSERS
+ X(EUSERS,"too many users")
+#endif
+#ifdef EDQUOT
+ X(EDQUOT,"disk quota exceeded")
+#endif
+#ifdef ESTALE
+ X(ESTALE,"stale NFS file handle")
+#endif
+#ifdef EREMOTE
+ X(EREMOTE,"too many levels of remote in path")
+#endif
+#ifdef EBADRPC
+ X(EBADRPC,"RPC structure is bad")
+#endif
+#ifdef ERPCMISMATCH
+ X(ERPCMISMATCH,"RPC version mismatch")
+#endif
+#ifdef EPROGUNAVAIL
+ X(EPROGUNAVAIL,"RPC program unavailable")
+#endif
+#ifdef EPROGMISMATCH
+ X(EPROGMISMATCH,"program version mismatch")
+#endif
+#ifdef EPROCUNAVAIL
+ X(EPROCUNAVAIL,"bad procedure for program")
+#endif
+#ifdef ENOLCK
+ X(ENOLCK,"no locks available")
+#endif
+#ifdef ENOSYS
+ X(ENOSYS,"system call not available")
+#endif
+#ifdef EFTYPE
+ X(EFTYPE,"bad file type")
+#endif
+#ifdef EAUTH
+ X(EAUTH,"authentication error")
+#endif
+#ifdef ENEEDAUTH
+ X(ENEEDAUTH,"not authenticated")
+#endif
+#ifdef ENOSTR
+ X(ENOSTR,"not a stream device")
+#endif
+#ifdef ETIME
+ X(ETIME,"timer expired")
+#endif
+#ifdef ENOSR
+ X(ENOSR,"out of stream resources")
+#endif
+#ifdef ENOMSG
+ X(ENOMSG,"no message of desired type")
+#endif
+#ifdef EBADMSG
+ X(EBADMSG,"bad message type")
+#endif
+#ifdef EIDRM
+ X(EIDRM,"identifier removed")
+#endif
+#ifdef ENONET
+ X(ENONET,"machine not on network")
+#endif
+#ifdef ERREMOTE
+ X(ERREMOTE,"object not local")
+#endif
+#ifdef ENOLINK
+ X(ENOLINK,"link severed")
+#endif
+#ifdef EADV
+ X(EADV,"advertise error")
+#endif
+#ifdef ESRMNT
+ X(ESRMNT,"srmount error")
+#endif
+#ifdef ECOMM
+ X(ECOMM,"communication error")
+#endif
+#ifdef EPROTO
+ X(EPROTO,"protocol error")
+#endif
+#ifdef EMULTIHOP
+ X(EMULTIHOP,"multihop attempted")
+#endif
+#ifdef EREMCHG
+ X(EREMCHG,"remote address changed")
+#endif
+ return "unknown error";
+}
diff --git a/error_temp.3 b/error_temp.3
new file mode 100644
index 0000000..2f8229d
--- /dev/null
+++ b/error_temp.3
@@ -0,0 +1,27 @@
+.TH error_temp 3
+.SH NAME
+error_temp \- identify soft syscall error codes
+.SH SYNTAX
+.B #include <error.h>
+
+int \fBerror_temp\fP(\fIe\fR);
+
+int \fIe\fR;
+.SH DESCRIPTION
+.B error_temp
+returns 1 if syscall error code
+.I e
+is a soft error, 0 if it is a hard error.
+Normally
+.I e
+is
+.BR errno .
+
+A hard error is persistent:
+file not found, read-only file system, symbolic link loop, etc.
+
+A soft error is usually transient:
+out of memory, out of disk space, I/O error, disk quota exceeded,
+connection refused, host unreachable, etc.
+.SH "SEE ALSO"
+error(3)
diff --git a/error_temp.c b/error_temp.c
new file mode 100644
index 0000000..6782cef
--- /dev/null
+++ b/error_temp.c
@@ -0,0 +1,80 @@
+#include <errno.h>
+#include "error.h"
+
+#define X(n) if (e == n) return 1;
+
+int error_temp(e)
+int e;
+{
+ X(error_intr)
+ X(error_nomem)
+ X(error_txtbsy)
+ X(error_io)
+ X(error_timeout)
+ X(error_wouldblock)
+ X(error_again)
+#ifdef EDEADLK
+ X(EDEADLK)
+#endif
+#ifdef EBUSY
+ X(EBUSY)
+#endif
+#ifdef ENFILE
+ X(ENFILE)
+#endif
+#ifdef EMFILE
+ X(EMFILE)
+#endif
+#ifdef EFBIG
+ X(EFBIG)
+#endif
+#ifdef ENOSPC
+ X(ENOSPC)
+#endif
+#ifdef ENETDOWN
+ X(ENETDOWN)
+#endif
+#ifdef ENETUNREACH
+ X(ENETUNREACH)
+#endif
+#ifdef ENETRESET
+ X(ENETRESET)
+#endif
+#ifdef ECONNABORTED
+ X(ECONNABORTED)
+#endif
+#ifdef ECONNRESET
+ X(ECONNRESET)
+#endif
+#ifdef ENOBUFS
+ X(ENOBUFS)
+#endif
+#ifdef ETOOMANYREFS
+ X(ETOOMANYREFS)
+#endif
+#ifdef ECONNREFUSED
+ X(ECONNREFUSED)
+#endif
+#ifdef EHOSTDOWN
+ X(EHOSTDOWN)
+#endif
+#ifdef EHOSTUNREACH
+ X(EHOSTUNREACH)
+#endif
+#ifdef EPROCLIM
+ X(EPROCLIM)
+#endif
+#ifdef EUSERS
+ X(EUSERS)
+#endif
+#ifdef EDQUOT
+ X(EDQUOT)
+#endif
+#ifdef ESTALE
+ X(ESTALE)
+#endif
+#ifdef ENOLCK
+ X(ENOLCK)
+#endif
+ return 0;
+}
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/exit.h b/exit.h
new file mode 100644
index 0000000..39011c8
--- /dev/null
+++ b/exit.h
@@ -0,0 +1,6 @@
+#ifndef EXIT_H
+#define EXIT_H
+
+extern void _exit();
+
+#endif
diff --git a/extra.h b/extra.h
new file mode 100644
index 0000000..c598175
--- /dev/null
+++ b/extra.h
@@ -0,0 +1,7 @@
+#ifndef EXTRA_H
+#define EXTRA_H
+
+#define QUEUE_EXTRA ""
+#define QUEUE_EXTRALEN 0
+
+#endif
diff --git a/fd.h b/fd.h
new file mode 100644
index 0000000..c3d6e3e
--- /dev/null
+++ b/fd.h
@@ -0,0 +1,7 @@
+#ifndef FD_H
+#define FD_H
+
+extern int fd_copy();
+extern int fd_move();
+
+#endif
diff --git a/fd_copy.3 b/fd_copy.3
new file mode 100644
index 0000000..758a7e7
--- /dev/null
+++ b/fd_copy.3
@@ -0,0 +1,44 @@
+.TH fd_copy 3
+.SH NAME
+fd_copy \- duplicate a descriptor
+.SH SYNTAX
+.B #include <fd.h>
+
+int \fBfd_copy\fP(\fIto\fR,\fIfrom\fR);
+
+int \fIto\fR;
+.br
+int \fIfrom\fR;
+.SH DESCRIPTION
+.B fd_copy
+copies
+descriptor
+.I from
+to descriptor
+.IR to .
+If
+.I to
+was already open,
+.B fd_copy
+closes it.
+.B fd_copy
+always leaves
+.I from
+intact;
+if
+.I to
+and
+.I from
+are the same number,
+.B fd_copy
+does nothing.
+
+.B fd_copy
+returns 0 on success, -1 on error.
+.B fd_copy
+does not guarantee that
+.I to
+will remain open, if it was open, in case of error.
+.SH "SEE ALSO"
+dup(2),
+fd_move(3)
diff --git a/fd_copy.c b/fd_copy.c
new file mode 100644
index 0000000..b9f7167
--- /dev/null
+++ b/fd_copy.c
@@ -0,0 +1,13 @@
+#include <fcntl.h>
+#include "fd.h"
+
+int fd_copy(to,from)
+int to;
+int from;
+{
+ if (to == from) return 0;
+ if (fcntl(from,F_GETFL,0) == -1) return -1;
+ close(to);
+ if (fcntl(from,F_DUPFD,to) == -1) return -1;
+ return 0;
+}
diff --git a/fd_move.3 b/fd_move.3
new file mode 100644
index 0000000..94aa1b7
--- /dev/null
+++ b/fd_move.3
@@ -0,0 +1,41 @@
+.TH fd_move 3
+.SH NAME
+fd_move \- renumber a descriptor
+.SH SYNTAX
+.B #include <fd.h>
+
+int \fBfd_move\fP(\fIto\fR,\fIfrom\fR);
+
+int \fIto\fR;
+.br
+int \fIfrom\fR;
+.SH DESCRIPTION
+.B fd_move
+moves
+descriptor
+.I from
+to descriptor
+.IR to .
+If
+.I to
+was already open,
+.B fd_move
+closes it.
+If the move is successful,
+.B fd_move
+closes
+.IR from .
+Exception:
+if
+.I to
+and
+.I from
+are the same number,
+.B fd_move
+does nothing.
+
+.B fd_move
+returns 0 on success, -1 on error.
+.SH "SEE ALSO"
+dup(2),
+fd_copy(3)
diff --git a/fd_move.c b/fd_move.c
new file mode 100644
index 0000000..1aa557f
--- /dev/null
+++ b/fd_move.c
@@ -0,0 +1,11 @@
+#include "fd.h"
+
+int fd_move(to,from)
+int to;
+int from;
+{
+ if (to == from) return 0;
+ if (fd_copy(to,from) == -1) return -1;
+ close(from);
+ return 0;
+}
diff --git a/fifo.c b/fifo.c
new file mode 100644
index 0000000..1f3d150
--- /dev/null
+++ b/fifo.c
@@ -0,0 +1,10 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "hasmkffo.h"
+#include "fifo.h"
+
+#ifdef HASMKFIFO
+int fifo_make(fn,mode) char *fn; int mode; { return mkfifo(fn,mode); }
+#else
+int fifo_make(fn,mode) char *fn; int mode; { return mknod(fn,S_IFIFO | mode,0); }
+#endif
diff --git a/fifo.h b/fifo.h
new file mode 100644
index 0000000..2c5469b
--- /dev/null
+++ b/fifo.h
@@ -0,0 +1,6 @@
+#ifndef FIFO_H
+#define FIFO_H
+
+extern int fifo_make();
+
+#endif
diff --git a/fifo_make.3 b/fifo_make.3
new file mode 100644
index 0000000..489233d
--- /dev/null
+++ b/fifo_make.3
@@ -0,0 +1,24 @@
+.TH fifo_make 3
+.SH NAME
+fifo_make \- create a named pipe
+.SH SYNTAX
+.B #include <fifo.h>
+
+int \fBfifo_make\fP(\fIfn\fR,\fImode\fR);
+
+char *\fIfn\fR;
+.br
+int \fImode\fR;
+.SH DESCRIPTION
+.B fifo_make
+creates a new named pipe
+with name
+.I fn
+and mode
+.I mode
+(modified by the process umask).
+
+.B fifo_make
+returns 0 on success, -1 on error.
+.SH "SEE ALSO"
+mkfifo(2)
diff --git a/find-systype.sh b/find-systype.sh
new file mode 100644
index 0000000..16266d3
--- /dev/null
+++ b/find-systype.sh
@@ -0,0 +1,144 @@
+# oper-:arch-:syst-:chip-:kern-
+# oper = operating system type; e.g., sunos-4.1.4
+# arch = machine language; e.g., sparc
+# syst = which binaries can run; e.g., sun4
+# chip = chip model; e.g., micro-2-80
+# kern = kernel version; e.g., sun4m
+# dependence: arch --- chip
+# \ \
+# oper --- syst --- kern
+# so, for example, syst is interpreted in light of oper, but chip is not.
+# anyway, no slashes, no extra colons, no uppercase letters.
+# the point of the extra -'s is to ease parsing: can add hierarchies later.
+# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium,
+# and i386-486 (486s do have more instructions, you know) as well as i386.
+# the idea here is to include ALL useful available information.
+
+exec 2>/dev/null
+sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`"
+if [ x"$sys" != x ]
+then
+ unamer="`uname -r | tr /: ..`"
+ unamem="`uname -m | tr /: ..`"
+ unamev="`uname -v | tr /: ..`"
+
+ case "$sys" in
+ bsd.os)
+ # in bsd 4.4, uname -v does not have useful info.
+ # in bsd 4.4, uname -m is arch, not chip.
+ oper="$sys-$unamer"
+ arch="$unamem"
+ syst=""
+ chip="`sysctl -n hw.model`"
+ kern=""
+ ;;
+ freebsd)
+ # see above about bsd 4.4
+ oper="$sys-$unamer"
+ arch="$unamem"
+ syst=""
+ chip="`sysctl -n hw.model`" # hopefully
+ kern=""
+ ;;
+ netbsd)
+ # see above about bsd 4.4
+ oper="$sys-$unamer"
+ arch="$unamem"
+ syst=""
+ chip="`sysctl -n hw.model`" # hopefully
+ kern=""
+ ;;
+ linux)
+ # as in bsd 4.4, uname -v does not have useful info.
+ oper="$sys-$unamer"
+ syst=""
+ chip="$unamem"
+ kern=""
+ case "$chip" in
+ i386|i486|i586|i686)
+ arch="i386"
+ ;;
+ alpha)
+ arch="alpha"
+ ;;
+ esac
+ ;;
+ aix)
+ # naturally IBM has to get uname -r and uname -v backwards. dorks.
+ oper="$sys-$unamev-$unamer"
+ arch="`arch | tr /: ..`"
+ syst=""
+ chip="$unamem"
+ kern=""
+ ;;
+ sunos)
+ oper="$sys-$unamer-$unamev"
+ arch="`(uname -p || mach) | tr /: ..`"
+ syst="`arch | tr /: ..`"
+ chip="$unamem" # this is wrong; is there any way to get the real info?
+ kern="`arch -k | tr /: ..`"
+ ;;
+ unix_sv)
+ oper="$sys-$unamer-$unamev"
+ arch="`uname -m`"
+ syst=""
+ chip="$unamem"
+ kern=""
+ ;;
+ *)
+ oper="$sys-$unamer-$unamev"
+ arch="`arch | tr /: ..`"
+ syst=""
+ chip="$unamem"
+ kern=""
+ ;;
+ esac
+else
+ $CC -c trycpp.c
+ $LD -o trycpp trycpp.o
+ case `./trycpp` in
+ nextstep)
+ oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`"
+ arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`"
+ syst=""
+ chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`"
+ kern=""
+ ;;
+ *)
+ oper="unknown"
+ arch=""
+ syst=""
+ chip=""
+ kern=""
+ ;;
+ esac
+ rm -f trycpp.o trycpp
+fi
+
+case "$chip" in
+80486)
+ # let's try to be consistent here. (BSD/OS)
+ chip=i486
+ ;;
+i486DX)
+ # respect the hyphen hierarchy. (FreeBSD)
+ chip=i486-dx
+ ;;
+i486.DX2)
+ # respect the hyphen hierarchy. (FreeBSD)
+ chip=i486-dx2
+ ;;
+Intel.586)
+ # no, you nitwits, there is no such chip. (NeXTStep)
+ chip=pentium
+ ;;
+i586)
+ # no, you nitwits, there is no such chip. (Linux)
+ chip=pentium
+ ;;
+i686)
+ # STOP SAYING THAT! (Linux)
+ chip=ppro
+esac
+
+echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]'
diff --git a/fmt.h b/fmt.h
new file mode 100644
index 0000000..ba2fe16
--- /dev/null
+++ b/fmt.h
@@ -0,0 +1,25 @@
+#ifndef FMT_H
+#define FMT_H
+
+#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */
+#define FMT_LEN ((char *) 0) /* convenient abbreviation */
+
+extern unsigned int fmt_uint();
+extern unsigned int fmt_uint0();
+extern unsigned int fmt_xint();
+extern unsigned int fmt_nbbint();
+extern unsigned int fmt_ushort();
+extern unsigned int fmt_xshort();
+extern unsigned int fmt_nbbshort();
+extern unsigned int fmt_ulong();
+extern unsigned int fmt_xlong();
+extern unsigned int fmt_nbblong();
+
+extern unsigned int fmt_plusminus();
+extern unsigned int fmt_minus();
+extern unsigned int fmt_0x();
+
+extern unsigned int fmt_str();
+extern unsigned int fmt_strn();
+
+#endif
diff --git a/fmt_str.c b/fmt_str.c
new file mode 100644
index 0000000..48930cf
--- /dev/null
+++ b/fmt_str.c
@@ -0,0 +1,12 @@
+#include "fmt.h"
+
+unsigned int fmt_str(s,t)
+register char *s; register char *t;
+{
+ register unsigned int len;
+ char ch;
+ len = 0;
+ if (s) { while (ch = t[len]) s[len++] = ch; }
+ else while (t[len]) len++;
+ return len;
+}
diff --git a/fmt_strn.c b/fmt_strn.c
new file mode 100644
index 0000000..3ef58a6
--- /dev/null
+++ b/fmt_strn.c
@@ -0,0 +1,12 @@
+#include "fmt.h"
+
+unsigned int fmt_strn(s,t,n)
+register char *s; register char *t; register unsigned int n;
+{
+ register unsigned int len;
+ char ch;
+ len = 0;
+ if (s) { while (n-- && (ch = t[len])) s[len++] = ch; }
+ else while (n-- && t[len]) len++;
+ return len;
+}
diff --git a/fmt_uint.c b/fmt_uint.c
new file mode 100644
index 0000000..8595be8
--- /dev/null
+++ b/fmt_uint.c
@@ -0,0 +1,6 @@
+#include "fmt.h"
+
+unsigned int fmt_uint(s,u) register char *s; register unsigned int u;
+{
+ register unsigned long l; l = u; return fmt_ulong(s,l);
+}
diff --git a/fmt_uint0.c b/fmt_uint0.c
new file mode 100644
index 0000000..81705f6
--- /dev/null
+++ b/fmt_uint0.c
@@ -0,0 +1,10 @@
+#include "fmt.h"
+
+unsigned int fmt_uint0(s,u,n) char *s; unsigned int u; unsigned int n;
+{
+ unsigned int len;
+ len = fmt_uint(FMT_LEN,u);
+ while (len < n) { if (s) *s++ = '0'; ++len; }
+ if (s) fmt_uint(s,u);
+ return len;
+}
diff --git a/fmt_ulong.c b/fmt_ulong.c
new file mode 100644
index 0000000..ab12e8c
--- /dev/null
+++ b/fmt_ulong.c
@@ -0,0 +1,13 @@
+#include "fmt.h"
+
+unsigned int fmt_ulong(s,u) register char *s; register unsigned long u;
+{
+ register unsigned int len; register unsigned long q;
+ len = 1; q = u;
+ while (q > 9) { ++len; q /= 10; }
+ if (s) {
+ s += len;
+ do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */
+ }
+ return len;
+}
diff --git a/fmtqfn.c b/fmtqfn.c
new file mode 100644
index 0000000..6229b4a
--- /dev/null
+++ b/fmtqfn.c
@@ -0,0 +1,24 @@
+#include "fmtqfn.h"
+#include "fmt.h"
+#include "auto_split.h"
+
+unsigned int fmtqfn(s,dirslash,id,flagsplit)
+char *s;
+char *dirslash;
+unsigned long id;
+int flagsplit;
+{
+ unsigned int len;
+ unsigned int i;
+
+ len = 0;
+ i = fmt_str(s,dirslash); len += i; if (s) s += i;
+ if (flagsplit)
+ {
+ i = fmt_ulong(s,id % auto_split); len += i; if (s) s += i;
+ i = fmt_str(s,"/"); len += i; if (s) s += i;
+ }
+ i = fmt_ulong(s,id); len += i; if (s) s += i;
+ if (s) *s++ = 0; ++len;
+ return len;
+}
diff --git a/fmtqfn.h b/fmtqfn.h
new file mode 100644
index 0000000..a449aa1
--- /dev/null
+++ b/fmtqfn.h
@@ -0,0 +1,8 @@
+#ifndef FMTQFN_H
+#define FMTQFN_H
+
+extern unsigned int fmtqfn();
+
+#define FMTQFN 40 /* maximum space needed, if len(dirslash) <= 10 */
+
+#endif
diff --git a/forgeries.7 b/forgeries.7
new file mode 100644
index 0000000..cb99fa7
--- /dev/null
+++ b/forgeries.7
@@ -0,0 +1,104 @@
+.TH forgeries 7
+.SH "NAME"
+forgeries \- how easy it is to forge mail
+.SH "SUMMARY"
+An electronic mail message can easily be forged.
+Almost everything in it,
+including the return address,
+is completely under the control of the sender.
+
+An electronic mail message can be manually traced to its origin
+if (1) all system administrators of intermediate machines
+are both cooperative and competent,
+(2) the sender did not break low-level TCP/IP security,
+and
+(3) all intermediate machines are secure.
+
+Users of
+.I cryptography
+can automatically ensure the integrity and secrecy
+of their mail messages, as long as
+the sending and receiving machines are secure.
+.SH "FORGERIES"
+Like postal mail,
+electronic mail can be created entirely at the whim of the sender.
+.BR From ,
+.BR Sender ,
+.BR Return-Path ,
+and
+.BR Message-ID
+can all contain whatever information the sender wants.
+
+For example, if you inject a message through
+.B sendmail
+or
+.B qmail-inject
+or
+.BR SMTP ,
+you can simply type in a
+.B From
+field.
+In fact,
+.B qmail-inject
+lets you set up
+.BR MAILUSER ,
+.BR MAILHOST ,
+and
+.B MAILNAME
+environment variables
+to produce your desired
+.B From
+field on every message.
+.SH "TRACING FORGERIES"
+Like postal mail,
+electronic mail is postmarked when it is sent.
+Each machine that receives an electronic mail message
+adds a
+.B Received
+line to the top.
+
+A modern
+.B Received
+line contains quite a bit of information.
+In conjunction with the machine's logs,
+it lets a competent system administrator
+determine where the machine received the message from,
+as long as the sender did not break low-level TCP/IP security
+or security on that machine.
+
+Large multi-user machines often come with inadequate logging software.
+Fortunately, a system administrator can easily obtain a copy of a
+931/1413/Ident/TAP server, such as
+.BR pidentd .
+Unfortunately,
+some system administrators fail to do this,
+and are thus unable to figure out which local user
+was responsible for generating a message.
+
+If all intermediate system administrators are competent,
+and the sender did not break machine security or low-level TCP/IP security,
+it is possible to trace a message backwards.
+Unfortunately, some traces are stymied by intermediate system
+administrators who are uncooperative or untrustworthy.
+.SH "CRYPTOGRAPHY"
+The sender of a mail message may place his message into a
+.I cryptographic
+envelope stamped with his seal.
+Strong cryptography guarantees that any two messages with the same seal
+were sent by the same cryptographic entity:
+perhaps a single person, perhaps a group of cooperating people,
+but in any case somebody who knows a secret originally held
+only by the creator of the seal.
+The seal is called a
+.I public key\fR.
+
+Unfortunately, the creator of the seal is often an insecure machine,
+or an untrustworthy central agency,
+but most of the time seals are kept secure.
+
+One popular cryptographic program is
+.BR pgp .
+.SH "SEE ALSO"
+pgp(1),
+identd(8),
+qmail-header(8)
diff --git a/fork.h1 b/fork.h1
new file mode 100644
index 0000000..b786255
--- /dev/null
+++ b/fork.h1
@@ -0,0 +1,7 @@
+#ifndef FORK_H
+#define FORK_H
+
+extern int fork();
+#define vfork fork
+
+#endif
diff --git a/fork.h2 b/fork.h2
new file mode 100644
index 0000000..41773b6
--- /dev/null
+++ b/fork.h2
@@ -0,0 +1,7 @@
+#ifndef FORK_H
+#define FORK_H
+
+extern int fork();
+extern int vfork();
+
+#endif
diff --git a/forward.1 b/forward.1
new file mode 100644
index 0000000..d0a7f95
--- /dev/null
+++ b/forward.1
@@ -0,0 +1,24 @@
+.TH forward 1
+.SH NAME
+forward \- forward new mail to one or more addresses
+.SH SYNOPSIS
+in
+.BR .qmail :
+.B |forward
+.I address ...
+.SH DESCRIPTION
+.B forward
+forwards each new mail message to the specified list of addresses.
+It is a simple wrapper around
+.BR qmail-queue .
+It achieves the same results as listing each
+.I address
+separately in
+.BR .qmail ,
+but it is more programmable since
+.I address
+can be constructed on the fly.
+.SH "SEE ALSO"
+dot-qmail(5),
+qmail-command(8),
+qmail-queue(8)
diff --git a/forward.c b/forward.c
new file mode 100644
index 0000000..e7390aa
--- /dev/null
+++ b/forward.c
@@ -0,0 +1,60 @@
+#include "sig.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "env.h"
+#include "qmail.h"
+#include "strerr.h"
+#include "substdio.h"
+#include "fmt.h"
+
+#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;
+}
+
+char inbuf[SUBSTDIO_INSIZE];
+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;
+ 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/gen_alloc.h b/gen_alloc.h
new file mode 100644
index 0000000..b94a956
--- /dev/null
+++ b/gen_alloc.h
@@ -0,0 +1,7 @@
+#ifndef GEN_ALLOC_H
+#define GEN_ALLOC_H
+
+#define GEN_ALLOC_typedef(ta,type,field,len,a) \
+ typedef struct ta { type *field; unsigned int len; unsigned int a; } ta;
+
+#endif
diff --git a/gen_allocdefs.h b/gen_allocdefs.h
new file mode 100644
index 0000000..783a9b1
--- /dev/null
+++ b/gen_allocdefs.h
@@ -0,0 +1,34 @@
+#ifndef GEN_ALLOC_DEFS_H
+#define GEN_ALLOC_DEFS_H
+
+#define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \
+int ta_ready(x,n) register ta *x; register unsigned int n; \
+{ register unsigned int i; \
+ if (x->field) { \
+ i = x->a; \
+ if (n > i) { \
+ x->a = base + n + (n >> 3); \
+ if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \
+ x->a = i; return 0; } \
+ return 1; } \
+ x->len = 0; \
+ return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); }
+
+#define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \
+int ta_rplus(x,n) register ta *x; register unsigned int n; \
+{ register unsigned int i; \
+ if (x->field) { \
+ i = x->a; n += x->len; \
+ if (n > i) { \
+ x->a = base + n + (n >> 3); \
+ if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \
+ x->a = i; return 0; } \
+ return 1; } \
+ x->len = 0; \
+ return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); }
+
+#define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \
+int ta_append(x,i) register ta *x; register type *i; \
+{ if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; }
+
+#endif
diff --git a/getln.3 b/getln.3
new file mode 100644
index 0000000..ffe1953
--- /dev/null
+++ b/getln.3
@@ -0,0 +1,51 @@
+.TH getln 3
+.SH NAME
+getln \- read one line of data
+.SH SYNTAX
+.B #include <getln.h>
+
+int \fBgetln\fP(&\fIss\fR,&\fIsa\fR,&\fImatch\fR,\fIsep\fR);
+
+substdio \fIss\fR;
+.br
+stralloc \fIsa\fR;
+.br
+int \fImatch\fR;
+.br
+int \fIsep\fR;
+.SH DESCRIPTION
+.B getln
+reads a line of characters, terminated by a
+.I sep
+character,
+from
+.IR ss .
+It returns the line in
+.I sa
+and sets
+.I match
+to 1.
+
+If
+.B getln
+sees end-of-input before it sees
+.IR sep ,
+it returns the partial line in
+.I sa
+and sets
+.I match
+to 0.
+
+.B getln
+normally returns 0.
+If it runs out of memory,
+or encounters an error from
+.IR ss ,
+it returns -1,
+setting
+.B errno
+appropriately.
+.SH "SEE ALSO"
+stralloc(3),
+substdio(3),
+getln2(3)
diff --git a/getln.c b/getln.c
new file mode 100644
index 0000000..c5cb097
--- /dev/null
+++ b/getln.c
@@ -0,0 +1,20 @@
+#include "substdio.h"
+#include "byte.h"
+#include "stralloc.h"
+#include "getln.h"
+
+int getln(ss,sa,match,sep)
+register substdio *ss;
+register stralloc *sa;
+int *match;
+int sep;
+{
+ char *cont;
+ unsigned int clen;
+
+ if (getln2(ss,sa,&cont,&clen,sep) == -1) return -1;
+ if (!clen) { *match = 0; return 0; }
+ if (!stralloc_catb(sa,cont,clen)) return -1;
+ *match = 1;
+ return 0;
+}
diff --git a/getln.h b/getln.h
new file mode 100644
index 0000000..cf4f934
--- /dev/null
+++ b/getln.h
@@ -0,0 +1,7 @@
+#ifndef GETLN_H
+#define GETLN_H
+
+extern int getln();
+extern int getln2();
+
+#endif
diff --git a/getln2.3 b/getln2.3
new file mode 100644
index 0000000..f95105a
--- /dev/null
+++ b/getln2.3
@@ -0,0 +1,64 @@
+.TH getln2 3
+.SH NAME
+getln2 \- read one line of data
+.SH SYNTAX
+.B #include <getln.h>
+
+int \fBgetln2\fP(&\fIss\fR,&\fIsa\fR,&\fIcont\fR,&\fIclen\fR,\fIsep\fR);
+
+substdio \fIss\fR;
+.br
+stralloc \fIsa\fR;
+.br
+char *\fIcont\fR;
+.br
+unsigned int \fIclen\fR;
+.br
+int \fIsep\fR;
+.SH DESCRIPTION
+.B getln2
+reads a line of characters, terminated by a
+.I sep
+character,
+from
+.IR ss .
+
+The line is returned in two pieces.
+The first piece is stored in
+.IR sa .
+The second piece is
+.IR cont ,
+a pointer to
+.I clen
+characters inside the
+.I ss
+buffer.
+The second piece must be copied somewhere else
+before
+.I ss
+is used again.
+
+If
+.B getln2
+sees end-of-input before it sees
+.IR sep ,
+it sets
+.I clen
+to 0 and does not set
+.IR cont .
+It puts the partial line into
+.IR sa .
+
+.B getln2
+normally returns 0.
+If it runs out of memory,
+or encounters an error from
+.IR ss ,
+it returns -1,
+setting
+.B errno
+appropriately.
+.SH "SEE ALSO"
+stralloc(3),
+substdio(3),
+getln(3)
diff --git a/getln2.c b/getln2.c
new file mode 100644
index 0000000..9e576e9
--- /dev/null
+++ b/getln2.c
@@ -0,0 +1,31 @@
+#include "substdio.h"
+#include "stralloc.h"
+#include "byte.h"
+#include "getln.h"
+
+int getln2(ss,sa,cont,clen,sep)
+register substdio *ss;
+register stralloc *sa;
+/*@out@*/char **cont;
+/*@out@*/unsigned int *clen;
+int sep;
+{
+ register char *x;
+ register unsigned int i;
+ int n;
+
+ if (!stralloc_ready(sa,0)) return -1;
+ sa->len = 0;
+
+ for (;;) {
+ n = substdio_feed(ss);
+ if (n < 0) return -1;
+ if (n == 0) { *clen = 0; return 0; }
+ x = substdio_PEEK(ss);
+ i = byte_chr(x,n,sep);
+ if (i < n) { substdio_SEEK(ss,*clen = i + 1); *cont = x; return 0; }
+ if (!stralloc_readyplus(sa,n)) return -1;
+ i = sa->len;
+ sa->len = i + substdio_get(ss,sa->s + i,n);
+ }
+}
diff --git a/gfrom.c b/gfrom.c
new file mode 100644
index 0000000..87f9ad4
--- /dev/null
+++ b/gfrom.c
@@ -0,0 +1,10 @@
+#include "str.h"
+#include "gfrom.h"
+
+int gfrom(s,len)
+char *s;
+int len;
+{
+ while ((len > 0) && (*s == '>')) { ++s; --len; }
+ return (len >= 5) && !str_diffn(s,"From ",5);
+}
diff --git a/gfrom.h b/gfrom.h
new file mode 100644
index 0000000..488193c
--- /dev/null
+++ b/gfrom.h
@@ -0,0 +1,6 @@
+#ifndef GFROM_H
+#define GFROM_H
+
+extern int gfrom();
+
+#endif
diff --git a/headerbody.c b/headerbody.c
new file mode 100644
index 0000000..91965c0
--- /dev/null
+++ b/headerbody.c
@@ -0,0 +1,87 @@
+#include "stralloc.h"
+#include "substdio.h"
+#include "getln.h"
+#include "hfield.h"
+#include "headerbody.h"
+
+static int getsa(ss,sa,match)
+substdio *ss;
+stralloc *sa;
+int *match;
+{
+ if (!*match) return 0;
+ if (getln(ss,sa,match,'\n') == -1) return -1;
+ if (*match) return 1;
+ if (!sa->len) return 0;
+ if (!stralloc_append(sa,"\n")) return -1;
+ return 1;
+}
+
+static stralloc line = {0};
+static stralloc nextline = {0};
+
+int headerbody(ss,dohf,hdone,dobl)
+substdio *ss;
+void (*dohf)();
+void (*hdone)();
+void (*dobl)();
+{
+ int match;
+ int flaglineok;
+ match = 1;
+ flaglineok = 0;
+ for (;;)
+ {
+ switch(getsa(ss,&nextline,&match))
+ {
+ case -1:
+ return -1;
+ case 0:
+ if (flaglineok) dohf(&line);
+ hdone();
+ /* no message body; could insert blank line here */
+ return 0;
+ }
+ if (flaglineok)
+ {
+ if ((nextline.s[0] == ' ') || (nextline.s[0] == '\t'))
+ {
+ if (!stralloc_cat(&line,&nextline)) return -1;
+ continue;
+ }
+ dohf(&line);
+ }
+ if (nextline.len == 1)
+ {
+ hdone();
+ dobl(&nextline);
+ break;
+ }
+ if (stralloc_starts(&nextline,"From "))
+ {
+ if (!stralloc_copys(&line,"MBOX-Line: ")) return -1;
+ if (!stralloc_cat(&line,&nextline)) return -1;
+ }
+ else
+ if (hfield_valid(nextline.s,nextline.len))
+ {
+ if (!stralloc_copy(&line,&nextline)) return -1;
+ }
+ else
+ {
+ hdone();
+ if (!stralloc_copys(&line,"\n")) return -1;
+ dobl(&line);
+ dobl(&nextline);
+ break;
+ }
+ flaglineok = 1;
+ }
+ for (;;)
+ switch(getsa(ss,&nextline,&match))
+ {
+ case -1: return -1;
+ case 0: return 0;
+ case 1: dobl(&nextline);
+ }
+}
diff --git a/headerbody.h b/headerbody.h
new file mode 100644
index 0000000..3bb2e2f
--- /dev/null
+++ b/headerbody.h
@@ -0,0 +1,6 @@
+#ifndef HEADERBODY_H
+#define HEADERBODY_H
+
+extern int headerbody();
+
+#endif
diff --git a/hfield.c b/hfield.c
new file mode 100644
index 0000000..06de0be
--- /dev/null
+++ b/hfield.c
@@ -0,0 +1,125 @@
+#include "hfield.h"
+
+static char *(hname[]) = {
+ "unknown-header"
+, "sender"
+, "from"
+, "reply-to"
+, "to"
+, "cc"
+, "bcc"
+, "date"
+, "message-id"
+, "subject"
+, "resent-sender"
+, "resent-from"
+, "resent-reply-to"
+, "resent-to"
+, "resent-cc"
+, "resent-bcc"
+, "resent-date"
+, "resent-message-id"
+, "return-receipt-to"
+, "errors-to"
+, "apparently-to"
+, "received"
+, "return-path"
+, "delivered-to"
+, "content-length"
+, "content-type"
+, "content-transfer-encoding"
+, "notice-requested-upon-delivery-to"
+, "mail-followup-to"
+, 0
+};
+
+static int hmatch(s,len,t)
+char *s;
+int len;
+char *t;
+{
+ int i;
+ char ch;
+
+ for (i = 0;ch = t[i];++i)
+ {
+ if (i >= len) return 0;
+ if (ch != s[i])
+ {
+ if (ch == '-') return 0;
+ if (ch - 32 != s[i]) return 0;
+ }
+ }
+ for (;;)
+ {
+ if (i >= len) return 0;
+ ch = s[i];
+ if (ch == ':') return 1;
+ if ((ch != ' ') && (ch != '\t')) return 0;
+ ++i;
+ }
+}
+
+int hfield_known(s,len)
+char *s;
+int len;
+{
+ int i;
+ char *t;
+
+ for (i = 1;t = hname[i];++i)
+ if (hmatch(s,len,t))
+ return i;
+ return 0;
+}
+
+int hfield_valid(s,len)
+char *s;
+int len;
+{
+ int i;
+ int j;
+ char ch;
+
+ for (j = 0;j < len;++j)
+ if (s[j] == ':')
+ break;
+ if (j >= len) return 0;
+ while (j)
+ {
+ ch = s[j - 1];
+ if ((ch != ' ') && (ch != '\t'))
+ break;
+ --j;
+ }
+ if (!j) return 0;
+
+ for (i = 0;i < j;++i)
+ {
+ ch = s[i];
+ if (ch <= 32) return 0;
+ if (ch >= 127) return 0;
+ }
+ return 1;
+}
+
+unsigned int hfield_skipname(s,len)
+char *s;
+int len;
+{
+ int i;
+ char ch;
+
+ for (i = 0;i < len;++i)
+ if (s[i] == ':')
+ break;
+ if (i < len) ++i;
+ while (i < len)
+ {
+ ch = s[i];
+ if ((ch != '\t') && (ch != '\n') && (ch != '\r') && (ch != ' '))
+ break;
+ ++i;
+ }
+ return i;
+}
diff --git a/hfield.h b/hfield.h
new file mode 100644
index 0000000..20b30a5
--- /dev/null
+++ b/hfield.h
@@ -0,0 +1,38 @@
+#ifndef HFIELD_H
+#define HFIELD_H
+
+extern unsigned int hfield_skipname();
+extern int hfield_known();
+extern int hfield_valid();
+
+#define H_SENDER 1
+#define H_FROM 2
+#define H_REPLYTO 3
+#define H_TO 4
+#define H_CC 5
+#define H_BCC 6
+#define H_DATE 7
+#define H_MESSAGEID 8
+#define H_SUBJECT 9
+#define H_R_SENDER 10
+#define H_R_FROM 11
+#define H_R_REPLYTO 12
+#define H_R_TO 13
+#define H_R_CC 14
+#define H_R_BCC 15
+#define H_R_DATE 16
+#define H_R_MESSAGEID 17
+#define H_RETURNRECEIPTTO 18
+#define H_ERRORSTO 19
+#define H_APPARENTLYTO 20
+#define H_RECEIVED 21
+#define H_RETURNPATH 22
+#define H_DELIVEREDTO 23
+#define H_CONTENTLENGTH 24
+#define H_CONTENTTYPE 25
+#define H_CONTENTTRANSFERENCODING 26
+#define H_NOTICEREQUESTEDUPONDELIVERYTO 27
+#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/hostname.c b/hostname.c
new file mode 100644
index 0000000..39c7f87
--- /dev/null
+++ b/hostname.c
@@ -0,0 +1,17 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "readwrite.h"
+#include "exit.h"
+
+char host[256];
+
+void main()
+{
+ host[0] = 0; /* sigh */
+ gethostname(host,sizeof(host));
+ host[sizeof(host) - 1] = 0;
+ substdio_puts(subfdoutsmall,host);
+ substdio_puts(subfdoutsmall,"\n");
+ substdio_flush(subfdoutsmall);
+ _exit(0);
+}
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 <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#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
new file mode 100644
index 0000000..95034f2
--- /dev/null
+++ b/install.c
@@ -0,0 +1,164 @@
+#include "substdio.h"
+#include "strerr.h"
+#include "error.h"
+#include "open.h"
+#include "readwrite.h"
+#include "exit.h"
+
+extern void hier();
+
+#define FATAL "install: fatal: "
+
+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 c(home,subdir,file,uid,gid,mode)
+char *home;
+char *subdir;
+char *file;
+int uid;
+int gid;
+int mode;
+{
+ int fdin;
+ int fdout;
+
+ 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,": ");
+ }
+
+ 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,": ");
+}
+
+void z(home,file,len,uid,gid,mode)
+char *home;
+char *file;
+int len;
+int uid;
+int gid;
+int mode;
+{
+ int fdout;
+
+ 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,": ");
+}
+
+void main()
+{
+ fdsourcedir = open_read(".");
+ if (fdsourcedir == -1)
+ strerr_die2sys(111,FATAL,"unable to open current directory: ");
+
+ umask(077);
+ hier();
+ _exit(0);
+}
diff --git a/instcheck.c b/instcheck.c
new file mode 100644
index 0000000..d41efda
--- /dev/null
+++ b/instcheck.c
@@ -0,0 +1,108 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "strerr.h"
+#include "error.h"
+#include "readwrite.h"
+#include "exit.h"
+
+extern void hier();
+
+#define FATAL "instcheck: fatal: "
+#define WARNING "instcheck: warning: "
+
+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;
+
+ if (stat(file,&st) == -1) {
+ if (errno == error_noent)
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," does not exist",0);
+ else
+ strerr_warn4(WARNING,"unable to stat .../",file,": ",&strerr_sys);
+ return;
+ }
+
+ if ((uid != -1) && (st.st_uid != uid))
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong owner",0);
+ if ((gid != -1) && (st.st_gid != gid))
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong group",0);
+ if ((st.st_mode & 07777) != mode)
+ 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);
+}
+
+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 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,": ");
+ perm("",home,"/",fifo,S_IFIFO,uid,gid,mode);
+}
+
+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);
+}
+
+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);
+}
+
+void main()
+{
+ hier();
+ _exit(0);
+}
diff --git a/ip.c b/ip.c
new file mode 100644
index 0000000..5528ad5
--- /dev/null
+++ b/ip.c
@@ -0,0 +1,53 @@
+#include "fmt.h"
+#include "scan.h"
+#include "ip.h"
+
+unsigned int ip_fmt(s,ip)
+char *s;
+struct ip_address *ip;
+{
+ unsigned int len;
+ unsigned int i;
+
+ len = 0;
+ i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i;
+ return len;
+}
+
+unsigned int ip_scan(s,ip)
+char *s;
+struct ip_address *ip;
+{
+ unsigned int i;
+ unsigned int len;
+ unsigned long u;
+
+ len = 0;
+ i = scan_ulong(s,&u); if (!i) return 0; ip->d[0] = u; s += i; len += i;
+ if (*s != '.') return 0; ++s; ++len;
+ i = scan_ulong(s,&u); if (!i) return 0; ip->d[1] = u; s += i; len += i;
+ if (*s != '.') return 0; ++s; ++len;
+ i = scan_ulong(s,&u); if (!i) return 0; ip->d[2] = u; s += i; len += i;
+ if (*s != '.') return 0; ++s; ++len;
+ i = scan_ulong(s,&u); if (!i) return 0; ip->d[3] = u; s += i; len += i;
+ return len;
+}
+
+unsigned int ip_scanbracket(s,ip)
+char *s;
+struct ip_address *ip;
+{
+ unsigned int len;
+
+ if (*s != '[') return 0;
+ len = ip_scan(s + 1,ip);
+ if (!len) return 0;
+ if (s[len + 1] != ']') return 0;
+ return len + 2;
+}
diff --git a/ip.h b/ip.h
new file mode 100644
index 0000000..b99002f
--- /dev/null
+++ b/ip.h
@@ -0,0 +1,11 @@
+#ifndef IP_H
+#define IP_H
+
+struct ip_address { unsigned char d[4]; } ;
+
+extern unsigned int ip_fmt();
+#define IPFMT 19
+extern unsigned int ip_scan();
+extern unsigned int ip_scanbracket();
+
+#endif
diff --git a/ipalloc.c b/ipalloc.c
new file mode 100644
index 0000000..81792d5
--- /dev/null
+++ b/ipalloc.c
@@ -0,0 +1,7 @@
+#include "alloc.h"
+#include "gen_allocdefs.h"
+#include "ip.h"
+#include "ipalloc.h"
+
+GEN_ALLOC_readyplus(ipalloc,struct ip_mx,ix,len,a,i,n,x,10,ipalloc_readyplus)
+GEN_ALLOC_append(ipalloc,struct ip_mx,ix,len,a,i,n,x,10,ipalloc_readyplus,ipalloc_append)
diff --git a/ipalloc.h b/ipalloc.h
new file mode 100644
index 0000000..ad61475
--- /dev/null
+++ b/ipalloc.h
@@ -0,0 +1,14 @@
+#ifndef IPALLOC_H
+#define IPALLOC_H
+
+#include "ip.h"
+
+struct ip_mx { struct ip_address ip; int pref; } ;
+
+#include "gen_alloc.h"
+
+GEN_ALLOC_typedef(ipalloc,struct ip_mx,ix,len,a)
+extern int ipalloc_readyplus();
+extern int ipalloc_append();
+
+#endif
diff --git a/ipme.c b/ipme.c
new file mode 100644
index 0000000..3c86127
--- /dev/null
+++ b/ipme.c
@@ -0,0 +1,100 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#ifndef SIOCGIFCONF /* whatever works */
+#include <sys/sockio.h>
+#endif
+#include "hassalen.h"
+#include "byte.h"
+#include "ip.h"
+#include "ipalloc.h"
+#include "stralloc.h"
+#include "ipme.h"
+
+static int ipmeok = 0;
+ipalloc ipme = {0};
+
+int ipme_is(ip)
+struct ip_address *ip;
+{
+ int i;
+ if (ipme_init() != 1) return -1;
+ for (i = 0;i < ipme.len;++i)
+ if (byte_equal(&ipme.ix[i].ip,4,ip))
+ return 1;
+ return 0;
+}
+
+static stralloc buf = {0};
+
+int ipme_init()
+{
+ struct ifconf ifc;
+ char *x;
+ struct ifreq *ifr;
+ struct sockaddr_in *sin;
+ int len;
+ int s;
+ struct ip_mx ix;
+
+ if (ipmeok) return 1;
+ if (!ipalloc_readyplus(&ipme,0)) return 0;
+ ipme.len = 0;
+ ix.pref = 0;
+
+ /* 0.0.0.0 is a special address which always refers to
+ * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a.
+ */
+ byte_copy(&ix.ip,4,"\0\0\0\0");
+ if (!ipalloc_append(&ipme,&ix)) { return 0; }
+ if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
+
+ len = 256;
+ for (;;) {
+ if (!stralloc_ready(&buf,len)) { close(s); return 0; }
+ buf.len = 0;
+ ifc.ifc_buf = buf.s;
+ ifc.ifc_len = len;
+ if (ioctl(s,SIOCGIFCONF,&ifc) >= 0) /* > is for System V */
+ if (ifc.ifc_len + sizeof(*ifr) + 64 < len) { /* what a stupid interface */
+ buf.len = ifc.ifc_len;
+ break;
+ }
+ if (len > 200000) { close(s); return -1; }
+ len += 100 + (len >> 2);
+ }
+ x = buf.s;
+ while (x < buf.s + buf.len) {
+ ifr = (struct ifreq *) x;
+#ifdef HASSALEN
+ len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
+ if (len < sizeof(*ifr))
+ len = sizeof(*ifr);
+ if (ifr->ifr_addr.sa_family == AF_INET) {
+ sin = (struct sockaddr_in *) &ifr->ifr_addr;
+ byte_copy(&ix.ip,4,&sin->sin_addr);
+ if (ioctl(s,SIOCGIFFLAGS,x) == 0)
+ if (ifr->ifr_flags & IFF_UP)
+ if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
+ }
+#else
+ len = sizeof(*ifr);
+ if (ioctl(s,SIOCGIFFLAGS,x) == 0)
+ if (ifr->ifr_flags & IFF_UP)
+ if (ioctl(s,SIOCGIFADDR,x) == 0)
+ if (ifr->ifr_addr.sa_family == AF_INET) {
+ sin = (struct sockaddr_in *) &ifr->ifr_addr;
+ byte_copy(&ix.ip,4,&sin->sin_addr);
+ if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
+ }
+#endif
+ x += len;
+ }
+ close(s);
+ ipmeok = 1;
+ return 1;
+}
diff --git a/ipme.h b/ipme.h
new file mode 100644
index 0000000..5bbf515
--- /dev/null
+++ b/ipme.h
@@ -0,0 +1,12 @@
+#ifndef IPME_H
+#define IPME_H
+
+#include "ip.h"
+#include "ipalloc.h"
+
+extern ipalloc ipme;
+
+extern int ipme_init();
+extern int ipme_is();
+
+#endif
diff --git a/ipmeprint.c b/ipmeprint.c
new file mode 100644
index 0000000..1ef56e3
--- /dev/null
+++ b/ipmeprint.c
@@ -0,0 +1,24 @@
+#include "subfd.h"
+#include "substdio.h"
+#include "ip.h"
+#include "ipme.h"
+#include "exit.h"
+
+char temp[IPFMT];
+
+void main()
+{
+ int j;
+ switch(ipme_init())
+ {
+ case 0: substdio_putsflush(subfderr,"out of memory\n"); _exit(111);
+ case -1: substdio_putsflush(subfderr,"hard error\n"); _exit(100);
+ }
+ for (j = 0;j < ipme.len;++j)
+ {
+ substdio_put(subfdout,temp,ip_fmt(temp,&ipme.ix[j].ip));
+ substdio_puts(subfdout,"\n");
+ }
+ substdio_flush(subfdout);
+ _exit(0);
+}
diff --git a/lock.h b/lock.h
new file mode 100644
index 0000000..a7dee41
--- /dev/null
+++ b/lock.h
@@ -0,0 +1,8 @@
+#ifndef LOCK_H
+#define LOCK_H
+
+extern int lock_ex();
+extern int lock_un();
+extern int lock_exnb();
+
+#endif
diff --git a/lock_ex.c b/lock_ex.c
new file mode 100644
index 0000000..a3351c9
--- /dev/null
+++ b/lock_ex.c
@@ -0,0 +1,11 @@
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include "hasflock.h"
+#include "lock.h"
+
+#ifdef HASFLOCK
+int lock_ex(fd) int fd; { return flock(fd,LOCK_EX); }
+#else
+int lock_ex(fd) int fd; { return lockf(fd,1,0); }
+#endif
diff --git a/lock_exnb.c b/lock_exnb.c
new file mode 100644
index 0000000..5d2a14a
--- /dev/null
+++ b/lock_exnb.c
@@ -0,0 +1,11 @@
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include "hasflock.h"
+#include "lock.h"
+
+#ifdef HASFLOCK
+int lock_exnb(fd) int fd; { return flock(fd,LOCK_EX | LOCK_NB); }
+#else
+int lock_exnb(fd) int fd; { return lockf(fd,2,0); }
+#endif
diff --git a/lock_un.c b/lock_un.c
new file mode 100644
index 0000000..16e2f17
--- /dev/null
+++ b/lock_un.c
@@ -0,0 +1,11 @@
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include "hasflock.h"
+#include "lock.h"
+
+#ifdef HASFLOCK
+int lock_un(fd) int fd; { return flock(fd,LOCK_UN); }
+#else
+int lock_un(fd) int fd; { return lockf(fd,0,0); }
+#endif
diff --git a/maildir.5 b/maildir.5
new file mode 100644
index 0000000..5da9573
--- /dev/null
+++ b/maildir.5
@@ -0,0 +1,239 @@
+.TH maildir 5
+.SH "NAME"
+maildir \- directory for incoming mail messages
+.SH "INTRODUCTION"
+.I maildir
+is a structure for
+directories of incoming mail messages.
+It solves the reliability problems that plague
+.I mbox
+files and
+.I mh
+folders.
+.SH "RELIABILITY ISSUES"
+A machine may crash while it is delivering a message.
+For both
+.I mbox
+files and
+.I mh
+folders this means that the message will be silently truncated.
+Even worse: for
+.I mbox
+format, if the message is truncated in the middle of a line,
+it will be silently joined to the next message.
+The mail transport agent will try again later to deliver the message,
+but it is unacceptable that a corrupted message should show up at all.
+In
+.IR maildir ,
+every message is guaranteed complete upon delivery.
+
+A machine may have two programs simultaneously delivering mail
+to the same user.
+The
+.I mbox
+and
+.I mh
+formats require the programs to update a single central file.
+If the programs do not use some locking mechanism,
+the central file will be corrupted.
+There are several
+.I mbox
+and
+.I mh
+locking mechanisms,
+none of which work portably and reliably.
+In contrast, in
+.IR maildir ,
+no locks are ever necessary.
+Different delivery processes never touch the same file.
+
+A user may try to delete messages from his mailbox at the same
+moment that the machine delivers a new message.
+For
+.I mbox
+and
+.I mh
+formats, the user's mail-reading program must know
+what locking mechanism the mail-delivery programs use.
+In contrast, in
+.IR maildir ,
+any delivered message
+can be safely updated or deleted by a mail-reading program.
+
+Many sites use Sun's
+.B Network F\fPa\fBil\fPur\fBe System
+(NFS),
+presumably because the operating system vendor does not offer
+anything else.
+NFS exacerbates all of the above problems.
+Some NFS implementations don't provide
+.B any
+reliable locking mechanism.
+With
+.I mbox
+and
+.I mh
+formats,
+if two machines deliver mail to the same user,
+or if a user reads mail anywhere except the delivery machine,
+the user's mail is at risk.
+.I maildir
+works without trouble over NFS.
+.SH "THE MAILDIR STRUCTURE"
+A directory in
+.I maildir
+format has three subdirectories,
+all on the same filesystem:
+.BR tmp ,
+.BR new ,
+and
+.BR cur .
+
+Each file in
+.B new
+is a newly delivered mail message.
+The modification time of the file is the delivery date of the message.
+The message is delivered
+.I without
+an extra UUCP-style
+.B From_
+line,
+.I without
+any
+.B >From
+quoting,
+and
+.I without
+an extra blank line at the end.
+The message is normally in RFC 822 format,
+starting with a
+.B Return-Path
+line and a
+.B Delivered-To
+line,
+but it could contain arbitrary binary data.
+It might not even end with a newline.
+
+Files in
+.B cur
+are just like files in
+.BR new .
+The big difference is that files in
+.B cur
+are no longer new mail:
+they have been seen by the user's mail-reading program.
+.SH "HOW A MESSAGE IS DELIVERED"
+The
+.B tmp
+directory is used to ensure reliable delivery,
+as discussed here.
+
+A program delivers a mail message in six steps.
+First, it
+.B chdir()\fPs
+to the
+.I maildir
+directory.
+Second, it
+.B stat()s
+the name
+.BR tmp/\fItime.pid.host ,
+where
+.I time
+is the number of seconds since the beginning of 1970 GMT,
+.I pid
+is the program's process ID,
+and
+.I host
+is the host name.
+Third, if
+.B stat()
+returned anything other than ENOENT,
+the program sleeps for two seconds, updates
+.IR time ,
+and tries the
+.B stat()
+again, a limited number of times.
+Fourth, the program
+creates
+.BR tmp/\fItime.pid.host .
+Fifth, the program
+.I NFS-writes
+the message to the file.
+Sixth, the program
+.BR link() s
+the file to
+.BR new/\fItime.pid.host .
+At that instant the message has been successfully delivered.
+
+The delivery program is required to start a 24-hour timer before
+creating
+.BR tmp/\fItime.pid.host ,
+and to abort the delivery
+if the timer expires.
+Upon error, timeout, or normal completion,
+the delivery program may attempt to
+.B unlink()
+.BR tmp/\fItime.pid.host .
+
+.I NFS-writing
+means
+(1) as usual, checking the number of bytes returned from each
+.B write()
+call;
+(2) calling
+.B fsync()
+and checking its return value;
+(3) calling
+.B close()
+and checking its return value.
+(Standard NFS implementations handle
+.B fsync()
+incorrectly
+but make up for it by abusing
+.BR close() .)
+.SH "HOW A MESSAGE IS READ"
+A mail reader operates as follows.
+
+It looks through the
+.B new
+directory for new messages.
+Say there is a new message,
+.BR new/\fIunique .
+The reader may freely display the contents of
+.BR new/\fIunique ,
+delete
+.BR new/\fIunique ,
+or rename
+.B new/\fIunique
+as
+.BR cur/\fIunique:info .
+See
+.B http://pobox.com/~djb/proto/maildir.html
+for the meaning of
+.IR info .
+
+The reader is also expected to look through the
+.B tmp
+directory and to clean up any old files found there.
+A file in
+.B tmp
+may be safely removed if it
+has not been accessed in 36 hours.
+
+It is a good idea for readers to skip all filenames in
+.B new
+and
+.B cur
+starting with a dot.
+Other than this, readers should not attempt to parse filenames.
+.SH "ENVIRONMENT VARIABLES"
+Mail readers supporting
+.I maildir
+use the
+.B MAILDIR
+environment variable
+as the name of the user's primary mail directory.
+.SH "SEE ALSO"
+mbox(5),
+qmail-local(8)
diff --git a/maildir.c b/maildir.c
new file mode 100644
index 0000000..efbd3d4
--- /dev/null
+++ b/maildir.c
@@ -0,0 +1,108 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "prioq.h"
+#include "env.h"
+#include "stralloc.h"
+#include "direntry.h"
+#include "datetime.h"
+#include "now.h"
+#include "str.h"
+#include "maildir.h"
+
+struct strerr maildir_chdir_err;
+struct strerr maildir_scan_err;
+
+int maildir_chdir()
+{
+ char *maildir;
+ maildir = env_get("MAILDIR");
+ if (!maildir)
+ STRERR(-1,maildir_chdir_err,"MAILDIR not set")
+ if (chdir(maildir) == -1)
+ STRERR_SYS3(-1,maildir_chdir_err,"unable to chdir to ",maildir,": ")
+ return 0;
+}
+
+void maildir_clean(tmpname)
+stralloc *tmpname;
+{
+ DIR *dir;
+ direntry *d;
+ datetime_sec time;
+ struct stat st;
+
+ time = now();
+
+ dir = opendir("tmp");
+ if (!dir) return;
+
+ while (d = readdir(dir))
+ {
+ if (d->d_name[0] == '.') continue;
+ if (!stralloc_copys(tmpname,"tmp/")) break;
+ if (!stralloc_cats(tmpname,d->d_name)) break;
+ if (!stralloc_0(tmpname)) break;
+ if (stat(tmpname->s,&st) == 0)
+ if (time > st.st_atime + 129600)
+ unlink(tmpname->s);
+ }
+ closedir(dir);
+}
+
+static int append(pq,filenames,subdir,time)
+prioq *pq;
+stralloc *filenames;
+char *subdir;
+datetime_sec time;
+{
+ DIR *dir;
+ direntry *d;
+ struct prioq_elt pe;
+ unsigned int pos;
+ struct stat st;
+
+ dir = opendir(subdir);
+ if (!dir)
+ STRERR_SYS3(-1,maildir_scan_err,"unable to scan $MAILDIR/",subdir,": ")
+
+ while (d = readdir(dir))
+ {
+ if (d->d_name[0] == '.') continue;
+ pos = filenames->len;
+ if (!stralloc_cats(filenames,subdir)) break;
+ if (!stralloc_cats(filenames,"/")) break;
+ if (!stralloc_cats(filenames,d->d_name)) break;
+ if (!stralloc_0(filenames)) break;
+ if (stat(filenames->s + pos,&st) == 0)
+ if (st.st_mtime < time) /* don't want to mix up the order */
+ {
+ pe.dt = st.st_mtime;
+ pe.id = pos;
+ if (!prioq_insert(pq,&pe)) break;
+ }
+ }
+
+ closedir(dir);
+ if (d) STRERR_SYS3(-1,maildir_scan_err,"unable to read $MAILDIR/",subdir,": ")
+ return 0;
+}
+
+int maildir_scan(pq,filenames,flagnew,flagcur)
+prioq *pq;
+stralloc *filenames;
+int flagnew;
+int flagcur;
+{
+ struct prioq_elt pe;
+ datetime_sec time;
+ int r;
+
+ if (!stralloc_copys(filenames,"")) return 0;
+ while (prioq_min(pq,&pe)) prioq_delmin(pq);
+
+ time = now();
+
+ if (flagnew) if (append(pq,filenames,"new",time) == -1) return -1;
+ if (flagcur) if (append(pq,filenames,"cur",time) == -1) return -1;
+ return 0;
+}
diff --git a/maildir.h b/maildir.h
new file mode 100644
index 0000000..7dd8826
--- /dev/null
+++ b/maildir.h
@@ -0,0 +1,12 @@
+#ifndef MAILDIR_H
+#define MAILDIR_H
+
+#include "strerr.h"
+extern struct strerr maildir_chdir_err;
+extern struct strerr maildir_scan_err;
+
+extern int maildir_chdir();
+extern void maildir_clean();
+extern int maildir_scan();
+
+#endif
diff --git a/maildir2mbox.1 b/maildir2mbox.1
new file mode 100644
index 0000000..31423d9
--- /dev/null
+++ b/maildir2mbox.1
@@ -0,0 +1,53 @@
+.TH maildir2mbox 1
+.SH NAME
+maildir2mbox \- move mail from a maildir to an mbox
+.SH SYNOPSIS
+.B maildir2mbox
+.SH DESCRIPTION
+.B maildir2mbox
+moves mail from a
+.IR maildir -format
+directory to an
+.IR mbox -format
+file.
+
+You must supply three environment variables to
+.BR maildir2mbox :
+.B MAILDIR
+is the name of your
+.I maildir
+directory;
+.B MAIL
+is the name of your
+.I mbox
+file;
+and
+.B MAILTMP
+is a temporary file that
+.B maildir2mbox
+can overwrite.
+.B MAILTMP
+and
+.B MAIL
+must be on the same filesystem.
+
+.B maildir2mbox
+is reliable:
+it will not remove messages
+from
+.B MAILDIR
+until the messages have been successfully appended to
+.BR MAIL .
+
+.B maildir2mbox
+locks
+.B MAIL
+to protect against simultaneous access by a mail reader.
+This locking system does not protect against simultaneous access
+by another
+.BR maildir2mbox ;
+you should run only one
+.B maildir2mbox
+at a time.
+.SH "SEE ALSO"
+maildir(5)
diff --git a/maildir2mbox.c b/maildir2mbox.c
new file mode 100644
index 0000000..7364441
--- /dev/null
+++ b/maildir2mbox.c
@@ -0,0 +1,162 @@
+#include "readwrite.h"
+#include "prioq.h"
+#include "env.h"
+#include "stralloc.h"
+#include "subfd.h"
+#include "substdio.h"
+#include "getln.h"
+#include "error.h"
+#include "open.h"
+#include "lock.h"
+#include "gfrom.h"
+#include "str.h"
+#include "exit.h"
+#include "myctime.h"
+#include "maildir.h"
+
+char *mbox;
+char *mboxtmp;
+
+stralloc filenames = {0};
+prioq pq = {0};
+prioq pq2 = {0};
+
+stralloc line = {0};
+
+stralloc ufline = {0};
+
+char inbuf[SUBSTDIO_INSIZE];
+char outbuf[SUBSTDIO_OUTSIZE];
+
+#define FATAL "maildir2mbox: fatal: "
+#define WARNING "maildir2mbox: warning: "
+
+void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); }
+
+void main()
+{
+ substdio ssin;
+ substdio ssout;
+ struct prioq_elt pe;
+ int fdoldmbox;
+ int fdnewmbox;
+ int fd;
+ int match;
+ in