fastforward-0.51/004075500000000000001000000000000653033120000141125ustar00rootother00000000000000fastforward-0.51/BLURB010064400000000000001000000017530653033120600147140ustar00rootother00000000000000fastforward handles qmail forwarding according to a cdb database. It can create forwarding databases from a sendmail-style /etc/aliases or from user-oriented virtual-domain tables. fastforward supports external mailing lists, stored in a binary format for fast access. It has a tool to convert sendmail-style include files into binary lists. fastforward is more reliable than sendmail. sendmail can't deal with long aliases, or deeply nested aliases, or deeply nested include files; fastforward has no limits other than memory. sendmail can produce corrupted alias files if the system crashes; fastforward is crashproof. fastforward's database-building tools are much faster than sendmail's newaliases. Even better, fastforward deliveries don't pause while the database is being rebuilt. fastforward does not support insecure sendmail-style program deliveries from include files; you can use qmail's secure built-in mechanisms instead. fastforward does support program deliveries from /etc/aliases. fastforward-0.51/README010064400000000000001000000014470653033120600150030ustar00rootother00000000000000fastforward 0.51, alpha. 19980519 Copyright 1998 D. J. Bernstein, djb@pobox.com fastforward handles qmail forwarding according to a cdb database. It can create forwarding databases from a sendmail-style /etc/aliases or from user-oriented virtual-domain tables. See BLURB for a more detailed advertisement. INSTALL says how to set up fastforward. You may distribute unmodified copies of the fastforward package. The rest of this file is a list of systypes where various versions of fastforward have been reported to work. 0.50: bsd.os-2.0.1-:i386-:-:pentium-:- 0.50: irix-5.3-11091811-:-:-:ip19-:- (tnx JB) 0.50: linux-2.0.7-:i386-:-:i486-:- (tnx TLM) 0.50: linux-2.0.33-:i386-:-:i486-:- (tnx TB) 0.50: osf1-v4.0-878-:-:-:alpha-:- (tnx BJM) 0.50: sunos-5.6-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx TWH) fastforward-0.51/TODO010064400000000000001000000000420653033120600146010ustar00rootother00000000000000consider other table formats test fastforward-0.51/THANKS010064400000000000001000000002730653033120600150320ustar00rootother00000000000000BJM = Barry J. Miller JB = Jos Backus LW = Lionel Widdifield MS = Mikael Suokas PJG = Paul Graham SAC = Shawn A. Clifford TB = Thomas Bullinger TLM = Timothy L. Mayo TWH = Thomas W. Holt fastforward-0.51/CHANGES010064400000000000001000000012600653033120600151070ustar00rootother0000000000000019980519 version: fastforward 0.51, alpha. 19980519 code: added preline variant in fastforward; updated setforward, printforward, newaliases accordingly. 19980519 doc: added virtual-domains section to ALIASES. 19980519 doc: used -d in ALIASES. 19980519 code: added fastforward -d. 19980519 doc: put version and home page into fastforward.1. 19980519 doc: simplified INSTALL. 19980519 doc: added ALIASES. 19980519 doc: expanded explanation in conf-qmail. 19980519 code: switched to new install. 19980420 portability problem: IRIX doesn't have vfork(). impact: couldn't compile under IRIX. fix: include fork.h in fastforward.c. tnx JB. 19980420 fastforward 0.50, alpha. fastforward-0.51/FILES010064400000000000001000000027770653033120600147170ustar00rootother00000000000000BLURB README TODO THANKS CHANGES FILES TARGETS VERSION SYSDEPS Makefile ALIASES INSTALL hier.c fastforward.1 fastforward.c printforward.1 printforward.c setforward.1 setforward.c printmaillist.1 printmaillist.c setmaillist.1 setmaillist.c newaliases.1 newaliases.c newinclude.1 newinclude.c auto-str.c install.c instcheck.c conf-cc conf-ld find-systype.sh make-compile.sh make-load.sh make-makelib.sh trycpp.c warn-auto.sh alloc.h alloc.c alloc_re.c case.h case_lowerb.c cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c control.h control.c env.h envread.c error.h error.c error_str.c fd.h fd_copy.c fd_move.c fork.h1 fork.h2 tryvfork.c fmt.h fmt_ulong.c scan.h scan_ulong.c getln.h getln.c getln2.c sgetopt.h sgetopt.c subgetopt.h subgetopt.c open.h open_read.c open_trunc.c conf-qmail auto_qmail.h qmail.h qmail.c seek.h seek_set.c sig.h sig_catch.c sig_pipe.c trysgact.c byte.h byte_chr.c byte_copy.c byte_cr.c byte_diff.c str.h str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.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 stralloc_arts.c strset.h strset.c substdio.h substdio.c substdi.c substdo.c substdio_copy.c subfd.h subfderr.c subfdouts.c subfdins.c readwrite.h exit.h token822.h token822.c uint32.h1 uint32.h2 tryulong32.c wait.h wait_pid.c trywaitp.c strerr.h strerr_sys.c strerr_die.c slurpclose.h slurpclose.c coe.h coe.c fastforward-0.51/TARGETS010064400000000000001000000025470653033120600151610ustar00rootother00000000000000auto-ccld.sh make-load find-systype systype load make-compile compile uint32.h fork.h fastforward.o slurpclose.o coe.o strset.o qmail.o auto-str.o make-makelib makelib substdio.o substdi.o substdo.o subfderr.o subfdouts.o subfdins.o substdio_copy.o substdio.a error.o error_str.o error.a str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o str_rchr.o byte_chr.o byte_diff.o byte_copy.o byte_cr.o str.a auto-str auto_qmail.c auto_qmail.o subgetopt.o sgetopt.o getopt.a cdb_hash.o cdb_unpack.o cdb_seek.o cdb.a envread.o env.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_arts.o stralloc.a alloc.o alloc_re.o alloc.a case_lowerb.o case.a fmt_ulong.o scan_ulong.o fs.a hassgact.h sig_catch.o sig_pipe.o sig.a haswaitp.h wait_pid.o wait.a seek_set.o seek.a open_read.o open_trunc.o open.a fd_copy.o fd_move.o fd.a fastforward printforward.o printforward setforward.o cdbmss.o cdbmake_pack.o cdbmake_hash.o cdbmake_add.o cdbmake.a setforward newaliases.o token822.o control.o getln.o getln2.o getln.a newaliases printmaillist.o printmaillist setmaillist.o setmaillist newinclude.o newinclude prog fastforward.0 printforward.0 setforward.0 newaliases.0 printmaillist.0 setmaillist.0 newinclude.0 man it install.o hier.o install setup instcheck.o instcheck check fastforward-0.51/VERSION010064400000000000001000000000210653033120600151560ustar00rootother00000000000000fastforward 0.51 fastforward-0.51/SYSDEPS010064400000000000001000000000660653033120600151740ustar00rootother00000000000000VERSION systype hassgact.h haswaitp.h fork.h uint32.h fastforward-0.51/Makefile010064400000000000001000000332200653033120600155550ustar00rootother00000000000000# 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 byte_diff.o: \ compile byte_diff.c byte.h ./compile byte_diff.c case.a: \ makelib case_lowerb.o ./makelib case.a case_lowerb.o case_lowerb.o: \ compile case_lowerb.c case.h ./compile case_lowerb.c cdb.a: \ makelib cdb_hash.o cdb_unpack.o cdb_seek.o ./makelib cdb.a cdb_hash.o cdb_unpack.o cdb_seek.o cdb_hash.o: \ compile cdb_hash.c cdb.h uint32.h ./compile cdb_hash.c cdb_seek.o: \ compile cdb_seek.c cdb.h uint32.h ./compile cdb_seek.c cdb_unpack.o: \ compile cdb_unpack.c cdb.h uint32.h ./compile cdb_unpack.c cdbmake.a: \ makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o ./makelib cdbmake.a cdbmake_pack.o cdbmake_hash.o \ cdbmake_add.o cdbmake_add.o: \ compile cdbmake_add.c cdbmake.h uint32.h ./compile cdbmake_add.c cdbmake_hash.o: \ compile cdbmake_hash.c cdbmake.h uint32.h ./compile cdbmake_hash.c cdbmake_pack.o: \ compile cdbmake_pack.c cdbmake.h uint32.h ./compile cdbmake_pack.c cdbmss.o: \ compile cdbmss.c readwrite.h seek.h alloc.h cdbmss.h cdbmake.h \ uint32.h substdio.h ./compile cdbmss.c check: \ it instcheck ./instcheck coe.o: \ compile coe.c coe.h ./compile coe.c 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 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 fastforward: \ load fastforward.o slurpclose.o coe.o strset.o qmail.o auto_qmail.o \ getopt.a cdb.a env.a strerr.a substdio.a stralloc.a alloc.a error.a \ case.a str.a fs.a sig.a wait.a seek.a open.a fd.a ./load fastforward slurpclose.o coe.o strset.o qmail.o \ auto_qmail.o getopt.a cdb.a env.a strerr.a substdio.a \ stralloc.a alloc.a error.a case.a str.a fs.a sig.a wait.a \ seek.a open.a fd.a fastforward.0: \ fastforward.1 nroff -man fastforward.1 > fastforward.0 fastforward.o: \ compile fastforward.c stralloc.h gen_alloc.h substdio.h subfd.h \ substdio.h strset.h uint32.h sgetopt.h subgetopt.h readwrite.h exit.h \ strerr.h env.h sig.h qmail.h substdio.h fmt.h case.h alloc.h coe.h \ seek.h wait.h fork.h ./compile fastforward.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: \ fastforward.0 printforward.0 setforward.0 newaliases.0 \ printmaillist.0 setmaillist.0 newinclude.0 newaliases: \ load newaliases.o auto_qmail.o token822.o control.o cdbmss.o \ cdbmake.a strerr.a getln.a substdio.a stralloc.a alloc.a error.a \ str.a fs.a seek.a open.a case.a ./load newaliases auto_qmail.o token822.o control.o \ cdbmss.o cdbmake.a strerr.a getln.a substdio.a stralloc.a \ alloc.a error.a str.a fs.a seek.a open.a case.a newaliases.0: \ newaliases.1 nroff -man newaliases.1 > newaliases.0 newaliases.o: \ compile newaliases.c substdio.h strerr.h stralloc.h gen_alloc.h \ getln.h open.h readwrite.h token822.h gen_alloc.h control.h \ auto_qmail.h case.h cdbmss.h cdbmake.h uint32.h substdio.h ./compile newaliases.c newinclude: \ load newinclude.o auto_qmail.o token822.o control.o getln.a strerr.a \ stralloc.a env.a alloc.a substdio.a error.a str.a fs.a open.a wait.a \ fd.a ./load newinclude auto_qmail.o token822.o control.o \ getln.a strerr.a stralloc.a env.a alloc.a substdio.a \ error.a str.a fs.a open.a wait.a fd.a newinclude.0: \ newinclude.1 nroff -man newinclude.1 > newinclude.0 newinclude.o: \ compile newinclude.c substdio.h strerr.h stralloc.h gen_alloc.h \ getln.h open.h readwrite.h token822.h gen_alloc.h control.h \ auto_qmail.h env.h ./compile newinclude.c 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 printforward: \ load printforward.o cdb.a strerr.a substdio.a stralloc.a alloc.a \ error.a str.a ./load printforward cdb.a strerr.a substdio.a stralloc.a \ alloc.a error.a str.a printforward.0: \ printforward.1 nroff -man printforward.1 > printforward.0 printforward.o: \ compile printforward.c substdio.h subfd.h substdio.h strerr.h \ stralloc.h gen_alloc.h cdb.h uint32.h ./compile printforward.c printmaillist: \ load printmaillist.o getln.a strerr.a substdio.a stralloc.a alloc.a \ error.a str.a ./load printmaillist getln.a strerr.a substdio.a \ stralloc.a alloc.a error.a str.a printmaillist.0: \ printmaillist.1 nroff -man printmaillist.1 > printmaillist.0 printmaillist.o: \ compile printmaillist.c substdio.h subfd.h substdio.h strerr.h \ stralloc.h gen_alloc.h getln.h ./compile printmaillist.c prog: \ fastforward printforward setforward newaliases printmaillist \ setmaillist newinclude 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 setforward: \ load setforward.o cdbmss.o cdbmake.a strerr.a substdio.a stralloc.a \ alloc.a error.a str.a seek.a open.a case.a ./load setforward cdbmss.o cdbmake.a strerr.a substdio.a \ stralloc.a alloc.a error.a str.a seek.a open.a case.a setforward.0: \ setforward.1 nroff -man setforward.1 > setforward.0 setforward.o: \ compile setforward.c substdio.h subfd.h substdio.h strerr.h \ stralloc.h gen_alloc.h open.h case.h readwrite.h cdbmss.h cdbmake.h \ uint32.h substdio.h ./compile setforward.c setmaillist: \ load setmaillist.o getln.a strerr.a substdio.a stralloc.a alloc.a \ error.a str.a open.a ./load setmaillist getln.a strerr.a substdio.a stralloc.a \ alloc.a error.a str.a open.a setmaillist.0: \ setmaillist.1 nroff -man setmaillist.1 > setmaillist.0 setmaillist.o: \ compile setmaillist.c substdio.h subfd.h substdio.h strerr.h \ stralloc.h gen_alloc.h getln.h open.h readwrite.h ./compile setmaillist.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 slurpclose.o: \ compile slurpclose.c stralloc.h gen_alloc.h readwrite.h slurpclose.h \ error.h ./compile slurpclose.c str.a: \ makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \ str_rchr.o byte_chr.o byte_diff.o byte_copy.o byte_cr.o ./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \ str_chr.o str_rchr.o byte_chr.o byte_diff.o byte_copy.o \ byte_cr.o str_chr.o: \ compile str_chr.c str.h ./compile str_chr.c str_cpy.o: \ compile str_cpy.c str.h ./compile str_cpy.c str_diff.o: \ compile str_diff.c str.h ./compile str_diff.c str_diffn.o: \ compile str_diffn.c str.h ./compile str_diffn.c str_len.o: \ compile str_len.c str.h ./compile str_len.c str_rchr.o: \ compile str_rchr.c str.h ./compile str_rchr.c stralloc.a: \ makelib stralloc_eady.o stralloc_pend.o stralloc_copy.o \ stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o \ stralloc_catb.o stralloc_arts.o ./makelib stralloc.a stralloc_eady.o stralloc_pend.o \ stralloc_copy.o stralloc_opys.o stralloc_opyb.o \ stralloc_cat.o stralloc_cats.o stralloc_catb.o \ stralloc_arts.o stralloc_arts.o: \ compile stralloc_arts.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_arts.c stralloc_cat.o: \ compile stralloc_cat.c byte.h stralloc.h gen_alloc.h ./compile stralloc_cat.c stralloc_catb.o: \ compile stralloc_catb.c stralloc.h gen_alloc.h byte.h ./compile stralloc_catb.c stralloc_cats.o: \ compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_cats.c stralloc_copy.o: \ compile stralloc_copy.c byte.h stralloc.h gen_alloc.h ./compile stralloc_copy.c stralloc_eady.o: \ compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \ gen_allocdefs.h ./compile stralloc_eady.c stralloc_opyb.o: \ compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h ./compile stralloc_opyb.c stralloc_opys.o: \ compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_opys.c stralloc_pend.o: \ compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \ gen_allocdefs.h ./compile stralloc_pend.c strerr.a: \ makelib strerr_sys.o strerr_die.o ./makelib strerr.a strerr_sys.o strerr_die.o strerr_die.o: \ compile strerr_die.c substdio.h subfd.h substdio.h exit.h strerr.h ./compile strerr_die.c strerr_sys.o: \ compile strerr_sys.c error.h strerr.h ./compile strerr_sys.c strset.o: \ compile strset.c strset.h uint32.h str.h byte.h ./compile strset.c subfderr.o: \ compile subfderr.c readwrite.h substdio.h subfd.h substdio.h ./compile subfderr.c subfdins.o: \ compile subfdins.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdins.c subfdouts.o: \ compile subfdouts.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdouts.c subgetopt.o: \ compile subgetopt.c subgetopt.h ./compile subgetopt.c substdi.o: \ compile substdi.c substdio.h byte.h error.h ./compile substdi.c substdio.a: \ makelib substdio.o substdi.o substdo.o subfderr.o subfdouts.o \ subfdins.o substdio_copy.o ./makelib substdio.a substdio.o substdi.o substdo.o \ subfderr.o subfdouts.o subfdins.o substdio_copy.o substdio.o: \ compile substdio.c substdio.h ./compile substdio.c substdio_copy.o: \ compile substdio_copy.c substdio.h ./compile substdio_copy.c substdo.o: \ compile substdo.c substdio.h str.h byte.h error.h ./compile substdo.c 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 uint32.h: \ tryulong32.c compile load uint32.h1 uint32.h2 ( ( ./compile tryulong32.c && ./load tryulong32 && \ ./tryulong32 ) >/dev/null 2>&1 \ && cat uint32.h2 || cat uint32.h1 ) > uint32.h rm -f tryulong32.o tryulong32 wait.a: \ makelib wait_pid.o ./makelib wait.a wait_pid.o wait_pid.o: \ compile wait_pid.c error.h haswaitp.h ./compile wait_pid.c fastforward-0.51/ALIASES010064400000000000001000000060070653033120600151240ustar00rootother00000000000000--- Setting up /etc/aliases Create /etc/aliases if it does not already exist. You should include forwarding instructions for mailer-daemon, postmaster, and root: root: alias postmaster: alias mailer-daemon: alias Note that qmail never delivers mail to root. The instructions shown here will deliver messages to the mailbox of the ``alias'' user. For further details on the format of /etc/aliases, and a list of sendmail compatibility warnings, see the newaliases man page. --- Compiling /etc/aliases Once /etc/aliases is ready, run newaliases to compile /etc/aliases into /etc/aliases.cdb: # newaliases Review /etc/aliases.cdb to make sure it has the instructions you want: % printforward < /etc/aliases.cdb | more For the format of printforward's output, see the setforward man page. If you change /etc/aliases you will have to run newaliases again. You may want to add a comment at the top of /etc/aliases as a reminder. --- Compiling :include: files If you have an :include: file, say /etc/staff-list, compile it into /etc/staff-list.bin: # newinclude /etc/staff-list See the newinclude man page for a list of sendmail compatibility warnings. Review /etc/staff-list.bin: % printmaillist < /etc/staff-list.bin | more For the format of printmaillist's output, see the setmaillist man page. If you change /etc/staff-list you will have to run newinclude again. You may want to add a comment at the top of /etc/staff-list as a reminder. --- Configuring qmail to use /etc/aliases To activate /etc/aliases, put this line into ~alias/.qmail-default: | fastforward -d /etc/aliases.cdb If qmail is already running, make sure to chmod +t ~alias before you edit .qmail files in ~alias, and chmod -t ~alias after. --- Testing aliases To check the expansion of postmaster@your.host without sending any mail: % env DEFAULT=postmaster HOST=your.host fastforward -nd /etc/aliases.cdb Replace your.host with your fully qualified domain name. Make sure to include the -nd. Next, try sending a message to postmaster@your.host. Watch the qmail log and the final mailbox to make sure the alias works the way you want. You can check other aliases the same way. --- Using /etc/aliases for virtual domains To put all addresses at virt.dom under control of /etc/aliases, add virt.dom:alias to /var/qmail/control/virtualdomains, and give qmail-send a HUP signal. Also add virt.dom to /var/qmail/control/rcpthosts so that qmail accepts mail for virt.dom from remote hosts. Now you can handle virt.dom in /etc/aliases: billing@virt.dom: joe, fred (this line catches all other addresses)@virt.dom: joe Note that postmaster@virt.dom will go to joe; the @virt.dom instruction overrides the postmaster instruction. Note, however, that other .qmail files in ~alias override ~alias/.qmail-default, so you can set up ~alias/.qmail-postmaster to handle postmaster@everything. Beware that sendmail does not support domain-specific instructions in /etc/aliases; they are a fastforward feature. y /etc/staff-list, compile it into /etc/staff-list.bin: # newinclude /etc/staff-list See the newinclude man page for a list of sendmail compatibility warnings. Review /etc/staff-list.bin: % printmaillist < /etc/staff-list.bin | more For the format of printmaillist's output, see the setmaillist man page. If you change /etc/staff-list you will have to run newinclude again. You may want to add a comment at the top of /etc/staff-list as a reminder. --- Configuring qmail to use /etc/aliases fastforward-0.51/INSTALL010064400000000000001000000010370653033120600151470ustar00rootother00000000000000Like any other piece of software (and information generally), fastforward comes with NO WARRANTY. Things you have to decide before starting: * Where qmail is installed, 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. To configure qmail to use /etc/aliases, see ALIASES. 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. fastforward-0.51/hier.c010064400000000000001000000026660653033120600152220ustar00rootother00000000000000#include "auto_qmail.h" void hier() { h(auto_qmail,-1,-1,0755); d(auto_qmail,"bin",-1,-1,0755); d(auto_qmail,"doc",-1,-1,0755); d(auto_qmail,"doc/fastforward",-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","fastforward",-1,-1,0755); c(auto_qmail,"bin","printforward",-1,-1,0755); c(auto_qmail,"bin","setforward",-1,-1,0755); c(auto_qmail,"bin","newaliases",-1,-1,0755); c(auto_qmail,"bin","printmaillist",-1,-1,0755); c(auto_qmail,"bin","setmaillist",-1,-1,0755); c(auto_qmail,"bin","newinclude",-1,-1,0755); c(auto_qmail,"doc/fastforward","ALIASES",-1,-1,0644); c(auto_qmail,"man/man1","fastforward.1",-1,-1,0644); c(auto_qmail,"man/man1","printforward.1",-1,-1,0644); c(auto_qmail,"man/man1","setforward.1",-1,-1,0644); c(auto_qmail,"man/man1","newaliases.1",-1,-1,0644); c(auto_qmail,"man/man1","printmaillist.1",-1,-1,0644); c(auto_qmail,"man/man1","setmaillist.1",-1,-1,0644); c(auto_qmail,"man/man1","newinclude.1",-1,-1,0644); c(auto_qmail,"man/cat1","fastforward.0",-1,-1,0644); c(auto_qmail,"man/cat1","printforward.0",-1,-1,0644); c(auto_qmail,"man/cat1","setforward.0",-1,-1,0644); c(auto_qmail,"man/cat1","newaliases.0",-1,-1,0644); c(auto_qmail,"man/cat1","printmaillist.0",-1,-1,0644); c(auto_qmail,"man/cat1","setmaillist.0",-1,-1,0644); c(auto_qmail,"man/cat1","newinclude.0",-1,-1,0644); } fastforward-0.51/fastforward.1010064400000000000001000000040210653033120600165160ustar00rootother00000000000000.TH fastforward 1 .SH NAME fastforward \- forward mail according to a cdb database .SH SYNOPSIS in .BR .qmail-default : .B | fastforward [ .B \-nNpPdD ] .I cdb .SH DESCRIPTION .B fastforward forwards each incoming message according to instructions in .I cdb created by .BR setforward . If there is no forwarding instruction in .I cdb for the incoming recipient address, .B fastforward will bounce the message. You can override .B .qmail-default with a specific .BR .qmail-\fIrecipient ; see .BR dot-qmail (5). Warning to system administrators: Messages do not reach .B ~alias/.qmail-default unless they are controlled by the .B alias user. See .BR qmail-getpw (8). .B SECURITY WARNING: If .I cdb includes instructions pointing to a mailing list owned by another user, that user gains some amount of control over .BR fastforward 's behavior. In particular, he can force .B fastforward to open any file that you can access, and to read any world-readable file that you own, even if the file is in a world-inaccessible directory. .SH "OPTIONS" .TP 5 .B \-n No delivery. .B fastforward will print a description of its actions, but will not actually read or forward a message. .TP .B \-N (Default.) Forward a message as usual. .TP .B \-p Pass through. If .B fastforward does not find the recipient in .IR cdb , it exits 0, giving the message to further commands in .BR .qmail-default . If .B fastforward finds the recipient, it forwards the message and exits 99, so that further commands are skipped. .TP .B \-P (Default.) Do not pass through. If .B fastforward finds the recipient, it forwards the message and exits 0. Otherwise it bounces the message. .TP .B \-d Use .B $DEFAULT@$HOST as the recipient address, or .B $EXT@$HOST if .B $DEFAULT is not set. .TP .B \-D (Default.) Use .B $RECIPIENT as the recipient address. .SH VERSION This is .B fastforward 0.51. The .B fastforward home page is .BR http://pobox.com/~djb/fastforward.html . .SH "SEE ALSO" newaliases(1), printforward(1), setforward(1), dot-qmail(5), qmail-command(8), qmail-local(8), qmail-getpw(8) fastforward-0.51/fastforward.c010064400000000000001000000211030653033120600166000ustar00rootother00000000000000#include #include #include "stralloc.h" #include "substdio.h" #include "subfd.h" #include "strset.h" #include "sgetopt.h" #include "readwrite.h" #include "exit.h" #include "strerr.h" #include "env.h" #include "sig.h" #include "qmail.h" #include "fmt.h" #include "case.h" #include "alloc.h" #include "coe.h" #include "seek.h" #include "wait.h" #include "fork.h" #define FATAL "fastforward: fatal: " void usage() { strerr_die1x(100,"fastforward: usage: fastforward [ -nNpP ] data.cdb"); } void nomem() { strerr_die2x(111,FATAL,"out of memory"); } void print(s) char *s; { char ch; while (ch = *s++) { substdio_put(subfderr,&ch,1); } } void printsafe(s) char *s; { char ch; while (ch = *s++) { if (ch < 32) ch = '_'; substdio_put(subfderr,&ch,1); } } struct qmail qq; char qp[FMT_ULONG]; char qqbuf[1]; int qqwrite(fd,buf,len) int fd; char *buf; int len; { qmail_put(&qq,buf,len); return len; } substdio ssqq = SUBSTDIO_FDBUF(qqwrite,-1,qqbuf,sizeof qqbuf); char messbuf[4096]; substdio ssmess = SUBSTDIO_FDBUF(read,0,messbuf,sizeof messbuf); int flagdeliver = 1; int flagpassthrough = 0; char *dtline; stralloc sender = {0}; stralloc programs = {0}; stralloc forward = {0}; strset done; stralloc todo = {0}; stralloc mailinglist = {0}; void dofile(fn) char *fn; { int fd; struct stat st; int i; int j; if (!stralloc_copys(&mailinglist,"")) nomem(); fd = open_read(fn); if (fd == -1) strerr_die4sys(111,FATAL,"unable to read ",fn,": "); if (fstat(fd,&st) == -1) strerr_die4sys(111,FATAL,"unable to stat ",fn,": "); if ((st.st_mode & 0444) != 0444) strerr_die3x(111,FATAL,fn," is not world-readable"); if (slurpclose(fd,&mailinglist,1024) == -1) strerr_die4sys(111,FATAL,"unable to read ",fn,": "); i = 0; for (j = 0;j < mailinglist.len;++j) if (!mailinglist.s[j]) { if ((mailinglist.s[i] == '.') || (mailinglist.s[i] == '/')) { if (!stralloc_cats(&todo,mailinglist.s + i)) nomem(); if (!stralloc_0(&todo)) nomem(); } else if ((mailinglist.s[i] == '&') && (j - i < 900)) { if (!stralloc_cats(&todo,mailinglist.s + i)) nomem(); if (!stralloc_0(&todo)) nomem(); } i = j + 1; } } char *fncdb; int fdcdb; stralloc key = {0}; uint32 dlen; stralloc data = {0}; void cdbreaderror() { strerr_die4sys(111,FATAL,"unable to read ",fncdb,": "); } int findtarget(flagwild,prepend,addr) int flagwild; char *prepend; char *addr; { int r; int at; if (!stralloc_copys(&key,prepend)) nomem(); if (!stralloc_cats(&key,addr)) nomem(); case_lowerb(key.s,key.len); r = cdb_seek(fdcdb,key.s,key.len,&dlen); if (r == -1) cdbreaderror(); if (r) return 1; if (!flagwild) return 0; at = str_rchr(addr,'@'); if (!addr[at]) return 0; if (!stralloc_copys(&key,prepend)) nomem(); if (!stralloc_cats(&key,addr + at)) nomem(); case_lowerb(key.s,key.len); r = cdb_seek(fdcdb,key.s,key.len,&dlen); if (r == -1) cdbreaderror(); if (r) return 1; if (!stralloc_copys(&key,prepend)) nomem(); if (!stralloc_catb(&key,addr,at + 1)) nomem(); case_lowerb(key.s,key.len); r = cdb_seek(fdcdb,key.s,key.len,&dlen); if (r == -1) cdbreaderror(); if (r) return 1; return 0; } int gettarget(flagwild,prepend,addr) int flagwild; char *prepend; char *addr; { if (!findtarget(flagwild,prepend,addr)) return 0; if (!stralloc_ready(&data,(unsigned int) dlen)) nomem(); data.len = dlen; if (cdb_bread(fdcdb,data.s,data.len) == -1) cdbreaderror(); return 1; } void doprogram(arg) char *arg; { char *args[5]; int child; int wstat; if (!flagdeliver) { print("run "); printsafe(arg); print("\n"); substdio_flush(subfderr); return; } if (*arg == '!') { args[0] = "preline"; args[1] = "sh"; args[2] = "-c"; args[3] = arg + 1; args[4] = 0; } else { args[0] = "sh"; args[1] = "-c"; args[2] = arg + 1; args[3] = 0; } switch(child = vfork()) { case -1: strerr_die2sys(111,FATAL,"unable to fork: "); case 0: sig_pipedefault(); execvp(*args,args); strerr_die4sys(111,FATAL,"unable to run ",arg,": "); } wait_pid(&wstat,child); if (wait_crashed(wstat)) strerr_die4sys(111,FATAL,"child crashed in ",arg,": "); switch(wait_exitcode(wstat)) { case 64: case 65: case 70: case 76: case 77: case 78: case 112: case 100: _exit(100); case 0: break; default: _exit(111); } if (seek_begin(0) == -1) strerr_die2sys(111,FATAL,"unable to rewind input: "); } void dodata() { int i; int j; i = 0; for (j = 0;j < data.len;++j) if (!data.s[j]) { if ((data.s[i] == '|') || (data.s[i] == '!')) doprogram(data.s + i); else if ((data.s[i] == '.') || (data.s[i] == '/')) { if (!stralloc_cats(&todo,data.s + i)) nomem(); if (!stralloc_0(&todo)) nomem(); } else if ((data.s[i] == '&') && (j - i < 900)) { if (!stralloc_cats(&todo,data.s + i)) nomem(); if (!stralloc_0(&todo)) nomem(); } i = j + 1; } } void dorecip(addr) char *addr; { if (!findtarget(0,"?",addr)) if (gettarget(0,":",addr)) { dodata(); return; } if (!stralloc_cats(&forward,addr)) nomem(); if (!stralloc_0(&forward)) nomem(); } void doorigrecip(addr) char *addr; { if (sender.len) if ((sender.len != 4) || byte_diff(sender.s,4,"#@[]")) if (gettarget(1,"?",addr)) if (!stralloc_copy(&sender,&data)) nomem(); if (!gettarget(1,":",addr)) if (flagpassthrough) _exit(0); else strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)"); dodata(); } stralloc recipient = {0}; int flagdefault = 0; void main(argc,argv) int argc; char **argv; { int opt; char *x; int i; sig_pipeignore(); dtline = env_get("DTLINE"); if (!dtline) dtline = ""; x = env_get("SENDER"); if (!x) x = "original envelope sender"; if (!stralloc_copys(&sender,x)) nomem(); if (!stralloc_copys(&forward,"")) nomem(); if (!strset_init(&done)) nomem(); while ((opt = getopt(argc,argv,"nNpPdD")) != opteof) switch(opt) { case 'n': flagdeliver = 0; break; case 'N': flagdeliver = 1; break; case 'p': flagpassthrough = 1; break; case 'P': flagpassthrough = 0; break; case 'd': flagdefault = 1; break; case 'D': flagdefault = 0; break; default: usage(); } argv += optind; fncdb = *argv; if (!fncdb) usage(); fdcdb = open_read(fncdb); if (fdcdb == -1) cdbreaderror(); coe(fdcdb); if (flagdefault) { x = env_get("DEFAULT"); if (!x) x = env_get("EXT"); if (!x) strerr_die2x(100,FATAL,"$DEFAULT or $EXT must be set"); if (!stralloc_copys(&recipient,x)) nomem(); if (!stralloc_cats(&recipient,"@")) nomem(); x = env_get("HOST"); if (!x) strerr_die2x(100,FATAL,"$HOST must be set"); if (!stralloc_cats(&recipient,x)) nomem(); if (!stralloc_0(&recipient)) nomem(); x = recipient.s; } else { x = env_get("RECIPIENT"); if (!x) strerr_die2x(100,FATAL,"$RECIPIENT must be set"); } if (!strset_add(&done,x)) nomem(); doorigrecip(x); while (todo.len) { i = todo.len - 1; while ((i > 0) && todo.s[i - 1]) --i; todo.len = i; if (strset_in(&done,todo.s + i)) continue; x = alloc(str_len(todo.s + i) + 1); if (!x) nomem(); str_copy(x,todo.s + i); if (!strset_add(&done,x)) nomem(); x = todo.s + i; if (*x == 0) continue; else if ((*x == '.') || (*x == '/')) dofile(x); else dorecip(x + 1); } if (!forward.len) { if (!flagdeliver) { print("no forwarding\n"); substdio_flush(subfderr); } _exit(flagpassthrough ? 99 : 0); } if (!stralloc_0(&sender)) nomem(); if (!flagdeliver) { print("from <"); printsafe(sender.s); print(">\n"); while (forward.len) { i = forward.len - 1; while ((i > 0) && forward.s[i - 1]) --i; forward.len = i; print("to <"); printsafe(forward.s + i); print(">\n"); } substdio_flush(subfderr); _exit(flagpassthrough ? 99 : 0); } if (qmail_open(&qq) == -1) strerr_die2sys(111,FATAL,"unable to fork: "); qmail_puts(&qq,dtline); if (substdio_copy(&ssqq,&ssmess) != 0) strerr_die2sys(111,FATAL,"unable to read message: "); substdio_flush(&ssqq); qp[fmt_ulong(qp,qmail_qp(&qq))] = 0; qmail_from(&qq,sender.s); while (forward.len) { i = forward.len - 1; while ((i > 0) && forward.s[i - 1]) --i; forward.len = i; qmail_to(&qq,forward.s + i); } x = qmail_close(&qq); if (*x) strerr_die2x(*x == 'D' ? 100 : 111,FATAL,x + 1); strerr_die2x(flagpassthrough ? 99 : 0,"fastforward: qp ",qp); } fastforward-0.51/printforward.1010064400000000000001000000005570653033120600167270ustar00rootother00000000000000.TH printforward 1 .SH NAME printforward \- print the instructions in a forwarding database .SH SYNOPSIS .B printforward .SH DESCRIPTION .B printforward reads a forwarding database from its standard input and prints all the forwarding instructions in a format accepted by .BR setforward . .SH "SEE ALSO" fastforward(1), newaliases(1), printmaillist(1), setforward(1) fastforward-0.51/printforward.c010064400000000000001000000054450653033120600170120ustar00rootother00000000000000#include "substdio.h" #include "subfd.h" #include "strerr.h" #include "stralloc.h" #include "cdb.h" #define FATAL "printmaillist: fatal: " void badformat() { strerr_die2x(100,FATAL,"bad database format"); } void nomem() { strerr_die2x(111,FATAL,"out of memory"); } void getch(ch) char *ch; { int r; r = substdio_get(subfdinsmall,ch,1); if (r == -1) strerr_die2sys(111,FATAL,"unable to read input: "); if (r == 0) badformat(); } void putch(ch) char *ch; { if (substdio_put(subfdoutsmall,ch,1) == -1) strerr_die2x(111,FATAL,"unable to write output: "); } void print(buf) char *buf; { while (*buf) putch(buf++); } void printsafe(buf,len) char *buf; int len; { char ch; while (len) { ch = *buf; if ((ch <= 32) || (ch == ',') || (ch == ':') || (ch == ';') || (ch == '\\') || (ch == '#')) putch("\\"); putch(&ch); ++buf; --len; } } stralloc key = {0}; stralloc data = {0}; void main() { uint32 eod; uint32 pos; uint32 klen; uint32 dlen; char buf[8]; char ch; int i; int j; for (i = 0;i < 4;++i) getch(buf + i); eod = cdb_unpack(buf); for (i = 4;i < 2048;++i) getch(&ch); pos = 2048; while (pos < eod) { if (eod - pos < 8) badformat(); pos += 8; for (i = 0;i < 8;++i) getch(buf + i); klen = cdb_unpack(buf); dlen = cdb_unpack(buf + 4); if (!stralloc_copys(&key,"")) nomem(); if (eod - pos < klen) badformat(); pos += klen; while (klen) { --klen; getch(&ch); if (!stralloc_append(&key,&ch)) nomem(); } if (eod - pos < dlen) badformat(); pos += dlen; if (!stralloc_copys(&data,"")) nomem(); while (dlen) { --dlen; getch(&ch); if (!stralloc_append(&data,&ch)) nomem(); } if (!key.len) badformat(); if (key.s[0] == '?') { printsafe(key.s + 1,key.len - 1); print(": ?"); printsafe(data.s,data.len); print(";\n"); } else if (key.s[0] == ':') { printsafe(key.s + 1,key.len - 1); print(":\n"); i = 0; for (j = 0;j < data.len;++j) if (!data.s[j]) { if ((data.s[i] == '.') || (data.s[i] == '/')) { print(", "); printsafe(data.s + i,j - i); print("\n"); } else if ((data.s[i] == '|') || (data.s[i] == '!')) { print(", "); printsafe(data.s + i,j - i); print("\n"); } else if ((data.s[i] == '&') && (j - i < 900)) { print(", "); printsafe(data.s + i,j - i); print("\n"); } else badformat(); i = j + 1; } if (i != j) badformat(); print(";\n"); } else badformat(); } if (substdio_flush(subfdoutsmall) == -1) strerr_die2sys(111,FATAL,"unable to write output: "); _exit(0); } fastforward-0.51/setforward.1010064400000000000001000000107570653033120600163710ustar00rootother00000000000000.TH setforward 1 .SH NAME setforward \- create a forwarding database .SH SYNOPSIS .B setforward .I cdb .I tmp .SH DESCRIPTION .B setforward reads a table of forwarding instructions from its standard input. It converts the table into a forwarding database. The forwarding database can be used by .BR fastforward . .B setforward writes the forwarding database to .IR tmp ; it then moves .I tmp to .IR cdb . .I tmp and .I cdb must be on the same filesystem. If there is a problem creating .IR tmp , .B setforward complains and leaves .I cdb alone. The forwarding database format is portable across machines. .SH "INSTRUCTION FORMAT" A forwarding instruction contains a .I target\fR, a colon, a series of commands, and a semicolon. Each command is a .I recipient address\fR, .I owner address\fR, .I external mailing list\fR, or .I program\fR. Commands are separated by commas. For example, .EX root@yp.to: god@heaven.af.mil, staff@af.mil; .EE says that mail for .B root@yp.to should be forwarded to the recipient addresses .B god@heaven.af.mil and .BR staff@af.mil . When .B setforward sees # it ignores all text from # to the end of the line: .EX # this is a comment .EE .B setforward ignores all other line endings, so you can split a forwarding instruction across lines. It also ignores spaces and tabs. Exception: you can put a space (or tab or comma or whatever) into a target or command by putting a backslash in front of it. (However, NUL bytes are not permitted anywhere.) .SH "TARGETS" When .B fastforward sees the incoming address .IR user@host.dom , it tries three targets: .IR user@host.dom , .IR @host.dom , and .IR user@ . It obeys the commands for the first target that it finds. Target names are interpreted without regard to case. All the commands for a single target must be listed in a single instruction. Exception: an owner address can be listed in a separate instruction. .SH "RECIPIENT ADDRESSES" If a command begins with an ampersand, .B setforward takes the remaining bytes in the command as a recipient address: .EX boss@yp.to: &god@heaven.af.mil; .EE .B fastforward sends each incoming mail message to the recipient address. The recipient address must include a fully qualified domain name. It cannot be longer than 800 bytes. If a recipient address is itself a target in the forwarding table, .B fastforward will recursively handle the instructions for that target. Note that .I @host.dom and .I user@ wildcards do not apply here; they apply only to the incoming address. If a command begins with a letter or number, .B setforward takes the entire command as a recipient address: .EX boss@yp.to: god@heaven.af.mil; .EE .SH "OWNER ADDRESSES" If a command begins with a question mark, .B setforward takes the remaining bytes in the command as an owner address: .EX sos@heaven.af.mil: ?owner-sos@heaven.af.mil; .EE .B fastforward uses that address as the envelope sender for forwarded mail, so bounces will go back to that address. (Normally, if a message is forwarded to a bad address, it will bounce back to the original envelope sender.) .SH "EXTERNAL MAILING LISTS" If a command begins with a dot or slash, .B setforward takes the entire command as the name of a binary mailing list file created by .BR setmaillist : .EX sos@heaven.af.mil: /etc/lists/sos.bin; .EE .B fastforward will read and obey the commands in that file. The file must be world-readable and accessible to .BR fastforward . .SH "PROGRAMS" If a command begins with a vertical bar or exclamation point, .B setforward takes the rest of the command as the name of a program to run: .EX dew@: |dew-monitor; .EE For a vertical bar, .B fastforward feeds the message to that program. An exclamation point works the same way except that .B fastforward inserts .BR $UFLINE , .BR $RPLINE , and .B $DTLINE in front of the message. .SH "DUPLICATES" When .B fastforward is building the recipient list for a message, it keeps track of the recipient addresses and external mailing lists it has used. If the same command shows up again, it skips it. For example: .EX everybody@yp.to: programmers@yp.to, testers@yp.to; programmers@yp.to: joe@yp.to, bob@yp.to; testers@yp.to: joe@yp.to, fred@yp.to; .EE A message to .B everybody@yp.to will be sent to .B joe@yp.to only once. (This also means that addresses in an internal forwarding loop are discarded.) Exception: If a target has an owner address, commands for that target are considered different from commands for ``outside'' targets. .SH "SEE ALSO" newaliases(1), preline(1), printforward(1), setmaillist(1) fastforward-0.51/setforward.c010064400000000000001000000077220653033120600164510ustar00rootother00000000000000#include "substdio.h" #include "subfd.h" #include "strerr.h" #include "stralloc.h" #include "open.h" #include "case.h" #include "readwrite.h" #include "cdbmss.h" #define FATAL "setforward: fatal: " void usage() { strerr_die1x(100,"setforward: usage: setforward data.cdb data.tmp"); } void nomem() { strerr_die2x(111,FATAL,"out of memory"); } void missingsemicolon() { strerr_die2x(100,FATAL,"final instruction must end with semicolon"); } void extracolon() { strerr_die2x(100,FATAL,"double colons are not permitted"); } void extracomma() { strerr_die2x(100,FATAL,"commas are not permitted before colons"); } void nulbyte() { strerr_die2x(100,FATAL,"NUL bytes are not permitted"); } void longaddress() { strerr_die2x(100,FATAL,"addresses over 800 bytes are not permitted"); } char *fncdb; char *fntmp; int fd; struct cdbmss cdbmss; stralloc key = {0}; stralloc target = {0}; /* always initialized; no NUL */ stralloc command = {0}; /* always initialized; no NUL */ stralloc instr = {0}; /* always initialized */ int flagtarget = 0; /* 0: reading target; command is empty; instr is empty */ /* 1: target is complete; instr still has to be written; reading command */ void writeerr() { strerr_die4sys(111,FATAL,"unable to write to ",fntmp,": "); } void doit(prepend,data,datalen) char *prepend; char *data; int datalen; { if (!stralloc_copys(&key,prepend)) nomem(); if (!stralloc_cat(&key,&target)) nomem(); case_lowerb(key.s,key.len); if (cdbmss_add(&cdbmss,key.s,key.len,data,datalen) == -1) writeerr(); } int getch(ch) char *ch; { int r; r = substdio_get(subfdinsmall,ch,1); if (r == -1) strerr_die2sys(111,FATAL,"unable to read input: "); return r; } void main(argc,argv) int argc; char **argv; { char ch; int r; if (!stralloc_copys(&target,"")) nomem(); if (!stralloc_copys(&command,"")) nomem(); if (!stralloc_copys(&instr,"")) nomem(); fncdb = argv[1]; if (!fncdb) usage(); fntmp = argv[2]; if (!fntmp) usage(); fd = open_trunc(fntmp); if (fd == -1) strerr_die4sys(111,FATAL,"unable to create ",fntmp,": "); if (cdbmss_start(&cdbmss,fd) == -1) writeerr(); for (;;) { if (!getch(&ch)) goto eof; if (ch == '#') { while (ch != '\n') if (!getch(&ch)) goto eof; continue; } if (ch == ' ') continue; if (ch == '\n') continue; if (ch == '\t') continue; if (ch == ':') { if (flagtarget) extracolon(); flagtarget = 1; continue; } if ((ch == ',') || (ch == ';')) { if (!flagtarget) extracomma(); if (command.len) { if (command.s[0] == '?') { doit("?",command.s + 1,command.len - 1); } else if ((command.s[0] == '|') || (command.s[0] == '!')) { if (!stralloc_cat(&instr,&command)) nomem(); if (!stralloc_0(&instr)) nomem(); } else if ((command.s[0] == '.') || (command.s[0] == '/')) { if (!stralloc_cat(&instr,&command)) nomem(); if (!stralloc_0(&instr)) nomem(); } else { if (command.len > 800) longaddress(); if (command.s[0] != '&') if (!stralloc_cats(&instr,"&")) nomem(); if (!stralloc_cat(&instr,&command)) nomem(); if (!stralloc_0(&instr)) nomem(); } } if (!stralloc_copys(&command,"")) nomem(); if (ch == ';') { if (instr.len) doit(":",instr.s,instr.len); if (!stralloc_copys(&target,"")) nomem(); if (!stralloc_copys(&instr,"")) nomem(); flagtarget = 0; } continue; } if (ch == '\\') if (!getch(&ch)) goto eof; if (ch == 0) nulbyte(); if (!stralloc_append(flagtarget ? &command : &target,&ch)) nomem(); } eof: if (flagtarget || target.len) missingsemicolon(); if (cdbmss_finish(&cdbmss) == -1) writeerr(); if (fsync(fd) == -1) writeerr(); if (close(fd) == -1) writeerr(); /* NFS stupidity */ if (rename(fntmp,fncdb) == -1) strerr_die6sys(111,FATAL,"unable to move ",fntmp," to ",fncdb,": "); _exit(0); } .s,key.len,data,datalen) == -1) writeerr()fastforward-0.51/printmaillist.1010064400000000000001000000005400653033120600170710ustar00rootother00000000000000.TH printmaillist 1 .SH NAME printmaillist \- print the contents of a binary mailing list .SH SYNOPSIS .B printmaillist .SH DESCRIPTION .B printmaillist reads a binary mailing list from its standard input and prints all the forwarding instructions in a format accepted by .BR setmaillist . .SH "SEE ALSO" newinclude(1), printforward(1), setmaillist(1) fastforward-0.51/printmaillist.c010064400000000000001000000025400653033120600171550ustar00rootother00000000000000#include "substdio.h" #include "subfd.h" #include "strerr.h" #include "stralloc.h" #include "getln.h" #define FATAL "printmaillist: fatal: " void badformat() { strerr_die2x(100,FATAL,"bad mailing list format"); } stralloc line = {0}; int match; void main() { for (;;) { if (getln(subfdinsmall,&line,&match,'\0') == -1) strerr_die2sys(111,FATAL,"unable to read input: "); if (!match) { if (line.len) badformat(); if (substdio_flush(subfdoutsmall) == -1) strerr_die2sys(111,FATAL,"unable to write output: "); _exit(0); } if (line.s[str_chr(line.s,'\n')]) badformat(); if (line.s[line.len - 1] == ' ') badformat(); if (line.s[line.len - 1] == '\t') badformat(); if ((line.s[0] == '.') || (line.s[0] == '/')) { if (substdio_puts(subfdoutsmall,line.s) == -1) strerr_die2sys(111,FATAL,"unable to write output: "); if (substdio_puts(subfdoutsmall,"\n") == -1) strerr_die2sys(111,FATAL,"unable to write output: "); continue; } if (line.s[0] == '&') { if (line.len > 900) badformat(); if (substdio_puts(subfdoutsmall,line.s) == -1) strerr_die2sys(111,FATAL,"unable to write output: "); if (substdio_puts(subfdoutsmall,"\n") == -1) strerr_die2sys(111,FATAL,"unable to write output: "); continue; } badformat(); } } fastforward-0.51/setmaillist.1010064400000000000001000000025620653033120600165360ustar00rootother00000000000000.TH setmaillist 1 .SH NAME setmaillist \- create a binary mailing list .SH SYNOPSIS .B setmaillist .I bin .I tmp .SH DESCRIPTION .B setmaillist reads a mailing list from its standard input. .B setmaillist writes the mailing list in a binary format to .IR tmp ; it then moves .I tmp to .IR bin . .I tmp and .I bin must be on the same filesystem. If there is a problem creating .IR tmp , .B setmaillist complains and leaves .I bin alone. The binary mailing list format is portable across machines. .B setmaillist always creates .I bin world-readable. .SH "MAILING LIST FORMAT" The mailing list read by .B setmaillist is a series of lines. NUL bytes are not allowed. If a line begins with a dot or slash, .B setmaillist takes the entire line as an include file name. If a line begins with an ampersand, .B setmaillist takes the rest of the line as a recipient address. If a line begins with a letter or number, .B setmaillist takes the entire line as a recipient address. Each recipient address must include a fully qualified domain name. Recipient addresses longer than 800 bytes are not allowed. .B setmaillist ignores blank lines and lines beginning with #. It also ignores spaces and tabs at the ends of lines. For example, .EX god@heaven.af.mil djb@silverton.berkeley.edu .EE is a mailing list with two addresses. .SH "SEE ALSO" setforward(1), newinclude(1), printmaillist(1) fastforward-0.51/setmaillist.c010064400000000000001000000036240653033120600166200ustar00rootother00000000000000#include "substdio.h" #include "subfd.h" #include "strerr.h" #include "stralloc.h" #include "getln.h" #include "open.h" #include "readwrite.h" #define FATAL "setmaillist: fatal: " void usage() { strerr_die1x(100,"setmaillist: usage: setmaillist list.bin list.tmp"); } stralloc line = {0}; int match; char *fnbin; char *fntmp; int fd; substdio ss; char buf[1024]; void writeerr() { strerr_die4sys(111,FATAL,"unable to write to ",fntmp,": "); } void out(s,len) char *s; int len; { if (substdio_put(&ss,s,len) == -1) writeerr(); } void main(argc,argv) int argc; char **argv; { umask(033); fnbin = argv[1]; if (!fnbin) usage(); fntmp = argv[2]; if (!fntmp) usage(); fd = open_trunc(fntmp); if (fd == -1) strerr_die4sys(111,FATAL,"unable to create ",fntmp,": "); substdio_fdbuf(&ss,write,fd,buf,sizeof buf); do { if (getln(subfdinsmall,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,"unable to read input: "); while (line.len) { if (line.s[line.len - 1] != '\n') if (line.s[line.len - 1] != ' ') if (line.s[line.len - 1] != '\t') break; --line.len; } if (byte_chr(line.s,line.len,'\0') != line.len) strerr_die2x(111,FATAL,"NUL in input"); if (line.len) if (line.s[0] != '#') { if ((line.s[0] == '.') || (line.s[0] == '/')) { out(line.s,line.len); out("",1); } else { if (line.len > 800) strerr_die2x(111,FATAL,"addresses must be under 800 bytes"); if (line.s[0] != '&') out("&",1); out(line.s,line.len); out("",1); } } } while (match); if (substdio_flush(&ss) == -1) writeerr(); if (fsync(fd) == -1) writeerr(); if (close(fd) == -1) writeerr(); /* NFS stupidity */ if (rename(fntmp,fnbin) == -1) strerr_die6sys(111,FATAL,"unable to move ",fntmp," to ",fnbin,": "); _exit(0); } fastforward-0.51/newaliases.1010064400000000000001000000156150653033120600163420ustar00rootother00000000000000.TH newaliases 1 .SH NAME newaliases \- create a forwarding database from /etc/aliases .SH SYNOPSIS .B newaliases .SH DESCRIPTION .B newaliases reads a table of sendmail-style forwarding instructions from .B /etc/aliases and converts them into a forwarding database in .BR /etc/aliases.cdb . The forwarding database can be used by .BR fastforward . For safety, .B newaliases writes the forwarding database to .B /etc/aliases.tmp and then moves .B /etc/aliases.tmp to .BR /etc/aliases.cdb . If there is a problem creating .BR /etc/aliases.tmp , .B newaliases complains and leaves .B /etc/aliases.cdb alone. Deliveries can continue using .B /etc/aliases.cdb in the meantime. .B newaliases always creates .B /etc/aliases.cdb world-readable. .B newaliases makes no attempt to protect against simultaneous updates of .BR /etc/aliases.cdb . .SH "INSTRUCTION FORMAT" .B newaliases imitates sendmail's handling of .BR /etc/aliases . For example, .EX root: alice, bill .EE says that mail for .B root should be forwarded to .B alice and .BR bill . .B COMPATIBILITY WARNING: .B newaliases does not support file deliveries. You can use the file delivery mechanism described in .B dot-qmail(5) instead. .SH "SIMPLE ALIASES" The simplest type of forwarding instruction is a line of the form .EX alias: recip .EE Any message sent to .I alias will be forwarded to the recipient address .IR recip . Addresses are compared to .I alias without regard to case. Forwarding instructions are cumulative. If .I recip is itself an alias, messages to .I alias will be forwarded the same way as messages to .IR recip . For example, with the following instructions, messages to .B postmaster@heaven.af.mil or .B root@heaven.af.mil will be delivered to Bob: .EX postmaster@heaven.af.mil: bob@heaven.af.mil .EE .br .EX root@heaven.af.mil: postmaster@heaven.af.mil .EE .B COMPATIBILITY WARNING: With sendmail, entries in .B /etc/aliases can override usernames. With .BR qmail , if you install .B fastforward in .BR ~alias/.qmail-default , it will not see addresses that are controlled by other users. See .BR qmail-getpw (8). To change this, see .BR qmail-users (5). .B COMPATIBILITY WARNING: Various versions of sendmail do various strange things with circular alias definitions. See .BR setforward (1) for details on .BR fastforward 's behavior. .B COMPATIBILITY WARNING: If there are several forwarding instructions for a single .IR alias , sendmail will complain; .B fastforward will silently use the first instruction. .SH "WILDCARDS" .I alias can have the form .I user@host.dom for one user at one host, .I @host.dom for all users at one host, or .I user for one user at all hosts. .B COMPATIBILITY WARNING: sendmail supports only .IR user ; it does not support per-host aliases. It accepts .I user@host.dom if .I host.dom is a local host, but it then treats it the same way as .IR user , applying to all local hosts and virtual domains. .SH "ADDRESS FORMATS" Addresses in .B /etc/aliases are parsed the same way as addresses in RFC 822 message headers. Parenthesized comments and bracketed addresses are permitted: .EX root: bob (Bob, the postmaster) joe: Joe Shmoe .EE Addresses with special characters must be quoted: .EX fred: "spaced out mailbox"@heaven.af.mil .EE Address groups are not permitted, since colons have a different use in .BR /etc/aliases . Any recipient address without a fully qualified domain name is fed through the .BR defaulthost , .BR defaultdomain , and .B plusdomain mechanisms described in .BR qmail-header (5). .B COMPATIBILITY WARNING: sendmail's handling of quotes and backslashes violates RFC 821 and RFC 822, and is not supported by .BR newaliases . The .B qmail-local delivery mechanism lets each user manage several addresses, so there is no need for a special syntax to get around forwarding. .SH "MULTIPLE RECIPIENTS" An instruction may list more than one recipient address: .EX alias: recip1, recip2, recip3 .EE Any message sent to .I alias will be forwarded to all of the addresses. A forwarding instruction may be split across several lines. Each line past the first must either (1) begin with space or tab or (2) be empty: .EX hostmaster: .EE .br .EX fred, .EE .br .EX joe .EE .B COMPATIBILITY WARNING: sendmail requires the colon to be on the first line of a multi-line forwarding instruction. .B newaliases doesn't care whether the colon is present at all. .B COMPATIBILITY WARNING: sendmail does not permit blank lines in the middle of continuations. This has the undesirable effect that a blank line behaves differently from a line containing a single space. .SH "COMMENTS" Any line in .B /etc/aliases that begins with # is ignored: .EX # this is a comment .EE A comment may be split across several lines. Each line past the first must either (1) begin with space or tab or (2) be empty. .B COMPATIBILITY WARNING: sendmail does not permit continuations of comment lines. .SH "PROGRAMS" If a recipient address does not contain a domain name, and begins with a vertical bar, .B newaliases takes the rest of the address as a program to run: .EX weather: "|weather-server" .EE .B fastforward will run .B weather-server when a message arrives for .BR weather . .B COMPATIBILITY WARNING: Internet addresses can legitimately start with a slash or vertical bar. .B newaliases treats anything with an unquoted @ as an address. sendmail appears to have various problems coping with these addresses, and with commands that contain @ signs. .B COMPATIBILITY WARNING: .B newaliases does not allow a vertical bar before double quotes. .SH "INCLUDE FILES" A recipient address of the form .B :include:\fIfile means ``every address listed in .IR file .'' (Actually .B fastforward reads .IR file\fB.bin ; see .BR newinclude (1) for further details.) Note that .I file is read by .BR fastforward , not .BR newaliases , so the system administrator does not have to run .B newaliases every time .I file changes. .I file must be world-readable and accessible to .BR fastforward . .B COMPATIBILITY WARNING: If an .B :include: file is unreadable or nonexistent, sendmail skips it; .B fastforward defers delivery of the message. .B COMPATIBILITY WARNING: sendmail does not permit spaces inside the literal text .BR :include: . .B newaliases does. .B COMPATIBILITY WARNING: Versions of sendmail before V8 did not strip quotes from .B :include: filenames. .SH "ALIAS OWNERS" If there is an alias for .BR owner-\fIlist , any message forwarded through .I list will have its envelope sender set to .BR owner-\fIlist , so that bounces go back to .BR owner-\fIlist . .B COMPATIBILITY WARNING: When an alias includes the same recipient both inside and outside a mailing list, .B fastforward sends the message twice, once with each envelope sender. sendmail sends the message only once; its choice of envelope sender for that recipient depends on the phase of the moon. .SH "SEE ALSO" fastforward(1), setforward(1), newinclude(1), printforward(1), dot-qmail(5) fastforward-0.51/newaliases.c010064400000000000001000000204340653033120600164170ustar00rootother00000000000000#include "substdio.h" #include "strerr.h" #include "stralloc.h" #include "getln.h" #include "open.h" #include "readwrite.h" #include "token822.h" #include "control.h" #include "auto_qmail.h" #include "case.h" #include "cdbmss.h" #define FATAL "newaliases: fatal: " void nomem() { strerr_die2x(111,FATAL,"out of memory"); } void nulbyte() { strerr_die2x(100,FATAL,"NUL bytes are not permitted"); } void longaddress() { strerr_die2x(100,FATAL,"addresses over 800 bytes are not permitted"); } void writeerr() { strerr_die2sys(111,FATAL,"unable to write to /etc/aliases.tmp: "); } void readerr() { strerr_die2sys(111,FATAL,"unable to read /etc/aliases: "); } void die_control() { strerr_die2sys(111,FATAL,"unable to read controls: "); } 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")) nomem(); r = control_readline(&defaultdomain,"control/defaultdomain"); if (r == -1) die_control(); if (!r) if (!stralloc_copy(&defaultdomain,&me)) nomem(); r = control_readline(&defaulthost,"control/defaulthost"); if (r == -1) die_control(); if (!r) if (!stralloc_copy(&defaulthost,&me)) nomem(); r = control_readline(&plusdomain,"control/plusdomain"); if (r == -1) die_control(); if (!r) if (!stralloc_copy(&plusdomain,&me)) nomem(); if (fchdir(fddir) == -1) strerr_die2sys(111,FATAL,"unable to set current directory: "); } stralloc target = {0}; stralloc fulltarget = {0}; stralloc instr = {0}; stralloc cbuf = {0}; token822_alloc toks = {0}; token822_alloc tokaddr = {0}; stralloc address = {0}; void gotincl() { token822_reverse(&tokaddr); if (token822_unquote(&address,&tokaddr) != 1) nomem(); tokaddr.len = 0; if (!address.len) strerr_die2x(111,FATAL,"empty :include: filenames not permitted"); if (byte_chr(address.s,address.len,'\0') < address.len) strerr_die2x(111,FATAL,"NUL not permitted in :include: filenames"); if ((address.s[0] != '.') && (address.s[0] != '/')) if (!stralloc_cats(&instr,"./")) nomem(); if (!stralloc_cat(&instr,&address)) nomem(); if (!stralloc_cats(&instr,".bin")) nomem(); if (!stralloc_0(&instr)) nomem(); } void gotaddr() { int i; int j; int flaghasat; token822_reverse(&tokaddr); if (token822_unquote(&address,&tokaddr) != 1) nomem(); if (!address.len) strerr_die2x(111,FATAL,"empty recipient addresses not permitted"); 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.s[0] == '/') { if (!stralloc_0(&address)) nomem(); strerr_die4x(111,FATAL,"file delivery ",address.s," not supported"); } if (!flaghasat) if (address.s[0] == '|') { if (byte_chr(address.s,address.len,'\0') < address.len) strerr_die2x(111,FATAL,"NUL not permitted in program names"); if (!stralloc_cats(&instr,"!")) nomem(); if (!stralloc_catb(&instr,address.s + 1,address.len - 1)) nomem(); if (!stralloc_0(&instr)) nomem(); return; } if (target.len) { if (!stralloc_cats(&instr,"&")) nomem(); if (!stralloc_cat(&instr,&fulltarget)) nomem(); if (!stralloc_0(&instr)) nomem(); } if (!flaghasat) if (!stralloc_cats(&address,"@")) nomem(); if (!stralloc_copy(&target,&address)) nomem(); if (!stralloc_copy(&fulltarget,&address)) nomem(); if (fulltarget.s[fulltarget.len - 1] == '@') if (!stralloc_cat(&fulltarget,&defaulthost)) nomem(); if (fulltarget.s[fulltarget.len - 1] == '+') { fulltarget.s[fulltarget.len - 1] = '.'; if (!stralloc_cat(&fulltarget,&plusdomain)) nomem(); } j = 0; for (i = 0;i < fulltarget.len;++i) if (fulltarget.s[i] == '@') j = i; for (i = j;i < fulltarget.len;++i) if (fulltarget.s[i] == '.') break; if (i == fulltarget.len) { if (!stralloc_cats(&fulltarget,".")) nomem(); if (!stralloc_cat(&fulltarget,&defaultdomain)) nomem(); } if (fulltarget.len > 800) longaddress(); if (byte_chr(fulltarget.s,fulltarget.len,'\0') < fulltarget.len) strerr_die2x(111,FATAL,"NUL not permitted in recipient addresses"); } stralloc line = {0}; stralloc newline = {0}; int match; void parseerr() { if (!stralloc_0(&line)) nomem(); strerr_die3x(111,FATAL,"unable to parse this line: ",line.s); } void parseline() { int wordok; struct token822 *t; struct token822 *beginning; switch(token822_parse(&toks,&line,&cbuf)) { case -1: nomem(); case 0: parseerr(); } beginning = toks.t; t = toks.t + toks.len; wordok = 1; if (!token822_readyplus(&tokaddr,1)) nomem(); tokaddr.len = 0; while (t > beginning) switch((--t)->type) { case TOKEN822_SEMI: break; /*XXX*/ case TOKEN822_COLON: if (t >= beginning + 2) if (t[-2].type == TOKEN822_COLON) if (t[-1].type == TOKEN822_ATOM) if (t[-1].slen == 7) if (!byte_diff(t[-1].s,7,"include")) { gotincl(); t -= 2; } break; /*XXX*/ case TOKEN822_RIGHT: if (tokaddr.len) gotaddr(); while ((t > beginning) && (t[-1].type != TOKEN822_LEFT)) if (!token822_append(&tokaddr,--t)) nomem(); gotaddr(); if (t <= beginning) parseerr(); --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)) 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)) nomem(); continue; } if (tokaddr.len) gotaddr(); } char inbuf[1024]; substdio ssin; struct cdbmss cdbmss; stralloc key = {0}; void doit() { if (!instr.len) { if (target.len) parseerr(); return; } if (!target.len) parseerr(); if (stralloc_starts(&target,"owner-")) { if (!stralloc_copys(&key,"?")) nomem(); if (!stralloc_catb(&key,target.s + 6,target.len - 6)) nomem(); case_lowerb(key.s,key.len); if (cdbmss_add(&cdbmss,key.s,key.len,fulltarget.s,fulltarget.len) == -1) writeerr(); } if (!stralloc_copys(&key,":")) nomem(); if (!stralloc_cat(&key,&target)) nomem(); case_lowerb(key.s,key.len); if (cdbmss_add(&cdbmss,key.s,key.len,instr.s,instr.len) == -1) writeerr(); } void main() { int fd; umask(033); readcontrols(); fd = open_read("/etc/aliases"); if (fd == -1) readerr(); substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf); fd = open_trunc("/etc/aliases.tmp"); if (fd == -1) strerr_die2sys(111,FATAL,"unable to create /etc/aliases.tmp: "); if (cdbmss_start(&cdbmss,fd) == -1) writeerr(); if (!stralloc_copys(&line,"")) nomem(); for (;;) { if (getln(&ssin,&newline,&match,'\n') != 0) readerr(); if (match && (newline.s[0] == '\n')) continue; if (match && ((newline.s[0] == ' ') || (newline.s[0] == '\t'))) { if (!stralloc_cat(&line,&newline)) nomem(); continue; } if (line.len) if (line.s[0] != '#') { if (!stralloc_copys(&target,"")) nomem(); if (!stralloc_copys(&fulltarget,"")) nomem(); if (!stralloc_copys(&instr,"")) nomem(); parseline(); doit(); } if (!match) break; if (!stralloc_copy(&line,&newline)) nomem(); } if (cdbmss_finish(&cdbmss) == -1) writeerr(); if (fsync(fd) == -1) writeerr(); if (close(fd) == -1) writeerr(); /* NFS stupidity */ if (rename("/etc/aliases.tmp","/etc/aliases.cdb") == -1) strerr_die2sys(111,FATAL,"unable to move /etc/aliases.tmp to /etc/aliases.cdb: "); _exit(0); } fastforward-0.51/newinclude.1010064400000000000001000000030420653033120600163330ustar00rootother00000000000000.TH newinclude 1 .SH NAME newinclude \- create a binary mailing list from an :include: file .SH SYNOPSIS .B newinclude .I list .SH DESCRIPTION .B newinclude reads a sendmail-style .B :include: file, .IR list , and converts it into a binary format in .I list\fB.bin for use by .BR fastforward . .B newinclude first writes the mailing list to .IR list\fB.tmp , and then moves it to .IR list\fB.bin . If there is any problem creating .IR list\fB.tmp , .B newinclude leaves .I list\fB.bin alone. .B newinclude always creates .I list\fB.bin world-readable. .B COMPATIBILITY WARNING: sendmail reads .I list directly; .B fastforward needs .IR list\fB.bin . sendmail's strategy is a disaster if you save .I list to disk at the same moment that sendmail reads it; the list will be truncated at a random spot, perhaps in the middle of an address. Furthermore, if the system crashes while you are writing .IR list , .I list could be filled with all sorts of garbage. .SH "LIST FORMAT" .I list may contain any number of lines; each line may contain any number of addresses or further .B :include: files. See .BR newaliases (1) for details on the address format. Any line in .I file beginning with # is ignored. .B COMPATIBILITY WARNING: .B newinclude does not support file or program deliveries in .B :include: files. You can use the secure delivery mechanisms described in .B dot-qmail(5) instead. .B COMPATIBILITY WARNING: Versions of sendmail before V8 did not allow comments in .B :include: files. .SH "SEE ALSO" fastforward(1), newaliases(1), setmaillist(1), dot-qmail(5) fastforward-0.51/newinclude.c010064400000000000001000000171140653033120600164220ustar00rootother00000000000000#include "substdio.h" #include "strerr.h" #include "stralloc.h" #include "getln.h" #include "open.h" #include "readwrite.h" #include "token822.h" #include "control.h" #include "auto_qmail.h" #include "env.h" #define FATAL "newinclude: fatal: " void nomem() { strerr_die2x(111,FATAL,"out of memory"); } void usage() { strerr_die1x(100,"newinclude: usage: newinclude list"); } char *fnlist; substdio sslist; char listbuf[1024]; stralloc bin = {0}; #define fnbin bin.s stralloc tmp = {0}; #define fntmp tmp.s substdio sstmp; char tmpbuf[1024]; void readerr() { strerr_die4sys(111,FATAL,"unable to read ",fnlist,": "); } void writeerr() { strerr_die4sys(111,FATAL,"unable to write to ",fntmp,": "); } void out(s,len) char *s; int len; { if (substdio_put(&sstmp,s,len) == -1) writeerr(); } void doincl(buf,len) char *buf; int len; { if (!len) strerr_die2x(111,FATAL,"empty :include: filenames not permitted"); if (byte_chr(buf,len,'\n') != len) strerr_die2x(111,FATAL,"newlines not permitted in :include: filenames"); if (byte_chr(buf,len,'\0') != len) strerr_die2x(111,FATAL,"NUL not permitted in :include: filenames"); if ((buf[0] != '.') && (buf[0] != '/')) out("./",2); out(buf,len); out("",1); } void dorecip(buf,len) char *buf; int len; { if (!len) strerr_die2x(111,FATAL,"empty recipient addresses not permitted"); if (byte_chr(buf,len,'\n') != len) strerr_die2x(111,FATAL,"newlines not permitted in recipient addresses"); if (byte_chr(buf,len,'\0') != len) strerr_die2x(111,FATAL,"NUL not permitted in recipient addresses"); if (len > 800) strerr_die2x(111,FATAL,"addresses must be under 800 bytes"); if ((buf[len - 1] == ' ') || (buf[len - 1] == '\t')) strerr_die2x(111,FATAL,"spaces and tabs not permitted at ends of addresses"); out("&",1); out(buf,len); out("",1); } void die_control() { strerr_die2sys(111,FATAL,"unable to read controls: "); } stralloc me = {0}; stralloc defaulthost = {0}; stralloc defaultdomain = {0}; stralloc plusdomain = {0}; void readcontrols() { int r; int fddir; char *x; 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")) nomem(); r = control_readline(&defaultdomain,"control/defaultdomain"); if (r == -1) die_control(); if (!r) if (!stralloc_copy(&defaultdomain,&me)) nomem(); x = env_get("QMAILDEFAULTDOMAIN"); if (x) if (!stralloc_copys(&defaultdomain,x)) nomem(); r = control_readline(&defaulthost,"control/defaulthost"); if (r == -1) die_control(); if (!r) if (!stralloc_copy(&defaulthost,&me)) nomem(); x = env_get("QMAILDEFAULTHOST"); if (x) if (!stralloc_copys(&defaulthost,x)) nomem(); r = control_readline(&plusdomain,"control/plusdomain"); if (r == -1) die_control(); if (!r) if (!stralloc_copy(&plusdomain,&me)) nomem(); x = env_get("QMAILPLUSDOMAIN"); if (x) if (!stralloc_copys(&plusdomain,x)) 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 gotincl() { token822_reverse(&tokaddr); if (token822_unquote(&address,&tokaddr) != 1) nomem(); tokaddr.len = 0; doincl(address.s,address.len); } void gotaddr() { int i; int j; int flaghasat; token822_reverse(&tokaddr); if (token822_unquote(&address,&tokaddr) != 1) 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.s[0] == '/') { if (!stralloc_0(&address)) nomem(); strerr_die4x(111,FATAL,"file delivery ",address.s," not supported"); } if (!flaghasat) if (address.s[0] == '|') { if (!stralloc_0(&address)) nomem(); strerr_die4x(111,FATAL,"program delivery ",address.s," not supported"); } if (!flaghasat) { if (!stralloc_cats(&address,"@")) nomem(); if (!stralloc_cat(&address,&defaulthost)) nomem(); } if (address.s[address.len - 1] == '+') { address.s[address.len - 1] = '.'; if (!stralloc_cat(&address,&plusdomain)) 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,".")) nomem(); if (!stralloc_cat(&address,&defaultdomain)) nomem(); } dorecip(address.s,address.len); } stralloc line = {0}; int match; void parseerr() { if (!stralloc_0(&line)) nomem(); strerr_die3x(111,FATAL,"unable to parse this line: ",line.s); } void parseline() { int wordok; struct token822 *t; struct token822 *beginning; switch(token822_parse(&toks,&line,&cbuf)) { case -1: nomem(); case 0: parseerr(); } beginning = toks.t; t = toks.t + toks.len; wordok = 1; if (!token822_readyplus(&tokaddr,1)) nomem(); tokaddr.len = 0; while (t > beginning) switch((--t)->type) { case TOKEN822_SEMI: break; /*XXX*/ case TOKEN822_COLON: if (t >= beginning + 2) if (t[-2].type == TOKEN822_COLON) if (t[-1].type == TOKEN822_ATOM) if (t[-1].slen == 7) if (!byte_diff(t[-1].s,7,"include")) { gotincl(); t -= 2; } break; /*XXX*/ case TOKEN822_RIGHT: if (tokaddr.len) gotaddr(); while ((t > beginning) && (t[-1].type != TOKEN822_LEFT)) if (!token822_append(&tokaddr,--t)) nomem(); gotaddr(); if (t <= beginning) parseerr(); --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)) 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)) nomem(); continue; } if (tokaddr.len) gotaddr(); } void main(argc,argv) int argc; char **argv; { int fd; umask(033); readcontrols(); fnlist = argv[1]; if (!fnlist) usage(); if (!stralloc_copys(&bin,fnlist)) nomem(); if (!stralloc_cats(&bin,".bin")) nomem(); if (!stralloc_0(&bin)) nomem(); if (!stralloc_copys(&tmp,fnlist)) nomem(); if (!stralloc_cats(&tmp,".tmp")) nomem(); if (!stralloc_0(&tmp)) nomem(); fd = open_read(fnlist); if (fd == -1) readerr(); substdio_fdbuf(&sslist,read,fd,listbuf,sizeof listbuf); fd = open_trunc(fntmp); if (fd == -1) writeerr(); substdio_fdbuf(&sstmp,write,fd,tmpbuf,sizeof tmpbuf); for (;;) { if (getln(&sslist,&line,&match,'\n') == -1) readerr(); if (!line.len) break; if (line.s[0] != '#') parseline(); if (!match) break; } if (substdio_flush(&sstmp) == -1) writeerr(); if (fsync(fd) == -1) writeerr(); if (close(fd) == -1) writeerr(); /* NFS stupidity */ if (rename(fntmp,fnbin) == -1) strerr_die6sys(111,FATAL,"unable to move ",fntmp," to ",fnbin,": "); _exit(0); } fastforward-0.51/auto-str.c010064400000000000001000000013520653033120600160400ustar00rootother00000000000000#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); } fastforward-0.51/install.c010064400000000000001000000055470653033120600157420ustar00rootother00000000000000#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); } AL,"unable to switch back to source directory: "); fdin = open_read(file); if (fdin == -1) strerr_die4sys(111,FATAL,"unable to read ",file,": ")fastforward-0.51/instcheck.c010064400000000000001000000034600653033120600162370ustar00rootother00000000000000#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); } fastforward-0.51/conf-cc010064400000000000001000000000570653033120600153520ustar00rootother00000000000000cc -O2 This will be used to compile .c files. fastforward-0.51/conf-ld010064400000000000001000000000760653033120600153650ustar00rootother00000000000000cc -s This will be used to link .o files into an executable. fastforward-0.51/find-systype.sh010064400000000000001000000065030653033120600171130ustar00rootother00000000000000# 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]' fastforward-0.51/make-compile.sh010064400000000000001000000000370653033120600170140ustar00rootother00000000000000echo exec "$CC" -c '${1+"$@"}' fastforward-0.51/make-load.sh010064400000000000001000000001110653033120600162740ustar00rootother00000000000000echo 'main="$1"; shift' echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}' fastforward-0.51/make-makelib.sh010064400000000000001000000003220653033120600167650ustar00rootother00000000000000echo '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 fastforward-0.51/trycpp.c010064400000000000001000000001440653033120600156010ustar00rootother00000000000000void main() { #ifdef NeXT printf("nextstep\n"); exit(0); #endif printf("unknown\n"); exit(0); } fastforward-0.51/warn-auto.sh010064400000000000001000000001000653033120600163550ustar00rootother00000000000000#!/bin/sh # WARNING: This file was auto-generated. Do not edit! fastforward-0.51/alloc.h010064400000000000001000000002030653033120600153530ustar00rootother00000000000000#ifndef ALLOC_H #define ALLOC_H extern /*@null@*//*@out@*/char *alloc(); extern void alloc_free(); extern int alloc_re(); #endif fastforward-0.51/alloc.c010064400000000000001000000015010653033120600153500ustar00rootother00000000000000#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); } fastforward-0.51/alloc_re.c010064400000000000001000000003260653033120600160420ustar00rootother00000000000000#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; } fastforward-0.51/case.h010064400000000000001000000003640653033120600152040ustar00rootother00000000000000#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 fastforward-0.51/case_lowerb.c010064400000000000001000000003010653033120600165400ustar00rootother00000000000000#include "case.h" void case_lowerb(s,len) char *s; unsigned int len; { unsigned char x; while (len > 0) { --len; x = *s - 'A'; if (x <= 'Z' - 'A') *s = x + 'a'; ++s; } } fastforward-0.51/cdb.h010064400000000000001000000002400653033120600150120ustar00rootother00000000000000#ifndef CDB_H #define CDB_H #include "uint32.h" extern uint32 cdb_hash(); extern uint32 cdb_unpack(); extern int cdb_bread(); extern int cdb_seek(); #endif fastforward-0.51/cdb_hash.c010064400000000000001000000003060653033120600160130ustar00rootother00000000000000#include "cdb.h" uint32 cdb_hash(buf,len) unsigned char *buf; unsigned int len; { uint32 h; h = 5381; while (len) { --len; h += (h << 5); h ^= (uint32) *buf++; } return h; } fastforward-0.51/cdb_seek.c010064400000000000001000000033650653033120600160270ustar00rootother00000000000000#include #include extern int errno; #include "cdb.h" #ifndef SEEK_SET #define SEEK_SET 0 #endif int cdb_bread(fd,buf,len) int fd; char *buf; int len; { int r; while (len > 0) { do r = read(fd,buf,len); while ((r == -1) && (errno == EINTR)); if (r == -1) return -1; if (r == 0) { errno = EIO; return -1; } buf += r; len -= r; } return 0; } static int match(fd,key,len) int fd; char *key; unsigned int len; { char buf[32]; int n; int i; while (len > 0) { n = sizeof(buf); if (n > len) n = len; if (cdb_bread(fd,buf,n) == -1) return -1; for (i = 0;i < n;++i) if (buf[i] != key[i]) return 0; key += n; len -= n; } return 1; } int cdb_seek(fd,key,len,dlen) int fd; char *key; unsigned int len; uint32 *dlen; { char packbuf[8]; uint32 pos; uint32 h; uint32 lenhash; uint32 h2; uint32 loop; uint32 poskd; h = cdb_hash(key,len); pos = 8 * (h & 255); if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; if (cdb_bread(fd,packbuf,8) == -1) return -1; pos = cdb_unpack(packbuf); lenhash = cdb_unpack(packbuf + 4); if (!lenhash) return 0; h2 = (h >> 8) % lenhash; for (loop = 0;loop < lenhash;++loop) { if (lseek(fd,(off_t) (pos + 8 * h2),SEEK_SET) == -1) return -1; if (cdb_bread(fd,packbuf,8) == -1) return -1; poskd = cdb_unpack(packbuf + 4); if (!poskd) return 0; if (cdb_unpack(packbuf) == h) { if (lseek(fd,(off_t) poskd,SEEK_SET) == -1) return -1; if (cdb_bread(fd,packbuf,8) == -1) return -1; if (cdb_unpack(packbuf) == len) switch(match(fd,key,len)) { case -1: return -1; case 1: *dlen = cdb_unpack(packbuf + 4); return 1; } } if (++h2 == lenhash) h2 = 0; } return 0; } fastforward-0.51/cdb_unpack.c010064400000000000001000000003010653033120600163440ustar00rootother00000000000000#include "cdb.h" uint32 cdb_unpack(buf) unsigned char *buf; { uint32 num; num = buf[3]; num <<= 8; num += buf[2]; num <<= 8; num += buf[1]; num <<= 8; num += buf[0]; return num; } fastforward-0.51/cdbmake.h010064400000000000001000000012610653033120600156540ustar00rootother00000000000000#ifndef CDBMAKE_H #define CDBMAKE_H #include "uint32.h" #define CDBMAKE_HPLIST 1000 struct cdbmake_hp { uint32 h; uint32 p; } ; struct cdbmake_hplist { struct cdbmake_hp hp[CDBMAKE_HPLIST]; struct cdbmake_hplist *next; int num; } ; struct cdbmake { char final[2048]; uint32 count[256]; uint32 start[256]; struct cdbmake_hplist *head; struct cdbmake_hp *split; /* includes space for hash */ struct cdbmake_hp *hash; uint32 numentries; } ; extern void cdbmake_pack(); #define CDBMAKE_HASHSTART ((uint32) 5381) extern uint32 cdbmake_hashadd(); extern void cdbmake_init(); extern int cdbmake_add(); extern int cdbmake_split(); extern uint32 cdbmake_throw(); #endif fastforward-0.51/cdbmake_add.c010064400000000000001000000044100653033120600164560ustar00rootother00000000000000#include "cdbmake.h" void cdbmake_init(cdbm) struct cdbmake *cdbm; { cdbm->head = 0; cdbm->split = 0; cdbm->hash = 0; cdbm->numentries = 0; } int cdbmake_add(cdbm,h,p,alloc) struct cdbmake *cdbm; uint32 h; uint32 p; char *(*alloc)(); { struct cdbmake_hplist *head; head = cdbm->head; if (!head || (head->num >= CDBMAKE_HPLIST)) { head = (struct cdbmake_hplist *) alloc(sizeof(struct cdbmake_hplist)); if (!head) return 0; head->num = 0; head->next = cdbm->head; cdbm->head = head; } head->hp[head->num].h = h; head->hp[head->num].p = p; ++head->num; ++cdbm->numentries; return 1; } int cdbmake_split(cdbm,alloc) struct cdbmake *cdbm; char *(*alloc)(); { int i; uint32 u; uint32 memsize; struct cdbmake_hplist *x; for (i = 0;i < 256;++i) cdbm->count[i] = 0; for (x = cdbm->head;x;x = x->next) { i = x->num; while (i--) ++cdbm->count[255 & x->hp[i].h]; } memsize = 1; for (i = 0;i < 256;++i) { u = cdbm->count[i] * 2; if (u > memsize) memsize = u; } memsize += cdbm->numentries; /* no overflow possible up to now */ u = (uint32) 0 - (uint32) 1; u /= sizeof(struct cdbmake_hp); if (memsize > u) return 0; cdbm->split = (struct cdbmake_hp *) alloc(memsize * sizeof(struct cdbmake_hp)); if (!cdbm->split) return 0; cdbm->hash = cdbm->split + cdbm->numentries; u = 0; for (i = 0;i < 256;++i) { u += cdbm->count[i]; /* bounded by numentries, so no overflow */ cdbm->start[i] = u; } for (x = cdbm->head;x;x = x->next) { i = x->num; while (i--) cdbm->split[--cdbm->start[255 & x->hp[i].h]] = x->hp[i]; } return 1; } uint32 cdbmake_throw(cdbm,pos,b) struct cdbmake *cdbm; uint32 pos; int b; { uint32 len; uint32 j; uint32 count; struct cdbmake_hp *hp; uint32 where; count = cdbm->count[b]; len = count + count; /* no overflow possible */ cdbmake_pack(cdbm->final + 8 * b,pos); cdbmake_pack(cdbm->final + 8 * b + 4,len); if (len) { for (j = 0;j < len;++j) cdbm->hash[j].h = cdbm->hash[j].p = 0; hp = cdbm->split + cdbm->start[b]; for (j = 0;j < count;++j) { where = (hp->h >> 8) % len; while (cdbm->hash[where].p) if (++where == len) where = 0; cdbm->hash[where] = *hp++; } } return len; } plist *head; head = cdbm->head; if (!head || (head->num >= CDBMAKE_HPLIST)) { head = (struct cdbmake_hplist *) alloc(sizeof(struct cdbmake_hplist)); if (!head) return 0; head->num = 0; head->next = cdbm->head; cdbm->head = fastforward-0.51/cdbmake_hash.c010064400000000000001000000002200653033120600166440ustar00rootother00000000000000#include "cdbmake.h" uint32 cdbmake_hashadd(h,c) uint32 h; unsigned int c; { h += (h << 5); h ^= (uint32) (unsigned char) c; return h; } fastforward-0.51/cdbmake_pack.c010064400000000000001000000002640653033120600166470ustar00rootother00000000000000#include "cdbmake.h" void cdbmake_pack(buf,num) unsigned char *buf; uint32 num; { *buf++ = num; num >>= 8; *buf++ = num; num >>= 8; *buf++ = num; num >>= 8; *buf = num; } fastforward-0.51/cdbmss.h010064400000000000001000000003200653033120600155340ustar00rootother00000000000000#ifndef CDBMSS_H #define CDBMSS_H #include "cdbmake.h" #include "substdio.h" struct cdbmss { char ssbuf[1024]; struct cdbmake cdbm; substdio ss; char packbuf[8]; uint32 pos; int fd; } ; #endif fastforward-0.51/cdbmss.c010064400000000000001000000030620653033120600155350ustar00rootother00000000000000#include "readwrite.h" #include "seek.h" #include "alloc.h" #include "cdbmss.h" int cdbmss_start(c,fd) struct cdbmss *c; int fd; { cdbmake_init(&c->cdbm); c->fd = fd; c->pos = sizeof(c->cdbm.final); substdio_fdbuf(&c->ss,write,fd,c->ssbuf,sizeof(c->ssbuf)); return seek_set(fd,(seek_pos) c->pos); } int cdbmss_add(c,key,keylen,data,datalen) struct cdbmss *c; unsigned char *key; unsigned int keylen; unsigned char *data; unsigned int datalen; { uint32 h; int i; cdbmake_pack(c->packbuf,(uint32) keylen); cdbmake_pack(c->packbuf + 4,(uint32) datalen); if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1; if (substdio_put(&c->ss,key,keylen) == -1) return -1; if (substdio_put(&c->ss,data,datalen) == -1) return -1; h = CDBMAKE_HASHSTART; for (i = 0;i < keylen;++i) h = cdbmake_hashadd(h,(unsigned int) key[i]); if (!cdbmake_add(&c->cdbm,h,c->pos,alloc)) return -1; c->pos += 8 + keylen + datalen; /* XXX: overflow? */ return 0; } int cdbmss_finish(c) struct cdbmss *c; { int i; uint32 len; uint32 u; if (!cdbmake_split(&c->cdbm,alloc)) return -1; for (i = 0;i < 256;++i) { len = cdbmake_throw(&c->cdbm,c->pos,i); for (u = 0;u < len;++u) { cdbmake_pack(c->packbuf,c->cdbm.hash[u].h); cdbmake_pack(c->packbuf + 4,c->cdbm.hash[u].p); if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1; c->pos += 8; /* XXX: overflow? */ } } if (substdio_flush(&c->ss) == -1) return -1; if (seek_begin(c->fd) == -1) return -1; return substdio_putflush(&c->ss,c->cdbm.final,sizeof(c->cdbm.final)); } fastforward-0.51/control.h010064400000000000001000000003000653033120600157370ustar00rootother00000000000000#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 fastforward-0.51/control.c010064400000000000001000000043500653033120600157430ustar00rootother00000000000000#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; } fastforward-0.51/env.h010064400000000000001000000004400653033120600150540ustar00rootother00000000000000#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 fastforward-0.51/envread.c010064400000000000001000000006670653033120600157160ustar00rootother00000000000000#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; } fastforward-0.51/error.h010064400000000000001000000006570653033120600154270ustar00rootother00000000000000#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 fastforward-0.51/error.c010064400000000000001000000015760653033120600154230ustar00rootother00000000000000#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 fastforward-0.51/error_str.c010064400000000000001000000126670653033120600163160ustar00rootother00000000000000#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"; } orary failure") X(error_wouldblock,"input/output would block") X(errofastforward-0.51/fd.h010064400000000000001000000001170653033120600146560ustar00rootother00000000000000#ifndef FD_H #define FD_H extern int fd_copy(); extern int fd_move(); #endif fastforward-0.51/fd_copy.c010064400000000000001000000003410653033120600157020ustar00rootother00000000000000#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; } fastforward-0.51/fd_move.c010064400000000000001000000002340653033120600156770ustar00rootother00000000000000#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; } fastforward-0.51/fork.h1010064400000000000001000000001150653033120600153050ustar00rootother00000000000000#ifndef FORK_H #define FORK_H extern int fork(); #define vfork fork #endif fastforward-0.51/fork.h2010064400000000000001000000001160653033120600153070ustar00rootother00000000000000#ifndef FORK_H #define FORK_H extern int fork(); extern int vfork(); #endif fastforward-0.51/tryvfork.c010064400000000000001000000000330653033120600161430ustar00rootother00000000000000void main() { vfork(); } fastforward-0.51/fmt.h010064400000000000001000000012440653033120600150550ustar00rootother00000000000000#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 fastforward-0.51/fmt_ulong.c010064400000000000001000000005000653033120600162460ustar00rootother00000000000000#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; } fastforward-0.51/scan.h010064400000000000001000000012660653033120600152170ustar00rootother00000000000000#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 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 ifastforward-0.51/scan_ulong.c010064400000000000001000000005300653033120600164070ustar00rootother00000000000000#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; } fastforward-0.51/getln.h010064400000000000001000000001220653033120600153720ustar00rootother00000000000000#ifndef GETLN_H #define GETLN_H extern int getln(); extern int getln2(); #endif fastforward-0.51/getln.c010064400000000000001000000005760653033120600154020ustar00rootother00000000000000#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; } fastforward-0.51/getln2.c010064400000000000001000000012600653033120600154530ustar00rootother00000000000000#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); } } fastforward-0.51/sgetopt.h010064400000000000001000000006410653033120600157540ustar00rootother00000000000000#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 fastforward-0.51/sgetopt.c010064400000000000001000000023750653033120600157550ustar00rootother00000000000000/* 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; } fastforward-0.51/subgetopt.h010064400000000000001000000010100653033120600162720ustar00rootother00000000000000#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 fastforward-0.51/subgetopt.c010064400000000000001000000031510653033120600162750ustar00rootother00000000000000/* 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 '?'; } fastforward-0.51/open.h010064400000000000001000000002430653033120600152260ustar00rootother00000000000000#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 fastforward-0.51/open_read.c010064400000000000001000000002020653033120600162070ustar00rootother00000000000000#include #include #include "open.h" int open_read(fn) char *fn; { return open(fn,O_RDONLY | O_NDELAY); } fastforward-0.51/open_trunc.c010064400000000000001000000002340653033120600164340ustar00rootother00000000000000#include #include #include "open.h" int open_trunc(fn) char *fn; { return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } fastforward-0.51/conf-qmail010064400000000000001000000003010653033120600160600ustar00rootother00000000000000/var/qmail This is the qmail home directory. The fastforward programs will be installed in the bin subdirectory; they also need to know where qmail is so that they can forward mail properly. fastforward-0.51/auto_qmail.h010064400000000000001000000001150653033120600164160ustar00rootother00000000000000#ifndef AUTO_QMAIL_H #define AUTO_QMAIL_H extern char auto_qmail[]; #endif fastforward-0.51/qmail.h010064400000000000001000000006040653033120600153710ustar00rootother00000000000000#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 fastforward-0.51/qmail.c010064400000000000001000000065430653033120600153740ustar00rootother00000000000000#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)"; } } fastforward-0.51/seek.h010064400000000000001000000003430653033120600152150ustar00rootother00000000000000#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 fastforward-0.51/seek_set.c010064400000000000001000000002550653033120600160650ustar00rootother00000000000000#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; } fastforward-0.51/sig.h010064400000000000001000000016460653033120600150570ustar00rootother00000000000000#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 fastforward-0.51/sig_catch.c010064400000000000001000000005350653033120600162100ustar00rootother00000000000000#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 } fastforward-0.51/sig_pipe.c010064400000000000001000000002230653033120600160550ustar00rootother00000000000000#include #include "sig.h" void sig_pipeignore() { sig_catch(SIGPIPE,SIG_IGN); } void sig_pipedefault() { sig_catch(SIGPIPE,SIG_DFL); } fastforward-0.51/trysgact.c010064400000000000001000000002530653033120600161210ustar00rootother00000000000000#include void main() { struct sigaction sa; sa.sa_handler = 0; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(0,&sa,(struct sigaction *) 0); } fastforward-0.51/byte.h010064400000000000001000000004010653033120600152240ustar00rootother00000000000000#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 fastforward-0.51/byte_chr.c010064400000000000001000000006020653033120600160560ustar00rootother00000000000000#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; } fastforward-0.51/byte_copy.c010064400000000000001000000004530653033120600162600ustar00rootother00000000000000#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; } } fastforward-0.51/byte_cr.c010064400000000000001000000005040653033120600157070ustar00rootother00000000000000#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; } } fastforward-0.51/byte_diff.c010064400000000000001000000007050653033120600162160ustar00rootother00000000000000#include "byte.h" int byte_diff(s,n,t) register char *s; register unsigned int n; register char *t; { for (;;) { if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; } return ((int)(unsigned int)(unsigned char) *s) - ((int)(unsigned int)(unsigned char) *t); } fastforward-0.51/str.h010064400000000000001000000004270653033120600151010ustar00rootother00000000000000#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 fastforward-0.51/str_chr.c010064400000000000001000000005360653033120600157310ustar00rootother00000000000000#include "str.h" unsigned int str_chr(s,c) register char *s; int c; { register char ch; register char *t; ch = c; t = s; for (;;) { if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; } return t - s; } fastforward-0.51/str_cpy.c010064400000000000001000000005120653033120600157420ustar00rootother00000000000000#include "str.h" unsigned int str_copy(s,t) register char *s; register char *t; { register int len; len = 0; for (;;) { if (!(*s = *t)) return len; ++s; ++t; ++len; if (!(*s = *t)) return len; ++s; ++t; ++len; if (!(*s = *t)) return len; ++s; ++t; ++len; if (!(*s = *t)) return len; ++s; ++t; ++len; } } fastforward-0.51/str_diff.c010064400000000000001000000006670653033120600160720ustar00rootother00000000000000#include "str.h" int str_diff(s,t) register char *s; register char *t; { register char x; for (;;) { x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; } return ((int)(unsigned int)(unsigned char) x) - ((int)(unsigned int)(unsigned char) *t); } fastforward-0.51/str_diffn.c010064400000000000001000000010460653033120600162400ustar00rootother00000000000000#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); } fastforward-0.51/str_len.c010064400000000000001000000003570653033120600157340ustar00rootother00000000000000#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; } } fastforward-0.51/str_rchr.c010064400000000000001000000006150653033120600161110ustar00rootother00000000000000#include "str.h" unsigned int str_rchr(s,c) register char *s; int c; { register char ch; register char *t; register char *u; ch = c; t = s; u = 0; for (;;) { if (!*t) break; if (*t == ch) u = t; ++t; if (!*t) break; if (*t == ch) u = t; ++t; if (!*t) break; if (*t == ch) u = t; ++t; if (!*t) break; if (*t == ch) u = t; ++t; } if (!u) u = t; return u - s; } fastforward-0.51/gen_alloc.h010064400000000000001000000002550653033120600162130ustar00rootother00000000000000#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 fastforward-0.51/gen_allocdefs.h010064400000000000001000000022620653033120600170550ustar00rootother00000000000000#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 fastforward-0.51/stralloc.h010064400000000000001000000007600653033120600161140ustar00rootother00000000000000#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 fastforward-0.51/stralloc_eady.c010064400000000000001000000003130653033120600171030ustar00rootother00000000000000#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) fastforward-0.51/stralloc_pend.c010064400000000000001000000002310653033120600171060ustar00rootother00000000000000#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) fastforward-0.51/stralloc_copy.c010064400000000000001000000002430653033120600171350ustar00rootother00000000000000#include "byte.h" #include "stralloc.h" int stralloc_copy(sato,safrom) stralloc *sato; stralloc *safrom; { return stralloc_copyb(sato,safrom->s,safrom->len); } fastforward-0.51/stralloc_opyb.c010064400000000000001000000003770653033120600171440ustar00rootother00000000000000#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; } fastforward-0.51/stralloc_opys.c010064400000000000001000000002300653033120600171510ustar00rootother00000000000000#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)); } fastforward-0.51/stralloc_cat.c010064400000000000001000000002410653033120600167300ustar00rootother00000000000000#include "byte.h" #include "stralloc.h" int stralloc_cat(sato,safrom) stralloc *sato; stralloc *safrom; { return stralloc_catb(sato,safrom->s,safrom->len); } fastforward-0.51/stralloc_catb.c010064400000000000001000000005000653033120600170700ustar00rootother00000000000000#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; } fastforward-0.51/stralloc_cats.c010064400000000000001000000002260653033120600171160ustar00rootother00000000000000#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)); } fastforward-0.51/stralloc_arts.c010064400000000000001000000003040653033120600171320ustar00rootother00000000000000#include "byte.h" #include "str.h" #include "stralloc.h" int stralloc_starts(sa,s) stralloc *sa; char *s; { int len; len = str_len(s); return (sa->len >= len) && byte_equal(s,len,sa->s); } fastforward-0.51/strset.h010064400000000000001000000011220653033120600156060ustar00rootother00000000000000#ifndef STRSET_H #define STRSET_H #include "uint32.h" typedef struct strset_list { uint32 h; int next; } strset_list; typedef struct { int mask; /* mask + 1 is power of 2, size of hash table */ int n; /* number of entries used in list and x */ int a; /* number of entries allocated in list and x */ int *first; /* first[h] is front of hash list h */ strset_list *p; /* p[i].next is next; p[i].h is hash of x[i] */ char **x; /* x[i] is entry i */ } strset; extern uint32 strset_hash(); extern int strset_init(); extern char *strset_in(); extern int strset_add(); #endif fastforward-0.51/strset.c010064400000000000001000000043460653033120600156140ustar00rootother00000000000000#include "strset.h" #include "str.h" #include "byte.h" uint32 strset_hash(s) char *s; { unsigned char ch; uint32 h; h = 5381; while (ch = *s) { h = ((h << 5) + h) ^ ch; ++s; } return h; } int strset_init(set) strset *set; { int h; set->mask = 15; set->n = 0; set->a = 10; set->first = (int *) alloc(sizeof(int) * (set->mask + 1)); if (!set->first) return 0; set->p = (strset_list *) alloc(sizeof(strset_list) * set->a); if (!set->p) { alloc_free(set->first); return 0; } set->x = (char **) alloc(sizeof(char *) * set->a); if (!set->x) { alloc_free(set->p); alloc_free(set->first); return 0; } for (h = 0;h <= set->mask;++h) set->first[h] = -1; return 1; } char *strset_in(set,s) strset *set; char *s; { uint32 h; strset_list *sl; int i; char *xi; h = strset_hash(s); i = set->first[h & set->mask]; while (i >= 0) { sl = set->p + i; if (sl->h == h) { xi = set->x[i]; if (!str_diff(xi,s)) return xi; } i = sl->next; } return 0; } int strset_add(set,s) strset *set; char *s; { uint32 h; int n; strset_list *sl; n = set->n; if (n == set->a) { int newa; strset_list *newp; char **newx; newa = n + 10 + (n >> 3); newp = (strset_list *) alloc(sizeof(strset_list) * newa); if (!newp) return 0; newx = (char **) alloc(sizeof(char *) * newa); if (!newx) { alloc_free(newp); return 0; } byte_copy(newp,sizeof(strset_list) * n,set->p); byte_copy(newx,sizeof(char *) * n,set->x); alloc_free(set->p); alloc_free(set->x); set->p = newp; set->x = newx; set->a = newa; if (n + n + n > set->mask) { int newmask; int *newfirst; int i; uint32 h; newmask = set->mask + set->mask + 1; newfirst = (int *) alloc(sizeof(int) * (newmask + 1)); if (!newfirst) return 0; for (h = 0;h <= newmask;++h) newfirst[h] = -1; for (i = 0;i < n;++i) { sl = set->p + i; h = sl->h & newmask; sl->next = newfirst[h]; newfirst[h] = i; } alloc_free(set->first); set->first = newfirst; set->mask = newmask; } } h = strset_hash(s); sl = set->p + n; sl->h = h; h &= set->mask; sl->next = set->first[h]; set->first[h] = n; set->x[n] = s; set->n = n + 1; return 1; } fastforward-0.51/substdio.h010064400000000000001000000017140653033120600161250ustar00rootother00000000000000#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 fastforward-0.51/substdio.c010064400000000000001000000003470653033120600161210ustar00rootother00000000000000#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; } fastforward-0.51/substdi.c010064400000000000001000000031170653033120600157400ustar00rootother00000000000000#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; } fastforward-0.51/substdo.c010064400000000000001000000037450653033120600157550ustar00rootother00000000000000#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)); } fastforward-0.51/substdio_copy.c010064400000000000001000000005330653033120600171500ustar00rootother00000000000000#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); } } fastforward-0.51/subfd.h010064400000000000001000000004070653033120600153720ustar00rootother00000000000000#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 fastforward-0.51/subfderr.c010064400000000000001000000002620653033120600160750ustar00rootother00000000000000#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 = ⁢ fastforward-0.51/subfdouts.c010064400000000000001000000003010653033120600162710ustar00rootother00000000000000#include "readwrite.h" #include "substdio.h" #include "subfd.h" char subfd_outbufsmall[256]; static substdio it = SUBSTDIO_FDBUF(write,1,subfd_outbufsmall,256); substdio *subfdoutsmall = ⁢ fastforward-0.51/subfdins.c010064400000000000001000000005320653033120600160760ustar00rootother00000000000000#include "readwrite.h" #include "substdio.h" #include "subfd.h" int subfd_readsmall(fd,buf,len) int fd; char *buf; int len; { if (substdio_flush(subfdoutsmall) == -1) return -1; return read(fd,buf,len); } char subfd_inbufsmall[256]; static substdio it = SUBSTDIO_FDBUF(subfd_readsmall,0,subfd_inbufsmall,256); substdio *subfdinsmall = ⁢ fastforward-0.51/readwrite.h010064400000000000001000000001300653033120600162460ustar00rootother00000000000000#ifndef READWRITE_H #define READWRITE_H extern int read(); extern int write(); #endif fastforward-0.51/exit.h010064400000000000001000000000740653033120600152400ustar00rootother00000000000000#ifndef EXIT_H #define EXIT_H extern void _exit(); #endif fastforward-0.51/token822.h010064400000000000001000000013430653033120600156430ustar00rootother00000000000000#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 fastforward-0.51/token822.c010064400000000000001000000262240653033120600156430ustar00rootother00000000000000#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; } fastforward-0.51/uint32.h1010064400000000000001000000001100653033120600154630ustar00rootother00000000000000#ifndef UINT32_H #define UINT32_H typedef unsigned int uint32; #endif fastforward-0.51/uint32.h2010064400000000000001000000001110653033120600154650ustar00rootother00000000000000#ifndef UINT32_H #define UINT32_H typedef unsigned long uint32; #endif fastforward-0.51/tryulong32.c010064400000000000001000000005240653033120600163120ustar00rootother00000000000000void main() { unsigned long u; u = 1; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; if (!u) _exit(0); _exit(1); } fastforward-0.51/wait.h010064400000000000001000000004470653033120600152370ustar00rootother00000000000000#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 fastforward-0.51/wait_pid.c010064400000000000001000000013050653033120600160600ustar00rootother00000000000000#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 fastforward-0.51/trywaitp.c010064400000000000001000000001200653033120600161350ustar00rootother00000000000000#include #include void main() { waitpid(0,0,0); } fastforward-0.51/strerr.h010064400000000000001000000064430653033120600156160ustar00rootother00000000000000#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 fastforward-0.51/strerr_sys.c010064400000000000001000000003000653033120600164710ustar00rootother00000000000000#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 = ""; } fastforward-0.51/strerr_die.c010064400000000000001000000015460653033120600164310ustar00rootother00000000000000#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); } fastforward-0.51/slurpclose.h010064400000000000001000000001140653033120600164550ustar00rootother00000000000000#ifndef SLURPCLOSE_H #define SLURPCLOSE_H extern int slurpclose(); #endif fastforward-0.51/slurpclose.c010064400000000000001000000006240653033120600164560ustar00rootother00000000000000#include "stralloc.h" #include "readwrite.h" #include "slurpclose.h" #include "error.h" int slurpclose(fd,sa,bufsize) int fd; stralloc *sa; int bufsize; { int r; for (;;) { if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } r = read(fd,sa->s + sa->len,bufsize); if (r == -1) if (errno == error_intr) continue; if (r <= 0) { close(fd); return r; } sa->len += r; } } fastforward-0.51/coe.h010064400000000000001000000000670653033120600150370ustar00rootother00000000000000#ifndef COE_H #define COE_H extern int coe(); #endif fastforward-0.51/coe.c010064400000000000001000000001330653033120600150240ustar00rootother00000000000000#include #include "coe.h" int coe(fd) int fd; { return fcntl(fd,F_SETFD,1); }