From cbd69c7ae2a504b2f6e335c92319284f50290ac3 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Wed, 15 Feb 2006 18:39:22 +0000 Subject: [PATCH] Import dot-forward 0.71 --- BLURB | 9 + CHANGES | 17 ++ FILES | 102 +++++++++++ INSTALL | 23 +++ Makefile | 400 +++++++++++++++++++++++++++++++++++++++++++ README | 23 +++ SYSDEPS | 5 + TARGETS | 88 ++++++++++ THANKS | 7 + TODO | 1 + VERSION | 1 + alloc.c | 32 ++++ alloc.h | 8 + alloc_re.c | 17 ++ auto-str.c | 44 +++++ auto_qmail.h | 6 + byte.h | 13 ++ byte_chr.c | 20 +++ byte_copy.c | 14 ++ byte_cr.c | 16 ++ case.h | 13 ++ case_diffb.c | 21 +++ conf-cc | 3 + conf-ld | 3 + conf-qmail | 7 + control.c | 130 ++++++++++++++ control.h | 10 ++ dot-forward.1 | 246 +++++++++++++++++++++++++++ dot-forward.c | 419 +++++++++++++++++++++++++++++++++++++++++++++ env.h | 17 ++ envread.c | 30 ++++ error.c | 95 +++++++++++ error.h | 23 +++ error_str.c | 276 ++++++++++++++++++++++++++++++ exit.h | 6 + fd.h | 7 + fd_copy.c | 13 ++ fd_move.c | 11 ++ find-systype.sh | 144 ++++++++++++++++ fmt.h | 25 +++ fmt_ulong.c | 13 ++ fork.h1 | 7 + fork.h2 | 7 + gen_alloc.h | 7 + gen_allocdefs.h | 34 ++++ getln.c | 20 +++ getln.h | 7 + getln2.c | 31 ++++ hier.c | 16 ++ install.c | 111 ++++++++++++ instcheck.c | 83 +++++++++ make-compile.sh | 1 + make-load.sh | 2 + make-makelib.sh | 16 ++ open.h | 10 ++ open_read.c | 6 + open_trunc.c | 6 + qmail.c | 125 ++++++++++++++ qmail.h | 24 +++ readwrite.h | 7 + scan.h | 27 +++ scan_ulong.c | 11 ++ seek.h | 15 ++ seek_set.c | 7 + sgetopt.c | 54 ++++++ sgetopt.h | 21 +++ sig.h | 43 +++++ sig_catch.c | 18 ++ sig_pipe.c | 5 + str.h | 14 ++ str_diffn.c | 18 ++ str_len.c | 15 ++ stralloc.h | 21 +++ stralloc_cat.c | 9 + stralloc_catb.c | 15 ++ stralloc_cats.c | 10 ++ stralloc_copy.c | 9 + stralloc_eady.c | 6 + stralloc_opyb.c | 14 ++ stralloc_opys.c | 10 ++ stralloc_pend.c | 5 + strerr.h | 80 +++++++++ strerr_die.c | 37 ++++ strerr_sys.c | 12 ++ subfd.h | 15 ++ subfderr.c | 7 + subgetopt.c | 79 +++++++++ subgetopt.h | 24 +++ substdi.c | 91 ++++++++++ substdio.c | 15 ++ substdio.h | 47 ++++++ substdio_copy.c | 18 ++ substdo.c | 108 ++++++++++++ token822.c | 513 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ token822.h | 37 ++++ trycpp.c | 7 + trysgact.c | 10 ++ tryvfork.c | 4 + trywaitp.c | 7 + wait.h | 14 ++ wait_pid.c | 39 +++++ warn-auto.sh | 2 + 102 files changed, 4391 insertions(+) create mode 100644 BLURB create mode 100644 CHANGES create mode 100644 FILES create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 README create mode 100644 SYSDEPS create mode 100644 TARGETS create mode 100644 THANKS create mode 100644 TODO create mode 100644 VERSION create mode 100644 alloc.c create mode 100644 alloc.h create mode 100644 alloc_re.c create mode 100644 auto-str.c create mode 100644 auto_qmail.h create mode 100644 byte.h create mode 100644 byte_chr.c create mode 100644 byte_copy.c create mode 100644 byte_cr.c create mode 100644 case.h create mode 100644 case_diffb.c create mode 100644 conf-cc create mode 100644 conf-ld create mode 100644 conf-qmail create mode 100644 control.c create mode 100644 control.h create mode 100644 dot-forward.1 create mode 100644 dot-forward.c create mode 100644 env.h create mode 100644 envread.c create mode 100644 error.c create mode 100644 error.h create mode 100644 error_str.c create mode 100644 exit.h create mode 100644 fd.h create mode 100644 fd_copy.c create mode 100644 fd_move.c create mode 100644 find-systype.sh create mode 100644 fmt.h create mode 100644 fmt_ulong.c create mode 100644 fork.h1 create mode 100644 fork.h2 create mode 100644 gen_alloc.h create mode 100644 gen_allocdefs.h create mode 100644 getln.c create mode 100644 getln.h create mode 100644 getln2.c create mode 100644 hier.c create mode 100644 install.c create mode 100644 instcheck.c create mode 100644 make-compile.sh create mode 100644 make-load.sh create mode 100644 make-makelib.sh create mode 100644 open.h create mode 100644 open_read.c create mode 100644 open_trunc.c create mode 100644 qmail.c create mode 100644 qmail.h create mode 100644 readwrite.h create mode 100644 scan.h create mode 100644 scan_ulong.c create mode 100644 seek.h create mode 100644 seek_set.c create mode 100644 sgetopt.c create mode 100644 sgetopt.h create mode 100644 sig.h create mode 100644 sig_catch.c create mode 100644 sig_pipe.c create mode 100644 str.h create mode 100644 str_diffn.c create mode 100644 str_len.c create mode 100644 stralloc.h create mode 100644 stralloc_cat.c create mode 100644 stralloc_catb.c create mode 100644 stralloc_cats.c create mode 100644 stralloc_copy.c create mode 100644 stralloc_eady.c create mode 100644 stralloc_opyb.c create mode 100644 stralloc_opys.c create mode 100644 stralloc_pend.c create mode 100644 strerr.h create mode 100644 strerr_die.c create mode 100644 strerr_sys.c create mode 100644 subfd.h create mode 100644 subfderr.c create mode 100644 subgetopt.c create mode 100644 subgetopt.h create mode 100644 substdi.c create mode 100644 substdio.c create mode 100644 substdio.h create mode 100644 substdio_copy.c create mode 100644 substdo.c create mode 100644 token822.c create mode 100644 token822.h create mode 100644 trycpp.c create mode 100644 trysgact.c create mode 100644 tryvfork.c create mode 100644 trywaitp.c create mode 100644 wait.h create mode 100644 wait_pid.c create mode 100644 warn-auto.sh diff --git a/BLURB b/BLURB new file mode 100644 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 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 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 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 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 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 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 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 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 index 0000000..9daeafb --- /dev/null +++ b/TODO @@ -0,0 +1 @@ +test diff --git a/VERSION b/VERSION new file mode 100644 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 index 0000000..c661453 --- /dev/null +++ b/alloc.c @@ -0,0 +1,32 @@ +#include "alloc.h" +#include "error.h" +extern char *malloc(); +extern void free(); + +#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ +#define SPACE 4096 /* must be multiple of ALIGNMENT */ + +typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; +static aligned realspace[SPACE / ALIGNMENT]; +#define space ((char *) realspace) +static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ + +/*@null@*//*@out@*/char *alloc(n) +unsigned int n; +{ + char *x; + n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ + if (n <= avail) { avail -= n; return space + avail; } + x = malloc(n); + if (!x) errno = error_nomem; + return x; +} + +void alloc_free(x) +char *x; +{ + if (x >= space) + if (x < space + SPACE) + return; /* XXX: assuming that pointers are flat */ + free(x); +} diff --git a/alloc.h b/alloc.h new file mode 100644 index 0000000..1b1d893 --- /dev/null +++ b/alloc.h @@ -0,0 +1,8 @@ +#ifndef ALLOC_H +#define ALLOC_H + +extern /*@null@*//*@out@*/char *alloc(); +extern void alloc_free(); +extern int alloc_re(); + +#endif diff --git a/alloc_re.c b/alloc_re.c new file mode 100644 index 0000000..feb8b49 --- /dev/null +++ b/alloc_re.c @@ -0,0 +1,17 @@ +#include "alloc.h" +#include "byte.h" + +int alloc_re(x,m,n) +char **x; +unsigned int m; +unsigned int n; +{ + char *y; + + y = alloc(n); + if (!y) return 0; + byte_copy(y,m,*x); + alloc_free(*x); + *x = y; + return 1; +} diff --git a/auto-str.c b/auto-str.c new file mode 100644 index 0000000..acc3d60 --- /dev/null +++ b/auto-str.c @@ -0,0 +1,44 @@ +#include "substdio.h" +#include "readwrite.h" +#include "exit.h" + +char buf1[256]; +substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); + +void puts(s) +char *s; +{ + if (substdio_puts(&ss1,s) == -1) _exit(111); +} + +void main(argc,argv) +int argc; +char **argv; +{ + char *name; + char *value; + unsigned char ch; + char octal[4]; + + name = argv[1]; + if (!name) _exit(100); + value = argv[2]; + if (!value) _exit(100); + + puts("char "); + puts(name); + puts("[] = \"\\\n"); + + while (ch = *value++) { + puts("\\"); + octal[3] = 0; + octal[2] = '0' + (ch & 7); ch >>= 3; + octal[1] = '0' + (ch & 7); ch >>= 3; + octal[0] = '0' + (ch & 7); + puts(octal); + } + + puts("\\\n\";\n"); + if (substdio_flush(&ss1) == -1) _exit(111); + _exit(0); +} diff --git a/auto_qmail.h b/auto_qmail.h new file mode 100644 index 0000000..0c56001 --- /dev/null +++ b/auto_qmail.h @@ -0,0 +1,6 @@ +#ifndef AUTO_QMAIL_H +#define AUTO_QMAIL_H + +extern char auto_qmail[]; + +#endif diff --git a/byte.h b/byte.h new file mode 100644 index 0000000..de06c69 --- /dev/null +++ b/byte.h @@ -0,0 +1,13 @@ +#ifndef BYTE_H +#define BYTE_H + +extern unsigned int byte_chr(); +extern unsigned int byte_rchr(); +extern void byte_copy(); +extern void byte_copyr(); +extern int byte_diff(); +extern void byte_zero(); + +#define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) + +#endif diff --git a/byte_chr.c b/byte_chr.c new file mode 100644 index 0000000..f81dde8 --- /dev/null +++ b/byte_chr.c @@ -0,0 +1,20 @@ +#include "byte.h" + +unsigned int byte_chr(s,n,c) +char *s; +register unsigned int n; +int c; +{ + register char ch; + register char *t; + + ch = c; + t = s; + for (;;) { + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + } + return t - s; +} diff --git a/byte_copy.c b/byte_copy.c new file mode 100644 index 0000000..eaad11b --- /dev/null +++ b/byte_copy.c @@ -0,0 +1,14 @@ +#include "byte.h" + +void byte_copy(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + for (;;) { + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + } +} diff --git a/byte_cr.c b/byte_cr.c new file mode 100644 index 0000000..3e7a1d5 --- /dev/null +++ b/byte_cr.c @@ -0,0 +1,16 @@ +#include "byte.h" + +void byte_copyr(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + to += n; + from += n; + for (;;) { + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + } +} diff --git a/case.h b/case.h new file mode 100644 index 0000000..35a2434 --- /dev/null +++ b/case.h @@ -0,0 +1,13 @@ +#ifndef CASE_H +#define CASE_H + +extern void case_lowers(); +extern void case_lowerb(); +extern int case_diffs(); +extern int case_diffb(); +extern int case_starts(); +extern int case_startb(); + +#define case_equals(s,t) (!case_diffs((s),(t))) + +#endif diff --git a/case_diffb.c b/case_diffb.c new file mode 100644 index 0000000..9064b8a --- /dev/null +++ b/case_diffb.c @@ -0,0 +1,21 @@ +#include "case.h" + +int case_diffb(s,len,t) +register char *s; +unsigned int len; +register char *t; +{ + register unsigned char x; + register unsigned char y; + + while (len > 0) { + --len; + x = *s++ - 'A'; + if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; + y = *t++ - 'A'; + if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; + if (x != y) + return ((int)(unsigned int) x) - ((int)(unsigned int) y); + } + return 0; +} diff --git a/conf-cc b/conf-cc new file mode 100644 index 0000000..e58fb9b --- /dev/null +++ b/conf-cc @@ -0,0 +1,3 @@ +cc -O2 + +This will be used to compile .c files. diff --git a/conf-ld b/conf-ld new file mode 100644 index 0000000..a9e796a --- /dev/null +++ b/conf-ld @@ -0,0 +1,3 @@ +cc -s + +This will be used to link .o files into an executable. diff --git a/conf-qmail b/conf-qmail new file mode 100644 index 0000000..a988177 --- /dev/null +++ b/conf-qmail @@ -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 index 0000000..b655352 --- /dev/null +++ b/control.c @@ -0,0 +1,130 @@ +#include "readwrite.h" +#include "open.h" +#include "getln.h" +#include "stralloc.h" +#include "substdio.h" +#include "error.h" +#include "control.h" +#include "alloc.h" +#include "scan.h" + +static char inbuf[64]; +static stralloc line = {0}; +static stralloc me = {0}; +static int meok = 0; + +static void striptrailingwhitespace(sa) +stralloc *sa; +{ + while (sa->len > 0) + switch(sa->s[sa->len - 1]) + { + case '\n': case ' ': case '\t': + --sa->len; + break; + default: + return; + } +} + +int control_init() +{ + int r; + r = control_readline(&me,"control/me"); + if (r == 1) meok = 1; + return r; +} + +int control_rldef(sa,fn,flagme,def) +stralloc *sa; +char *fn; +int flagme; +char *def; +{ + int r; + r = control_readline(sa,fn); + if (r) return r; + if (flagme) if (meok) return stralloc_copy(sa,&me) ? 1 : -1; + if (def) return stralloc_copys(sa,def) ? 1 : -1; + return r; +} + +int control_readline(sa,fn) +stralloc *sa; +char *fn; +{ + substdio ss; + int fd; + int match; + + fd = open_read(fn); + if (fd == -1) { if (errno == error_noent) return 0; return -1; } + + substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf)); + + if (getln(&ss,sa,&match,'\n') == -1) { close(fd); return -1; } + + striptrailingwhitespace(sa); + close(fd); + return 1; +} + +int control_readint(i,fn) +int *i; +char *fn; +{ + unsigned long u; + switch(control_readline(&line,fn)) + { + case 0: return 0; + case -1: return -1; + } + if (!stralloc_0(&line)) return -1; + if (!scan_ulong(line.s,&u)) return 0; + *i = u; + return 1; +} + +int control_readfile(sa,fn,flagme) +stralloc *sa; +char *fn; +int flagme; +{ + substdio ss; + int fd; + int match; + + if (!stralloc_copys(sa,"")) return -1; + + fd = open_read(fn); + if (fd == -1) + { + if (errno == error_noent) + { + if (flagme && meok) + { + if (!stralloc_copy(sa,&me)) return -1; + if (!stralloc_0(sa)) return -1; + return 1; + } + return 0; + } + return -1; + } + + substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf)); + + for (;;) + { + if (getln(&ss,&line,&match,'\n') == -1) break; + if (!match && !line.len) { close(fd); return 1; } + striptrailingwhitespace(&line); + if (!stralloc_0(&line)) break; + if (line.s[0]) + if (line.s[0] != '#') + if (!stralloc_cat(sa,&line)) break; + if (!match) { close(fd); return 1; } + } + close(fd); + return -1; +} diff --git a/control.h b/control.h new file mode 100644 index 0000000..7cba89b --- /dev/null +++ b/control.h @@ -0,0 +1,10 @@ +#ifndef CONTROL_H +#define CONTROL_H + +extern int control_init(); +extern int control_readline(); +extern int control_rldef(); +extern int control_readint(); +extern int control_readfile(); + +#endif diff --git a/dot-forward.1 b/dot-forward.1 new file mode 100644 index 0000000..a8b90b1 --- /dev/null +++ b/dot-forward.1 @@ -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 +.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 index 0000000..66510ad --- /dev/null +++ b/dot-forward.c @@ -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 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 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 index 0000000..d51304f --- /dev/null +++ b/error.c @@ -0,0 +1,95 @@ +#include +#include "error.h" + +/* warning: as coverage improves here, should update error_{str,temp} */ + +int error_intr = +#ifdef EINTR +EINTR; +#else +-1; +#endif + +int error_nomem = +#ifdef ENOMEM +ENOMEM; +#else +-2; +#endif + +int error_noent = +#ifdef ENOENT +ENOENT; +#else +-3; +#endif + +int error_txtbsy = +#ifdef ETXTBSY +ETXTBSY; +#else +-4; +#endif + +int error_io = +#ifdef EIO +EIO; +#else +-5; +#endif + +int error_exist = +#ifdef EEXIST +EEXIST; +#else +-6; +#endif + +int error_timeout = +#ifdef ETIMEDOUT +ETIMEDOUT; +#else +-7; +#endif + +int error_inprogress = +#ifdef EINPROGRESS +EINPROGRESS; +#else +-8; +#endif + +int error_wouldblock = +#ifdef EWOULDBLOCK +EWOULDBLOCK; +#else +-9; +#endif + +int error_again = +#ifdef EAGAIN +EAGAIN; +#else +-10; +#endif + +int error_pipe = +#ifdef EPIPE +EPIPE; +#else +-11; +#endif + +int error_perm = +#ifdef EPERM +EPERM; +#else +-12; +#endif + +int error_acces = +#ifdef EACCES +EACCES; +#else +-13; +#endif diff --git a/error.h b/error.h new file mode 100644 index 0000000..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 index 0000000..804d1fa --- /dev/null +++ b/error_str.c @@ -0,0 +1,276 @@ +#include +#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 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 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 index 0000000..b9f7167 --- /dev/null +++ b/fd_copy.c @@ -0,0 +1,13 @@ +#include +#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 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 index 0000000..16266d3 --- /dev/null +++ b/find-systype.sh @@ -0,0 +1,144 @@ +# oper-:arch-:syst-:chip-:kern- +# oper = operating system type; e.g., sunos-4.1.4 +# arch = machine language; e.g., sparc +# syst = which binaries can run; e.g., sun4 +# chip = chip model; e.g., micro-2-80 +# kern = kernel version; e.g., sun4m +# dependence: arch --- chip +# \ \ +# oper --- syst --- kern +# so, for example, syst is interpreted in light of oper, but chip is not. +# anyway, no slashes, no extra colons, no uppercase letters. +# the point of the extra -'s is to ease parsing: can add hierarchies later. +# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, +# and i386-486 (486s do have more instructions, you know) as well as i386. +# the idea here is to include ALL useful available information. + +exec 2>/dev/null +sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" +if [ x"$sys" != x ] +then + unamer="`uname -r | tr /: ..`" + unamem="`uname -m | tr /: ..`" + unamev="`uname -v | tr /: ..`" + + case "$sys" in + bsd.os) + # in bsd 4.4, uname -v does not have useful info. + # in bsd 4.4, uname -m is arch, not chip. + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" + kern="" + ;; + freebsd) + # see above about bsd 4.4 + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + netbsd) + # see above about bsd 4.4 + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + linux) + # as in bsd 4.4, uname -v does not have useful info. + oper="$sys-$unamer" + syst="" + chip="$unamem" + kern="" + case "$chip" in + i386|i486|i586|i686) + arch="i386" + ;; + alpha) + arch="alpha" + ;; + esac + ;; + aix) + # naturally IBM has to get uname -r and uname -v backwards. dorks. + oper="$sys-$unamev-$unamer" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + sunos) + oper="$sys-$unamer-$unamev" + arch="`(uname -p || mach) | tr /: ..`" + syst="`arch | tr /: ..`" + chip="$unamem" # this is wrong; is there any way to get the real info? + kern="`arch -k | tr /: ..`" + ;; + unix_sv) + oper="$sys-$unamer-$unamev" + arch="`uname -m`" + syst="" + chip="$unamem" + kern="" + ;; + *) + oper="$sys-$unamer-$unamev" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + esac +else + $CC -c trycpp.c + $LD -o trycpp trycpp.o + case `./trycpp` in + nextstep) + oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" + arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" + syst="" + chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" + kern="" + ;; + *) + oper="unknown" + arch="" + syst="" + chip="" + kern="" + ;; + esac + rm -f trycpp.o trycpp +fi + +case "$chip" in +80486) + # let's try to be consistent here. (BSD/OS) + chip=i486 + ;; +i486DX) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx + ;; +i486.DX2) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx2 + ;; +Intel.586) + # no, you nitwits, there is no such chip. (NeXTStep) + chip=pentium + ;; +i586) + # no, you nitwits, there is no such chip. (Linux) + chip=pentium + ;; +i686) + # STOP SAYING THAT! (Linux) + chip=ppro +esac + +echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' diff --git a/fmt.h b/fmt.h new file mode 100644 index 0000000..ba2fe16 --- /dev/null +++ b/fmt.h @@ -0,0 +1,25 @@ +#ifndef FMT_H +#define FMT_H + +#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ +#define FMT_LEN ((char *) 0) /* convenient abbreviation */ + +extern unsigned int fmt_uint(); +extern unsigned int fmt_uint0(); +extern unsigned int fmt_xint(); +extern unsigned int fmt_nbbint(); +extern unsigned int fmt_ushort(); +extern unsigned int fmt_xshort(); +extern unsigned int fmt_nbbshort(); +extern unsigned int fmt_ulong(); +extern unsigned int fmt_xlong(); +extern unsigned int fmt_nbblong(); + +extern unsigned int fmt_plusminus(); +extern unsigned int fmt_minus(); +extern unsigned int fmt_0x(); + +extern unsigned int fmt_str(); +extern unsigned int fmt_strn(); + +#endif diff --git a/fmt_ulong.c b/fmt_ulong.c new file mode 100644 index 0000000..ab12e8c --- /dev/null +++ b/fmt_ulong.c @@ -0,0 +1,13 @@ +#include "fmt.h" + +unsigned int fmt_ulong(s,u) register char *s; register unsigned long u; +{ + register unsigned int len; register unsigned long q; + len = 1; q = u; + while (q > 9) { ++len; q /= 10; } + if (s) { + s += len; + do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ + } + return len; +} diff --git a/fork.h1 b/fork.h1 new file mode 100644 index 0000000..b786255 --- /dev/null +++ b/fork.h1 @@ -0,0 +1,7 @@ +#ifndef FORK_H +#define FORK_H + +extern int fork(); +#define vfork fork + +#endif diff --git a/fork.h2 b/fork.h2 new file mode 100644 index 0000000..41773b6 --- /dev/null +++ b/fork.h2 @@ -0,0 +1,7 @@ +#ifndef FORK_H +#define FORK_H + +extern int fork(); +extern int vfork(); + +#endif diff --git a/gen_alloc.h b/gen_alloc.h new file mode 100644 index 0000000..b94a956 --- /dev/null +++ b/gen_alloc.h @@ -0,0 +1,7 @@ +#ifndef GEN_ALLOC_H +#define GEN_ALLOC_H + +#define GEN_ALLOC_typedef(ta,type,field,len,a) \ + typedef struct ta { type *field; unsigned int len; unsigned int a; } ta; + +#endif diff --git a/gen_allocdefs.h b/gen_allocdefs.h new file mode 100644 index 0000000..783a9b1 --- /dev/null +++ b/gen_allocdefs.h @@ -0,0 +1,34 @@ +#ifndef GEN_ALLOC_DEFS_H +#define GEN_ALLOC_DEFS_H + +#define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ +int ta_ready(x,n) register ta *x; register unsigned int n; \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ +int ta_rplus(x,n) register ta *x; register unsigned int n; \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; n += x->len; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ +int ta_append(x,i) register ta *x; register type *i; \ +{ if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } + +#endif diff --git a/getln.c b/getln.c new file mode 100644 index 0000000..c5cb097 --- /dev/null +++ b/getln.c @@ -0,0 +1,20 @@ +#include "substdio.h" +#include "byte.h" +#include "stralloc.h" +#include "getln.h" + +int getln(ss,sa,match,sep) +register substdio *ss; +register stralloc *sa; +int *match; +int sep; +{ + char *cont; + unsigned int clen; + + if (getln2(ss,sa,&cont,&clen,sep) == -1) return -1; + if (!clen) { *match = 0; return 0; } + if (!stralloc_catb(sa,cont,clen)) return -1; + *match = 1; + return 0; +} diff --git a/getln.h b/getln.h new file mode 100644 index 0000000..cf4f934 --- /dev/null +++ b/getln.h @@ -0,0 +1,7 @@ +#ifndef GETLN_H +#define GETLN_H + +extern int getln(); +extern int getln2(); + +#endif diff --git a/getln2.c b/getln2.c new file mode 100644 index 0000000..9e576e9 --- /dev/null +++ b/getln2.c @@ -0,0 +1,31 @@ +#include "substdio.h" +#include "stralloc.h" +#include "byte.h" +#include "getln.h" + +int getln2(ss,sa,cont,clen,sep) +register substdio *ss; +register stralloc *sa; +/*@out@*/char **cont; +/*@out@*/unsigned int *clen; +int sep; +{ + register char *x; + register unsigned int i; + int n; + + if (!stralloc_ready(sa,0)) return -1; + sa->len = 0; + + for (;;) { + n = substdio_feed(ss); + if (n < 0) return -1; + if (n == 0) { *clen = 0; return 0; } + x = substdio_PEEK(ss); + i = byte_chr(x,n,sep); + if (i < n) { substdio_SEEK(ss,*clen = i + 1); *cont = x; return 0; } + if (!stralloc_readyplus(sa,n)) return -1; + i = sa->len; + sa->len = i + substdio_get(ss,sa->s + i,n); + } +} diff --git a/hier.c b/hier.c new file mode 100644 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 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 index 0000000..0b77e45 --- /dev/null +++ b/instcheck.c @@ -0,0 +1,83 @@ +#include +#include +#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 index 0000000..a1eb501 --- /dev/null +++ b/make-compile.sh @@ -0,0 +1 @@ +echo exec "$CC" -c '${1+"$@"}' diff --git a/make-load.sh b/make-load.sh new file mode 100644 index 0000000..de07d2e --- /dev/null +++ b/make-load.sh @@ -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 index 0000000..d6b7c8c --- /dev/null +++ b/make-makelib.sh @@ -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 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 index 0000000..f503e48 --- /dev/null +++ b/open_read.c @@ -0,0 +1,6 @@ +#include +#include +#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 index 0000000..e275085 --- /dev/null +++ b/open_trunc.c @@ -0,0 +1,6 @@ +#include +#include +#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 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 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 index 0000000..2a64968 --- /dev/null +++ b/readwrite.h @@ -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 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 index 0000000..27c41ea --- /dev/null +++ b/scan_ulong.c @@ -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 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 index 0000000..f540664 --- /dev/null +++ b/seek_set.c @@ -0,0 +1,7 @@ +#include +#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 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 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 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 index 0000000..1888765 --- /dev/null +++ b/sig_catch.c @@ -0,0 +1,18 @@ +#include +#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 index 0000000..594ae7d --- /dev/null +++ b/sig_pipe.c @@ -0,0 +1,5 @@ +#include +#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 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 index 0000000..89142f1 --- /dev/null +++ b/str_diffn.c @@ -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 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 index 0000000..fca496c --- /dev/null +++ b/stralloc.h @@ -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 index 0000000..efbb112 --- /dev/null +++ b/stralloc_cat.c @@ -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 index 0000000..67dbcc0 --- /dev/null +++ b/stralloc_catb.c @@ -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 index 0000000..d300286 --- /dev/null +++ b/stralloc_cats.c @@ -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 index 0000000..652aed6 --- /dev/null +++ b/stralloc_copy.c @@ -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 index 0000000..3a31f4b --- /dev/null +++ b/stralloc_eady.c @@ -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 index 0000000..ac258b3 --- /dev/null +++ b/stralloc_opyb.c @@ -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 index 0000000..fdd7807 --- /dev/null +++ b/stralloc_opys.c @@ -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 index 0000000..a3443b8 --- /dev/null +++ b/stralloc_pend.c @@ -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 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 index 0000000..6092020 --- /dev/null +++ b/strerr_die.c @@ -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 index 0000000..198198b --- /dev/null +++ b/strerr_sys.c @@ -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 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 index 0000000..011ab0f --- /dev/null +++ b/subfderr.c @@ -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 = ⁢ diff --git a/subgetopt.c b/subgetopt.c new file mode 100644 index 0000000..dacf376 --- /dev/null +++ b/subgetopt.c @@ -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 index 0000000..d26c62a --- /dev/null +++ b/subgetopt.h @@ -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 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 index 0000000..d03dff2 --- /dev/null +++ b/substdio.c @@ -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 index 0000000..c3f7f7d --- /dev/null +++ b/substdio.h @@ -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 index 0000000..71cf200 --- /dev/null +++ b/substdio_copy.c @@ -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 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 index 0000000..48a4388 --- /dev/null +++ b/token822.c @@ -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 index 0000000..9ca35cf --- /dev/null +++ b/token822.h @@ -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 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 index 0000000..263cb21 --- /dev/null +++ b/trysgact.c @@ -0,0 +1,10 @@ +#include + +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 index 0000000..21387e4 --- /dev/null +++ b/tryvfork.c @@ -0,0 +1,4 @@ +void main() +{ + vfork(); +} diff --git a/trywaitp.c b/trywaitp.c new file mode 100644 index 0000000..7e73bfa --- /dev/null +++ b/trywaitp.c @@ -0,0 +1,7 @@ +#include +#include + +void main() +{ + waitpid(0,0,0); +} diff --git a/wait.h b/wait.h new file mode 100644 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 index 0000000..d7a7e84 --- /dev/null +++ b/wait_pid.c @@ -0,0 +1,39 @@ +#include +#include +#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 index 0000000..36d2313 --- /dev/null +++ b/warn-auto.sh @@ -0,0 +1,2 @@ +#!/bin/sh +# WARNING: This file was auto-generated. Do not edit! -- 2.11.0