Import dot-forward 0.71 djb djb/0.71
authorMark Wooding <mdw@distorted.org.uk>
Wed, 15 Feb 2006 18:39:22 +0000 (18:39 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 15 Feb 2006 18:39:22 +0000 (18:39 +0000)
102 files changed:
BLURB [new file with mode: 0644]
CHANGES [new file with mode: 0644]
FILES [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
SYSDEPS [new file with mode: 0644]
TARGETS [new file with mode: 0644]
THANKS [new file with mode: 0644]
TODO [new file with mode: 0644]
VERSION [new file with mode: 0644]
alloc.c [new file with mode: 0644]
alloc.h [new file with mode: 0644]
alloc_re.c [new file with mode: 0644]
auto-str.c [new file with mode: 0644]
auto_qmail.h [new file with mode: 0644]
byte.h [new file with mode: 0644]
byte_chr.c [new file with mode: 0644]
byte_copy.c [new file with mode: 0644]
byte_cr.c [new file with mode: 0644]
case.h [new file with mode: 0644]
case_diffb.c [new file with mode: 0644]
conf-cc [new file with mode: 0644]
conf-ld [new file with mode: 0644]
conf-qmail [new file with mode: 0644]
control.c [new file with mode: 0644]
control.h [new file with mode: 0644]
dot-forward.1 [new file with mode: 0644]
dot-forward.c [new file with mode: 0644]
env.h [new file with mode: 0644]
envread.c [new file with mode: 0644]
error.c [new file with mode: 0644]
error.h [new file with mode: 0644]
error_str.c [new file with mode: 0644]
exit.h [new file with mode: 0644]
fd.h [new file with mode: 0644]
fd_copy.c [new file with mode: 0644]
fd_move.c [new file with mode: 0644]
find-systype.sh [new file with mode: 0644]
fmt.h [new file with mode: 0644]
fmt_ulong.c [new file with mode: 0644]
fork.h1 [new file with mode: 0644]
fork.h2 [new file with mode: 0644]
gen_alloc.h [new file with mode: 0644]
gen_allocdefs.h [new file with mode: 0644]
getln.c [new file with mode: 0644]
getln.h [new file with mode: 0644]
getln2.c [new file with mode: 0644]
hier.c [new file with mode: 0644]
install.c [new file with mode: 0644]
instcheck.c [new file with mode: 0644]
make-compile.sh [new file with mode: 0644]
make-load.sh [new file with mode: 0644]
make-makelib.sh [new file with mode: 0644]
open.h [new file with mode: 0644]
open_read.c [new file with mode: 0644]
open_trunc.c [new file with mode: 0644]
qmail.c [new file with mode: 0644]
qmail.h [new file with mode: 0644]
readwrite.h [new file with mode: 0644]
scan.h [new file with mode: 0644]
scan_ulong.c [new file with mode: 0644]
seek.h [new file with mode: 0644]
seek_set.c [new file with mode: 0644]
sgetopt.c [new file with mode: 0644]
sgetopt.h [new file with mode: 0644]
sig.h [new file with mode: 0644]
sig_catch.c [new file with mode: 0644]
sig_pipe.c [new file with mode: 0644]
str.h [new file with mode: 0644]
str_diffn.c [new file with mode: 0644]
str_len.c [new file with mode: 0644]
stralloc.h [new file with mode: 0644]
stralloc_cat.c [new file with mode: 0644]
stralloc_catb.c [new file with mode: 0644]
stralloc_cats.c [new file with mode: 0644]
stralloc_copy.c [new file with mode: 0644]
stralloc_eady.c [new file with mode: 0644]
stralloc_opyb.c [new file with mode: 0644]
stralloc_opys.c [new file with mode: 0644]
stralloc_pend.c [new file with mode: 0644]
strerr.h [new file with mode: 0644]
strerr_die.c [new file with mode: 0644]
strerr_sys.c [new file with mode: 0644]
subfd.h [new file with mode: 0644]
subfderr.c [new file with mode: 0644]
subgetopt.c [new file with mode: 0644]
subgetopt.h [new file with mode: 0644]
substdi.c [new file with mode: 0644]
substdio.c [new file with mode: 0644]
substdio.h [new file with mode: 0644]
substdio_copy.c [new file with mode: 0644]
substdo.c [new file with mode: 0644]
token822.c [new file with mode: 0644]
token822.h [new file with mode: 0644]
trycpp.c [new file with mode: 0644]
trysgact.c [new file with mode: 0644]
tryvfork.c [new file with mode: 0644]
trywaitp.c [new file with mode: 0644]
wait.h [new file with mode: 0644]
wait_pid.c [new file with mode: 0644]
warn-auto.sh [new file with mode: 0644]

diff --git a/BLURB b/BLURB
new file mode 100644 (file)
index 0000000..3f41124
--- /dev/null
+++ b/BLURB
@@ -0,0 +1,9 @@
+dot-forward reads sendmail's .forward files under qmail. You can run it
+in the qmail startup script to support all your existing .forward files
+automatically. Individual users can switch to the .qmail mechanism at
+their leisure.
+
+dot-forward supports forwarding, program deliveries, and comments. It
+does not support file deliveries or :include:. (However, it recognizes
+file delivery attempts, and defers delivery to give you a chance to set
+up a .qmail file.)
diff --git a/CHANGES b/CHANGES
new file mode 100644 (file)
index 0000000..68ae442
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,17 @@
+19980519 version: dot-forward 0.71, beta.
+19980519 doc: simplified INSTALL.
+19980519 doc: documented -n in dot-forward.1.
+19980519 code: eliminated home+df.
+19980519 doc: put version and home page into dot-forward.1.
+19980519 code: switched to new install.
+19980421 dot-forward 0.70, beta.
+19980421 code: recognized $USER@$HOST the same way as $USER.
+19980421 doc: reorganized compatibility warnings in dot-forward.0.
+19980421 doc: eliminated *.3.
+19980421 doc: added note about file deferrals to BLURB.
+19980421 code: added home+df.sh; updated INSTALL accordingly.
+19980421 code: moved installation from /usr/local to /var/qmail.
+19971001 doc: eliminated hassgprm.h from SYSDEPS. tnx JB.
+19971001 dot-forward 0.51, alpha.
+19971001 doc: changed ./forward to .forward in man page and INSTALL.
+19970930 dot-forward 0.50, alpha.
diff --git a/FILES b/FILES
new file mode 100644 (file)
index 0000000..9c851e4
--- /dev/null
+++ b/FILES
@@ -0,0 +1,102 @@
+BLURB
+README
+TODO
+THANKS
+CHANGES
+FILES
+VERSION
+SYSDEPS
+Makefile
+TARGETS
+dot-forward.1
+dot-forward.c
+conf-cc
+conf-ld
+find-systype.sh
+make-compile.sh
+make-load.sh
+make-makelib.sh
+trycpp.c
+warn-auto.sh
+conf-qmail
+auto_qmail.h
+qmail.h
+qmail.c
+INSTALL
+hier.c
+auto-str.c
+install.c
+instcheck.c
+sgetopt.h
+sgetopt.c
+subgetopt.h
+subgetopt.c
+substdio.h
+substdio.c
+substdi.c
+substdo.c
+substdio_copy.c
+subfd.h
+subfderr.c
+readwrite.h
+exit.h
+strerr.h
+strerr_sys.c
+strerr_die.c
+byte.h
+byte_chr.c
+byte_copy.c
+byte_cr.c
+str.h
+str_diffn.c
+str_len.c
+error.h
+error.c
+error_str.c
+wait.h
+wait_pid.c
+trywaitp.c
+fork.h1
+fork.h2
+tryvfork.c
+fd.h
+fd_copy.c
+fd_move.c
+getln.h
+getln.c
+getln2.c
+gen_alloc.h
+gen_allocdefs.h
+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
+alloc.h
+alloc.c
+alloc_re.c
+env.h
+envread.c
+open.h
+open_read.c
+open_trunc.c
+sig.h
+sig_catch.c
+sig_pipe.c
+trysgact.c
+token822.h
+token822.c
+control.h
+control.c
+fmt.h
+fmt_ulong.c
+scan.h
+scan_ulong.c
+case.h
+case_diffb.c
+seek.h
+seek_set.c
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..3a70fd4
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,23 @@
+Like any other piece of software (and information generally),
+dot-forward comes with NO WARRANTY.
+
+
+Things you have to decide before starting:
+
+* The location of the qmail home directory, normally /var/qmail. (To
+change this directory, edit conf-qmail now.)
+
+
+How to install:
+
+ 1. Create and install the programs and man pages:
+       # make setup check
+
+ 2. With qmail 1.02 and above: To set up .forward handling for all
+    users, install a /var/qmail/rc script that invokes dot-forward.
+    Several scripts are supplied in /var/qmail/boot/*+df.
+
+
+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.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..188d9e9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,400 @@
+# Don't edit Makefile! Use conf-* for configuration.
+
+SHELL=/bin/sh
+
+default: it
+
+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-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_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
+
+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
+
+case.a: \
+makelib case_diffb.o
+       ./makelib case.a case_diffb.o
+
+case_diffb.o: \
+compile case_diffb.c case.h
+       ./compile case_diffb.c
+
+check: \
+it instcheck
+       ./instcheck
+
+compile: \
+make-compile warn-auto.sh systype
+       ( cat warn-auto.sh; ./make-compile "`cat systype`" ) > \
+       compile
+       chmod 755 compile
+
+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
+
+dot-forward: \
+load dot-forward.o control.o qmail.o auto_qmail.o token822.o env.a \
+getln.a getopt.a strerr.a error.a substdio.a stralloc.a alloc.a \
+case.a str.a sig.a seek.a open.a wait.a fd.a fs.a
+       ./load dot-forward control.o qmail.o auto_qmail.o \
+       token822.o env.a getln.a getopt.a strerr.a error.a \
+       substdio.a stralloc.a alloc.a case.a str.a sig.a seek.a \
+       open.a wait.a fd.a fs.a 
+
+dot-forward.0: \
+dot-forward.1
+       nroff -man dot-forward.1 > dot-forward.0
+
+dot-forward.o: \
+compile dot-forward.c sgetopt.h subgetopt.h substdio.h readwrite.h \
+stralloc.h gen_alloc.h getln.h strerr.h error.h exit.h open.h wait.h \
+seek.h env.h str.h fmt.h token822.h gen_alloc.h control.h qmail.h \
+substdio.h auto_qmail.h
+       ./compile dot-forward.c
+
+env.a: \
+makelib envread.o
+       ./makelib env.a envread.o
+
+envread.o: \
+compile envread.c env.h str.h
+       ./compile envread.c
+
+error.a: \
+makelib error.o error_str.o
+       ./makelib error.a error.o error_str.o
+
+error.o: \
+compile error.c error.h
+       ./compile error.c
+
+error_str.o: \
+compile error_str.c error.h
+       ./compile error_str.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
+
+find-systype: \
+find-systype.sh auto-ccld.sh
+       cat auto-ccld.sh find-systype.sh > find-systype
+       chmod 755 find-systype
+
+fmt_ulong.o: \
+compile fmt_ulong.c fmt.h
+       ./compile fmt_ulong.c
+
+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
+
+fs.a: \
+makelib fmt_ulong.o scan_ulong.o
+       ./makelib fs.a fmt_ulong.o scan_ulong.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
+
+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
+
+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
+
+hier.o: \
+compile hier.c auto_qmail.h
+       ./compile hier.c
+
+install: \
+load install.o hier.o auto_qmail.o strerr.a substdio.a error.a open.a \
+str.a
+       ./load install hier.o auto_qmail.o strerr.a substdio.a \
+       error.a open.a str.a 
+
+install.o: \
+compile install.c substdio.h strerr.h error.h open.h readwrite.h \
+exit.h
+       ./compile install.c
+
+instcheck: \
+load instcheck.o hier.o auto_qmail.o strerr.a substdio.a error.a \
+str.a
+       ./load instcheck hier.o auto_qmail.o strerr.a substdio.a \
+       error.a str.a 
+
+instcheck.o: \
+compile instcheck.c strerr.h error.h readwrite.h exit.h
+       ./compile instcheck.c
+
+it: \
+prog man
+
+load: \
+make-load warn-auto.sh systype
+       ( cat warn-auto.sh; ./make-load "`cat systype`" ) > load
+       chmod 755 load
+
+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: \
+dot-forward.0
+
+open.a: \
+makelib open_read.o open_trunc.o
+       ./makelib open.a open_read.o open_trunc.o
+
+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
+
+prog: \
+dot-forward
+
+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
+
+scan_ulong.o: \
+compile scan_ulong.c scan.h
+       ./compile scan_ulong.c
+
+seek.a: \
+makelib seek_set.o
+       ./makelib seek.a seek_set.o
+
+seek_set.o: \
+compile seek_set.c seek.h
+       ./compile seek_set.c
+
+setup: \
+it install
+       ./install
+
+sgetopt.o: \
+compile sgetopt.c substdio.h subfd.h substdio.h sgetopt.h subgetopt.h \
+subgetopt.h
+       ./compile sgetopt.c
+
+sig.a: \
+makelib sig_catch.o sig_pipe.o
+       ./makelib sig.a sig_catch.o sig_pipe.o
+
+sig_catch.o: \
+compile sig_catch.c sig.h hassgact.h
+       ./compile sig_catch.c
+
+sig_pipe.o: \
+compile sig_pipe.c sig.h
+       ./compile sig_pipe.c
+
+str.a: \
+makelib str_len.o str_diffn.o byte_chr.o byte_copy.o byte_cr.o
+       ./makelib str.a str_len.o str_diffn.o byte_chr.o \
+       byte_copy.o byte_cr.o
+
+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
+
+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
+       ./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_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
+
+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 substdio_copy.o
+       ./makelib substdio.a substdio.o substdi.o substdo.o \
+       subfderr.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
+
+systype: \
+find-systype trycpp.c
+       ./find-systype > systype
+
+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
+
+wait.a: \
+makelib wait_pid.o
+       ./makelib wait.a wait_pid.o
+
+wait_pid.o: \
+compile wait_pid.c error.h haswaitp.h
+       ./compile wait_pid.c
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..ce92402
--- /dev/null
+++ b/README
@@ -0,0 +1,23 @@
+dot-forward 0.71, beta.
+19980519
+Copyright 1998
+D. J. Bernstein, djb@pobox.com
+
+dot-forward reads sendmail's .forward files under qmail. See BLURB for a
+more detailed advertisement.
+
+INSTALL says how to set up dot-forward.
+
+You may distribute unmodified copies of the dot-forward package.
+
+The rest of this file is a list of systypes where various versions of
+dot-forward have been reported to work.
+
+0.70: bsd.os-2.0.1-:i386-:-:pentium-:-
+0.51: freebsd-2.2.2-release-:i386-:-:i486-dx-:- (tnx MM)
+0.51: freebsd-3.0-current-:i386-:-:pentium-:- (tnx KB)
+0.70: irix-5.3-11091811-:-:-:ip19-:- (tnx JB)
+0.51: linux-2.0.30-:i386-:-:pentium-:- (tnx MAP)
+0.51: linux-2.0.30-:i386-:-:ppro-:- (tnx LN)
+0.51: netbsd-1.2g-:i386-:-:intel.pentium.(p54c).(586-class)-:- (tnx GW)
+0.51: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4m-:sun4m- (tnx ESM)
diff --git a/SYSDEPS b/SYSDEPS
new file mode 100644 (file)
index 0000000..db3eae2
--- /dev/null
+++ b/SYSDEPS
@@ -0,0 +1,5 @@
+VERSION
+systype
+fork.h
+hassgact.h
+haswaitp.h
diff --git a/TARGETS b/TARGETS
new file mode 100644 (file)
index 0000000..c5ce7f5
--- /dev/null
+++ b/TARGETS
@@ -0,0 +1,88 @@
+auto-ccld.sh
+make-load
+find-systype
+systype
+load
+make-compile
+compile
+dot-forward.o
+control.o
+fork.h
+qmail.o
+auto-str.o
+make-makelib
+makelib
+substdio.o
+substdi.o
+substdo.o
+subfderr.o
+substdio_copy.o
+substdio.a
+error.o
+error_str.o
+error.a
+str_len.o
+str_diffn.o
+byte_chr.o
+byte_copy.o
+byte_cr.o
+str.a
+auto-str
+auto_qmail.c
+auto_qmail.o
+token822.o
+envread.o
+env.a
+getln.o
+getln2.o
+getln.a
+subgetopt.o
+sgetopt.o
+getopt.a
+strerr_sys.o
+strerr_die.o
+strerr.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.a
+alloc.o
+alloc_re.o
+alloc.a
+case_diffb.o
+case.a
+hassgact.h
+sig_catch.o
+sig_pipe.o
+sig.a
+seek_set.o
+seek.a
+open_read.o
+open_trunc.o
+open.a
+haswaitp.h
+wait_pid.o
+wait.a
+fd_copy.o
+fd_move.o
+fd.a
+fmt_ulong.o
+scan_ulong.o
+fs.a
+dot-forward
+prog
+dot-forward.0
+man
+it
+install.o
+hier.o
+install
+setup
+instcheck.o
+instcheck
+check
diff --git a/THANKS b/THANKS
new file mode 100644 (file)
index 0000000..70c4bad
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,7 @@
+ESM = Edward S. Marshall
+GW = Geoff Wing
+JB = Jos Backus
+KB = Keith Burdis
+LN = Lukas Nellen
+MAP = Michael A. Peck
+MM = Martin Mersberger
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..9daeafb
--- /dev/null
+++ b/TODO
@@ -0,0 +1 @@
+test
diff --git a/VERSION b/VERSION
new file mode 100644 (file)
index 0000000..5f3e574
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+dot-forward 0.71
diff --git a/alloc.c b/alloc.c
new file mode 100644 (file)
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 (file)
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 (file)
index 0000000..feb8b49
--- /dev/null
@@ -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-str.c b/auto-str.c
new file mode 100644 (file)
index 0000000..acc3d60
--- /dev/null
@@ -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_qmail.h b/auto_qmail.h
new file mode 100644 (file)
index 0000000..0c56001
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef AUTO_QMAIL_H
+#define AUTO_QMAIL_H
+
+extern char auto_qmail[];
+
+#endif
diff --git a/byte.h b/byte.h
new file mode 100644 (file)
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 (file)
index 0000000..f81dde8
--- /dev/null
@@ -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 (file)
index 0000000..eaad11b
--- /dev/null
@@ -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 (file)
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/case.h b/case.h
new file mode 100644 (file)
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 (file)
index 0000000..9064b8a
--- /dev/null
@@ -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/conf-cc b/conf-cc
new file mode 100644 (file)
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-ld b/conf-ld
new file mode 100644 (file)
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-qmail b/conf-qmail
new file mode 100644 (file)
index 0000000..a988177
--- /dev/null
@@ -0,0 +1,7 @@
+/var/qmail
+
+This is the qmail home directory.
+
+The dot-forward program will be installed in the bin subdirectory; it
+also needs to know where qmail is so that it can handle unqualified host
+names and forward mail properly.
diff --git a/control.c b/control.c
new file mode 100644 (file)
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 (file)
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/dot-forward.1 b/dot-forward.1
new file mode 100644 (file)
index 0000000..a8b90b1
--- /dev/null
@@ -0,0 +1,246 @@
+.TH dot-forward 1
+.SH NAME
+dot-forward \- read a .forward file under qmail
+.SH SYNOPSIS
+in
+.BR ~/.qmail :
+.B | dot-forward
+[
+.B \-nN
+]
+.I file ...
+.SH OVERVIEW
+.B dot-forward
+forwards incoming messages according to
+sendmail-style
+instructions in
+.IR file ,
+if
+.I file
+exists.
+Normally
+.I file
+is
+.BR .forward .
+
+.B WARNING:
+If you create a
+.B .qmail
+file to enable
+.BR dot-forward ,
+make sure to add a second line specifying delivery to your normal mailbox.
+For example:
+
+.EX
+   |dot-forward .forward
+.br
+   ./Mailbox
+.EE
+
+.B COMPATIBILITY WARNING:
+.B dot-forward
+does not support
+.B :include:
+or mbox deliveries.
+You can use the delivery mechanism described in
+.BR dot-qmail (5)
+instead.
+.SH OPTIONS
+.TP 5
+.B \-N
+(Default.)
+Read and forward a message.
+.TP
+.B \-n
+Parse
+.I file
+and print the forwarding instructions in it, one per line;
+do not follow the instructions.
+You can use this option from the command line to see how your
+.B .forward
+file will be interpreted:
+
+.EX
+   dot-forward -n .forward
+.EE
+.SH "FILE HANDLING"
+When a message arrives,
+.B dot-forward
+opens
+.I file
+and handles it as discussed below.
+It exits 99, so
+.B qmail-local
+will ignore further instructions in
+.BR .qmail .
+Exception: If
+.I file
+specifies delivery directly to you,
+.B dot-forward
+exits 0, so
+.B qmail-local
+will read further instructions in
+.BR .qmail .
+
+If
+.I file
+does not exist,
+.B dot-forward
+exits 0.
+You can list several
+.IR file s;
+then
+.B dot-forward
+will try each one in turn,
+using the first one that exists,
+or exiting 0 if none exist.
+
+.B COMPATIBILITY WARNING:
+.B dot-forward
+treats an empty
+.I file
+as if it did not exist.
+Versions of
+sendmail
+before V8 would throw away the incoming message.
+
+.B COMPATIBILITY WARNING:
+If
+.B dot-forward
+encounters a temporary error opening
+.IR file ,
+it exits 111, so that
+.B qmail-local
+will try again later.
+sendmail
+assumes incorrectly that
+.I file
+does not exist.
+
+.B COMPATIBILITY WARNING:
+.I file
+must be readable by
+.BR dot-forward ,
+which is normally running as the user.
+sendmail
+places different constraints on its
+.B .forward
+permissions,
+since it is normally running as root.
+.SH "FORWARDING"
+Normally
+.I file
+contains an address.
+.B dot-forward
+forwards the message to that address.
+
+The address is parsed as if it were in an RFC 822 message header.
+Parenthesized comments and bracketed addresses are permitted:
+
+.EX
+   bob (Bob, the postmaster) @heaven.af.mil
+.EE
+
+Addresses with special characters must be quoted:
+
+.EX
+   "spaced out mailbox"@heaven.af.mil
+.EE
+
+Address groups are not permitted.
+
+.I file
+can contain any number of lines,
+each line containing any number of addresses.
+.B dot-forward
+forwards the message to each address:
+
+.EX
+   bob, fred, susan
+.br
+   Joe Shmoe <shmoe@heaven.af.mil>
+.EE
+
+An address without a fully qualified domain name is handled
+as described in
+.BR qmail-header (5).
+Exception: Certain addresses without domain names are handled specially,
+as described below.
+.SH "DIRECT DELIVERY"
+If an address does not contain a domain name,
+and matches the environment variable
+.B $USER
+(without regard to case),
+it specifies delivery directly to you.
+
+If an address matches
+.B $USER@$HOST
+(without regard to case),
+it specifies delivery directly to you.
+
+.B COMPATIBILITY WARNING:
+sendmail's
+handling of quotes and backslashes violates RFC 821 and RFC 822,
+and is not supported by
+.BR dot-forward .
+.B dot-forward
+treats
+.B \ejoe
+the same way as
+.BR joe .
+The
+.B dot-qmail
+delivery mechanism
+lets each user manage several addresses,
+so there is no need for a special syntax to get around forwarding.
+.SH "COMMANDS"
+If an address does not contain a domain name,
+and begins with a vertical bar,
+.B dot-forward
+takes the rest of the address as a command to run:
+
+.EX
+   bob, "|vacation bob"
+.EE
+
+.B dot-forward
+feeds the message to the command,
+preceded by the environment variables
+.BR $UFLINE ,
+.BR $RPLINE ,
+and
+.BR $DTLINE .
+
+.B COMPATIBILITY WARNING:
+Internet addresses can legitimately start with a slash or vertical bar.
+.B dot-forward
+treats anything with an unquoted @ as an address.
+sendmail
+appears to have various problems coping with these addresses,
+and with commands that contain @ signs.
+.SH "COMMENTS"
+Any line in
+.I file
+that begins with # is ignored:
+
+.EX
+   # this is a comment
+.EE
+
+.B COMPATIBILITY WARNING:
+Versions of
+sendmail
+before V8 did not allow comments in
+.B .forward
+files.
+.SH VERSION
+This is
+.B dot-forward
+0.71.
+The
+.B dot-forward
+home page is
+.BR http://pobox.com/~djb/dot-forward.html .
+.SH "SEE ALSO"
+qmail-header(5),
+dot-qmail(5)
diff --git a/dot-forward.c b/dot-forward.c
new file mode 100644 (file)
index 0000000..66510ad
--- /dev/null
@@ -0,0 +1,419 @@
+#include "sgetopt.h"
+#include "substdio.h"
+#include "readwrite.h"
+#include "stralloc.h"
+#include "getln.h"
+#include "strerr.h"
+#include "error.h"
+#include "exit.h"
+#include "open.h"
+#include "wait.h"
+#include "seek.h"
+#include "env.h"
+#include "str.h"
+#include "fmt.h"
+#include "token822.h"
+#include "control.h"
+#include "qmail.h"
+#include "auto_qmail.h"
+
+#define FATAL "dot-forward: fatal: "
+#define INFO "dot-forward: info: "
+
+void die_nomem()
+{ strerr_die2x(111,FATAL,"out of memory"); }
+void die_control()
+{ strerr_die2sys(111,FATAL,"unable to read controls: "); }
+void die_qq()
+{ strerr_die2sys(111,FATAL,"unable to run qq: "); }
+void die_readmess()
+{ strerr_die2sys(111,FATAL,"unable to read message: "); }
+
+stralloc line = {0};
+
+void die_parse()
+{
+  if (!stralloc_0(&line)) die_nomem();
+  strerr_die3x(111,FATAL,"unable to parse this line: ",line.s);
+}
+
+int flagdoit = 1;
+int flagacted;
+int flagdirect;
+
+char *ufline;
+char *rpline;
+char *dtline;
+char *sender;
+char *user;
+int userlen;
+char *host;
+int hostlen;
+
+char messbuf[1024];
+substdio ssmess;
+char childbuf[1024];
+substdio sschild;
+
+int blindwrite(fd,buf,len)
+int fd; char *buf; int len;
+{
+  write(fd,buf,len);
+  return len;
+}
+
+void run(cmd)
+char *cmd;
+{
+  int child;
+  int pi[2];
+  char *args[4];
+  int wstat;
+
+  if (!flagdoit) {
+    strerr_warn2("pipe through ",cmd,0);
+    return;
+  }
+
+  if (pipe(pi) == -1)
+    strerr_die2sys(111,FATAL,"unable to create pipe: ");
+
+  switch (child = fork()) {
+    case -1:
+      strerr_die2sys(111,FATAL,"unable to fork: ");
+    case 0:
+      close(pi[1]);
+      if (fd_move(0,pi[0]) == -1)
+        strerr_die2sys(111,FATAL,"unable to set fd: ");
+      args[0] = "/bin/sh"; args[1] = "-c"; args[2] = cmd; args[3] = 0;
+      sig_pipedefault();
+      execv(*args,args);
+      strerr_die2sys(111,FATAL,"unable to run /bin/sh: ");
+  }
+
+  close(pi[0]);
+
+  substdio_fdbuf(&ssmess,read,0,messbuf,sizeof messbuf);
+  substdio_fdbuf(&sschild,blindwrite,pi[1],childbuf,sizeof childbuf);
+
+  substdio_puts(&sschild,ufline);
+  substdio_puts(&sschild,rpline);
+  substdio_puts(&sschild,dtline);
+  if (substdio_copy(&sschild,&ssmess) != 0) die_readmess();
+  substdio_flush(&sschild);
+
+  close(pi[1]);
+
+  wait_pid(&wstat,child);
+  if (wait_crashed(wstat))
+    strerr_die2x(111,FATAL,"child crashed");
+
+  switch(wait_exitcode(wstat)) {
+    case 100:
+    case 64: case 65: case 70: case 76: case 77: case 78: case 112:
+      _exit(100);
+    case 0:
+      break;
+    default:
+      _exit(111);
+  }
+
+  if (seek_begin(0) == -1)
+    strerr_die2sys(111,FATAL,"unable to rewind input: ");
+}
+
+stralloc targets = {0};
+
+stralloc me = {0};
+stralloc defaulthost = {0};
+stralloc defaultdomain = {0};
+stralloc plusdomain = {0};
+
+void readcontrols()
+{
+  int r;
+  int fddir;
+
+  fddir = open_read(".");
+  if (fddir == -1)
+    strerr_die2sys(111,FATAL,"unable to open current directory: ");
+
+  if (chdir(auto_qmail) == -1)
+    strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": ");
+
+  r = control_readline(&me,"control/me");
+  if (r == -1) die_control();
+  if (!r) if (!stralloc_copys(&me,"me")) die_nomem();
+
+  r = control_readline(&defaultdomain,"control/defaultdomain");
+  if (r == -1) die_control();
+  if (!r) if (!stralloc_copy(&defaultdomain,&me)) die_nomem();
+
+  r = control_readline(&defaulthost,"control/defaulthost");
+  if (r == -1) die_control();
+  if (!r) if (!stralloc_copy(&defaulthost,&me)) die_nomem();
+
+  r = control_readline(&plusdomain,"control/plusdomain");
+  if (r == -1) die_control();
+  if (!r) if (!stralloc_copy(&plusdomain,&me)) die_nomem();
+
+  if (fchdir(fddir) == -1)
+    strerr_die2sys(111,FATAL,"unable to set current directory: ");
+}
+
+stralloc cbuf = {0};
+token822_alloc toks = {0};
+token822_alloc tokaddr = {0};
+stralloc address = {0};
+
+void gotaddr()
+{
+  int i;
+  int j;
+  int flaghasat;
+  token822_reverse(&tokaddr);
+  if (token822_unquote(&address,&tokaddr) != 1) die_nomem();
+  flaghasat = 0;
+  for (i = 0;i < tokaddr.len;++i)
+    if (tokaddr.t[i].type == TOKEN822_AT)
+      flaghasat = 1;
+  tokaddr.len = 0;
+
+  if (!address.len) return;
+
+  if (!flaghasat)
+    if (address.len == userlen)
+      if (!case_diffb(address.s,address.len,user)) {
+        flagacted = 1;
+        flagdirect = 1;
+        return;
+      }
+
+  if (flaghasat)
+    if (address.len == userlen + 1 + hostlen)
+      if (!case_diffb(address.s,userlen,user))
+        if (address.s[userlen] == '@')
+          if (!case_diffb(address.s + userlen + 1,hostlen,host)) {
+            flagacted = 1;
+            flagdirect = 1;
+            return;
+          }
+
+  if (!flaghasat)
+    if (address.s[0] == '/') {
+      if (!stralloc_0(&address)) die_nomem();
+      strerr_die4x(111,FATAL,"file delivery ",address.s," not supported");
+    }
+
+  if (!flaghasat)
+    if (address.s[0] == '|') {
+      if (!stralloc_0(&address)) die_nomem();
+      flagacted = 1;
+      run(address.s + 1);
+      return;
+    }
+
+  if (!flaghasat) {
+    if (!stralloc_cats(&address,"@")) die_nomem();
+    if (!stralloc_cat(&address,&defaulthost)) die_nomem();
+  }
+  if (address.s[address.len - 1] == '+') {
+    address.s[address.len - 1] = '.';
+    if (!stralloc_cat(&address,&plusdomain)) die_nomem();
+  }
+  j = 0;
+  for (i = 0;i < address.len;++i) if (address.s[i] == '@') j = i;
+  for (i = j;i < address.len;++i) if (address.s[i] == '.') break;
+  if (i == address.len) {
+    if (!stralloc_cats(&address,".")) die_nomem();
+    if (!stralloc_cat(&address,&defaultdomain)) die_nomem();
+  }
+
+  if (!stralloc_0(&address)) die_nomem();
+
+  if (!stralloc_cats(&targets,"T")) die_nomem();
+  if (!stralloc_cats(&targets,address.s)) die_nomem();
+  if (!stralloc_0(&targets)) die_nomem();
+
+  if (!flagdoit)
+    strerr_warn2("forward ",address.s,0);
+}
+
+void parseline()
+{
+  int wordok;
+  struct token822 *t;
+  struct token822 *beginning;
+  int r;
+
+  r = token822_parse(&toks,&line,&cbuf);
+  if (r == -1) die_nomem();
+  if (r == 0) die_parse();
+
+  beginning = toks.t;
+  t = toks.t + toks.len;
+  wordok = 1;
+
+  if (!token822_readyplus(&tokaddr,1)) die_nomem();
+  tokaddr.len = 0;
+  while (t > beginning)
+    switch((--t)->type) {
+      case TOKEN822_SEMI:
+        break; /*XXX*/
+      case TOKEN822_COLON:
+        break; /*XXX*/
+      case TOKEN822_RIGHT:
+        if (tokaddr.len) gotaddr();
+        while ((t > beginning) && (t[-1].type != TOKEN822_LEFT))
+          if (!token822_append(&tokaddr,--t)) die_nomem();
+        gotaddr();
+        if (t <= beginning) die_parse();
+        --t;
+        while ((t > beginning) && ((t[-1].type == TOKEN822_COMMENT) || (t[-1].type == TOKEN822_ATOM) || (t[-1].type == TOKEN822_QUOTE) || (t[-1].type == TOKEN822_AT) || (t[-1].type == TOKEN822_DOT)))
+          --t;
+        wordok = 0;
+        continue;
+      case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL:
+        if (!wordok) if (tokaddr.len) gotaddr();
+        wordok = 0;
+        if (!token822_append(&tokaddr,t)) die_nomem();
+        continue;
+      case TOKEN822_COMMENT:
+        /* comment is lexically a space; shouldn't affect wordok */
+        break;
+      case TOKEN822_COMMA:
+        if (tokaddr.len) gotaddr();
+        wordok = 1;
+        break;
+      default:
+        wordok = 1;
+        if (!token822_append(&tokaddr,t)) die_nomem();
+        continue;
+    }
+  if (tokaddr.len) gotaddr();
+}
+
+struct qmail qq;
+unsigned long qp;
+char *qqx;
+char strnum[FMT_ULONG];
+
+int mywrite(fd,buf,len)
+int fd; char *buf; int len;
+{
+  qmail_put(&qq,buf,len);
+  return len;
+}
+
+char qqbuf[256];
+substdio ssqq = SUBSTDIO_FDBUF(mywrite,-1,qqbuf,sizeof qqbuf);
+
+char inbuf[256];
+
+void try(fn)
+char *fn;
+{
+  int fd;
+  int match;
+  substdio ss;
+
+  fd = open_read(fn);
+  if (fd == -1) {
+    if (errno == error_noent) return;
+    strerr_die4sys(111,FATAL,"unable to open ",fn,": ");
+  }
+
+  if (!stralloc_copys(&targets,"")) die_nomem();
+  flagacted = 0;
+  flagdirect = 0;
+
+  substdio_fdbuf(&ss,read,fd,inbuf,sizeof inbuf);
+
+  for (;;) {
+    if (getln(&ss,&line,&match,'\n') == -1)
+      strerr_die4sys(111,FATAL,"unable to read ",fn,": ");
+    if (!line.len) break;
+    if (line.s[0] != '#') parseline();
+    if (!match) break;
+  }
+
+  close(fd);
+
+  if (targets.len) {
+    flagacted = 1;
+    if (flagdoit) {
+      if (qmail_open(&qq) == -1)
+        strerr_die2sys(111,FATAL,"unable to run qmail-queue: ");
+      qp = qmail_qp(&qq);
+      qmail_puts(&qq,dtline);
+
+      substdio_fdbuf(&ssmess,read,0,messbuf,sizeof messbuf);
+      if (substdio_copy(&ssqq,&ssmess) != 0) die_readmess();
+      substdio_flush(&ssqq);
+
+      qmail_from(&qq,sender);
+      qmail_put(&qq,targets.s,targets.len);
+
+      qqx = qmail_close(&qq);
+      if (*qqx == 'D')
+        strerr_die3x(100,FATAL,"unable to forward message: ",qqx + 1);
+      if (*qqx)
+        strerr_die3x(111,FATAL,"unable to forward message: ",qqx + 1);
+      strnum[fmt_ulong(strnum,qp)] = 0;
+      strerr_warn3(INFO,"qp ",strnum,0);
+    }
+  }
+
+  if (flagdirect) {
+    if (!flagdoit) strerr_warn1("direct delivery",0);
+    _exit(0);
+  }
+  if (!flagacted) {
+    if (!flagdoit) strerr_warn2("skipping empty file ",fn,0);
+    return;
+  }
+  _exit(99);
+}
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+  int opt;
+  int fddir;
+
+  sig_pipeignore();
+
+  while ((opt = getopt(argc,argv,"nN")) != opteof)
+    switch(opt) {
+      case 'n':
+        flagdoit = 0; break;
+      case 'N':
+        flagdoit = 1; break;
+      default:
+        strerr_die1x(100,"dot-forward: usage: dot-forward [ -nN ] file ...");
+    }
+  argv += optind;
+
+  ufline = env_get("UFLINE"); if (!ufline) ufline = "";
+  rpline = env_get("RPLINE"); if (!rpline) rpline = "";
+  dtline = env_get("DTLINE"); if (!dtline) dtline = "";
+  sender = env_get("NEWSENDER"); if (!sender) sender = "";
+
+  user = env_get("USER"); if (!user) user = "";
+  userlen = str_len(user);
+  host = env_get("HOST"); if (!host) host = "";
+  hostlen = str_len(host);
+
+  readcontrols();
+
+  while (*argv)
+    try(*argv++);
+
+  if (!flagdoit) strerr_warn1("direct delivery",0);
+  _exit(0);
+}
diff --git a/env.h b/env.h
new file mode 100644 (file)
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/envread.c b/envread.c
new file mode 100644 (file)
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.c b/error.c
new file mode 100644 (file)
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 (file)
index 0000000..01bd3dc
--- /dev/null
+++ b/error.h
@@ -0,0 +1,23 @@
+#ifndef ERROR_H
+#define ERROR_H
+
+extern int errno;
+
+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.c b/error_str.c
new file mode 100644 (file)
index 0000000..804d1fa
--- /dev/null
@@ -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/exit.h b/exit.h
new file mode 100644 (file)
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/fd.h b/fd.h
new file mode 100644 (file)
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.c b/fd_copy.c
new file mode 100644 (file)
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.c b/fd_move.c
new file mode 100644 (file)
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/find-systype.sh b/find-systype.sh
new file mode 100644 (file)
index 0000000..16266d3
--- /dev/null
@@ -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 (file)
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_ulong.c b/fmt_ulong.c
new file mode 100644 (file)
index 0000000..ab12e8c
--- /dev/null
@@ -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/fork.h1 b/fork.h1
new file mode 100644 (file)
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 (file)
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/gen_alloc.h b/gen_alloc.h
new file mode 100644 (file)
index 0000000..b94a956
--- /dev/null
@@ -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 (file)
index 0000000..783a9b1
--- /dev/null
@@ -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.c b/getln.c
new file mode 100644 (file)
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 (file)
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.c b/getln2.c
new file mode 100644 (file)
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/hier.c b/hier.c
new file mode 100644 (file)
index 0000000..05a32cb
--- /dev/null
+++ b/hier.c
@@ -0,0 +1,16 @@
+#include "auto_qmail.h"
+
+void hier()
+{
+  h(auto_qmail,-1,-1,0755);
+
+  d(auto_qmail,"bin",-1,-1,0755);
+  d(auto_qmail,"man",-1,-1,0755);
+  d(auto_qmail,"man/man1",-1,-1,0755);
+  d(auto_qmail,"man/cat1",-1,-1,0755);
+
+  c(auto_qmail,"bin","dot-forward",-1,-1,0755);
+
+  c(auto_qmail,"man/man1","dot-forward.1",-1,-1,0644);
+  c(auto_qmail,"man/cat1","dot-forward.0",-1,-1,0644);
+}
diff --git a/install.c b/install.c
new file mode 100644 (file)
index 0000000..beec00c
--- /dev/null
+++ b/install.c
@@ -0,0 +1,111 @@
+#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,": ");
+}
+
+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 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 (file)
index 0000000..0b77e45
--- /dev/null
@@ -0,0 +1,83 @@
+#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 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 main()
+{
+  hier();
+  _exit(0);
+}
diff --git a/make-compile.sh b/make-compile.sh
new file mode 100644 (file)
index 0000000..a1eb501
--- /dev/null
@@ -0,0 +1 @@
+echo exec "$CC" -c '${1+"$@"}'
diff --git a/make-load.sh b/make-load.sh
new file mode 100644 (file)
index 0000000..de07d2e
--- /dev/null
@@ -0,0 +1,2 @@
+echo 'main="$1"; shift'
+echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}'
diff --git a/make-makelib.sh b/make-makelib.sh
new file mode 100644 (file)
index 0000000..d6b7c8c
--- /dev/null
@@ -0,0 +1,16 @@
+echo 'main="$1"; shift'
+echo 'rm -f "$main"'
+echo 'ar cr "$main" ${1+"$@"}'
+
+case "$1" in
+sunos-5.*) ;;
+unix_sv*) ;;
+irix64-*) ;;
+irix-*) ;;
+dgux-*) ;;
+hp-ux-*) ;;
+sco*) ;;
+*)
+  echo 'ranlib "$main"'
+  ;;
+esac
diff --git a/open.h b/open.h
new file mode 100644 (file)
index 0000000..c903113
--- /dev/null
+++ b/open.h
@@ -0,0 +1,10 @@
+#ifndef OPEN_H
+#define OPEN_H
+
+extern int open_read();
+extern int open_excl();
+extern int open_append();
+extern int open_trunc();
+extern int open_write();
+
+#endif
diff --git a/open_read.c b/open_read.c
new file mode 100644 (file)
index 0000000..f503e48
--- /dev/null
@@ -0,0 +1,6 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "open.h"
+
+int open_read(fn) char *fn;
+{ return open(fn,O_RDONLY | O_NDELAY); }
diff --git a/open_trunc.c b/open_trunc.c
new file mode 100644 (file)
index 0000000..e275085
--- /dev/null
@@ -0,0 +1,6 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "open.h"
+
+int open_trunc(fn) char *fn;
+{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); }
diff --git a/qmail.c b/qmail.c
new file mode 100644 (file)
index 0000000..0fe0dfa
--- /dev/null
+++ b/qmail.c
@@ -0,0 +1,125 @@
+#include "substdio.h"
+#include "readwrite.h"
+#include "wait.h"
+#include "exit.h"
+#include "fork.h"
+#include "fd.h"
+#include "qmail.h"
+#include "auto_qmail.h"
+
+static char *binqqargs[2] = { "bin/qmail-queue", 0 } ;
+
+int qmail_open(qq)
+struct qmail *qq;
+{
+  int pim[2];
+  int pie[2];
+
+  if (pipe(pim) == -1) return -1;
+  if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
+  switch(qq->pid = vfork()) {
+    case -1:
+      close(pim[0]); close(pim[1]);
+      close(pie[0]); close(pie[1]);
+      return -1;
+    case 0:
+      close(pim[1]);
+      close(pie[1]);
+      if (fd_move(0,pim[0]) == -1) _exit(120);
+      if (fd_move(1,pie[0]) == -1) _exit(120);
+      if (chdir(auto_qmail) == -1) _exit(61);
+      execv(*binqqargs,binqqargs);
+      _exit(120);
+  }
+
+  qq->fdm = pim[1]; close(pim[0]);
+  qq->fde = pie[1]; close(pie[0]);
+  substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf));
+  qq->flagerr = 0;
+  return 0;
+}
+
+unsigned long qmail_qp(qq) struct qmail *qq;
+{
+  return qq->pid;
+}
+
+void qmail_fail(qq) struct qmail *qq;
+{
+  qq->flagerr = 1;
+}
+
+void qmail_put(qq,s,len) struct qmail *qq; char *s; int len;
+{
+  if (!qq->flagerr) if (substdio_put(&qq->ss,s,len) == -1) qq->flagerr = 1;
+}
+
+void qmail_puts(qq,s) struct qmail *qq; char *s;
+{
+  if (!qq->flagerr) if (substdio_puts(&qq->ss,s) == -1) qq->flagerr = 1;
+}
+
+void qmail_from(qq,s) struct qmail *qq; char *s;
+{
+  if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
+  close(qq->fdm);
+  substdio_fdbuf(&qq->ss,write,qq->fde,qq->buf,sizeof(qq->buf));
+  qmail_put(qq,"F",1);
+  qmail_puts(qq,s);
+  qmail_put(qq,"",1);
+}
+
+void qmail_to(qq,s) struct qmail *qq; char *s;
+{
+  qmail_put(qq,"T",1);
+  qmail_puts(qq,s);
+  qmail_put(qq,"",1);
+}
+
+char *qmail_close(qq)
+struct qmail *qq;
+{
+  int wstat;
+  int exitcode;
+
+  qmail_put(qq,"",1);
+  if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
+  close(qq->fde);
+
+  if (wait_pid(&wstat,qq->pid) != qq->pid)
+    return "Zqq waitpid surprise (#4.3.0)";
+  if (wait_crashed(wstat))
+    return "Zqq crashed (#4.3.0)";
+  exitcode = wait_exitcode(wstat);
+
+  switch(exitcode) {
+    case 115: /* compatibility */
+    case 11: return "Denvelope address too long for qq (#5.1.3)";
+    case 31: return "Dmail server permanently rejected message (#5.3.0)";
+    case 51: return "Zqq out of memory (#4.3.0)";
+    case 52: return "Zqq timeout (#4.3.0)";
+    case 53: return "Zqq write error or disk full (#4.3.0)";
+    case 0: if (!qq->flagerr) return ""; /* fall through */
+    case 54: return "Zqq read error (#4.3.0)";
+    case 55: return "Zqq unable to read configuration (#4.3.0)";
+    case 56: return "Zqq trouble making network connection (#4.3.0)";
+    case 61: return "Zqq trouble in home directory (#4.3.0)";
+    case 63:
+    case 64:
+    case 65:
+    case 66:
+    case 62: return "Zqq trouble creating files in queue (#4.3.0)";
+    case 71: return "Zmail server temporarily rejected message (#4.3.0)";
+    case 72: return "Zconnection to mail server timed out (#4.4.1)";
+    case 73: return "Zconnection to mail server rejected (#4.4.1)";
+    case 74: return "Zcommunication with mail server failed (#4.4.2)";
+    case 91: /* fall through */
+    case 81: return "Zqq internal bug (#4.3.0)";
+    case 120: return "Zunable to exec qq (#4.3.0)";
+    default:
+      if ((exitcode >= 11) && (exitcode <= 40))
+       return "Dqq permanent problem (#5.3.0)";
+      return "Zqq temporary problem (#4.3.0)";
+  }
+}
diff --git a/qmail.h b/qmail.h
new file mode 100644 (file)
index 0000000..7fa13e2
--- /dev/null
+++ b/qmail.h
@@ -0,0 +1,24 @@
+#ifndef QMAIL_H
+#define QMAIL_H
+
+#include "substdio.h"
+
+struct qmail {
+  int flagerr;
+  unsigned long pid;
+  int fdm;
+  int fde;
+  substdio ss;
+  char buf[1024];
+} ;
+
+extern int qmail_open();
+extern void qmail_put();
+extern void qmail_puts();
+extern void qmail_from();
+extern void qmail_to();
+extern void qmail_fail();
+extern char *qmail_close();
+extern unsigned long qmail_qp();
+
+#endif
diff --git a/readwrite.h b/readwrite.h
new file mode 100644 (file)
index 0000000..2a64968
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef READWRITE_H
+#define READWRITE_H
+
+extern int read();
+extern int write();
+
+#endif
diff --git a/scan.h b/scan.h
new file mode 100644 (file)
index 0000000..53ce703
--- /dev/null
+++ b/scan.h
@@ -0,0 +1,27 @@
+#ifndef SCAN_H
+#define SCAN_H
+
+extern unsigned int scan_uint();
+extern unsigned int scan_xint();
+extern unsigned int scan_nbbint();
+extern unsigned int scan_ushort();
+extern unsigned int scan_xshort();
+extern unsigned int scan_nbbshort();
+extern unsigned int scan_ulong();
+extern unsigned int scan_xlong();
+extern unsigned int scan_nbblong();
+
+extern unsigned int scan_plusminus();
+extern unsigned int scan_0x();
+
+extern unsigned int scan_whitenskip();
+extern unsigned int scan_nonwhitenskip();
+extern unsigned int scan_charsetnskip();
+extern unsigned int scan_noncharsetnskip();
+
+extern unsigned int scan_strncmp();
+extern unsigned int scan_memcmp();
+
+extern unsigned int scan_long();
+
+#endif
diff --git a/scan_ulong.c b/scan_ulong.c
new file mode 100644 (file)
index 0000000..27c41ea
--- /dev/null
@@ -0,0 +1,11 @@
+#include "scan.h"
+
+unsigned int scan_ulong(s,u) register char *s; register unsigned long *u;
+{
+  register unsigned int pos; register unsigned long result;
+  register unsigned long c;
+  pos = 0; result = 0;
+  while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10)
+    { result = result * 10 + c; ++pos; }
+  *u = result; return pos;
+}
diff --git a/seek.h b/seek.h
new file mode 100644 (file)
index 0000000..964fba3
--- /dev/null
+++ b/seek.h
@@ -0,0 +1,15 @@
+#ifndef SEEK_H
+#define SEEK_H
+
+typedef unsigned long seek_pos;
+
+extern seek_pos seek_cur();
+
+extern int seek_set();
+extern int seek_end();
+
+extern int seek_trunc();
+
+#define seek_begin(fd) (seek_set((fd),(seek_pos) 0))
+
+#endif
diff --git a/seek_set.c b/seek_set.c
new file mode 100644 (file)
index 0000000..f540664
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/types.h>
+#include "seek.h"
+
+#define SET 0 /* sigh */
+
+int seek_set(fd,pos) int fd; seek_pos pos;
+{ if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; }
diff --git a/sgetopt.c b/sgetopt.c
new file mode 100644 (file)
index 0000000..a8bffc0
--- /dev/null
+++ b/sgetopt.c
@@ -0,0 +1,54 @@
+/* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer
+D. J. Bernstein, djb@pobox.com.
+Depends on subgetopt.h, substdio.h, subfd.h.
+No system requirements.
+19970208: Cleanups.
+931201: Baseline.
+No known patent problems.
+
+Documentation in sgetopt.3.
+*/
+
+#include "substdio.h"
+#include "subfd.h"
+#define SGETOPTNOSHORT
+#include "sgetopt.h"
+#define SUBGETOPTNOSHORT
+#include "subgetopt.h"
+
+#define getopt sgetoptmine
+#define optind subgetoptind
+#define opterr sgetopterr
+#define optproblem subgetoptproblem
+#define optprogname sgetoptprogname
+
+int opterr = 1;
+char *optprogname = 0;
+
+int getopt(argc,argv,opts)
+int argc;
+char **argv;
+char *opts;
+{
+  int c;
+  char *s;
+
+  if (!optprogname) {
+    optprogname = *argv;
+    if (!optprogname) optprogname = "";
+    for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1;
+  }
+  c = subgetopt(argc,argv,opts);
+  if (opterr)
+    if (c == '?') {
+      char chp[2]; chp[0] = optproblem; chp[1] = '\n';
+      substdio_puts(subfderr,optprogname);
+      if (argv[optind] && (optind < argc))
+        substdio_puts(subfderr,": illegal option -- ");
+      else
+        substdio_puts(subfderr,": option requires an argument -- ");
+      substdio_put(subfderr,chp,2);
+      substdio_flush(subfderr);
+    }
+  return c;
+}
diff --git a/sgetopt.h b/sgetopt.h
new file mode 100644 (file)
index 0000000..5f89127
--- /dev/null
+++ b/sgetopt.h
@@ -0,0 +1,21 @@
+#ifndef SGETOPT_H
+#define SGETOPT_H
+
+#ifndef SGETOPTNOSHORT
+#define getopt sgetoptmine
+#define optarg subgetoptarg
+#define optind subgetoptind
+#define optpos subgetoptpos
+#define opterr sgetopterr
+#define optproblem subgetoptproblem
+#define optprogname sgetoptprogname
+#define opteof subgetoptdone
+#endif
+
+#include "subgetopt.h"
+
+extern int sgetoptmine();
+extern int sgetopterr;
+extern char *sgetoptprogname;
+
+#endif
diff --git a/sig.h b/sig.h
new file mode 100644 (file)
index 0000000..9c3a28c
--- /dev/null
+++ b/sig.h
@@ -0,0 +1,43 @@
+#ifndef SIG_H
+#define SIG_H
+
+extern void sig_catch();
+extern void sig_block();
+extern void sig_unblock();
+extern void sig_blocknone();
+extern void sig_pause();
+
+extern void sig_dfl();
+
+extern void sig_miscignore();
+extern void sig_bugcatch();
+
+extern void sig_pipeignore();
+extern void sig_pipedefault();
+
+extern void sig_contblock();
+extern void sig_contunblock();
+extern void sig_contcatch();
+extern void sig_contdefault();
+
+extern void sig_termblock();
+extern void sig_termunblock();
+extern void sig_termcatch();
+extern void sig_termdefault();
+
+extern void sig_alarmblock();
+extern void sig_alarmunblock();
+extern void sig_alarmcatch();
+extern void sig_alarmdefault();
+
+extern void sig_childblock();
+extern void sig_childunblock();
+extern void sig_childcatch();
+extern void sig_childdefault();
+
+extern void sig_hangupblock();
+extern void sig_hangupunblock();
+extern void sig_hangupcatch();
+extern void sig_hangupdefault();
+
+#endif
diff --git a/sig_catch.c b/sig_catch.c
new file mode 100644 (file)
index 0000000..1888765
--- /dev/null
@@ -0,0 +1,18 @@
+#include <signal.h>
+#include "sig.h"
+#include "hassgact.h"
+
+void sig_catch(sig,f)
+int sig;
+void (*f)();
+{
+#ifdef HASSIGACTION
+  struct sigaction sa;
+  sa.sa_handler = f;
+  sa.sa_flags = 0;
+  sigemptyset(&sa.sa_mask);
+  sigaction(sig,&sa,(struct sigaction *) 0);
+#else
+  signal(sig,f); /* won't work under System V, even nowadays---dorks */
+#endif
+}
diff --git a/sig_pipe.c b/sig_pipe.c
new file mode 100644 (file)
index 0000000..594ae7d
--- /dev/null
@@ -0,0 +1,5 @@
+#include <signal.h>
+#include "sig.h"
+
+void sig_pipeignore() { sig_catch(SIGPIPE,SIG_IGN); }
+void sig_pipedefault() { sig_catch(SIGPIPE,SIG_DFL); }
diff --git a/str.h b/str.h
new file mode 100644 (file)
index 0000000..e00773c
--- /dev/null
+++ b/str.h
@@ -0,0 +1,14 @@
+#ifndef STR_H
+#define STR_H
+
+extern unsigned int str_copy();
+extern int str_diff();
+extern int str_diffn();
+extern unsigned int str_len();
+extern unsigned int str_chr();
+extern unsigned int str_rchr();
+extern int str_start();
+
+#define str_equal(s,t) (!str_diff((s),(t)))
+
+#endif
diff --git a/str_diffn.c b/str_diffn.c
new file mode 100644 (file)
index 0000000..89142f1
--- /dev/null
@@ -0,0 +1,18 @@
+#include "str.h"
+
+int str_diffn(s,t,len)
+register char *s;
+register char *t;
+unsigned int len;
+{
+  register char x;
+
+  for (;;) {
+    if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
+    if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
+    if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
+    if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
+  }
+  return ((int)(unsigned int)(unsigned char) x)
+       - ((int)(unsigned int)(unsigned char) *t);
+}
diff --git a/str_len.c b/str_len.c
new file mode 100644 (file)
index 0000000..2d2f88b
--- /dev/null
+++ b/str_len.c
@@ -0,0 +1,15 @@
+#include "str.h"
+
+unsigned int str_len(s)
+register char *s;
+{
+  register char *t;
+
+  t = s;
+  for (;;) {
+    if (!*t) return t - s; ++t;
+    if (!*t) return t - s; ++t;
+    if (!*t) return t - s; ++t;
+    if (!*t) return t - s; ++t;
+  }
+}
diff --git a/stralloc.h b/stralloc.h
new file mode 100644 (file)
index 0000000..fca496c
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef STRALLOC_H
+#define STRALLOC_H
+
+#include "gen_alloc.h"
+
+GEN_ALLOC_typedef(stralloc,char,s,len,a)
+
+extern int stralloc_ready();
+extern int stralloc_readyplus();
+extern int stralloc_copy();
+extern int stralloc_cat();
+extern int stralloc_copys();
+extern int stralloc_cats();
+extern int stralloc_copyb();
+extern int stralloc_catb();
+extern int stralloc_append(); /* beware: this takes a pointer to 1 char */
+extern int stralloc_starts();
+
+#define stralloc_0(sa) stralloc_append(sa,"")
+
+#endif
diff --git a/stralloc_cat.c b/stralloc_cat.c
new file mode 100644 (file)
index 0000000..efbb112
--- /dev/null
@@ -0,0 +1,9 @@
+#include "byte.h"
+#include "stralloc.h"
+
+int stralloc_cat(sato,safrom)
+stralloc *sato;
+stralloc *safrom;
+{
+  return stralloc_catb(sato,safrom->s,safrom->len);
+}
diff --git a/stralloc_catb.c b/stralloc_catb.c
new file mode 100644 (file)
index 0000000..67dbcc0
--- /dev/null
@@ -0,0 +1,15 @@
+#include "stralloc.h"
+#include "byte.h"
+
+int stralloc_catb(sa,s,n)
+stralloc *sa;
+char *s;
+unsigned int n;
+{
+  if (!sa->s) return stralloc_copyb(sa,s,n);
+  if (!stralloc_readyplus(sa,n + 1)) return 0;
+  byte_copy(sa->s + sa->len,n,s);
+  sa->len += n;
+  sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
+  return 1;
+}
diff --git a/stralloc_cats.c b/stralloc_cats.c
new file mode 100644 (file)
index 0000000..d300286
--- /dev/null
@@ -0,0 +1,10 @@
+#include "byte.h"
+#include "str.h"
+#include "stralloc.h"
+
+int stralloc_cats(sa,s)
+stralloc *sa;
+char *s;
+{
+  return stralloc_catb(sa,s,str_len(s));
+}
diff --git a/stralloc_copy.c b/stralloc_copy.c
new file mode 100644 (file)
index 0000000..652aed6
--- /dev/null
@@ -0,0 +1,9 @@
+#include "byte.h"
+#include "stralloc.h"
+
+int stralloc_copy(sato,safrom)
+stralloc *sato;
+stralloc *safrom;
+{
+  return stralloc_copyb(sato,safrom->s,safrom->len);
+}
diff --git a/stralloc_eady.c b/stralloc_eady.c
new file mode 100644 (file)
index 0000000..3a31f4b
--- /dev/null
@@ -0,0 +1,6 @@
+#include "alloc.h"
+#include "stralloc.h"
+#include "gen_allocdefs.h"
+
+GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
+GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
diff --git a/stralloc_opyb.c b/stralloc_opyb.c
new file mode 100644 (file)
index 0000000..ac258b3
--- /dev/null
@@ -0,0 +1,14 @@
+#include "stralloc.h"
+#include "byte.h"
+
+int stralloc_copyb(sa,s,n)
+stralloc *sa;
+char *s;
+unsigned int n;
+{
+  if (!stralloc_ready(sa,n + 1)) return 0;
+  byte_copy(sa->s,n,s);
+  sa->len = n;
+  sa->s[n] = 'Z'; /* ``offensive programming'' */
+  return 1;
+}
diff --git a/stralloc_opys.c b/stralloc_opys.c
new file mode 100644 (file)
index 0000000..fdd7807
--- /dev/null
@@ -0,0 +1,10 @@
+#include "byte.h"
+#include "str.h"
+#include "stralloc.h"
+
+int stralloc_copys(sa,s)
+stralloc *sa;
+char *s;
+{
+  return stralloc_copyb(sa,s,str_len(s));
+}
diff --git a/stralloc_pend.c b/stralloc_pend.c
new file mode 100644 (file)
index 0000000..a3443b8
--- /dev/null
@@ -0,0 +1,5 @@
+#include "alloc.h"
+#include "stralloc.h"
+#include "gen_allocdefs.h"
+
+GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
diff --git a/strerr.h b/strerr.h
new file mode 100644 (file)
index 0000000..d18e833
--- /dev/null
+++ b/strerr.h
@@ -0,0 +1,80 @@
+#ifndef STRERR_H
+#define STRERR_H
+
+struct strerr
+ {
+  struct strerr *who;
+  char *x;
+  char *y;
+  char *z;
+ }
+;
+
+extern struct strerr strerr_sys;
+extern void strerr_sysinit();
+
+extern char *strerr();
+extern void strerr_warn();
+extern void strerr_die();
+
+#define STRERR(r,se,a) \
+{ se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; }
+
+#define STRERR_SYS(r,se,a) \
+{ se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; }
+#define STRERR_SYS3(r,se,a,b,c) \
+{ se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; }
+
+#define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \
+strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se))
+#define strerr_warn5(x1,x2,x3,x4,x5,se) \
+strerr_warn((x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se))
+#define strerr_warn4(x1,x2,x3,x4,se) \
+strerr_warn((x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se))
+#define strerr_warn3(x1,x2,x3,se) \
+strerr_warn((x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se))
+#define strerr_warn2(x1,x2,se) \
+strerr_warn((x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se))
+#define strerr_warn1(x1,se) \
+strerr_warn((x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se))
+
+#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se))
+#define strerr_die5(e,x1,x2,x3,x4,x5,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se))
+#define strerr_die4(e,x1,x2,x3,x4,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se))
+#define strerr_die3(e,x1,x2,x3,se) \
+strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se))
+#define strerr_die2(e,x1,x2,se) \
+strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se))
+#define strerr_die1(e,x1,se) \
+strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se))
+
+#define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys)
+#define strerr_die5sys(e,x1,x2,x3,x4,x5) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,&strerr_sys)
+#define strerr_die4sys(e,x1,x2,x3,x4) \
+strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,&strerr_sys)
+#define strerr_die3sys(e,x1,x2,x3) \
+strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,&strerr_sys)
+#define strerr_die2sys(e,x1,x2) \
+strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys)
+#define strerr_die1sys(e,x1) \
+strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys)
+
+#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) 0)
+#define strerr_die5x(e,x1,x2,x3,x4,x5) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) 0)
+#define strerr_die4x(e,x1,x2,x3,x4) \
+strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) 0)
+#define strerr_die3x(e,x1,x2,x3) \
+strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0)
+#define strerr_die2x(e,x1,x2) \
+strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0)
+#define strerr_die1x(e,x1) \
+strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0)
+
+#endif
diff --git a/strerr_die.c b/strerr_die.c
new file mode 100644 (file)
index 0000000..6092020
--- /dev/null
@@ -0,0 +1,37 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "exit.h"
+#include "strerr.h"
+
+void strerr_warn(x1,x2,x3,x4,x5,x6,se)
+char *x1; char *x2; char *x3; char *x4; char *x5; char *x6;
+struct strerr *se;
+{
+  strerr_sysinit();
+  if (x1) substdio_puts(subfderr,x1);
+  if (x2) substdio_puts(subfderr,x2);
+  if (x3) substdio_puts(subfderr,x3);
+  if (x4) substdio_puts(subfderr,x4);
+  if (x5) substdio_puts(subfderr,x5);
+  if (x6) substdio_puts(subfderr,x6);
+  while(se) {
+    if (se->x) substdio_puts(subfderr,se->x);
+    if (se->y) substdio_puts(subfderr,se->y);
+    if (se->z) substdio_puts(subfderr,se->z);
+    se = se->who;
+  }
+  substdio_puts(subfderr,"\n");
+  substdio_flush(subfderr);
+}
+
+void strerr_die(e,x1,x2,x3,x4,x5,x6,se)
+int e;
+char *x1; char *x2; char *x3; char *x4; char *x5; char *x6;
+struct strerr *se;
+{
+  strerr_warn(x1,x2,x3,x4,x5,x6,se);
+  _exit(e);
+}
diff --git a/strerr_sys.c b/strerr_sys.c
new file mode 100644 (file)
index 0000000..198198b
--- /dev/null
@@ -0,0 +1,12 @@
+#include "error.h"
+#include "strerr.h"
+
+struct strerr strerr_sys;
+
+void strerr_sysinit()
+{
+  strerr_sys.who = 0;
+  strerr_sys.x = error_str(errno);
+  strerr_sys.y = "";
+  strerr_sys.z = "";
+}
diff --git a/subfd.h b/subfd.h
new file mode 100644 (file)
index 0000000..bcb2e1e
--- /dev/null
+++ b/subfd.h
@@ -0,0 +1,15 @@
+#ifndef SUBFD_H
+#define SUBFD_H
+
+#include "substdio.h"
+
+extern substdio *subfdin;
+extern substdio *subfdinsmall;
+extern substdio *subfdout;
+extern substdio *subfdoutsmall;
+extern substdio *subfderr;
+
+extern int subfd_read();
+extern int subfd_readsmall();
+
+#endif
diff --git a/subfderr.c b/subfderr.c
new file mode 100644 (file)
index 0000000..011ab0f
--- /dev/null
@@ -0,0 +1,7 @@
+#include "readwrite.h"
+#include "substdio.h"
+#include "subfd.h"
+
+char subfd_errbuf[256];
+static substdio it = SUBSTDIO_FDBUF(write,2,subfd_errbuf,256);
+substdio *subfderr = &it;
diff --git a/subgetopt.c b/subgetopt.c
new file mode 100644 (file)
index 0000000..dacf376
--- /dev/null
@@ -0,0 +1,79 @@
+/* subgetopt.c, subgetopt.h: (yet another) improved getopt clone, inner layer
+D. J. Bernstein, djb@pobox.com.
+No dependencies.
+No system requirements.
+19970228: Cleanups.
+931129: Adapted from getopt.c.
+No known patent problems.
+
+Documentation in subgetopt.3.
+*/
+
+#define SUBGETOPTNOSHORT
+#include "subgetopt.h"
+
+#define sgopt subgetopt
+#define optind subgetoptind
+#define optpos subgetoptpos
+#define optarg subgetoptarg
+#define optproblem subgetoptproblem
+#define optdone subgetoptdone
+
+int optind = 1;
+int optpos = 0;
+char *optarg = 0;
+int optproblem = 0;
+int optdone = SUBGETOPTDONE;
+
+int sgopt(argc,argv,opts)
+int argc;
+char **argv;
+char *opts;
+{
+  int c;
+  char *s;
+
+  optarg = 0;
+  if (!argv || (optind >= argc) || !argv[optind]) return optdone;
+  if (optpos && !argv[optind][optpos]) {
+    ++optind;
+    optpos = 0;
+    if ((optind >= argc) || !argv[optind]) return optdone;
+  }
+  if (!optpos) {
+    if (argv[optind][0] != '-') return optdone;
+    ++optpos;
+    c = argv[optind][1];
+    if ((c == '-') || (c == 0)) {
+      if (c) ++optind;
+      optpos = 0;
+      return optdone;
+    }
+    /* otherwise c is reassigned below */
+  }
+  c = argv[optind][optpos];
+  ++optpos;
+  s = opts;
+  while (*s) {
+    if (c == *s) {
+      if (s[1] == ':') {
+        optarg = argv[optind] + optpos;
+        ++optind;
+        optpos = 0;
+        if (!*optarg) {
+          optarg = argv[optind];
+          if ((optind >= argc) || !optarg) { /* argument past end */
+            optproblem = c;
+            return '?';
+          }
+         ++optind;
+        }
+      }
+      return c;
+    }
+    ++s;
+    if (*s == ':') ++s;
+  }
+  optproblem = c;
+  return '?';
+}
diff --git a/subgetopt.h b/subgetopt.h
new file mode 100644 (file)
index 0000000..d26c62a
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef SUBGETOPT_H
+#define SUBGETOPT_H
+
+#ifndef SUBGETOPTNOSHORT
+#define sgopt subgetopt
+#define sgoptarg subgetoptarg
+#define sgoptind subgetoptind
+#define sgoptpos subgetoptpos
+#define sgoptproblem subgetoptproblem
+#define sgoptprogname subgetoptprogname
+#define sgoptdone subgetoptdone
+#endif
+
+#define SUBGETOPTDONE -1
+
+extern int subgetopt();
+extern char *subgetoptarg;
+extern int subgetoptind;
+extern int subgetoptpos;
+extern int subgetoptproblem;
+extern char *subgetoptprogname;
+extern int subgetoptdone;
+
+#endif
diff --git a/substdi.c b/substdi.c
new file mode 100644 (file)
index 0000000..42407a1
--- /dev/null
+++ b/substdi.c
@@ -0,0 +1,91 @@
+#include "substdio.h"
+#include "byte.h"
+#include "error.h"
+
+static int oneread(op,fd,buf,len)
+register int (*op)();
+register int fd;
+register char *buf;
+register int len;
+{
+  register int r;
+
+  for (;;) {
+    r = op(fd,buf,len);
+    if (r == -1) if (errno == error_intr) continue;
+    return r;
+  }
+}
+
+static int getthis(s,buf,len)
+register substdio *s;
+register char *buf;
+register int len;
+{
+  register int r;
+  register int q;
+  r = s->p;
+  q = r - len;
+  if (q > 0) { r = len; s->p = q; } else s->p = 0;
+  byte_copy(buf,r,s->x + s->n);
+  s->n += r;
+  return r;
+}
+
+int substdio_feed(s)
+register substdio *s;
+{
+  register int r;
+  register int q;
+
+  if (s->p) return s->p;
+  q = s->n;
+  r = oneread(s->op,s->fd,s->x,q);
+  if (r <= 0) return r;
+  s->p = r;
+  q -= r;
+  s->n = q;
+  if (q > 0) /* damn, gotta shift */ byte_copyr(s->x + q,r,s->x);
+  return r;
+}
+
+int substdio_bget(s,buf,len)
+register substdio *s;
+register char *buf;
+register int len;
+{
+  register int r;
+  if (s->p > 0) return getthis(s,buf,len);
+  r = s->n; if (r <= len) return oneread(s->op,s->fd,buf,r);
+  r = substdio_feed(s); if (r <= 0) return r;
+  return getthis(s,buf,len);
+}
+
+int substdio_get(s,buf,len)
+register substdio *s;
+register char *buf;
+register int len;
+{
+  register int r;
+  if (s->p > 0) return getthis(s,buf,len);
+  if (s->n <= len) return oneread(s->op,s->fd,buf,len);
+  r = substdio_feed(s); if (r <= 0) return r;
+  return getthis(s,buf,len);
+}
+
+char *substdio_peek(s)
+register substdio *s;
+{
+  return s->x + s->n;
+}
+
+void substdio_seek(s,len)
+register substdio *s;
+register int len;
+{
+  s->n += len;
+  s->p -= len;
+}
diff --git a/substdio.c b/substdio.c
new file mode 100644 (file)
index 0000000..d03dff2
--- /dev/null
@@ -0,0 +1,15 @@
+#include "substdio.h"
+
+void substdio_fdbuf(s,op,fd,buf,len)
+register substdio *s;
+register int (*op)();
+register int fd;
+register char *buf;
+register int len;
+{
+  s->x = buf;
+  s->fd = fd;
+  s->op = op;
+  s->p = 0;
+  s->n = len;
+}
diff --git a/substdio.h b/substdio.h
new file mode 100644 (file)
index 0000000..c3f7f7d
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef SUBSTDIO_H
+#define SUBSTDIO_H
+
+typedef struct substdio {
+  char *x;
+  int p;
+  int n;
+  int fd;
+  int (*op)();
+} substdio;
+
+#define SUBSTDIO_FDBUF(op,fd,buf,len) { (buf), 0, (len), (fd), (op) }
+
+extern void substdio_fdbuf();
+
+extern int substdio_flush();
+extern int substdio_put();
+extern int substdio_bput();
+extern int substdio_putflush();
+extern int substdio_puts();
+extern int substdio_bputs();
+extern int substdio_putsflush();
+
+extern int substdio_get();
+extern int substdio_bget();
+extern int substdio_feed();
+
+extern char *substdio_peek();
+extern void substdio_seek();
+
+#define substdio_fileno(s) ((s)->fd)
+
+#define SUBSTDIO_INSIZE 8192
+#define SUBSTDIO_OUTSIZE 8192
+
+#define substdio_PEEK(s) ( (s)->x + (s)->n )
+#define substdio_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) )
+
+#define substdio_BPUTC(s,c) \
+  ( ((s)->n != (s)->p) \
+    ? ( (s)->x[(s)->p++] = (c), 0 ) \
+    : substdio_bput((s),&(c),1) \
+  )
+
+extern int substdio_copy();
+
+#endif
diff --git a/substdio_copy.c b/substdio_copy.c
new file mode 100644 (file)
index 0000000..71cf200
--- /dev/null
@@ -0,0 +1,18 @@
+#include "substdio.h"
+
+int substdio_copy(ssout,ssin)
+register substdio *ssout;
+register substdio *ssin;
+{
+  register int n;
+  register char *x;
+
+  for (;;) {
+    n = substdio_feed(ssin);
+    if (n < 0) return -2;
+    if (!n) return 0;
+    x = substdio_PEEK(ssin);
+    if (substdio_put(ssout,x,n) == -1) return -3;
+    substdio_SEEK(ssin,n);
+  }
+}
diff --git a/substdo.c b/substdo.c
new file mode 100644 (file)
index 0000000..fb616f7
--- /dev/null
+++ b/substdo.c
@@ -0,0 +1,108 @@
+#include "substdio.h"
+#include "str.h"
+#include "byte.h"
+#include "error.h"
+
+static int allwrite(op,fd,buf,len)
+register int (*op)();
+register int fd;
+register char *buf;
+register int len;
+{
+  register int w;
+
+  while (len) {
+    w = op(fd,buf,len);
+    if (w == -1) {
+      if (errno == error_intr) continue;
+      return -1; /* note that some data may have been written */
+    }
+    if (w == 0) ; /* luser's fault */
+    buf += w;
+    len -= w;
+  }
+  return 0;
+}
+
+int substdio_flush(s)
+register substdio *s;
+{
+  register int p;
+  p = s->p;
+  if (!p) return 0;
+  s->p = 0;
+  return allwrite(s->op,s->fd,s->x,p);
+}
+
+int substdio_bput(s,buf,len)
+register substdio *s;
+register char *buf;
+register int len;
+{
+  register int n;
+  while (len > (n = s->n - s->p)) {
+    byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n;
+    if (substdio_flush(s) == -1) return -1;
+  }
+  /* now len <= s->n - s->p */
+  byte_copy(s->x + s->p,len,buf);
+  s->p += len;
+  return 0;
+}
+
+int substdio_put(s,buf,len)
+register substdio *s;
+register char *buf;
+register int len;
+{
+  register int n;
+  n = s->n;
+  if (len > n - s->p) {
+    if (substdio_flush(s) == -1) return -1;
+    /* now s->p == 0 */
+    if (n < SUBSTDIO_OUTSIZE) n = SUBSTDIO_OUTSIZE;
+    while (len > s->n) {
+      if (n > len) n = len;
+      if (allwrite(s->op,s->fd,buf,n) == -1) return -1;
+      buf += n;
+      len -= n;
+    }
+  }
+  /* now len <= s->n - s->p */
+  byte_copy(s->x + s->p,len,buf);
+  s->p += len;
+  return 0;
+}
+
+int substdio_putflush(s,buf,len)
+register substdio *s;
+register char *buf;
+register int len;
+{
+  if (substdio_flush(s) == -1) return -1;
+  return allwrite(s->op,s->fd,buf,len);
+}
+
+int substdio_bputs(s,buf)
+register substdio *s;
+register char *buf;
+{
+  return substdio_bput(s,buf,str_len(buf));
+}
+
+int substdio_puts(s,buf)
+register substdio *s;
+register char *buf;
+{
+  return substdio_put(s,buf,str_len(buf));
+}
+
+int substdio_putsflush(s,buf)
+register substdio *s;
+register char *buf;
+{
+  return substdio_putflush(s,buf,str_len(buf));
+}
diff --git a/token822.c b/token822.c
new file mode 100644 (file)
index 0000000..48a4388
--- /dev/null
@@ -0,0 +1,513 @@
+#include "stralloc.h"
+#include "alloc.h"
+#include "str.h"
+#include "token822.h"
+#include "gen_allocdefs.h"
+
+static struct token822 comma = { TOKEN822_COMMA };
+
+void token822_reverse(ta)
+token822_alloc *ta;
+{
+ int i;
+ int n;
+ struct token822 temp;
+
+ n = ta->len - 1;
+ for (i = 0;i + i < n;++i)
+  {
+   temp = ta->t[i];
+   ta->t[i] = ta->t[n - i];
+   ta->t[n - i] = temp;
+  }
+}
+
+GEN_ALLOC_ready(token822_alloc,struct token822,t,len,a,i,n,x,30,token822_ready)
+GEN_ALLOC_readyplus(token822_alloc,struct token822,t,len,a,i,n,x,30,token822_readyplus)
+GEN_ALLOC_append(token822_alloc,struct token822,t,len,a,i,n,x,30,token822_readyplus,token822_append)
+
+static int needspace(t1,t2)
+int t1;
+int t2;
+{
+ if (!t1) return 0;
+ if (t1 == TOKEN822_COLON) return 1;
+ if (t1 == TOKEN822_COMMA) return 1;
+ if (t2 == TOKEN822_LEFT) return 1;
+ switch(t1)
+  {
+   case TOKEN822_ATOM: case TOKEN822_LITERAL:
+   case TOKEN822_QUOTE: case TOKEN822_COMMENT:
+     switch(t2)
+      {
+       case TOKEN822_ATOM: case TOKEN822_LITERAL:
+       case TOKEN822_QUOTE: case TOKEN822_COMMENT:
+         return 1;
+      }
+  }
+ return 0;
+}
+
+static int atomok(ch)
+char ch;
+{
+ switch(ch)
+  {
+   case ' ': case '\t': case '\r': case '\n':
+   case '(': case '[': case '"':
+   case '<': case '>': case ';': case ':':
+   case '@': case ',': case '.':
+     return 0;
+  }
+ return 1;
+}
+
+static void atomcheck(t)
+struct token822 *t;
+{
+ int i;
+ char ch;
+ for (i = 0;i < t->slen;++i)
+  {
+   ch = t->s[i];
+   if ((ch < 32) || (ch > 126) || (ch == ')') || (ch == ']') || (ch == '\\'))
+    {
+     t->type = TOKEN822_QUOTE;
+     return;
+    }
+  }
+}
+
+int token822_unparse(sa,ta,linelen)
+stralloc *sa;
+token822_alloc *ta;
+unsigned int linelen;
+{
+ struct token822 *t;
+ int len;
+ int ch;
+ int i;
+ int j;
+ int lasttype;
+ int newtype;
+ char *s;
+ char *lineb;
+ char *linee;
+
+ len = 0;
+ lasttype = 0;
+ for (i = 0;i < ta->len;++i)
+  {
+   t = ta->t + i;
+   newtype = t->type;
+   if (needspace(lasttype,newtype))
+     ++len;
+   lasttype = newtype;
+   switch(newtype)
+    {
+     case TOKEN822_COMMA:
+       len += 3; break;
+     case TOKEN822_AT: case TOKEN822_DOT: case TOKEN822_LEFT: case TOKEN822_RIGHT:
+     case TOKEN822_SEMI: case TOKEN822_COLON:
+       ++len; break;
+     case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL: case TOKEN822_COMMENT:
+       if (t->type != TOKEN822_ATOM) len += 2;
+       for (j = 0;j < t->slen;++j)
+        switch(ch = t->s[j])
+         {
+          case '"': case '[': case ']': case '(': case ')':
+          case '\\': case '\r': case '\n': ++len;
+          default: ++len;
+         }
+       break;
+    }
+  }
+ len += 2;
+
+ if (!stralloc_ready(sa,len))
+   return -1;
+
+ s = sa->s;
+ lineb = s;
+ linee = 0;
+
+ lasttype = 0;
+ for (i = 0;i < ta->len;++i)
+  {
+   t = ta->t + i;
+   newtype = t->type;
+   if (needspace(lasttype,newtype))
+     *s++ = ' ';
+   lasttype = newtype;
+   switch(newtype)
+    {
+     case TOKEN822_COMMA:
+       *s++ = ',';
+#define NSUW \
+ s[0] = '\n'; s[1] = ' '; \
+ if (linee && (!linelen || (s - lineb <= linelen))) \
+  { while (linee < s) { linee[0] = linee[2]; ++linee; } linee -= 2; } \
+ else { if (linee) lineb = linee + 1; linee = s; s += 2; }
+       NSUW
+       break;
+     case TOKEN822_AT: *s++ = '@'; break;
+     case TOKEN822_DOT: *s++ = '.'; break;
+     case TOKEN822_LEFT: *s++ = '<'; break;
+     case TOKEN822_RIGHT: *s++ = '>'; break;
+     case TOKEN822_SEMI: *s++ = ';'; break;
+     case TOKEN822_COLON: *s++ = ':'; break;
+     case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL: case TOKEN822_COMMENT:
+       if (t->type == TOKEN822_QUOTE) *s++ = '"';
+       if (t->type == TOKEN822_LITERAL) *s++ = '[';
+       if (t->type == TOKEN822_COMMENT) *s++ = '(';
+       for (j = 0;j < t->slen;++j)
+        switch(ch = t->s[j])
+         {
+          case '"': case '[': case ']': case '(': case ')':
+          case '\\': case '\r': case '\n': *s++ = '\\';
+          default: *s++ = ch;
+         }
+       if (t->type == TOKEN822_QUOTE) *s++ = '"';
+       if (t->type == TOKEN822_LITERAL) *s++ = ']';
+       if (t->type == TOKEN822_COMMENT) *s++ = ')';
+       break;
+    }
+  }
+ NSUW
+ --s;
+ sa->len = s - sa->s;
+ return 1;
+}
+
+int token822_unquote(sa,ta)
+stralloc *sa;
+token822_alloc *ta;
+{
+ struct token822 *t;
+ int len;
+ int i;
+ int j;
+ char *s;
+
+ len = 0;
+ for (i = 0;i < ta->len;++i)
+  {
+   t = ta->t + i;
+   switch(t->type)
+    {
+     case TOKEN822_COMMA: case TOKEN822_AT: case TOKEN822_DOT: case TOKEN822_LEFT: 
+     case TOKEN822_RIGHT: case TOKEN822_SEMI: case TOKEN822_COLON: 
+       ++len; break;
+     case TOKEN822_LITERAL:
+       len += 2;
+     case TOKEN822_ATOM: case TOKEN822_QUOTE:
+       len += t->slen;
+    }
+  }
+
+ if (!stralloc_ready(sa,len))
+   return -1;
+
+ s = sa->s;
+
+ for (i = 0;i < ta->len;++i)
+  {
+   t = ta->t + i;
+   switch(t->type)
+    {
+     case TOKEN822_COMMA: *s++ = ','; break;
+     case TOKEN822_AT: *s++ = '@'; break;
+     case TOKEN822_DOT: *s++ = '.'; break;
+     case TOKEN822_LEFT: *s++ = '<'; break;
+     case TOKEN822_RIGHT: *s++ = '>'; break;
+     case TOKEN822_SEMI: *s++ = ';'; break;
+     case TOKEN822_COLON: *s++ = ':'; break;
+     case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL:
+       if (t->type == TOKEN822_LITERAL) *s++ = '[';
+       for (j = 0;j < t->slen;++j)
+        *s++ = t->s[j];
+       if (t->type == TOKEN822_LITERAL) *s++ = ']';
+       break;
+     case TOKEN822_COMMENT: break;
+    }
+  }
+ sa->len = s - sa->s;
+ return 1;
+}
+
+int token822_parse(ta,sa,buf)
+token822_alloc *ta;
+stralloc *sa;
+stralloc *buf;
+{
+ int i;
+ int salen;
+ int level;
+ struct token822 *t;
+ int numtoks;
+ int numchars;
+ char *cbuf;
+
+ salen = sa->len;
+
+ numchars = 0;
+ numtoks = 0;
+ for (i = 0;i < salen;++i)
+   switch(sa->s[i])
+    {
+     case '.': case ',': case '@': case '<': case '>': case ':': case ';':
+       ++numtoks; break;
+     case ' ': case '\t': case '\r': case '\n': break;
+     case ')': case ']': return 0;
+     /* other control chars and non-ASCII chars are also bad, in theory */
+     case '(':
+       level = 1;
+       while (level)
+       {
+        if (++i >= salen) return 0;
+        switch(sa->s[i])
+         {
+          case '(': ++level; break;
+          case ')': --level; break;
+          case '\\': if (++i >= salen) return 0;
+          default: ++numchars;
+         }
+       }
+       ++numtoks;
+       break;
+     case '"':
+       level = 1;
+       while (level)
+       {
+        if (++i >= salen) return 0;
+        switch(sa->s[i])
+         {
+          case '"': --level; break;
+          case '\\': if (++i >= salen) return 0;
+          default: ++numchars;
+         }
+       }
+       ++numtoks;
+       break;
+     case '[':
+       level = 1;
+       while (level)
+       {
+        if (++i >= salen) return 0;
+        switch(sa->s[i])
+         {
+          case ']': --level; break;
+          case '\\': if (++i >= salen) return 0;
+          default: ++numchars;
+         }
+       }
+       ++numtoks;
+       break;
+     default:
+       do
+       {
+        if (sa->s[i] == '\\') if (++i >= salen) break;
+        ++numchars;
+        if (++i >= salen)
+          break;
+       }
+       while (atomok(sa->s[i]));
+       --i;
+       ++numtoks;
+    }
+
+ if (!token822_ready(ta,numtoks))
+   return -1;
+ if (!stralloc_ready(buf,numchars))
+   return -1;
+ cbuf = buf->s;
+ ta->len = numtoks;
+
+ t = ta->t;
+ for (i = 0;i < salen;++i)
+   switch(sa->s[i])
+    {
+     case '.': t->type = TOKEN822_DOT; ++t; break;
+     case ',': t->type = TOKEN822_COMMA; ++t; break;
+     case '@': t->type = TOKEN822_AT; ++t; break;
+     case '<': t->type = TOKEN822_LEFT; ++t; break;
+     case '>': t->type = TOKEN822_RIGHT; ++t; break;
+     case ':': t->type = TOKEN822_COLON; ++t; break;
+     case ';': t->type = TOKEN822_SEMI; ++t; break;
+     case ' ': case '\t': case '\r': case '\n': break;
+     case '(':
+       t->type = TOKEN822_COMMENT; t->s = cbuf; t->slen = 0;
+       level = 1;
+       while (level)
+       {
+        ++i; /* assert: < salen */
+        switch(sa->s[i])
+         {
+          case '(': ++level; break;
+          case ')': --level; break;
+          case '\\': ++i; /* assert: < salen */
+          default: *cbuf++ = sa->s[i]; ++t->slen;
+         }
+       }
+       ++t;
+       break;
+     case '"':
+       t->type = TOKEN822_QUOTE; t->s = cbuf; t->slen = 0;
+       level = 1;
+       while (level)
+       {
+        ++i; /* assert: < salen */
+        switch(sa->s[i])
+         {
+          case '"': --level; break;
+          case '\\': ++i; /* assert: < salen */
+          default: *cbuf++ = sa->s[i]; ++t->slen;
+         }
+       }
+       ++t;
+       break;
+     case '[':
+       t->type = TOKEN822_LITERAL; t->s = cbuf; t->slen = 0;
+       level = 1;
+       while (level)
+       {
+        ++i; /* assert: < salen */
+        switch(sa->s[i])
+         {
+          case ']': --level; break;
+          case '\\': ++i; /* assert: < salen */
+          default: *cbuf++ = sa->s[i]; ++t->slen;
+         }
+       }
+       ++t;
+       break;
+     default:
+       t->type = TOKEN822_ATOM; t->s = cbuf; t->slen = 0;
+       do
+       {
+        if (sa->s[i] == '\\') if (++i >= salen) break;
+        *cbuf++ = sa->s[i]; ++t->slen;
+        if (++i >= salen)
+          break;
+       }
+       while (atomok(sa->s[i]));
+       atomcheck(t);
+       --i;
+       ++t;
+    }
+ return 1;
+}
+
+static int gotaddr(taout,taaddr,callback)
+token822_alloc *taout;
+token822_alloc *taaddr;
+int (*callback)();
+{
+ int i;
+
+ if (callback(taaddr) != 1)
+   return 0;
+
+ if (!token822_readyplus(taout,taaddr->len))
+   return 0;
+ for (i = 0;i < taaddr->len;++i)
+   taout->t[taout->len++] = taaddr->t[i];
+
+ taaddr->len = 0;
+ return 1;
+}
+
+int token822_addrlist(taout,taaddr,ta,callback)
+token822_alloc *taout;
+token822_alloc *taaddr;
+token822_alloc *ta;
+int (*callback)();
+{
+ struct token822 *t;
+ struct token822 *beginning;
+ int ingroup;
+ int wordok;
+
+ taout->len = 0;
+ taaddr->len = 0;
+
+ if (!token822_readyplus(taout,1)) return -1;
+ if (!token822_readyplus(taaddr,1)) return -1;
+ ingroup = 0;
+ wordok = 1;
+
+ beginning = ta->t + 2;
+ t = ta->t + ta->len - 1;
+
+ /* rfc 822 address lists are easy to parse from right to left */
+
+#define FLUSH if (taaddr->len) if (!gotaddr(taout,taaddr,callback)) return -1;
+#define FLUSHCOMMA if (taaddr->len) { \
+if (!gotaddr(taout,taaddr,callback)) return -1; \
+if (!token822_append(taout,&comma)) return -1; }
+#define ADDRLEFT if (!token822_append(taaddr,t--)) return -1;
+#define OUTLEFT if (!token822_append(taout,t--)) return -1;
+
+ while (t >= beginning)
+  {
+   switch(t->type)
+    {
+     case TOKEN822_SEMI:
+       FLUSHCOMMA
+       if (ingroup) return 0;
+       ingroup = 1;
+       wordok = 1;
+       break;
+     case TOKEN822_COLON:
+       FLUSH
+       if (!ingroup) return 0;
+       ingroup = 0;
+       while ((t >= beginning) && (t->type != TOKEN822_COMMA))
+        OUTLEFT
+       if (t >= beginning)
+        OUTLEFT
+       wordok = 1;
+       continue;
+     case TOKEN822_RIGHT:
+       FLUSHCOMMA
+       OUTLEFT
+       while ((t >= beginning) && (t->type != TOKEN822_LEFT))
+        ADDRLEFT
+       /* important to use address here even if it's empty: <> */
+       if (!gotaddr(taout,taaddr,callback)) return -1;
+       if (t < beginning) return 0;
+       OUTLEFT
+       while ((t >= beginning) && ((t->type == TOKEN822_COMMENT) || (t->type == TOKEN822_ATOM) || (t->type == TOKEN822_QUOTE) || (t->type == TOKEN822_AT) || (t->type == TOKEN822_DOT)))
+        OUTLEFT
+       wordok = 0;
+       continue;
+     case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL:
+       if (!wordok)
+        FLUSHCOMMA
+       wordok = 0;
+       ADDRLEFT
+       continue;
+     case TOKEN822_COMMENT:
+       /* comment is lexically a space; shouldn't affect wordok */
+       break;
+     case TOKEN822_COMMA:
+       FLUSH
+       wordok = 1;
+       break;
+     default:
+       wordok = 1;
+       ADDRLEFT
+       continue;
+    }
+   OUTLEFT
+  }
+ FLUSH
+ ++t;
+ while (t > ta->t)
+   if (!token822_append(taout,--t)) return -1;
+
+ token822_reverse(taout);
+ return 1;
+}
diff --git a/token822.h b/token822.h
new file mode 100644 (file)
index 0000000..9ca35cf
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef TOKEN822_H
+#define TOKEN822_H
+
+struct token822
+ {
+  int type;
+  char *s;
+  int slen;
+ }
+;
+
+#include "gen_alloc.h"
+GEN_ALLOC_typedef(token822_alloc,struct token822,t,len,a)
+
+extern int token822_parse();
+extern int token822_addrlist();
+extern int token822_unquote();
+extern int token822_unparse();
+extern void token822_free();
+extern void token822_reverse();
+extern int token822_ready();
+extern int token822_readyplus();
+extern int token822_append();
+
+#define TOKEN822_ATOM 1
+#define TOKEN822_QUOTE 2
+#define TOKEN822_LITERAL 3
+#define TOKEN822_COMMENT 4
+#define TOKEN822_LEFT 5
+#define TOKEN822_RIGHT 6
+#define TOKEN822_AT 7
+#define TOKEN822_COMMA 8
+#define TOKEN822_SEMI 9
+#define TOKEN822_COLON 10
+#define TOKEN822_DOT 11
+
+#endif
diff --git a/trycpp.c b/trycpp.c
new file mode 100644 (file)
index 0000000..d7d83ad
--- /dev/null
+++ b/trycpp.c
@@ -0,0 +1,7 @@
+void main()
+{
+#ifdef NeXT
+  printf("nextstep\n"); exit(0);
+#endif
+  printf("unknown\n"); exit(0);
+}
diff --git a/trysgact.c b/trysgact.c
new file mode 100644 (file)
index 0000000..263cb21
--- /dev/null
@@ -0,0 +1,10 @@
+#include <signal.h>
+
+void main()
+{
+  struct sigaction sa;
+  sa.sa_handler = 0;
+  sa.sa_flags = 0;
+  sigemptyset(&sa.sa_mask);
+  sigaction(0,&sa,(struct sigaction *) 0);
+}
diff --git a/tryvfork.c b/tryvfork.c
new file mode 100644 (file)
index 0000000..21387e4
--- /dev/null
@@ -0,0 +1,4 @@
+void main()
+{
+  vfork();
+}
diff --git a/trywaitp.c b/trywaitp.c
new file mode 100644 (file)
index 0000000..7e73bfa
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+
+void main()
+{
+  waitpid(0,0,0);
+}
diff --git a/wait.h b/wait.h
new file mode 100644 (file)
index 0000000..cdb77c3
--- /dev/null
+++ b/wait.h
@@ -0,0 +1,14 @@
+#ifndef WAIT_H
+#define WAIT_H
+
+extern int wait_pid();
+extern int wait_nohang();
+extern int wait_stop();
+extern int wait_stopnohang();
+
+#define wait_crashed(w) ((w) & 127)
+#define wait_exitcode(w) ((w) >> 8)
+#define wait_stopsig(w) ((w) >> 8)
+#define wait_stopped(w) (((w) & 127) == 127)
+
+#endif
diff --git a/wait_pid.c b/wait_pid.c
new file mode 100644 (file)
index 0000000..d7a7e84
--- /dev/null
@@ -0,0 +1,39 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "error.h"
+#include "haswaitp.h"
+
+#ifdef HASWAITPID
+
+int wait_pid(wstat,pid) int *wstat; int pid;
+{
+  int r;
+
+  do
+    r = waitpid(pid,wstat,0);
+  while ((r == -1) && (errno == error_intr));
+  return r;
+}
+
+#else
+
+/* XXX untested */
+/* XXX breaks down with more than two children */
+static int oldpid = 0;
+static int oldwstat; /* defined if(oldpid) */
+
+int wait_pid(wstat,pid) int *wstat; int pid;
+{
+  int r;
+
+  if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; }
+
+  do {
+    r = wait(wstat);
+    if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; }
+  }
+  while ((r == -1) && (errno == error_intr));
+  return r;
+}
+
+#endif
diff --git a/warn-auto.sh b/warn-auto.sh
new file mode 100644 (file)
index 0000000..36d2313
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+# WARNING: This file was auto-generated. Do not edit!