diff options
author | Dmitry Bogatov <KAction@debian.org> | 2018-11-29 05:18:27 +0000 |
---|---|---|
committer | Dmitry Bogatov <KAction@debian.org> | 2018-11-29 05:18:27 +0000 |
commit | 78fbb41eaf3abb208abe6acfb06db005adeadf35 (patch) | |
tree | f09dac61e9f2fe6d865d76d57dac12674eec1279 |
Import Upstream version 0.80
-rw-r--r-- | BIN | 11 | ||||
-rw-r--r-- | BLURB | 19 | ||||
-rw-r--r-- | CHANGES | 7 | ||||
-rw-r--r-- | FILES | 212 | ||||
-rw-r--r-- | INSTALL | 26 | ||||
-rw-r--r-- | MAN | 13 | ||||
-rw-r--r-- | Makefile | 626 | ||||
-rw-r--r-- | README | 89 | ||||
-rw-r--r-- | SYSDEPS | 9 | ||||
-rw-r--r-- | TARGETS | 133 | ||||
-rw-r--r-- | TCP | 45 | ||||
-rw-r--r-- | THANKS | 62 | ||||
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | UCSPI | 131 | ||||
-rw-r--r-- | VERSION | 1 | ||||
-rw-r--r-- | addcr.c | 23 | ||||
-rw-r--r-- | addcr=x | 3 | ||||
-rw-r--r-- | alloc.c | 32 | ||||
-rw-r--r-- | alloc.h | 8 | ||||
-rw-r--r-- | alloc=l | 2 | ||||
-rw-r--r-- | alloc_re.c | 17 | ||||
-rw-r--r-- | auto-str.c | 44 | ||||
-rw-r--r-- | auto-str=x | 3 | ||||
-rw-r--r-- | byte.h | 13 | ||||
-rw-r--r-- | byte_chr.c | 20 | ||||
-rw-r--r-- | byte_copy.c | 14 | ||||
-rw-r--r-- | byte_cr.c | 16 | ||||
-rw-r--r-- | byte_diff.c | 16 | ||||
-rw-r--r-- | byte_rchr.c | 23 | ||||
-rw-r--r-- | byte_zero.c | 13 | ||||
-rw-r--r-- | case.h | 13 | ||||
-rw-r--r-- | case=l | 1 | ||||
-rw-r--r-- | case_lowers.c | 12 | ||||
-rw-r--r-- | cdb.h | 12 | ||||
-rw-r--r-- | cdb=l | 3 | ||||
-rw-r--r-- | cdb_hash.c | 16 | ||||
-rw-r--r-- | cdb_seek.c | 95 | ||||
-rw-r--r-- | cdb_unpack.c | 12 | ||||
-rw-r--r-- | cdbmake.h | 35 | ||||
-rw-r--r-- | cdbmake=l | 3 | ||||
-rw-r--r-- | cdbmake_add.c | 117 | ||||
-rw-r--r-- | cdbmake_hash.c | 10 | ||||
-rw-r--r-- | cdbmake_pack.c | 11 | ||||
-rw-r--r-- | cdbmss.c | 65 | ||||
-rw-r--r-- | cdbmss.h | 16 | ||||
-rw-r--r-- | conf-bin | 3 | ||||
-rw-r--r-- | conf-cc | 3 | ||||
-rw-r--r-- | conf-ld | 3 | ||||
-rw-r--r-- | conf-man | 5 | ||||
-rw-r--r-- | date@.sh | 1 | ||||
-rw-r--r-- | date@=s | 0 | ||||
-rw-r--r-- | default.0.do | 9 | ||||
-rw-r--r-- | default.a.do | 10 | ||||
-rw-r--r-- | default.do | 77 | ||||
-rw-r--r-- | default.o.do | 15 | ||||
-rw-r--r-- | delcr.c | 37 | ||||
-rw-r--r-- | delcr=x | 3 | ||||
-rw-r--r-- | dns.c | 402 | ||||
-rw-r--r-- | dns.h | 14 | ||||
-rw-r--r-- | dns.lib.do | 14 | ||||
-rw-r--r-- | env.c | 113 | ||||
-rw-r--r-- | env.h | 17 | ||||
-rw-r--r-- | env=l | 2 | ||||
-rw-r--r-- | envread.c | 30 | ||||
-rw-r--r-- | error.c | 95 | ||||
-rw-r--r-- | error.h | 23 | ||||
-rw-r--r-- | error=l | 2 | ||||
-rw-r--r-- | error_str.c | 276 | ||||
-rw-r--r-- | exit.h | 6 | ||||
-rw-r--r-- | fd.h | 7 | ||||
-rw-r--r-- | fd=l | 2 | ||||
-rw-r--r-- | fd_copy.c | 13 | ||||
-rw-r--r-- | fd_move.c | 11 | ||||
-rw-r--r-- | find-systype.sh | 144 | ||||
-rw-r--r-- | finger@.sh | 4 | ||||
-rw-r--r-- | finger@=s | 0 | ||||
-rw-r--r-- | fmt.h | 25 | ||||
-rw-r--r-- | fmt_str.c | 12 | ||||
-rw-r--r-- | fmt_ulong.c | 13 | ||||
-rw-r--r-- | fs=l | 4 | ||||
-rw-r--r-- | gen_alloc.h | 7 | ||||
-rw-r--r-- | gen_allocdefs.h | 34 | ||||
-rw-r--r-- | getln.c | 20 | ||||
-rw-r--r-- | getln.h | 7 | ||||
-rw-r--r-- | getln2.c | 31 | ||||
-rw-r--r-- | getln=l | 2 | ||||
-rw-r--r-- | getopt=l | 2 | ||||
-rw-r--r-- | hassgact.h.do | 7 | ||||
-rw-r--r-- | hassgprm.h.do | 7 | ||||
-rw-r--r-- | haswaitp.h.do | 7 | ||||
-rw-r--r-- | install.c | 140 | ||||
-rw-r--r-- | install=x | 9 | ||||
-rw-r--r-- | ip.c | 53 | ||||
-rw-r--r-- | ip.h | 11 | ||||
-rw-r--r-- | ipalloc.c | 7 | ||||
-rw-r--r-- | ipalloc.h | 14 | ||||
-rw-r--r-- | it.do | 5 | ||||
-rw-r--r-- | make-compile.sh | 1 | ||||
-rw-r--r-- | make-load.sh | 2 | ||||
-rw-r--r-- | make-makelib.sh | 16 | ||||
-rw-r--r-- | man.do | 5 | ||||
-rw-r--r-- | mconnect.sh | 7 | ||||
-rw-r--r-- | mconnect=s | 0 | ||||
-rw-r--r-- | ndelay.c | 13 | ||||
-rw-r--r-- | ndelay.h | 7 | ||||
-rw-r--r-- | ndelay=l | 2 | ||||
-rw-r--r-- | ndelay_off.c | 13 | ||||
-rw-r--r-- | open.h | 10 | ||||
-rw-r--r-- | open=l | 2 | ||||
-rw-r--r-- | open_read.c | 6 | ||||
-rw-r--r-- | open_trunc.c | 6 | ||||
-rw-r--r-- | readwrite.h | 7 | ||||
-rw-r--r-- | remoteinfo.c | 77 | ||||
-rw-r--r-- | remoteinfo.h | 6 | ||||
-rw-r--r-- | scan.h | 27 | ||||
-rw-r--r-- | scan_8long.c | 11 | ||||
-rw-r--r-- | scan_ulong.c | 11 | ||||
-rw-r--r-- | seek.h | 15 | ||||
-rw-r--r-- | seek=l | 4 | ||||
-rw-r--r-- | seek_cur.c | 7 | ||||
-rw-r--r-- | seek_end.c | 7 | ||||
-rw-r--r-- | seek_set.c | 7 | ||||
-rw-r--r-- | seek_trunc.c | 5 | ||||
-rw-r--r-- | select.h.do | 6 | ||||
-rw-r--r-- | select.h1 | 8 | ||||
-rw-r--r-- | select.h2 | 9 | ||||
-rw-r--r-- | setup.do | 5 | ||||
-rw-r--r-- | sgetopt.c | 54 | ||||
-rw-r--r-- | sgetopt.h | 21 | ||||
-rw-r--r-- | sig.h | 43 | ||||
-rw-r--r-- | sig=l | 7 | ||||
-rw-r--r-- | sig_block.c | 40 | ||||
-rw-r--r-- | sig_catch.c | 18 | ||||
-rw-r--r-- | sig_child.c | 7 | ||||
-rw-r--r-- | sig_cont.c | 0 | ||||
-rw-r--r-- | sig_dfl.c | 82 | ||||
-rw-r--r-- | sig_pause.c | 14 | ||||
-rw-r--r-- | sig_pipe.c | 5 | ||||
-rw-r--r-- | sig_term.c | 7 | ||||
-rw-r--r-- | socket.lib.do | 8 | ||||
-rw-r--r-- | str.h | 14 | ||||
-rw-r--r-- | str=l | 10 | ||||
-rw-r--r-- | str_cpy.c | 16 | ||||
-rw-r--r-- | str_diff.c | 17 | ||||
-rw-r--r-- | str_diffn.c | 18 | ||||
-rw-r--r-- | str_len.c | 15 | ||||
-rw-r--r-- | stralloc.h | 21 | ||||
-rw-r--r-- | stralloc=l | 8 | ||||
-rw-r--r-- | stralloc_arts.c | 12 | ||||
-rw-r--r-- | stralloc_cat.c | 9 | ||||
-rw-r--r-- | stralloc_catb.c | 15 | ||||
-rw-r--r-- | stralloc_cats.c | 10 | ||||
-rw-r--r-- | stralloc_copy.c | 9 | ||||
-rw-r--r-- | stralloc_eady.c | 6 | ||||
-rw-r--r-- | stralloc_opyb.c | 14 | ||||
-rw-r--r-- | stralloc_opys.c | 10 | ||||
-rw-r--r-- | stralloc_pend.c | 5 | ||||
-rw-r--r-- | strerr.h | 80 | ||||
-rw-r--r-- | strerr=l | 2 | ||||
-rw-r--r-- | strerr_die.c | 37 | ||||
-rw-r--r-- | strerr_sys.c | 12 | ||||
-rw-r--r-- | subfd.h | 15 | ||||
-rw-r--r-- | subfderr.c | 7 | ||||
-rw-r--r-- | subfdin.c | 13 | ||||
-rw-r--r-- | subfdout.c | 7 | ||||
-rw-r--r-- | subgetopt.c | 79 | ||||
-rw-r--r-- | subgetopt.h | 24 | ||||
-rw-r--r-- | substdi.c | 91 | ||||
-rw-r--r-- | substdio.c | 15 | ||||
-rw-r--r-- | substdio.h | 47 | ||||
-rw-r--r-- | substdio=l | 7 | ||||
-rw-r--r-- | substdio_copy.c | 18 | ||||
-rw-r--r-- | substdo.c | 108 | ||||
-rw-r--r-- | tcp-environ.5 | 62 | ||||
-rw-r--r-- | tcp-environ=0 | 1 | ||||
-rw-r--r-- | tcpcat.sh | 1 | ||||
-rw-r--r-- | tcpcat=s | 0 | ||||
-rw-r--r-- | tcpclient.1 | 134 | ||||
-rw-r--r-- | tcpclient.c | 236 | ||||
-rw-r--r-- | tcpclient=0 | 1 | ||||
-rw-r--r-- | tcpclient=x | 21 | ||||
-rw-r--r-- | tcprules.1 | 207 | ||||
-rw-r--r-- | tcprules.c | 177 | ||||
-rw-r--r-- | tcprules=0 | 1 | ||||
-rw-r--r-- | tcprules=x | 12 | ||||
-rw-r--r-- | tcpserver.1 | 220 | ||||
-rw-r--r-- | tcpserver.c | 475 | ||||
-rw-r--r-- | tcpserver=0 | 1 | ||||
-rw-r--r-- | tcpserver=x | 25 | ||||
-rw-r--r-- | timeoutconn.c | 59 | ||||
-rw-r--r-- | timeoutconn.h | 6 | ||||
-rw-r--r-- | timeoutread.c | 22 | ||||
-rw-r--r-- | timeoutread.h | 6 | ||||
-rw-r--r-- | timeoutwrite.c | 22 | ||||
-rw-r--r-- | timeoutwrite.h | 6 | ||||
-rw-r--r-- | trycpp.c | 7 | ||||
-rw-r--r-- | trylsock.c | 4 | ||||
-rw-r--r-- | tryrsolv.c | 4 | ||||
-rw-r--r-- | trysgact.c | 10 | ||||
-rw-r--r-- | trysgprm.c | 10 | ||||
-rw-r--r-- | trysysel.c | 8 | ||||
-rw-r--r-- | tryulong32.c | 11 | ||||
-rw-r--r-- | trywaitp.c | 7 | ||||
-rw-r--r-- | uint32.h.do | 7 | ||||
-rw-r--r-- | uint32.h1 | 6 | ||||
-rw-r--r-- | uint32.h2 | 6 | ||||
-rw-r--r-- | wait.h | 14 | ||||
-rw-r--r-- | wait=l | 1 | ||||
-rw-r--r-- | wait_nohang.c | 12 | ||||
-rw-r--r-- | warn-auto.sh | 2 | ||||
-rw-r--r-- | who@.sh | 1 | ||||
-rw-r--r-- | who@=s | 0 |
212 files changed, 6997 insertions, 0 deletions
@@ -0,0 +1,11 @@ +d:::755::: +c:::711:/:tcpclient: +c:::711:/:tcpserver: +c:::711:/:tcprules: +c:::711:/:addcr: +c:::711:/:delcr: +c:::755:/:who@: +c:::755:/:date@: +c:::755:/:finger@: +c:::755:/:tcpcat: +c:::755:/:mconnect: @@ -0,0 +1,19 @@ +tcpclient and tcpserver are easy-to-use command-line tools for building +TCP client-server applications. tcpclient makes a TCP connection and +runs a program of your choice. tcpserver waits for incoming connections +and, for each connection, runs a program of your choice. Your program +receives environment variables showing the local and remote host names, +IP addresses, and port numbers. + +tcpserver offers a concurrency limit to protect you from running out of +processes and memory. When you are handling 40 (by default) simultaneous +connections, tcpserver smoothly defers acceptance of new connections. + +tcpserver also provides TCP access control features, similar to +tcp-wrappers/tcpd's hosts.allow but much faster. Its access control +rules are compiled into a hashed format with cdb, so it can easily deal +with thousands of different hosts. + +tcpclient and tcpserver conform to UCSPI, the UNIX Client-Server Program +Interface, using the TCP protocol. UCSPI tools are available for several +different networks. @@ -0,0 +1,7 @@ +19980118 ucspi-tcp 0.80, beta. +19970410 ucspi-tcp 0.73, beta. +19960922 ucspi-tcp 0.72, beta. +19960914 ucspi-tcp 0.71, beta. +19960903 ucspi-tcp 0.70, beta. +19960803 ucspi-tcp 0.60, alpha. +19960311 ucspi-tcp 0.50, alpha. @@ -0,0 +1,212 @@ +BLURB +README +INSTALL +TODO +THANKS +CHANGES +UCSPI +TCP +FILES +BIN +MAN +VERSION +SYSDEPS +TARGETS +Makefile +tcpclient=0 +tcpclient.1 +tcpclient=x +tcpclient.c +tcpserver=0 +tcpserver.1 +tcpserver=x +tcpserver.c +tcprules=0 +tcprules.1 +tcprules=x +tcprules.c +tcp-environ=0 +tcp-environ.5 +addcr=x +addcr.c +delcr=x +delcr.c +date@=s +date@.sh +finger@=s +finger@.sh +who@=s +who@.sh +mconnect=s +mconnect.sh +tcpcat=s +tcpcat.sh +it.do +man.do +setup.do +default.do +default.a.do +default.o.do +default.0.do +conf-cc +conf-ld +find-systype.sh +make-compile.sh +make-load.sh +make-makelib.sh +trycpp.c +warn-auto.sh +conf-bin +conf-man +auto-str=x +install=x +auto-str.c +install.c +substdio=l +substdio.h +substdio.c +substdi.c +substdo.c +substdio_copy.c +subfd.h +subfderr.c +subfdout.c +subfdin.c +readwrite.h +exit.h +error=l +error.h +error.c +error_str.c +str=l +byte.h +byte_chr.c +byte_rchr.c +byte_copy.c +byte_cr.c +byte_diff.c +byte_zero.c +str.h +str_cpy.c +str_diff.c +str_diffn.c +str_len.c +sig=l +sig.h +sig_block.c +sig_catch.c +sig_dfl.c +sig_pipe.c +sig_cont.c +sig_child.c +sig_pause.c +sig_term.c +hassgact.h.do +hassgprm.h.do +trysgact.c +trysgprm.c +fd=l +fd.h +fd_copy.c +fd_move.c +ip.h +ip.c +ipalloc.h +ipalloc.c +case=l +case.h +case_lowers.c +getopt=l +sgetopt.h +sgetopt.c +subgetopt.h +subgetopt.c +fs=l +fmt.h +fmt_str.c +fmt_ulong.c +scan.h +scan_ulong.c +scan_8long.c +env=l +env.h +env.c +envread.c +dns.h +dns.c +dns.lib.do +socket.lib.do +tryrsolv.c +trylsock.c +timeoutread.h +timeoutread.c +timeoutwrite.h +timeoutwrite.c +timeoutconn.h +timeoutconn.c +remoteinfo.h +remoteinfo.c +wait=l +wait.h +wait_nohang.c +trywaitp.c +haswaitp.h.do +select.h.do +select.h1 +select.h2 +trysysel.c +stralloc=l +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 +alloc=l +alloc.h +alloc.c +alloc_re.c +ndelay=l +ndelay.h +ndelay.c +ndelay_off.c +strerr=l +strerr.h +strerr_sys.c +strerr_die.c +open=l +open.h +open_read.c +open_trunc.c +getln=l +getln.h +getln.c +getln2.c +cdb=l +cdbmake=l +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 +uint32.h.do +uint32.h1 +uint32.h2 +tryulong32.c +seek=l +seek.h +seek_cur.c +seek_end.c +seek_set.c +seek_trunc.c @@ -0,0 +1,26 @@ +Like any other piece of software (and information generally), ucspi-tcp +comes with NO WARRANTY. + + +Things you have to decide before starting: + +* Where programs will be installed, normally /usr/local/bin. To change +this directory, edit conf-bin now. + +* Where man pages will be installed, normally /usr/local/man. To change +this directory, edit conf-man now. + + +How to install: + + 1. Compile the programs: + % make + 2. Create the formatted man pages, *.0: + % make man + 3. Install the programs and man pages: + # make setup + + +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. @@ -0,0 +1,13 @@ +d:::755::: +d:::755:/man1:: +d:::755:/cat1:: +d:::755:/man5:: +d:::755:/cat5:: +c:::644:/man1/:tcpclient.1: +c:::644:/cat1/:tcpclient.0: +c:::644:/man1/:tcpserver.1: +c:::644:/cat1/:tcpserver.0: +c:::644:/man1/:tcprules.1: +c:::644:/cat1/:tcprules.0: +c:::644:/man5/:tcp-environ.5: +c:::644:/cat5/:tcp-environ.0: diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..be4a723 --- /dev/null +++ b/Makefile @@ -0,0 +1,626 @@ +# Don't edit Makefile! Use conf-* for configuration. + +SHELL=/bin/sh + +default: it + +addcr: \ +load addcr.o substdio.a error.a str.a + ./load addcr substdio.a error.a str.a + +addcr.o: \ +compile addcr.c substdio.h subfd.h exit.h + ./compile addcr.c + +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 + +byte_chr.o: \ +compile byte_chr.c byte.h + ./compile byte_chr.c + +byte_copy.o: \ +compile byte_copy.c byte.h + ./compile byte_copy.c + +byte_cr.o: \ +compile byte_cr.c byte.h + ./compile byte_cr.c + +byte_diff.o: \ +compile byte_diff.c byte.h + ./compile byte_diff.c + +byte_rchr.o: \ +compile byte_rchr.c byte.h + ./compile byte_rchr.c + +byte_zero.o: \ +compile byte_zero.c byte.h + ./compile byte_zero.c + +case.a: \ +makelib case_lowers.o + ./makelib case.a case_lowers.o + +case_lowers.o: \ +compile case_lowers.c case.h + ./compile case_lowers.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 + +compile: \ +make-compile warn-auto.sh systype + ( cat warn-auto.sh; ./make-compile "`cat systype`" ) > \ + compile + chmod 755 compile + +date@: \ +warn-auto.sh date@.sh conf-bin + cat warn-auto.sh date@.sh \ + | sed s}BIN}"`head -1 conf-bin`"}g > date@ + chmod 755 date@ + +delcr: \ +load delcr.o substdio.a error.a str.a + ./load delcr substdio.a error.a str.a + +delcr.o: \ +compile delcr.c substdio.h subfd.h exit.h + ./compile delcr.c + +dns.lib: \ +tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \ +alloc.a error.a fs.a str.a + ( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \ + ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \ + -lresolv `cat socket.lib` ) >/dev/null 2>&1 \ + && echo -lresolv || exit 0 ) > dns.lib + rm -f tryrsolv.o tryrsolv + +dns.o: \ +compile dns.c ip.h ipalloc.h gen_alloc.h fmt.h alloc.h str.h \ +stralloc.h dns.h case.h + ./compile dns.c + +env.a: \ +makelib env.o envread.o + ./makelib env.a env.o envread.o + +env.o: \ +compile env.c str.h alloc.h env.h + ./compile env.c + +envread.o: \ +compile envread.c env.h str.h + ./compile envread.c + +error.a: \ +makelib error.o error_str.o + ./makelib error.a error.o error_str.o + +error.o: \ +compile error.c error.h + ./compile error.c + +error_str.o: \ +compile error_str.c error.h + ./compile error_str.c + +fd.a: \ +makelib fd_copy.o fd_move.o + ./makelib fd.a fd_copy.o fd_move.o + +fd_copy.o: \ +compile fd_copy.c fd.h + ./compile fd_copy.c + +fd_move.o: \ +compile fd_move.c fd.h + ./compile fd_move.c + +find-systype: \ +find-systype.sh auto-ccld.sh + cat auto-ccld.sh find-systype.sh > find-systype + chmod 755 find-systype + +finger@: \ +warn-auto.sh finger@.sh conf-bin + cat warn-auto.sh finger@.sh \ + | sed s}BIN}"`head -1 conf-bin`"}g > finger@ + chmod 755 finger@ + +fmt_str.o: \ +compile fmt_str.c fmt.h + ./compile fmt_str.c + +fmt_ulong.o: \ +compile fmt_ulong.c fmt.h + ./compile fmt_ulong.c + +fs.a: \ +makelib fmt_str.o fmt_ulong.o scan_ulong.o scan_8long.o + ./makelib fs.a fmt_str.o fmt_ulong.o scan_ulong.o \ + scan_8long.o + +getln.a: \ +makelib getln.o getln2.o + ./makelib getln.a getln.o getln2.o + +getln.o: \ +compile getln.c substdio.h byte.h stralloc.h gen_alloc.h getln.h + ./compile getln.c + +getln2.o: \ +compile getln2.c substdio.h stralloc.h gen_alloc.h byte.h getln.h + ./compile getln2.c + +getopt.a: \ +makelib subgetopt.o sgetopt.o + ./makelib getopt.a subgetopt.o sgetopt.o + +hassgact.h: \ +trysgact.c compile load + ( ( ./compile trysgact.c && ./load trysgact ) >/dev/null \ + 2>&1 \ + && echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h + rm -f trysgact.o trysgact + +hassgprm.h: \ +trysgprm.c compile load + ( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null \ + 2>&1 \ + && echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h + rm -f trysgprm.o trysgprm + +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 + +install: \ +load install.o getln.a strerr.a substdio.a stralloc.a alloc.a open.a \ +error.a str.a fs.a + ./load install getln.a strerr.a substdio.a stralloc.a \ + alloc.a open.a error.a str.a fs.a + +install.o: \ +compile install.c substdio.h stralloc.h gen_alloc.h getln.h \ +readwrite.h exit.h open.h error.h strerr.h byte.h + ./compile install.c + +ip.o: \ +compile ip.c fmt.h scan.h ip.h + ./compile ip.c + +ipalloc.o: \ +compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h gen_alloc.h + ./compile ipalloc.c + +it: \ +tcpclient tcpserver tcprules who@ date@ finger@ tcpcat mconnect addcr \ +delcr + +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: \ +tcpclient.0 tcpserver.0 tcprules.0 tcp-environ.0 + +mconnect: \ +warn-auto.sh mconnect.sh conf-bin + cat warn-auto.sh mconnect.sh \ + | sed s}BIN}"`head -1 conf-bin`"}g > mconnect + chmod 755 mconnect + +ndelay.a: \ +makelib ndelay.o ndelay_off.o + ./makelib ndelay.a ndelay.o ndelay_off.o + +ndelay.o: \ +compile ndelay.c ndelay.h + ./compile ndelay.c + +ndelay_off.o: \ +compile ndelay_off.c ndelay.h + ./compile ndelay_off.c + +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 + +remoteinfo.o: \ +compile remoteinfo.c byte.h substdio.h ip.h fmt.h timeoutconn.h \ +timeoutread.h timeoutwrite.h remoteinfo.h + ./compile remoteinfo.c + +scan_8long.o: \ +compile scan_8long.c scan.h + ./compile scan_8long.c + +scan_ulong.o: \ +compile scan_ulong.c scan.h + ./compile scan_ulong.c + +seek.a: \ +makelib seek_cur.o seek_end.o seek_set.o seek_trunc.o + ./makelib seek.a seek_cur.o seek_end.o seek_set.o \ + seek_trunc.o + +seek_cur.o: \ +compile seek_cur.c seek.h + ./compile seek_cur.c + +seek_end.o: \ +compile seek_end.c seek.h + ./compile seek_end.c + +seek_set.o: \ +compile seek_set.c seek.h + ./compile seek_set.c + +seek_trunc.o: \ +compile seek_trunc.c seek.h + ./compile seek_trunc.c + +select.h: \ +compile trysysel.c select.h1 select.h2 + ( ./compile trysysel.c >/dev/null 2>&1 \ + && cat select.h2 || cat select.h1 ) > select.h + rm -f trysysel.o trysysel + +setup: \ +it man install conf-bin conf-man BIN MAN + ./install "`head -1 conf-bin`" < BIN + ./install "`head -1 conf-man`" < MAN + +sgetopt.o: \ +compile sgetopt.c substdio.h subfd.h sgetopt.h subgetopt.h + ./compile sgetopt.c + +sig.a: \ +makelib sig_block.o sig_catch.o sig_pause.o sig_dfl.o sig_pipe.o \ +sig_child.o sig_term.o + ./makelib sig.a sig_block.o sig_catch.o sig_pause.o \ + sig_dfl.o sig_pipe.o sig_child.o sig_term.o + +sig_block.o: \ +compile sig_block.c sig.h hassgprm.h + ./compile sig_block.c + +sig_catch.o: \ +compile sig_catch.c sig.h hassgact.h + ./compile sig_catch.c + +sig_child.o: \ +compile sig_child.c sig.h + ./compile sig_child.c + +sig_dfl.o: \ +compile sig_dfl.c sig.h hassgact.h hassgprm.h + ./compile sig_dfl.c + +sig_pause.o: \ +compile sig_pause.c sig.h hassgprm.h + ./compile sig_pause.c + +sig_pipe.o: \ +compile sig_pipe.c sig.h + ./compile sig_pipe.c + +sig_term.o: \ +compile sig_term.c sig.h + ./compile sig_term.c + +socket.lib: \ +trylsock.c compile load + ( ( ./compile trylsock.c && \ + ./load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \ + && echo -lsocket -lnsl || exit 0 ) > socket.lib + rm -f trylsock.o trylsock + +str.a: \ +makelib str_len.o str_diff.o str_diffn.o str_cpy.o byte_chr.o \ +byte_rchr.o byte_diff.o byte_copy.o byte_cr.o byte_zero.o + ./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \ + byte_chr.o byte_rchr.o byte_diff.o byte_copy.o byte_cr.o \ + byte_zero.o + +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 + +stralloc.a: \ +makelib stralloc_eady.o stralloc_pend.o stralloc_copy.o \ +stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o \ +stralloc_catb.o + ./makelib stralloc.a stralloc_eady.o stralloc_pend.o \ + stralloc_copy.o stralloc_opys.o stralloc_opyb.o \ + stralloc_cat.o stralloc_cats.o stralloc_catb.o + +stralloc_cat.o: \ +compile stralloc_cat.c byte.h stralloc.h gen_alloc.h + ./compile stralloc_cat.c + +stralloc_catb.o: \ +compile stralloc_catb.c stralloc.h gen_alloc.h byte.h + ./compile stralloc_catb.c + +stralloc_cats.o: \ +compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h + ./compile stralloc_cats.c + +stralloc_copy.o: \ +compile stralloc_copy.c byte.h stralloc.h gen_alloc.h + ./compile stralloc_copy.c + +stralloc_eady.o: \ +compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \ +gen_allocdefs.h + ./compile stralloc_eady.c + +stralloc_opyb.o: \ +compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h + ./compile stralloc_opyb.c + +stralloc_opys.o: \ +compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h + ./compile stralloc_opys.c + +stralloc_pend.o: \ +compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \ +gen_allocdefs.h + ./compile stralloc_pend.c + +strerr.a: \ +makelib strerr_sys.o strerr_die.o + ./makelib strerr.a strerr_sys.o strerr_die.o + +strerr_die.o: \ +compile strerr_die.c substdio.h subfd.h exit.h strerr.h + ./compile strerr_die.c + +strerr_sys.o: \ +compile strerr_sys.c error.h strerr.h + ./compile strerr_sys.c + +subfderr.o: \ +compile subfderr.c readwrite.h substdio.h subfd.h + ./compile subfderr.c + +subfdin.o: \ +compile subfdin.c readwrite.h substdio.h subfd.h + ./compile subfdin.c + +subfdout.o: \ +compile subfdout.c readwrite.h substdio.h subfd.h + ./compile subfdout.c + +subgetopt.o: \ +compile subgetopt.c subgetopt.h + ./compile subgetopt.c + +substdi.o: \ +compile substdi.c substdio.h byte.h error.h + ./compile substdi.c + +substdio.a: \ +makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \ +subfdin.o substdio_copy.o + ./makelib substdio.a substdio.o substdi.o substdo.o \ + subfderr.o subfdout.o subfdin.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 + +tcp-environ.0: \ +tcp-environ.5 + nroff -man tcp-environ.5 > tcp-environ.0 + +tcpcat: \ +warn-auto.sh tcpcat.sh conf-bin + cat warn-auto.sh tcpcat.sh \ + | sed s}BIN}"`head -1 conf-bin`"}g > tcpcat + chmod 755 tcpcat + +tcpclient: \ +load tcpclient.o ip.o ipalloc.o dns.o remoteinfo.o timeoutconn.o \ +timeoutread.o timeoutwrite.o stralloc.a env.a alloc.a ndelay.a \ +substdio.a error.a str.a sig.a fd.a case.a getopt.a fs.a dns.lib \ +socket.lib + ./load tcpclient ip.o ipalloc.o dns.o remoteinfo.o \ + timeoutconn.o timeoutread.o timeoutwrite.o stralloc.a env.a \ + alloc.a ndelay.a substdio.a error.a str.a sig.a fd.a case.a \ + getopt.a fs.a `cat dns.lib` `cat socket.lib` + +tcpclient.0: \ +tcpclient.1 + nroff -man tcpclient.1 > tcpclient.0 + +tcpclient.o: \ +compile tcpclient.c substdio.h stralloc.h gen_alloc.h str.h byte.h \ +error.h sig.h subfd.h fd.h ip.h ipalloc.h case.h sgetopt.h \ +subgetopt.h exit.h scan.h fmt.h env.h dns.h remoteinfo.h + ./compile tcpclient.c + +tcprules: \ +load tcprules.o cdbmss.o cdbmake.a getln.a strerr.a stralloc.a \ +substdio.a alloc.a error.a open.a seek.a str.a fs.a + ./load tcprules cdbmss.o cdbmake.a getln.a strerr.a \ + stralloc.a substdio.a alloc.a error.a open.a seek.a str.a \ + fs.a + +tcprules.0: \ +tcprules.1 + nroff -man tcprules.1 > tcprules.0 + +tcprules.o: \ +compile tcprules.c strerr.h stralloc.h gen_alloc.h getln.h substdio.h \ +subfd.h exit.h fmt.h byte.h cdbmss.h cdbmake.h uint32.h + ./compile tcprules.c + +tcpserver: \ +load tcpserver.o ip.o ipalloc.o dns.o remoteinfo.o timeoutconn.o \ +timeoutread.o timeoutwrite.o cdb.a open.a wait.a strerr.a stralloc.a \ +env.a ndelay.a alloc.a getopt.a substdio.a error.a str.a sig.a fd.a \ +case.a fs.a dns.lib socket.lib + ./load tcpserver ip.o ipalloc.o dns.o remoteinfo.o \ + timeoutconn.o timeoutread.o timeoutwrite.o cdb.a open.a \ + wait.a strerr.a stralloc.a env.a ndelay.a alloc.a getopt.a \ + substdio.a error.a str.a sig.a fd.a case.a fs.a `cat \ + dns.lib` `cat socket.lib` + +tcpserver.0: \ +tcpserver.1 + nroff -man tcpserver.1 > tcpserver.0 + +tcpserver.o: \ +compile tcpserver.c strerr.h substdio.h stralloc.h gen_alloc.h \ +alloc.h readwrite.h fd.h sig.h wait.h ip.h ipalloc.h dns.h str.h \ +case.h byte.h sgetopt.h subgetopt.h remoteinfo.h exit.h open.h scan.h \ +fmt.h env.h cdb.h uint32.h + ./compile tcpserver.c + +timeoutconn.o: \ +compile timeoutconn.c ndelay.h select.h error.h readwrite.h ip.h \ +byte.h timeoutconn.h + ./compile timeoutconn.c + +timeoutread.o: \ +compile timeoutread.c timeoutread.h select.h error.h readwrite.h + ./compile timeoutread.c + +timeoutwrite.o: \ +compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h + ./compile timeoutwrite.c + +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_nohang.o + ./makelib wait.a wait_nohang.o + +wait_nohang.o: \ +compile wait_nohang.c haswaitp.h + ./compile wait_nohang.c + +who@: \ +warn-auto.sh who@.sh conf-bin + cat warn-auto.sh who@.sh \ + | sed s}BIN}"`head -1 conf-bin`"}g > who@ + chmod 755 who@ @@ -0,0 +1,89 @@ +ucspi-tcp 0.80, beta. +19980118 +Copyright 1998 +D. J. Bernstein, djb@pobox.com + +tcpclient and tcpserver are easy-to-use command-line tools for building +TCP client-server applications. See BLURB for a more detailed +advertisement. + +You may distribute unmodified copies of the ucspi-tcp package. + +INSTALL says how to set up tcpclient and tcpserver. + +See http://pobox.com/~djb/ucspi-tcp.html for the latest information +about ucspi-tcp. See http://pobox.com/~djb/proto/ucspi.txt for general +information about UCSPI. + +The rest of this file is a list of systypes where various versions of +ucspi-tcp have been reported to work. 0.70 was the first beta version. + +0.73: aix-4-2-:-:-:000055247900-:- (tnx JLB) +0.73: bsd.os-2.0.1-:i386-:-:pentium-:- +0.73: bsd.os-2.1-:i386-:-:pentium-:- (tnx MPS) +0.73: bsd.os-3.0-:i386-:-:pentium-:- (tnx SN) +0.73: freebsd-2.1.0-release-:i386-:-:i486.dx2-:- (tnx NM) +0.73: freebsd-2.1.0-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MBS) +0.73: freebsd-2.2-970422-releng-:i386-:-:pentium-:- (tnx TM) +0.73: freebsd-2.2-970618-releng-:i386-:-:pentium-:- (tnx LST) +0.72: freebsd-2.2-release-:i386-:-:pentium-:- (tnx frank@news=???) +0.73: freebsd-2.2-stable-:i386-:-:pentium-:- (tnx JJE) +0.73: freebsd-2.2.1-release-:i386-:-:-:- (tnx TM) +0.73: freebsd-2.2.1-release-:i386-:-:pentium-:- (tnx RWL) +0.73: freebsd-2.2.2-release-:i386-:-:amd.unknown-:- (tnx FN) +0.73: freebsd-2.2.2-release-:i386-:-:pentium-:- (tnx BJR) +0.73: freebsd-2.2.5-release-:i386-:-:pentium.pro-:- (tnx AI) +0.73: freebsd-3.0-971012-snap-:i386-:-:i486.dx2-:- (tnx AY) +0.72: freebsd-3.0-current-:i386-:-:pentium-:- (tnx black@shadow=???) +0.72: hp-ux-b.09.00-a-:-:-:9000.360-:- (tnx VV) +0.72: hp-ux-b.10.01-a-:-:-:9000.715-:- (tnx BG) +0.72: irix-5.3-11091812-:-:-:ip22-:- (tnx PW) +0.73: irix-6.2-03131015-:-:-:ip22-:- (tnx JL) +0.72: linux-1.2.13-:i386-:-:i486-:- (tnx JDM) +0.73: linux-2.0.18-:i386-:-:pentium-:- (tnx JDM) +0.72: linux-2.0.21-:i386-:-:pentium-:- (tnx SJ) +0.72: linux-2.0.23-:i386-:-:i486-:- (tnx J2W) +0.72: linux-2.0.24-:i386-:-:pentium-:- (tnx VV) +0.72: linux-2.0.25-:i386-:-:i486-:- (tnx FPL) +0.73: linux-2.0.25-:i386-:-:pentium-:- (tnx AW) +0.72: linux-2.0.26-:i386-:-:pentium-:- (tnx root@pointer=???) +0.73: linux-2.0.27-:i386-:-:ppro-:- (tnx PMK) +0.73: linux-2.0.28-:alpha-:-:alpha-:- (tnx T2K) +0.73: linux-2.0.29-:i386-:-:i486-:- (tnx keith@gadget=???) +0.73: linux-2.0.29-:i386-:-:pentium-:- (tnx RAL) +0.73: linux-2.0.29-:i386-:-:ppro-:- (tnx GDP) +0.73: linux-2.0.30-:-:-:sparc-:- (tnx DJ) +0.73: linux-2.0.30-:i386-:-:i386-:- (tnx DMV) +0.73: linux-2.0.30-:i386-:-:pentium-:- (tnx AV) +0.73: linux-2.0.32-:i386-:-:pentium-:- (tnx AS) +0.73: linux-2.0.7-:i386-:-:i486-:- (tnx TLM) +0.73: linux-2.1.30-:i386-:-:pentium-:- (tnx RAS) +0.73: linux-2.1.36-:i386-:-:pentium-:- (tnx JF) +0.73: netbsd-1.1-:i386-:-:pentium.(genuineintel.586-class.cpu)-:- (tnx GL) +0.73: netbsd-1.3_alpha-:i386-:-:intel.pentium.(p54c).(586-class)-:- (tnx GL) +0.73: nextstep-3.3-:mc680x0-:-:68040-:- (tnx WEB) +0.73: osf1-v3.2-214-:-:-:alpha-:- (tnx A2P) +0.73: osf1-v4.0-564-:-:-:alpha-:- (tnx A2P) +0.73: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4c-:sun4c- (tnx MBS) +0.73: sunos-4.1.3_u1-4-:unknown-:sun4-:sun4m-:sun4m- (tnx J2B) +0.73: sunos-4.1.4-2-:sparc-:sun4-:sun4m-:sun4m- +0.73: sunos-5.4-generic-:sparc-:sun4-:sun4m-:sun4m- +0.72: sunos-5.4-generic_101945-32-:sparc-:sun4-:sun4m-:sun4m- (tnx RDM) +0.73: sunos-5.5-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx PW) +0.72: sunos-5.5-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx CG) +0.73: sunos-5.5-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx RDM) +0.72: sunos-5.5-generic-:sparc-:sun4-:sun4u-:sun4u- (tnx SAC) +0.72: sunos-5.5-generic_103094-03-:i386-:i86pc-:i86pc-:i86pc- (tnx root@utahdining=???) +0.73: sunos-5.5-generic_103094-07-:i386-:i86pc-:i86pc-:i86pc- (tnx MAZ) +0.73: sunos-5.5.1-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx CG) +0.73: sunos-5.5.1-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx MBS) +0.73: sunos-5.5.1-generic_103640-03-:sparc-:sun4-:sun4m-:sun4m- (tnx DPS) +0.72: sunos-5.5.1-generic_103640-03-:sparc-:sun4-:sun4u-:sun4u- (tnx root@adrastea=???) +0.73: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4m-:sun4m- (tnx RA) +0.72: sunos-5.5.1-generic_patch-:i386-:i86pc-:i86pc-:i86pc- (tnx D2K) +0.73: sunos-5.5.1-iss_1.0-:sparc-:sun4-:sun4u-:sun4u- (tnx LST) +0.73: sunos-5.6-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx DS) +0.73: sunos-5.6-generic-:sparc-:sun4-:sun4u-:sun4u- (tnx DV) +0.73: ultrix-4.3-0-:-:-:risc-:- (tnx bruno@cerberus=???) +0.73: unix_sv-4.2mp-2.03-:i386-:-:i386-:- (tnx HP) +0.73: unix_sv-4.2mp-2.1.2-:i386-:-:i386-:- (tnx RN) @@ -0,0 +1,9 @@ +VERSION +systype +hassgact.h +hassgprm.h +haswaitp.h +select.h +dns.lib +socket.lib +uint32.h @@ -0,0 +1,133 @@ +auto-ccld.sh +make-load +find-systype +systype +load +make-compile +compile +tcpclient.o +ip.o +ipalloc.o +dns.o +remoteinfo.o +select.h +timeoutconn.o +timeoutread.o +timeoutwrite.o +make-makelib +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.a +env.o +envread.o +env.a +alloc.o +alloc_re.o +alloc.a +ndelay.o +ndelay_off.o +ndelay.a +substdio.o +substdi.o +substdo.o +subfderr.o +subfdout.o +subfdin.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 +byte_chr.o +byte_rchr.o +byte_diff.o +byte_copy.o +byte_cr.o +byte_zero.o +str.a +hassgprm.h +sig_block.o +hassgact.h +sig_catch.o +sig_pause.o +sig_dfl.o +sig_pipe.o +sig_child.o +sig_term.o +sig.a +fd_copy.o +fd_move.o +fd.a +case_lowers.o +case.a +subgetopt.o +sgetopt.o +getopt.a +fmt_str.o +fmt_ulong.o +scan_ulong.o +scan_8long.o +fs.a +socket.lib +dns.lib +tcpclient +uint32.h +tcpserver.o +cdb_hash.o +cdb_unpack.o +cdb_seek.o +cdb.a +open_read.o +open_trunc.o +open.a +haswaitp.h +wait_nohang.o +wait.a +strerr_sys.o +strerr_die.o +strerr.a +tcpserver +tcprules.o +cdbmss.o +cdbmake_pack.o +cdbmake_hash.o +cdbmake_add.o +cdbmake.a +getln.o +getln2.o +getln.a +seek_cur.o +seek_end.o +seek_set.o +seek_trunc.o +seek.a +tcprules +who@ +date@ +finger@ +tcpcat +mconnect +addcr.o +addcr +delcr.o +delcr +it +tcpclient.0 +tcpserver.0 +tcprules.0 +tcp-environ.0 +man +install.o +install +setup @@ -0,0 +1,45 @@ +TCP UCSPI protocol definition +Copyright 1996 +D. J. Bernstein, djb@pobox.com + + +This document defines the TCP protocol for UCSPI-1996 tools. A TCP +client communicates with a TCP server, on the same machine or on a +different machine, via the TCP/IP protocol through an Internet-domain +socket. The descriptors passed to a TCP UCSPI application are copies of +that socket, dup()ed from a single connect() or accept(). + +[address] consists of two arguments: [hostname] [port]. + +There are three possibilities for [hostname]: the number 0, referring to +the local host; a dotted-decimal IP address, such as 192.48.96.5; or a +name understood by the system's resolver, such as mail.uu.net. TCP UCSPI +servers use only the first IP address from the resolver; TCP UCSPI +clients try each address in turn. + +There are three possibilities for [port]: a positive numeric TCP port +number, such as 25; the number 0, which permits selection of any port +number; or a name understood by the system's getservbyname(), such as +smtp. + +The client and server set up the following environment variables: + + PROTO: the string TCP + TCPLOCALIP: the dotted-decimal IP address of the local host + TCPLOCALPORT: the local TCP port number, in decimal + TCPREMOTEIP: the dotted-decimal IP address of the remote host + TCPREMOTEPORT: the remote TCP port number, in decimal + TCPLOCALHOST, if possible: the resolver's name for TCPLOCALIP + TCPREMOTEHOST, if possible: the resolver's name for TCPREMOTEIP + TCPREMOTEINFO, if possible: the result of a 931/1413/IDENT/TAP query + +Uppercase letters in TCPLOCALHOST and TCPREMOTEHOST are converted to +lowercase. TCPREMOTEINFO is a connection-specific string supplied by the +remote host via 931/1413/IDENT/TAP. + +TCP UCSPI tools take a -R option to turn off 931/1413/IDENT/TAP +querying, and a -r option to turn it back on. TCP UCSPI clients take a +-p [locport] option to require a particular TCP port on the local side +of the connection. TCP UCSPI servers take a -1 option to print the local +port number (in decimal, followed by a newline) to descriptor 1 before +closing descriptor 1 and after preparing to receive connections. @@ -0,0 +1,62 @@ +Thanks to various people for bug reports and other comments on various +versions of tcpclient, tcpserver, and tcpcontrol: + +RA = Russ Allbery +J2B = Jos Backus +JLB = Julie L. Baumler +HB = Harald Barth +WEB = William E. Baxter +DEB = Donald E. Blais +SAC = Shawn A. Clifford +JJE = Joshua J. Ellis +JF = Janos Farkas +CG = Chris Garrigues +BG = Bert Gijsbers +TG = Tim Goodwin +J2H = Jeff Hayward +J1H = Johan Holmberg +AI = Akihiro Iijima +DJ = Dirk Jaeckel +SJ = Sudish Joseph +PMK = Patrick M. Kane +D2K = Dax Kelson +T2K = Thomas Kuerten +GL = Giles Lean +KL = Karl Lehenbauer +FPL = Frederik P. Lindberg +SML = Stefan M. Linnemann +JL = Jim Littlefield +RWL = Robert W. Luce +RAL = Roberto A. Lumbreras +TM = Toshinori Maeno +TLM = Timothy L. Mayo +RDM = Raul D. Miller +JDM = John D. Mitchell +NM = Nobuhiro Murata +FN = Faried Nawaz +RN = Russell Nelson +SN = Stan Norton +A2P = Andrea Paolini +HP = Hitesh Patel +GDP = Greg D. Patterson +EAP = Eric A. Perlman +BJR = Brian J. Reichert +M1S = Michael Salmon +MBS = Mike Scher +AS = Amos Shapira +DS = Dave Sill +MPS = Matt P. Simerson +DPS = David P. Smith +RAS = Richard A. Soderberg +LST = Louis S. Theran +VV = Vince Vielhaber +DV = Dirk Vluegels +DMV = Dan M. Vogel +AV = Alex Vostrikov +EW = Erik Wallin +CW = Christian Wettergren +AW = Arne Wichmann +PW = Peter Wilkinson +J2W = Jeremy Wohl +AY = Araki Yasuhiro +MAZ = Matthew A. Zahorik @@ -0,0 +1,3 @@ +use strerr in tcpclient +maybe include multitee in package +include more clients @@ -0,0 +1,131 @@ +UNIX Client-Server Program Interface, UCSPI-1996 +Copyright 1996 +D. J. Bernstein, djb@pobox.com + + +1. Introduction + +This document describes the UNIX Client-Server Program Interface, UCSPI +(ooks-pie), a command-line interface to client-server communications +tools. + +UCSPI provides several benefits. First, the UCSPI interface is +independent of the underlying communications medium; UCSPI applications +don't even have to be recompiled as the Internet upgrades from IPv4 to +IPv6. Second, UCSPI lets shell scripts take advantage of networking. +Third, UCSPI clients and servers conventionally set up environment +variables that display the local and remote addresses, so the +information is readily available to applications and users. + +Here is the general UCSPI framework. An UCSPI tool is a program that +understands how to talk to some communications medium. It sets up two +descriptors and then invokes an UCSPI application, which can read from +one descriptor and write to the other. Every communications medium +provides reliable two-way full-duplex strictly ordered not necessarily +timed stream communication. Some media may provide other types of +communication, such as expedited (``out-of-band'') transmission, in +which the stream is no longer ordered, but most UCSPI applications are +medium-independent and do not rely on such features. + + +2. Tools + +UCSPI tools are executable programs. They accept command lines in the +following general format: + + [tool] [options] [address] [application] + +Here [tool] is the name of the tool, [options] are zero or more option +arguments, [address] is a protocol-specific address, and [application] +is a user-specified program to run for each connection. + +[options] are processed by the getopt standard; thus an argument of -- +terminates [options]. [tool] supports three options to control how +much information it prints to stderr: + + -v all available messages + -Q all available error messages; no messages in case of success + -q no messages in any case + +The default is -Q; later arguments override earlier arguments. [tool] +may support many further options. + +[application] consists of one or more arguments, handled by the +conventions of execvp(). [tool] passes on all [application] arguments +without change, no matter what characters appear in those arguments. + +[tool] always changes certain file descriptors, as described in section +3, and environment variables, as described in section 4, before +executing [application]. + +[tool] might fork before executing [application], and it might reset +some signals that were previously ignored. Other than this, [tool] does +not change its process state before executing [application]. + +[tool] does not assume that any particular descriptors are open or +closed upon entry. [tool] does not force itself into the background; nor +does it attempt to detach from a controlling terminal. + +If [tool] cannot perform its functions, it exits with a nonzero code. + + +3. Clients and servers + +There are two types of UCSPI tools: clients and servers. + +An UCSPI client closes descriptors 6 and 7 and connects to a server at +[address]. Upon connecting, it spawns [application] with descriptor 6 +reading from the connection and descriptor 7 writing to the connection. +The client does not make any further connections. When [application] +dies, the client dies; the client exits with a zero code if and only if +[application] exited with a zero code. + +An UCSPI server closes descriptors 0 and 1 and waits for a client to +connect to [address]. Upon accepting a connection, it spawns +[application] with descriptor 0 reading from the connection and +descriptor 1 writing to the connection. Meanwhile, and subsequently, it +continues accepting connections to [address]. If the server receives +signal SIGTERM, it exits with code 0; this does not affect any current +connections. + + +4. Protocols + +Each UCSPI tool supports a protocol. A protocol definition provides +three pieces of information: the name of the protocol; the format and +meaning of [address]; and the environment variables set up by the tool. + +A protocol name is a sequence of one or more alphanumeric characters. +See section 5 for information about the allocation of protocol names. + +A protocol definition always states the number of arguments taken by +[address] and the allowed form for each argument. It also states an +underlying communications medium to be used by the tool, and gives the +interpretation of [address] in terms of that medium. + +Each tool passes the following environment variables to [application]: +PROTO=[PROTO], the name of the supported protocol; zero or more +variables beginning with [PROTO]LOCAL, as stated in the protocol +definition; and zero or more variables beginning with [PROTO]REMOTE, as +stated in the protocol definition. For clients, [PROTO]LOCAL variables +give information about the client, and [PROTO]REMOTE variables give +information about the server; vice versa for servers. + +Protocol definitions may specify environment variables that, in some +situations, are not set. Those variables might be set upon entry to an +UCSPI tool; if so, they must be unset, not passed along. + +A protocol definition may impose further requirements on clients and +servers, such as supported options, forking behavior, and the nature of +the descriptors passed to [application]. + + +5. Protocol management + +Public protocol definitions may be registered with me. I may refuse a +registration request on the grounds of a namespace problem, but in that +case I will suggest an acceptable replacement name. + +Protocol names beginning with x will be parcelled out to organizations +that would like to define their own protocols. Protocol names beginning +with X are reserved for experimental use. @@ -0,0 +1 @@ +ucspi-tcp 0.80 @@ -0,0 +1,23 @@ +#include "substdio.h" +#include "subfd.h" +#include "exit.h" + +void main() +{ + register int n; + register char *x; + char ch; + + for (;;) { + n = substdio_feed(subfdin); + if (n < 0) _exit(111); + if (!n) _exit(0); + x = substdio_PEEK(subfdin); + substdio_SEEK(subfdin,n); + while (n > 0) { + ch = *x++; --n; + if (ch == '\n') substdio_BPUTC(subfdout,"\r"[0]); + substdio_BPUTC(subfdout,ch); + } + } +} @@ -0,0 +1,3 @@ +substdio.a +error.a +str.a @@ -0,0 +1,32 @@ +#include "alloc.h" +#include "error.h" +extern char *malloc(); +extern void free(); + +#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ +#define SPACE 4096 /* must be multiple of ALIGNMENT */ + +typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; +static aligned realspace[SPACE / ALIGNMENT]; +#define space ((char *) realspace) +static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ + +/*@null@*//*@out@*/char *alloc(n) +unsigned int n; +{ + char *x; + n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ + if (n <= avail) { avail -= n; return space + avail; } + x = malloc(n); + if (!x) errno = error_nomem; + return x; +} + +void alloc_free(x) +char *x; +{ + if (x >= space) + if (x < space + SPACE) + return; /* XXX: assuming that pointers are flat */ + free(x); +} @@ -0,0 +1,8 @@ +#ifndef ALLOC_H +#define ALLOC_H + +extern /*@null@*//*@out@*/char *alloc(); +extern void alloc_free(); +extern int alloc_re(); + +#endif @@ -0,0 +1,2 @@ +alloc.o +alloc_re.o diff --git a/alloc_re.c b/alloc_re.c new file mode 100644 index 0000000..feb8b49 --- /dev/null +++ b/alloc_re.c @@ -0,0 +1,17 @@ +#include "alloc.h" +#include "byte.h" + +int alloc_re(x,m,n) +char **x; +unsigned int m; +unsigned int n; +{ + char *y; + + y = alloc(n); + if (!y) return 0; + byte_copy(y,m,*x); + alloc_free(*x); + *x = y; + return 1; +} diff --git a/auto-str.c b/auto-str.c new file mode 100644 index 0000000..acc3d60 --- /dev/null +++ b/auto-str.c @@ -0,0 +1,44 @@ +#include "substdio.h" +#include "readwrite.h" +#include "exit.h" + +char buf1[256]; +substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); + +void puts(s) +char *s; +{ + if (substdio_puts(&ss1,s) == -1) _exit(111); +} + +void main(argc,argv) +int argc; +char **argv; +{ + char *name; + char *value; + unsigned char ch; + char octal[4]; + + name = argv[1]; + if (!name) _exit(100); + value = argv[2]; + if (!value) _exit(100); + + puts("char "); + puts(name); + puts("[] = \"\\\n"); + + while (ch = *value++) { + puts("\\"); + octal[3] = 0; + octal[2] = '0' + (ch & 7); ch >>= 3; + octal[1] = '0' + (ch & 7); ch >>= 3; + octal[0] = '0' + (ch & 7); + puts(octal); + } + + puts("\\\n\";\n"); + if (substdio_flush(&ss1) == -1) _exit(111); + _exit(0); +} diff --git a/auto-str=x b/auto-str=x new file mode 100644 index 0000000..f3e9229 --- /dev/null +++ b/auto-str=x @@ -0,0 +1,3 @@ +substdio.a +error.a +str.a @@ -0,0 +1,13 @@ +#ifndef BYTE_H +#define BYTE_H + +extern unsigned int byte_chr(); +extern unsigned int byte_rchr(); +extern void byte_copy(); +extern void byte_copyr(); +extern int byte_diff(); +extern void byte_zero(); + +#define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) + +#endif diff --git a/byte_chr.c b/byte_chr.c new file mode 100644 index 0000000..f81dde8 --- /dev/null +++ b/byte_chr.c @@ -0,0 +1,20 @@ +#include "byte.h" + +unsigned int byte_chr(s,n,c) +char *s; +register unsigned int n; +int c; +{ + register char ch; + register char *t; + + ch = c; + t = s; + for (;;) { + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + } + return t - s; +} diff --git a/byte_copy.c b/byte_copy.c new file mode 100644 index 0000000..eaad11b --- /dev/null +++ b/byte_copy.c @@ -0,0 +1,14 @@ +#include "byte.h" + +void byte_copy(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + for (;;) { + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + } +} diff --git a/byte_cr.c b/byte_cr.c new file mode 100644 index 0000000..3e7a1d5 --- /dev/null +++ b/byte_cr.c @@ -0,0 +1,16 @@ +#include "byte.h" + +void byte_copyr(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + to += n; + from += n; + for (;;) { + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + } +} diff --git a/byte_diff.c b/byte_diff.c new file mode 100644 index 0000000..cdbd760 --- /dev/null +++ b/byte_diff.c @@ -0,0 +1,16 @@ +#include "byte.h" + +int byte_diff(s,n,t) +register char *s; +register unsigned int n; +register char *t; +{ + for (;;) { + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + } + return ((int)(unsigned int)(unsigned char) *s) + - ((int)(unsigned int)(unsigned char) *t); +} diff --git a/byte_rchr.c b/byte_rchr.c new file mode 100644 index 0000000..476bc22 --- /dev/null +++ b/byte_rchr.c @@ -0,0 +1,23 @@ +#include "byte.h" + +unsigned int byte_rchr(s,n,c) +char *s; +register unsigned int n; +int c; +{ + register char ch; + register char *t; + register char *u; + + ch = c; + t = s; + u = 0; + for (;;) { + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + } + if (!u) u = t; + return u - s; +} diff --git a/byte_zero.c b/byte_zero.c new file mode 100644 index 0000000..92009ba --- /dev/null +++ b/byte_zero.c @@ -0,0 +1,13 @@ +#include "byte.h" + +void byte_zero(s,n) +char *s; +register unsigned int n; +{ + for (;;) { + if (!n) break; *s++ = 0; --n; + if (!n) break; *s++ = 0; --n; + if (!n) break; *s++ = 0; --n; + if (!n) break; *s++ = 0; --n; + } +} @@ -0,0 +1,13 @@ +#ifndef CASE_H +#define CASE_H + +extern void case_lowers(); +extern void case_lowerb(); +extern int case_diffs(); +extern int case_diffb(); +extern int case_starts(); +extern int case_startb(); + +#define case_equals(s,t) (!case_diffs((s),(t))) + +#endif @@ -0,0 +1 @@ +case_lowers.o diff --git a/case_lowers.c b/case_lowers.c new file mode 100644 index 0000000..208b3f5 --- /dev/null +++ b/case_lowers.c @@ -0,0 +1,12 @@ +#include "case.h" + +void case_lowers(s) +char *s; +{ + unsigned char x; + while (x = *s) { + x -= 'A'; + if (x <= 'Z' - 'A') *s = x + 'a'; + ++s; + } +} @@ -0,0 +1,12 @@ +#ifndef CDB_H +#define CDB_H + +#include "uint32.h" + +extern uint32 cdb_hash(); +extern uint32 cdb_unpack(); + +extern int cdb_bread(); +extern int cdb_seek(); + +#endif @@ -0,0 +1,3 @@ +cdb_hash.o +cdb_unpack.o +cdb_seek.o diff --git a/cdb_hash.c b/cdb_hash.c new file mode 100644 index 0000000..8238020 --- /dev/null +++ b/cdb_hash.c @@ -0,0 +1,16 @@ +#include "cdb.h" + +uint32 cdb_hash(buf,len) +unsigned char *buf; +unsigned int len; +{ + uint32 h; + + h = 5381; + while (len) { + --len; + h += (h << 5); + h ^= (uint32) *buf++; + } + return h; +} diff --git a/cdb_seek.c b/cdb_seek.c new file mode 100644 index 0000000..87ab614 --- /dev/null +++ b/cdb_seek.c @@ -0,0 +1,95 @@ +#include <sys/types.h> +#include <errno.h> +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; +} diff --git a/cdb_unpack.c b/cdb_unpack.c new file mode 100644 index 0000000..c882202 --- /dev/null +++ b/cdb_unpack.c @@ -0,0 +1,12 @@ +#include "cdb.h" + +uint32 cdb_unpack(buf) +unsigned char *buf; +{ + uint32 num; + num = buf[3]; num <<= 8; + num += buf[2]; num <<= 8; + num += buf[1]; num <<= 8; + num += buf[0]; + return num; +} diff --git a/cdbmake.h b/cdbmake.h new file mode 100644 index 0000000..883a231 --- /dev/null +++ b/cdbmake.h @@ -0,0 +1,35 @@ +#ifndef CDBMAKE_H +#define CDBMAKE_H + +#include "uint32.h" + +#define CDBMAKE_HPLIST 1000 + +struct cdbmake_hp { uint32 h; uint32 p; } ; + +struct cdbmake_hplist { + struct cdbmake_hp hp[CDBMAKE_HPLIST]; + struct cdbmake_hplist *next; + int num; +} ; + +struct cdbmake { + char final[2048]; + uint32 count[256]; + uint32 start[256]; + struct cdbmake_hplist *head; + struct cdbmake_hp *split; /* includes space for hash */ + struct cdbmake_hp *hash; + uint32 numentries; +} ; + +extern void cdbmake_pack(); +#define CDBMAKE_HASHSTART ((uint32) 5381) +extern uint32 cdbmake_hashadd(); + +extern void cdbmake_init(); +extern int cdbmake_add(); +extern int cdbmake_split(); +extern uint32 cdbmake_throw(); + +#endif diff --git a/cdbmake=l b/cdbmake=l new file mode 100644 index 0000000..5747fb0 --- /dev/null +++ b/cdbmake=l @@ -0,0 +1,3 @@ +cdbmake_pack.o +cdbmake_hash.o +cdbmake_add.o diff --git a/cdbmake_add.c b/cdbmake_add.c new file mode 100644 index 0000000..115f828 --- /dev/null +++ b/cdbmake_add.c @@ -0,0 +1,117 @@ +#include "cdbmake.h" + +void cdbmake_init(cdbm) +struct cdbmake *cdbm; +{ + cdbm->head = 0; + cdbm->split = 0; + cdbm->hash = 0; + cdbm->numentries = 0; +} + +int cdbmake_add(cdbm,h,p,alloc) +struct cdbmake *cdbm; +uint32 h; +uint32 p; +char *(*alloc)(); +{ + struct cdbmake_hplist *head; + + head = cdbm->head; + if (!head || (head->num >= CDBMAKE_HPLIST)) { + head = (struct cdbmake_hplist *) alloc(sizeof(struct cdbmake_hplist)); + if (!head) return 0; + head->num = 0; + head->next = cdbm->head; + cdbm->head = head; + } + head->hp[head->num].h = h; + head->hp[head->num].p = p; + ++head->num; + ++cdbm->numentries; + return 1; +} + +int cdbmake_split(cdbm,alloc) +struct cdbmake *cdbm; +char *(*alloc)(); +{ + int i; + uint32 u; + uint32 memsize; + struct cdbmake_hplist *x; + + for (i = 0;i < 256;++i) + cdbm->count[i] = 0; + + for (x = cdbm->head;x;x = x->next) { + i = x->num; + while (i--) + ++cdbm->count[255 & x->hp[i].h]; + } + + memsize = 1; + for (i = 0;i < 256;++i) { + u = cdbm->count[i] * 2; + if (u > memsize) + memsize = u; + } + + memsize += cdbm->numentries; /* no overflow possible up to now */ + u = (uint32) 0 - (uint32) 1; + u /= sizeof(struct cdbmake_hp); + if (memsize > u) return 0; + + cdbm->split = (struct cdbmake_hp *) alloc(memsize * sizeof(struct cdbmake_hp)); + if (!cdbm->split) return 0; + + cdbm->hash = cdbm->split + cdbm->numentries; + + u = 0; + for (i = 0;i < 256;++i) { + u += cdbm->count[i]; /* bounded by numentries, so no overflow */ + cdbm->start[i] = u; + } + + for (x = cdbm->head;x;x = x->next) { + i = x->num; + while (i--) + cdbm->split[--cdbm->start[255 & x->hp[i].h]] = x->hp[i]; + } + + return 1; +} + +uint32 cdbmake_throw(cdbm,pos,b) +struct cdbmake *cdbm; +uint32 pos; +int b; +{ + uint32 len; + uint32 j; + uint32 count; + struct cdbmake_hp *hp; + uint32 where; + + count = cdbm->count[b]; + + len = count + count; /* no overflow possible */ + cdbmake_pack(cdbm->final + 8 * b,pos); + cdbmake_pack(cdbm->final + 8 * b + 4,len); + + if (len) { + for (j = 0;j < len;++j) + cdbm->hash[j].h = cdbm->hash[j].p = 0; + + hp = cdbm->split + cdbm->start[b]; + for (j = 0;j < count;++j) { + where = (hp->h >> 8) % len; + while (cdbm->hash[where].p) + if (++where == len) + where = 0; + cdbm->hash[where] = *hp++; + } + } + + return len; +} diff --git a/cdbmake_hash.c b/cdbmake_hash.c new file mode 100644 index 0000000..f9dc3e5 --- /dev/null +++ b/cdbmake_hash.c @@ -0,0 +1,10 @@ +#include "cdbmake.h" + +uint32 cdbmake_hashadd(h,c) +uint32 h; +unsigned int c; +{ + h += (h << 5); + h ^= (uint32) (unsigned char) c; + return h; +} diff --git a/cdbmake_pack.c b/cdbmake_pack.c new file mode 100644 index 0000000..04b5f5b --- /dev/null +++ b/cdbmake_pack.c @@ -0,0 +1,11 @@ +#include "cdbmake.h" + +void cdbmake_pack(buf,num) +unsigned char *buf; +uint32 num; +{ + *buf++ = num; num >>= 8; + *buf++ = num; num >>= 8; + *buf++ = num; num >>= 8; + *buf = num; +} diff --git a/cdbmss.c b/cdbmss.c new file mode 100644 index 0000000..2d8f367 --- /dev/null +++ b/cdbmss.c @@ -0,0 +1,65 @@ +#include "readwrite.h" +#include "seek.h" +#include "alloc.h" +#include "cdbmss.h" + +int cdbmss_start(c,fd) +struct cdbmss *c; +int fd; +{ + cdbmake_init(&c->cdbm); + c->fd = fd; + c->pos = sizeof(c->cdbm.final); + substdio_fdbuf(&c->ss,write,fd,c->ssbuf,sizeof(c->ssbuf)); + return seek_set(fd,(seek_pos) c->pos); +} + +int cdbmss_add(c,key,keylen,data,datalen) +struct cdbmss *c; +unsigned char *key; +unsigned int keylen; +unsigned char *data; +unsigned int datalen; +{ + uint32 h; + int i; + + cdbmake_pack(c->packbuf,(uint32) keylen); + cdbmake_pack(c->packbuf + 4,(uint32) datalen); + if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1; + if (substdio_put(&c->ss,key,keylen) == -1) return -1; + if (substdio_put(&c->ss,data,datalen) == -1) return -1; + + h = CDBMAKE_HASHSTART; + for (i = 0;i < keylen;++i) + h = cdbmake_hashadd(h,(unsigned int) key[i]); + + if (!cdbmake_add(&c->cdbm,h,c->pos,alloc)) return -1; + + c->pos += 8 + keylen + datalen; /* XXX: overflow? */ + return 0; +} + +int cdbmss_finish(c) +struct cdbmss *c; +{ + int i; + uint32 len; + uint32 u; + + if (!cdbmake_split(&c->cdbm,alloc)) return -1; + + for (i = 0;i < 256;++i) { + len = cdbmake_throw(&c->cdbm,c->pos,i); + for (u = 0;u < len;++u) { + cdbmake_pack(c->packbuf,c->cdbm.hash[u].h); + cdbmake_pack(c->packbuf + 4,c->cdbm.hash[u].p); + if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1; + c->pos += 8; /* XXX: overflow? */ + } + } + + if (substdio_flush(&c->ss) == -1) return -1; + if (seek_begin(c->fd) == -1) return -1; + return substdio_putflush(&c->ss,c->cdbm.final,sizeof(c->cdbm.final)); +} diff --git a/cdbmss.h b/cdbmss.h new file mode 100644 index 0000000..5e6bdf4 --- /dev/null +++ b/cdbmss.h @@ -0,0 +1,16 @@ +#ifndef CDBMSS_H +#define CDBMSS_H + +#include "cdbmake.h" +#include "substdio.h" + +struct cdbmss { + char ssbuf[1024]; + struct cdbmake cdbm; + substdio ss; + char packbuf[8]; + uint32 pos; + int fd; +} ; + +#endif diff --git a/conf-bin b/conf-bin new file mode 100644 index 0000000..d1fe68e --- /dev/null +++ b/conf-bin @@ -0,0 +1,3 @@ +/usr/local/bin + +Programs will be installed in this directory. @@ -0,0 +1,3 @@ +cc -O2 + +This will be used to compile .c files. @@ -0,0 +1,3 @@ +cc -s + +This will be used to link .o files into an executable. diff --git a/conf-man b/conf-man new file mode 100644 index 0000000..b4e70a4 --- /dev/null +++ b/conf-man @@ -0,0 +1,5 @@ +/usr/local/man + +Man pages will be installed in subdirectories of this directory. An +unformatted man page foo.1 will go into .../man1/foo.1; a formatted man +page foo.0 will go into .../cat1/foo.0. diff --git a/date@.sh b/date@.sh new file mode 100644 index 0000000..80bfe5d --- /dev/null +++ b/date@.sh @@ -0,0 +1 @@ +BIN/tcpclient -RHl0 -- "${1-0}" 13 sh -c 'exec BIN/delcr <&6' | cat -v diff --git a/default.0.do b/default.0.do new file mode 100644 index 0000000..e40b50c --- /dev/null +++ b/default.0.do @@ -0,0 +1,9 @@ +if test -r "$2=0" +then + dependon "$2=0" + dependon `cat "$2=0"` + nroff -man `cat "$2=0"` + formake nroff -man `cat "$2=0"` '>' $1 +else + nosuchtarget +fi diff --git a/default.a.do b/default.a.do new file mode 100644 index 0000000..b61fc5c --- /dev/null +++ b/default.a.do @@ -0,0 +1,10 @@ +if test -r "$2=l" +then + dependon "$2=l" + dependon makelib `cat "$2=l"` + directtarget + formake ./makelib $1 `cat "$2=l"` + ./makelib $1 `cat "$2=l"` +else + nosuchtarget +fi diff --git a/default.do b/default.do new file mode 100644 index 0000000..6fe9f16 --- /dev/null +++ b/default.do @@ -0,0 +1,77 @@ +if test -r $1=x +then + dependon $1=x + libs=`grep '\.lib *$' "$1=x"` + libscat='' + for i in $libs + do + libscat="$libscat "'`'"cat $i"'`' + done + objs=`grep -v '\.lib *$' "$1=x"` + dependon load $1.o $objs $libs + directtarget + formake ./load $1 $objs "$libscat" + eval ./load $1 $objs $libscat + exit 0 +fi + +if test -r $1=s +then + dependon $1=s warn-auto.sh $1.sh conf-bin + formake cat warn-auto.sh $1.sh '\' + formake '| sed s}BIN}"`head -1 conf-bin`"}g >' $1 + formake chmod 755 $1 + cat warn-auto.sh $1.sh | sed s}BIN}"`head -1 conf-bin`"}g + chmod 755 $3 + exit 0 +fi + +case "$1" in + shar) + dependon FILES `cat FILES` + formake 'shar -m `cat FILES` > shar' + formake 'chmod 400 shar' + shar -m `cat FILES` + chmod 400 $3 + ;; + compile|load|makelib) + dependon make-$1 warn-auto.sh systype + formake "( cat warn-auto.sh; ./make-$1 "'"`cat systype`"'" ) > $1" + formake "chmod 755 $1" + cat warn-auto.sh + ./make-$1 "`cat systype`" + chmod 755 $3 + ;; + make-compile|make-load|make-makelib) + dependon $1.sh auto-ccld.sh + formake "cat auto-ccld.sh $1.sh > $1" + formake "chmod 755 $1" + cat auto-ccld.sh $1.sh + chmod 755 $3 + ;; + systype) + dependon find-systype trycpp.c + formake './find-systype > systype' + ./find-systype + ;; + find-systype) + dependon find-systype.sh auto-ccld.sh + formake 'cat auto-ccld.sh find-systype.sh > find-systype' + formake 'chmod 755 find-systype' + cat auto-ccld.sh find-systype.sh + chmod 755 $3 + ;; + auto-ccld.sh) + dependon conf-cc conf-ld warn-auto.sh + formake '( cat warn-auto.sh; \' + formake 'echo CC=\'\''`head -1 conf-cc`\'\''; \' + formake 'echo LD=\'\''`head -1 conf-ld`\'\'' \' + formake ') > auto-ccld.sh' + cat warn-auto.sh + echo CC=\'`head -1 conf-cc`\' + echo LD=\'`head -1 conf-ld`\' + ;; + *) + nosuchtarget + ;; +esac diff --git a/default.o.do b/default.o.do new file mode 100644 index 0000000..5d5ee1e --- /dev/null +++ b/default.o.do @@ -0,0 +1,15 @@ +if test -r $2=m +then + dependon $2=m $2.s + directtarget + as -o $1 $2.s + formake as -o $1 $2.s + exit 0 +fi +depend -$2=m + +directtarget +dependon compile +dependcc $2.c +formake ./compile $2.c +./compile $2.c @@ -0,0 +1,37 @@ +#include "substdio.h" +#include "subfd.h" +#include "exit.h" + +void main() +{ + register int n; + register char *x; + char ch; + register int flagcr = 0; + + for (;;) { + n = substdio_feed(subfdin); + if (n < 0) _exit(111); + if (!n) { + if (flagcr) substdio_BPUTC(subfdout,"\r"[0]); + _exit(0); + } + x = substdio_PEEK(subfdin); + substdio_SEEK(subfdin,n); + + while (n > 0) { + ch = *x++; --n; + if (!flagcr) { + if (ch == '\r') { flagcr = 1; continue; } + substdio_BPUTC(subfdout,ch); + continue; + } + if (ch != '\n') { + substdio_BPUTC(subfdout,"\r"[0]); + if (ch == '\r') continue; + } + flagcr = 0; + substdio_BPUTC(subfdout,ch); + } + } +} @@ -0,0 +1,3 @@ +substdio.a +error.a +str.a @@ -0,0 +1,402 @@ +#include <stdio.h> +#include <netdb.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <errno.h> +extern int res_query(); +extern int res_search(); +extern int errno; +extern int h_errno; +#include "ip.h" +#include "ipalloc.h" +#include "fmt.h" +#include "alloc.h" +#include "str.h" +#include "stralloc.h" +#include "dns.h" +#include "case.h" + +static unsigned short getshort(c) unsigned char *c; +{ unsigned short u; u = c[0]; return (u << 8) + c[1]; } + +static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response; +static int responselen; +static unsigned char *responseend; +static unsigned char *responsepos; + +static int numanswers; +static char name[MAXDNAME]; +static struct ip_address ip; +unsigned short pref; + +static stralloc glue = {0}; + +static int (*lookup)() = res_query; + +static int resolve(domain,type) +stralloc *domain; +int type; +{ + int n; + int i; + + errno = 0; + if (!stralloc_copy(&glue,domain)) return DNS_MEM; + if (!stralloc_0(&glue)) return DNS_MEM; + responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response)); + if (responselen <= 0) + { + if (errno == ECONNREFUSED) return DNS_SOFT; + if (h_errno == TRY_AGAIN) return DNS_SOFT; + return DNS_HARD; + } + if (responselen >= sizeof(response)) + responselen = sizeof(response); + responseend = response.buf + responselen; + responsepos = response.buf + sizeof(HEADER); + n = ntohs(response.hdr.qdcount); + while (n-- > 0) + { + i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); + if (i < 0) return DNS_SOFT; + responsepos += i; + i = responseend - responsepos; + if (i < QFIXEDSZ) return DNS_SOFT; + responsepos += QFIXEDSZ; + } + numanswers = ntohs(response.hdr.ancount); + return 0; +} + +static int findname(wanttype) +int wanttype; +{ + unsigned short rrtype; + unsigned short rrdlen; + int i; + + if (numanswers <= 0) return 2; + --numanswers; + if (responsepos == responseend) return DNS_SOFT; + + i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); + if (i < 0) return DNS_SOFT; + responsepos += i; + + i = responseend - responsepos; + if (i < 4 + 3 * 2) return DNS_SOFT; + + rrtype = getshort(responsepos); + rrdlen = getshort(responsepos + 8); + responsepos += 10; + + if (rrtype == wanttype) + { + if (dn_expand(response.buf,responseend,responsepos,name,MAXDNAME) < 0) + return DNS_SOFT; + responsepos += rrdlen; + return 1; + } + + responsepos += rrdlen; + return 0; +} + +static int findip(wanttype) +int wanttype; +{ + unsigned short rrtype; + unsigned short rrdlen; + int i; + + if (numanswers <= 0) return 2; + --numanswers; + if (responsepos == responseend) return DNS_SOFT; + + i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); + if (i < 0) return DNS_SOFT; + responsepos += i; + + i = responseend - responsepos; + if (i < 4 + 3 * 2) return DNS_SOFT; + + rrtype = getshort(responsepos); + rrdlen = getshort(responsepos + 8); + responsepos += 10; + + if (rrtype == wanttype) + { + if (rrdlen < 4) + return DNS_SOFT; + ip.d[0] = responsepos[0]; + ip.d[1] = responsepos[1]; + ip.d[2] = responsepos[2]; + ip.d[3] = responsepos[3]; + responsepos += rrdlen; + return 1; + } + + responsepos += rrdlen; + return 0; +} + +static int findmx(wanttype) +int wanttype; +{ + unsigned short rrtype; + unsigned short rrdlen; + int i; + + if (numanswers <= 0) return 2; + --numanswers; + if (responsepos == responseend) return DNS_SOFT; + + i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); + if (i < 0) return DNS_SOFT; + responsepos += i; + + i = responseend - responsepos; + if (i < 4 + 3 * 2) return DNS_SOFT; + + rrtype = getshort(responsepos); + rrdlen = getshort(responsepos + 8); + responsepos += 10; + + if (rrtype == wanttype) + { + if (rrdlen < 3) + return DNS_SOFT; + pref = (responsepos[0] << 8) + responsepos[1]; + if (dn_expand(response.buf,responseend,responsepos + 2,name,MAXDNAME) < 0) + return DNS_SOFT; + responsepos += rrdlen; + return 1; + } + + responsepos += rrdlen; + return 0; +} + +void dns_init(flagsearch) +int flagsearch; +{ + res_init(); + if (flagsearch) lookup = res_search; +} + +int dns_cname(sa) +stralloc *sa; +{ + int r; + int loop; + for (loop = 0;loop < 10;++loop) + { + if (!sa->len) return loop; + if (sa->s[sa->len - 1] == ']') return loop; + if (sa->s[sa->len - 1] == '.') { --sa->len; continue; } + switch(resolve(sa,T_ANY)) + { + case DNS_MEM: return DNS_MEM; + case DNS_SOFT: return DNS_SOFT; + case DNS_HARD: return loop; + default: + while ((r = findname(T_CNAME)) != 2) + { + if (r == DNS_SOFT) return DNS_SOFT; + if (r == 1) + { + if (!stralloc_copys(sa,name)) return DNS_MEM; + break; + } + } + if (r == 2) return loop; + } + } + return DNS_HARD; /* alias loop */ +} + +#define FMT_IAA 40 + +static int iaafmt(s,ip) +char *s; +struct ip_address *ip; +{ + unsigned int i; + unsigned int len; + len = 0; + i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i; + i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i; + return len; +} + +int dns_ptr(sa,ip) +stralloc *sa; +struct ip_address *ip; +{ + int r; + + if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM; + sa->len = iaafmt(sa->s,ip); + switch(resolve(sa,T_PTR)) + { + case DNS_MEM: return DNS_MEM; + case DNS_SOFT: return DNS_SOFT; + case DNS_HARD: return DNS_HARD; + } + while ((r = findname(T_PTR)) != 2) + { + if (r == DNS_SOFT) return DNS_SOFT; + if (r == 1) + { + if (!stralloc_copys(sa,name)) return DNS_MEM; + return 0; + } + } + return DNS_HARD; +} + +static int dns_ipplus(ia,sa,pref) +ipalloc *ia; +stralloc *sa; +int pref; +{ + int r; + struct ip_mx ix; + + if (sa->len && (sa->s[0] == '[')) + { + if (!stralloc_copy(&glue,sa)) return DNS_MEM; + if (!stralloc_0(&glue)) return DNS_MEM; + ix.pref = 0; + if (!glue.s[ip_scanbracket(glue.s,&ix.ip)]) + { + if (!ipalloc_append(ia,&ix)) return DNS_MEM; + return 0; + } + } + + switch(resolve(sa,T_A)) + { + case DNS_MEM: return DNS_MEM; + case DNS_SOFT: return DNS_SOFT; + case DNS_HARD: return DNS_HARD; + } + while ((r = findip(T_A)) != 2) + { + ix.ip = ip; + ix.pref = pref; + if (r == DNS_SOFT) return DNS_SOFT; + if (r == 1) + if (!ipalloc_append(ia,&ix)) return DNS_MEM; + } + return 0; +} + +int dns_ip(ia,sa) +ipalloc *ia; +stralloc *sa; +{ + if (!ipalloc_readyplus(ia,0)) return DNS_MEM; + ia->len = 0; + return dns_ipplus(ia,sa,0); +} + +int dns_mxip(ia,sa,random) +ipalloc *ia; +stralloc *sa; +unsigned long random; +{ + int r; + struct mx { stralloc sa; unsigned short p; } *mx; + int nummx; + int i; + int j; + int flagsoft; + + if (!ipalloc_readyplus(ia,0)) return DNS_MEM; + ia->len = 0; + + if (sa->len && (sa->s[0] == '[')) + { + struct ip_mx ix; + if (!stralloc_copy(&glue,sa)) return DNS_MEM; + if (!stralloc_0(&glue)) return DNS_MEM; + ix.pref = 0; + if (!glue.s[ip_scanbracket(glue.s,&ix.ip)]) + { + if (!ipalloc_append(ia,&ix)) return DNS_MEM; + return 0; + } + } + + switch(resolve(sa,T_MX)) + { + case DNS_MEM: return DNS_MEM; + case DNS_SOFT: return DNS_SOFT; + case DNS_HARD: return dns_ip(ia,sa); + } + + mx = (struct mx *) alloc(numanswers * sizeof(struct mx)); + if (!mx) return DNS_MEM; + nummx = 0; + + while ((r = findmx(T_MX)) != 2) + { + if (r == DNS_SOFT) { alloc_free(mx); return DNS_SOFT; } + if (r == 1) + { + mx[nummx].p = pref; + mx[nummx].sa.s = 0; + if (!stralloc_copys(&mx[nummx].sa,name)) + { + while (nummx > 0) alloc_free(mx[--nummx].sa.s); + alloc_free(mx); return DNS_MEM; + } + ++nummx; + } + } + + if (!nummx) return dns_ip(ia,sa); /* e.g., CNAME -> A */ + + flagsoft = 0; + while (nummx > 0) + { + unsigned long numsame; + + i = 0; + numsame = 1; + for (j = 1;j < nummx;++j) + if (mx[j].p < mx[i].p) + { + i = j; + numsame = 1; + } + else if (mx[j].p == mx[i].p) + { + ++numsame; + random = random * 69069 + 1; + if ((random / 2) < (2147483647 / numsame)) + i = j; + } + + switch(dns_ipplus(ia,&mx[i].sa,mx[i].p)) + { + case DNS_MEM: case DNS_SOFT: + flagsoft = 1; break; + } + + alloc_free(mx[i].sa.s); + mx[i] = mx[--nummx]; + } + + alloc_free(mx); + return flagsoft; +} @@ -0,0 +1,14 @@ +#ifndef DNS_H +#define DNS_H + +#define DNS_SOFT -1 +#define DNS_HARD -2 +#define DNS_MEM -3 + +void dns_init(); +int dns_cname(); +int dns_mxip(); +int dns_ip(); +int dns_ptr(); + +#endif diff --git a/dns.lib.do b/dns.lib.do new file mode 100644 index 0000000..2c73eab --- /dev/null +++ b/dns.lib.do @@ -0,0 +1,14 @@ +dependon tryrsolv.c compile load socket.lib dns.o \ +ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a + +( ./compile tryrsolv.c && ./load tryrsolv dns.o \ +ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \ +-lresolv `cat socket.lib` ) >/dev/null 2>&1 \ +&& echo -lresolv +rm -f tryrsolv.o tryrsolv + +formake '( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \' +formake 'ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \' +formake '-lresolv `cat socket.lib` ) >/dev/null 2>&1 \' +formake '&& echo -lresolv || exit 0 ) > dns.lib' +formake 'rm -f tryrsolv.o tryrsolv' @@ -0,0 +1,113 @@ +/* env.c, envread.c, env.h: environ library +Daniel J. Bernstein, djb@silverton.berkeley.edu. +Depends on str.h, alloc.h. +Requires environ. +19960113: rewrite. warning: interface is different. +No known patent problems. +*/ + +#include "str.h" +#include "alloc.h" +#include "env.h" + +int env_isinit = 0; /* if env_isinit: */ +static int ea; /* environ is a pointer to ea+1 char*'s. */ +static int en; /* the first en of those are ALLOCATED. environ[en] is 0. */ + +static void env_goodbye(i) int i; +{ + alloc_free(environ[i]); + environ[i] = environ[--en]; + environ[en] = 0; +} + +static char *null = 0; + +void env_clear() +{ + if (env_isinit) while (en) env_goodbye(0); + else environ = &null; +} + +static void env_unsetlen(s,len) char *s; int len; +{ + int i; + for (i = en - 1;i >= 0;--i) + if (!str_diffn(s,environ[i],len)) + if (environ[i][len] == '=') + env_goodbye(i); +} + +int env_unset(s) char *s; +{ + if (!env_isinit) if (!env_init()) return 0; + env_unsetlen(s,str_len(s)); + return 1; +} + +static int env_add(s) char *s; +{ + char *t; + t = env_findeq(s); + if (t) env_unsetlen(s,t - s); + if (en == ea) + { + ea += 30; + if (!alloc_re(&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *))) + { ea = en; return 0; } + } + environ[en++] = s; + environ[en] = 0; + return 1; +} + +int env_put(s) char *s; +{ + char *u; + if (!env_isinit) if (!env_init()) return 0; + u = alloc(str_len(s) + 1); + if (!u) return 0; + str_copy(u,s); + if (!env_add(u)) { alloc_free(u); return 0; } + return 1; +} + +int env_put2(s,t) char *s; char *t; +{ + char *u; + int slen; + if (!env_isinit) if (!env_init()) return 0; + slen = str_len(s); + u = alloc(slen + str_len(t) + 2); + if (!u) return 0; + str_copy(u,s); + u[slen] = '='; + str_copy(u + slen + 1,t); + if (!env_add(u)) { alloc_free(u); return 0; } + return 1; +} + +int env_init() +{ + char **newenviron; + int i; + for (en = 0;environ[en];++en) ; + ea = en + 10; + newenviron = (char **) alloc((ea + 1) * sizeof(char *)); + if (!newenviron) return 0; + for (en = 0;environ[en];++en) + { + newenviron[en] = alloc(str_len(environ[en]) + 1); + if (!newenviron[en]) + { + for (i = 0;i < en;++i) alloc_free(newenviron[i]); + alloc_free(newenviron); + return 0; + } + str_copy(newenviron[en],environ[en]); + } + newenviron[en] = 0; + environ = newenviron; + env_isinit = 1; + return 1; +} @@ -0,0 +1,17 @@ +#ifndef ENV_H +#define ENV_H + +extern int env_isinit; + +extern int env_init(); +extern int env_put(); +extern int env_put2(); +extern int env_unset(); +extern /*@null@*/char *env_get(); +extern char *env_pick(); +extern void env_clear(); +extern char *env_findeq(); + +extern char **environ; + +#endif @@ -0,0 +1,2 @@ +env.o +envread.o diff --git a/envread.c b/envread.c new file mode 100644 index 0000000..80185de --- /dev/null +++ b/envread.c @@ -0,0 +1,30 @@ +#include "env.h" +#include "str.h" + +extern /*@null@*/char *env_get(s) +char *s; +{ + int i; + unsigned int slen; + char *envi; + + slen = str_len(s); + for (i = 0;envi = environ[i];++i) + if ((!str_diffn(s,envi,slen)) && (envi[slen] == '=')) + return envi + slen + 1; + return 0; +} + +extern char *env_pick() +{ + return environ[0]; +} + +extern char *env_findeq(s) +char *s; +{ + for (;*s;++s) + if (*s == '=') + return s; + return 0; +} @@ -0,0 +1,95 @@ +#include <errno.h> +#include "error.h" + +/* warning: as coverage improves here, should update error_{str,temp} */ + +int error_intr = +#ifdef EINTR +EINTR; +#else +-1; +#endif + +int error_nomem = +#ifdef ENOMEM +ENOMEM; +#else +-2; +#endif + +int error_noent = +#ifdef ENOENT +ENOENT; +#else +-3; +#endif + +int error_txtbsy = +#ifdef ETXTBSY +ETXTBSY; +#else +-4; +#endif + +int error_io = +#ifdef EIO +EIO; +#else +-5; +#endif + +int error_exist = +#ifdef EEXIST +EEXIST; +#else +-6; +#endif + +int error_timeout = +#ifdef ETIMEDOUT +ETIMEDOUT; +#else +-7; +#endif + +int error_inprogress = +#ifdef EINPROGRESS +EINPROGRESS; +#else +-8; +#endif + +int error_wouldblock = +#ifdef EWOULDBLOCK +EWOULDBLOCK; +#else +-9; +#endif + +int error_again = +#ifdef EAGAIN +EAGAIN; +#else +-10; +#endif + +int error_pipe = +#ifdef EPIPE +EPIPE; +#else +-11; +#endif + +int error_perm = +#ifdef EPERM +EPERM; +#else +-12; +#endif + +int error_acces = +#ifdef EACCES +EACCES; +#else +-13; +#endif @@ -0,0 +1,23 @@ +#ifndef ERROR_H +#define ERROR_H + +extern int errno; + +extern int error_intr; +extern int error_nomem; +extern int error_noent; +extern int error_txtbsy; +extern int error_io; +extern int error_exist; +extern int error_timeout; +extern int error_inprogress; +extern int error_wouldblock; +extern int error_again; +extern int error_pipe; +extern int error_perm; +extern int error_acces; + +extern char *error_str(); +extern int error_temp(); + +#endif @@ -0,0 +1,2 @@ +error.o +error_str.o diff --git a/error_str.c b/error_str.c new file mode 100644 index 0000000..804d1fa --- /dev/null +++ b/error_str.c @@ -0,0 +1,276 @@ +#include <errno.h> +#include "error.h" + +#define X(e,s) if (i == e) return s; + +char *error_str(i) +int i; +{ + X(0,"no error") + X(error_intr,"interrupted system call") + X(error_nomem,"out of memory") + X(error_noent,"file does not exist") + X(error_txtbsy,"text busy") + X(error_io,"input/output error") + X(error_exist,"file already exists") + X(error_timeout,"timed out") + X(error_inprogress,"operation in progress") + X(error_again,"temporary failure") + X(error_wouldblock,"input/output would block") + X(error_pipe,"broken pipe") + X(error_perm,"permission denied") + X(error_acces,"access denied") +#ifdef ESRCH + X(ESRCH,"no such process") +#endif +#ifdef ENXIO + X(ENXIO,"device not configured") +#endif +#ifdef E2BIG + X(E2BIG,"argument list too long") +#endif +#ifdef ENOEXEC + X(ENOEXEC,"exec format error") +#endif +#ifdef EBADF + X(EBADF,"file descriptor not open") +#endif +#ifdef ECHILD + X(ECHILD,"no child processes") +#endif +#ifdef EDEADLK + X(EDEADLK,"operation would cause deadlock") +#endif +#ifdef EFAULT + X(EFAULT,"bad address") +#endif +#ifdef ENOTBLK + X(ENOTBLK,"not a block device") +#endif +#ifdef EBUSY + X(EBUSY,"device busy") +#endif +#ifdef EXDEV + X(EXDEV,"cross-device link") +#endif +#ifdef ENODEV + X(ENODEV,"device does not support operation") +#endif +#ifdef ENOTDIR + X(ENOTDIR,"not a directory") +#endif +#ifdef EISDIR + X(EISDIR,"is a directory") +#endif +#ifdef EINVAL + X(EINVAL,"invalid argument") +#endif +#ifdef ENFILE + X(ENFILE,"system cannot open more files") +#endif +#ifdef EMFILE + X(EMFILE,"process cannot open more files") +#endif +#ifdef ENOTTY + X(ENOTTY,"not a tty") +#endif +#ifdef EFBIG + X(EFBIG,"file too big") +#endif +#ifdef ENOSPC + X(ENOSPC,"out of disk space") +#endif +#ifdef ESPIPE + X(ESPIPE,"unseekable descriptor") +#endif +#ifdef EROFS + X(EROFS,"read-only file system") +#endif +#ifdef EMLINK + X(EMLINK,"too many links") +#endif +#ifdef EDOM + X(EDOM,"input out of range") +#endif +#ifdef ERANGE + X(ERANGE,"output out of range") +#endif +#ifdef EALREADY + X(EALREADY,"operation already in progress") +#endif +#ifdef ENOTSOCK + X(ENOTSOCK,"not a socket") +#endif +#ifdef EDESTADDRREQ + X(EDESTADDRREQ,"destination address required") +#endif +#ifdef EMSGSIZE + X(EMSGSIZE,"message too long") +#endif +#ifdef EPROTOTYPE + X(EPROTOTYPE,"incorrect protocol type") +#endif +#ifdef ENOPROTOOPT + X(ENOPROTOOPT,"protocol not available") +#endif +#ifdef EPROTONOSUPPORT + X(EPROTONOSUPPORT,"protocol not supported") +#endif +#ifdef ESOCKTNOSUPPORT + X(ESOCKTNOSUPPORT,"socket type not supported") +#endif +#ifdef EOPNOTSUPP + X(EOPNOTSUPP,"operation not supported") +#endif +#ifdef EPFNOSUPPORT + X(EPFNOSUPPORT,"protocol family not supported") +#endif +#ifdef EAFNOSUPPORT + X(EAFNOSUPPORT,"address family not supported") +#endif +#ifdef EADDRINUSE + X(EADDRINUSE,"address already used") +#endif +#ifdef EADDRNOTAVAIL + X(EADDRNOTAVAIL,"address not available") +#endif +#ifdef ENETDOWN + X(ENETDOWN,"network down") +#endif +#ifdef ENETUNREACH + X(ENETUNREACH,"network unreachable") +#endif +#ifdef ENETRESET + X(ENETRESET,"network reset") +#endif +#ifdef ECONNABORTED + X(ECONNABORTED,"connection aborted") +#endif +#ifdef ECONNRESET + X(ECONNRESET,"connection reset") +#endif +#ifdef ENOBUFS + X(ENOBUFS,"out of buffer space") +#endif +#ifdef EISCONN + X(EISCONN,"already connected") +#endif +#ifdef ENOTCONN + X(ENOTCONN,"not connected") +#endif +#ifdef ESHUTDOWN + X(ESHUTDOWN,"socket shut down") +#endif +#ifdef ETOOMANYREFS + X(ETOOMANYREFS,"too many references") +#endif +#ifdef ECONNREFUSED + X(ECONNREFUSED,"connection refused") +#endif +#ifdef ELOOP + X(ELOOP,"symbolic link loop") +#endif +#ifdef ENAMETOOLONG + X(ENAMETOOLONG,"file name too long") +#endif +#ifdef EHOSTDOWN + X(EHOSTDOWN,"host down") +#endif +#ifdef EHOSTUNREACH + X(EHOSTUNREACH,"host unreachable") +#endif +#ifdef ENOTEMPTY + X(ENOTEMPTY,"directory not empty") +#endif +#ifdef EPROCLIM + X(EPROCLIM,"too many processes") +#endif +#ifdef EUSERS + X(EUSERS,"too many users") +#endif +#ifdef EDQUOT + X(EDQUOT,"disk quota exceeded") +#endif +#ifdef ESTALE + X(ESTALE,"stale NFS file handle") +#endif +#ifdef EREMOTE + X(EREMOTE,"too many levels of remote in path") +#endif +#ifdef EBADRPC + X(EBADRPC,"RPC structure is bad") +#endif +#ifdef ERPCMISMATCH + X(ERPCMISMATCH,"RPC version mismatch") +#endif +#ifdef EPROGUNAVAIL + X(EPROGUNAVAIL,"RPC program unavailable") +#endif +#ifdef EPROGMISMATCH + X(EPROGMISMATCH,"program version mismatch") +#endif +#ifdef EPROCUNAVAIL + X(EPROCUNAVAIL,"bad procedure for program") +#endif +#ifdef ENOLCK + X(ENOLCK,"no locks available") +#endif +#ifdef ENOSYS + X(ENOSYS,"system call not available") +#endif +#ifdef EFTYPE + X(EFTYPE,"bad file type") +#endif +#ifdef EAUTH + X(EAUTH,"authentication error") +#endif +#ifdef ENEEDAUTH + X(ENEEDAUTH,"not authenticated") +#endif +#ifdef ENOSTR + X(ENOSTR,"not a stream device") +#endif +#ifdef ETIME + X(ETIME,"timer expired") +#endif +#ifdef ENOSR + X(ENOSR,"out of stream resources") +#endif +#ifdef ENOMSG + X(ENOMSG,"no message of desired type") +#endif +#ifdef EBADMSG + X(EBADMSG,"bad message type") +#endif +#ifdef EIDRM + X(EIDRM,"identifier removed") +#endif +#ifdef ENONET + X(ENONET,"machine not on network") +#endif +#ifdef ERREMOTE + X(ERREMOTE,"object not local") +#endif +#ifdef ENOLINK + X(ENOLINK,"link severed") +#endif +#ifdef EADV + X(EADV,"advertise error") +#endif +#ifdef ESRMNT + X(ESRMNT,"srmount error") +#endif +#ifdef ECOMM + X(ECOMM,"communication error") +#endif +#ifdef EPROTO + X(EPROTO,"protocol error") +#endif +#ifdef EMULTIHOP + X(EMULTIHOP,"multihop attempted") +#endif +#ifdef EREMCHG + X(EREMCHG,"remote address changed") +#endif + return "unknown error"; +} @@ -0,0 +1,6 @@ +#ifndef EXIT_H +#define EXIT_H + +extern void _exit(); + +#endif @@ -0,0 +1,7 @@ +#ifndef FD_H +#define FD_H + +extern int fd_copy(); +extern int fd_move(); + +#endif @@ -0,0 +1,2 @@ +fd_copy.o +fd_move.o diff --git a/fd_copy.c b/fd_copy.c new file mode 100644 index 0000000..b9f7167 --- /dev/null +++ b/fd_copy.c @@ -0,0 +1,13 @@ +#include <fcntl.h> +#include "fd.h" + +int fd_copy(to,from) +int to; +int from; +{ + if (to == from) return 0; + if (fcntl(from,F_GETFL,0) == -1) return -1; + close(to); + if (fcntl(from,F_DUPFD,to) == -1) return -1; + return 0; +} diff --git a/fd_move.c b/fd_move.c new file mode 100644 index 0000000..1aa557f --- /dev/null +++ b/fd_move.c @@ -0,0 +1,11 @@ +#include "fd.h" + +int fd_move(to,from) +int to; +int from; +{ + if (to == from) return 0; + if (fd_copy(to,from) == -1) return -1; + close(from); + return 0; +} diff --git a/find-systype.sh b/find-systype.sh new file mode 100644 index 0000000..16266d3 --- /dev/null +++ b/find-systype.sh @@ -0,0 +1,144 @@ +# oper-:arch-:syst-:chip-:kern- +# oper = operating system type; e.g., sunos-4.1.4 +# arch = machine language; e.g., sparc +# syst = which binaries can run; e.g., sun4 +# chip = chip model; e.g., micro-2-80 +# kern = kernel version; e.g., sun4m +# dependence: arch --- chip +# \ \ +# oper --- syst --- kern +# so, for example, syst is interpreted in light of oper, but chip is not. +# anyway, no slashes, no extra colons, no uppercase letters. +# the point of the extra -'s is to ease parsing: can add hierarchies later. +# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, +# and i386-486 (486s do have more instructions, you know) as well as i386. +# the idea here is to include ALL useful available information. + +exec 2>/dev/null +sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" +if [ x"$sys" != x ] +then + unamer="`uname -r | tr /: ..`" + unamem="`uname -m | tr /: ..`" + unamev="`uname -v | tr /: ..`" + + case "$sys" in + bsd.os) + # in bsd 4.4, uname -v does not have useful info. + # in bsd 4.4, uname -m is arch, not chip. + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" + kern="" + ;; + freebsd) + # see above about bsd 4.4 + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + netbsd) + # see above about bsd 4.4 + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + linux) + # as in bsd 4.4, uname -v does not have useful info. + oper="$sys-$unamer" + syst="" + chip="$unamem" + kern="" + case "$chip" in + i386|i486|i586|i686) + arch="i386" + ;; + alpha) + arch="alpha" + ;; + esac + ;; + aix) + # naturally IBM has to get uname -r and uname -v backwards. dorks. + oper="$sys-$unamev-$unamer" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + sunos) + oper="$sys-$unamer-$unamev" + arch="`(uname -p || mach) | tr /: ..`" + syst="`arch | tr /: ..`" + chip="$unamem" # this is wrong; is there any way to get the real info? + kern="`arch -k | tr /: ..`" + ;; + unix_sv) + oper="$sys-$unamer-$unamev" + arch="`uname -m`" + syst="" + chip="$unamem" + kern="" + ;; + *) + oper="$sys-$unamer-$unamev" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + esac +else + $CC -c trycpp.c + $LD -o trycpp trycpp.o + case `./trycpp` in + nextstep) + oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" + arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" + syst="" + chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" + kern="" + ;; + *) + oper="unknown" + arch="" + syst="" + chip="" + kern="" + ;; + esac + rm -f trycpp.o trycpp +fi + +case "$chip" in +80486) + # let's try to be consistent here. (BSD/OS) + chip=i486 + ;; +i486DX) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx + ;; +i486.DX2) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx2 + ;; +Intel.586) + # no, you nitwits, there is no such chip. (NeXTStep) + chip=pentium + ;; +i586) + # no, you nitwits, there is no such chip. (Linux) + chip=pentium + ;; +i686) + # STOP SAYING THAT! (Linux) + chip=ppro +esac + +echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' diff --git a/finger@.sh b/finger@.sh new file mode 100644 index 0000000..54f8a8c --- /dev/null +++ b/finger@.sh @@ -0,0 +1,4 @@ +echo "${2-}" | BIN/tcpclient -RHl0 -- "${1-0}" 79 sh -c ' + BIN/addcr >&7 + exec BIN/delcr <&6 +' | cat -v diff --git a/finger@=s b/finger@=s new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/finger@=s @@ -0,0 +1,25 @@ +#ifndef FMT_H +#define FMT_H + +#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ +#define FMT_LEN ((char *) 0) /* convenient abbreviation */ + +extern unsigned int fmt_uint(); +extern unsigned int fmt_uint0(); +extern unsigned int fmt_xint(); +extern unsigned int fmt_nbbint(); +extern unsigned int fmt_ushort(); +extern unsigned int fmt_xshort(); +extern unsigned int fmt_nbbshort(); +extern unsigned int fmt_ulong(); +extern unsigned int fmt_xlong(); +extern unsigned int fmt_nbblong(); + +extern unsigned int fmt_plusminus(); +extern unsigned int fmt_minus(); +extern unsigned int fmt_0x(); + +extern unsigned int fmt_str(); +extern unsigned int fmt_strn(); + +#endif diff --git a/fmt_str.c b/fmt_str.c new file mode 100644 index 0000000..48930cf --- /dev/null +++ b/fmt_str.c @@ -0,0 +1,12 @@ +#include "fmt.h" + +unsigned int fmt_str(s,t) +register char *s; register char *t; +{ + register unsigned int len; + char ch; + len = 0; + if (s) { while (ch = t[len]) s[len++] = ch; } + else while (t[len]) len++; + return len; +} diff --git a/fmt_ulong.c b/fmt_ulong.c new file mode 100644 index 0000000..ab12e8c --- /dev/null +++ b/fmt_ulong.c @@ -0,0 +1,13 @@ +#include "fmt.h" + +unsigned int fmt_ulong(s,u) register char *s; register unsigned long u; +{ + register unsigned int len; register unsigned long q; + len = 1; q = u; + while (q > 9) { ++len; q /= 10; } + if (s) { + s += len; + do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ + } + return len; +} @@ -0,0 +1,4 @@ +fmt_str.o +fmt_ulong.o +scan_ulong.o +scan_8long.o diff --git a/gen_alloc.h b/gen_alloc.h new file mode 100644 index 0000000..b94a956 --- /dev/null +++ b/gen_alloc.h @@ -0,0 +1,7 @@ +#ifndef GEN_ALLOC_H +#define GEN_ALLOC_H + +#define GEN_ALLOC_typedef(ta,type,field,len,a) \ + typedef struct ta { type *field; unsigned int len; unsigned int a; } ta; + +#endif diff --git a/gen_allocdefs.h b/gen_allocdefs.h new file mode 100644 index 0000000..783a9b1 --- /dev/null +++ b/gen_allocdefs.h @@ -0,0 +1,34 @@ +#ifndef GEN_ALLOC_DEFS_H +#define GEN_ALLOC_DEFS_H + +#define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ +int ta_ready(x,n) register ta *x; register unsigned int n; \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ +int ta_rplus(x,n) register ta *x; register unsigned int n; \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; n += x->len; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ +int ta_append(x,i) register ta *x; register type *i; \ +{ if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } + +#endif @@ -0,0 +1,20 @@ +#include "substdio.h" +#include "byte.h" +#include "stralloc.h" +#include "getln.h" + +int getln(ss,sa,match,sep) +register substdio *ss; +register stralloc *sa; +int *match; +int sep; +{ + char *cont; + unsigned int clen; + + if (getln2(ss,sa,&cont,&clen,sep) == -1) return -1; + if (!clen) { *match = 0; return 0; } + if (!stralloc_catb(sa,cont,clen)) return -1; + *match = 1; + return 0; +} @@ -0,0 +1,7 @@ +#ifndef GETLN_H +#define GETLN_H + +extern int getln(); +extern int getln2(); + +#endif diff --git a/getln2.c b/getln2.c new file mode 100644 index 0000000..9e576e9 --- /dev/null +++ b/getln2.c @@ -0,0 +1,31 @@ +#include "substdio.h" +#include "stralloc.h" +#include "byte.h" +#include "getln.h" + +int getln2(ss,sa,cont,clen,sep) +register substdio *ss; +register stralloc *sa; +/*@out@*/char **cont; +/*@out@*/unsigned int *clen; +int sep; +{ + register char *x; + register unsigned int i; + int n; + + if (!stralloc_ready(sa,0)) return -1; + sa->len = 0; + + for (;;) { + n = substdio_feed(ss); + if (n < 0) return -1; + if (n == 0) { *clen = 0; return 0; } + x = substdio_PEEK(ss); + i = byte_chr(x,n,sep); + if (i < n) { substdio_SEEK(ss,*clen = i + 1); *cont = x; return 0; } + if (!stralloc_readyplus(sa,n)) return -1; + i = sa->len; + sa->len = i + substdio_get(ss,sa->s + i,n); + } +} @@ -0,0 +1,2 @@ +getln.o +getln2.o diff --git a/getopt=l b/getopt=l new file mode 100644 index 0000000..a667e1e --- /dev/null +++ b/getopt=l @@ -0,0 +1,2 @@ +subgetopt.o +sgetopt.o diff --git a/hassgact.h.do b/hassgact.h.do new file mode 100644 index 0000000..df277d5 --- /dev/null +++ b/hassgact.h.do @@ -0,0 +1,7 @@ +dependon trysgact.c compile load +( ./compile trysgact.c && ./load trysgact ) >/dev/null 2>&1 \ +&& echo \#define HASSIGACTION 1 +rm -f trysgact.o trysgact +formake '( ( ./compile trysgact.c && ./load trysgact ) >/dev/null 2>&1 \' +formake '&& echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h' +formake 'rm -f trysgact.o trysgact' diff --git a/hassgprm.h.do b/hassgprm.h.do new file mode 100644 index 0000000..6ae8f47 --- /dev/null +++ b/hassgprm.h.do @@ -0,0 +1,7 @@ +dependon trysgprm.c compile load +( ./compile trysgprm.c && ./load trysgprm ) >/dev/null 2>&1 \ +&& echo \#define HASSIGPROCMASK 1 +rm -f trysgprm.o trysgprm +formake '( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null 2>&1 \' +formake '&& echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h' +formake 'rm -f trysgprm.o trysgprm' diff --git a/haswaitp.h.do b/haswaitp.h.do new file mode 100644 index 0000000..3cc09f5 --- /dev/null +++ b/haswaitp.h.do @@ -0,0 +1,7 @@ +dependon trywaitp.c compile load +( ./compile trywaitp.c && ./load trywaitp ) >/dev/null 2>&1 \ +&& echo \#define HASWAITPID 1 +rm -f trywaitp.o trywaitp +formake '( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null 2>&1 \' +formake '&& echo \#define HASWAITPID 1 || exit 0 ) > haswaitp.h' +formake 'rm -f trywaitp.o trywaitp' diff --git a/install.c b/install.c new file mode 100644 index 0000000..24f0916 --- /dev/null +++ b/install.c @@ -0,0 +1,140 @@ +#include "substdio.h" +#include "stralloc.h" +#include "getln.h" +#include "readwrite.h" +#include "exit.h" +#include "open.h" +#include "error.h" +#include "strerr.h" +#include "byte.h" + +stralloc target = {0}; +char *to; + +#define FATAL "install: fatal: " +void nomem() { strerr_die2x(111,FATAL,"out of memory"); } + +char inbuf[SUBSTDIO_INSIZE]; +char outbuf[SUBSTDIO_OUTSIZE]; +substdio ssin; +substdio ssout; + +void doit(line) +stralloc *line; +{ + char *x; + unsigned int xlen; + unsigned int i; + char *type; + char *uidstr; + char *gidstr; + char *modestr; + char *mid; + char *name; + unsigned long uid; + unsigned long gid; + unsigned long mode; + int fdin; + int fdout; + + x = line->s; xlen = line->len; + + type = x; + i = byte_chr(x,xlen,':'); if (i == xlen) return; + x[i++] = 0; x += i; xlen -= i; + + uidstr = x; + i = byte_chr(x,xlen,':'); if (i == xlen) return; + x[i++] = 0; x += i; xlen -= i; + + gidstr = x; + i = byte_chr(x,xlen,':'); if (i == xlen) return; + x[i++] = 0; x += i; xlen -= i; + + modestr = x; + i = byte_chr(x,xlen,':'); if (i == xlen) return; + x[i++] = 0; x += i; xlen -= i; + + mid = x; + i = byte_chr(x,xlen,':'); if (i == xlen) return; + x[i++] = 0; x += i; xlen -= i; + + name = x; + i = byte_chr(x,xlen,':'); if (i == xlen) return; + x[i++] = 0; x += i; xlen -= i; + + if (!stralloc_copys(&target,to)) nomem(); + if (!stralloc_cats(&target,mid)) nomem(); + if (!stralloc_cats(&target,name)) nomem(); + if (!stralloc_0(&target)) nomem(); + + uid = -1; if (*uidstr) scan_ulong(uidstr,&uid); + gid = -1; if (*gidstr) scan_ulong(gidstr,&gid); + scan_8long(modestr,&mode); + + switch(*type) { + case 'd': + if (mkdir(target.s,0700) == -1) + if (errno != error_exist) + strerr_die4sys(111,FATAL,"unable to mkdir ",target.s,": "); + break; + + case 'c': + fdin = open_read(name); + if (fdin == -1) + strerr_die4sys(111,FATAL,"unable to read ",name,": "); + substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof(inbuf)); + + fdout = open_trunc(target.s); + if (fdout == -1) + strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); + substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof(outbuf)); + + switch(substdio_copy(&ssout,&ssin)) { + case -2: + strerr_die4sys(111,FATAL,"unable to read ",name,": "); + case -3: + strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); + } + + close(fdin); + if (substdio_flush(&ssout) == -1) + strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); + if (fsync(fdout) == -1) + strerr_die4sys(111,FATAL,"unable to write ",target.s,": "); + close(fdout); + break; + + default: + return; + } + + if (chown(target.s,uid,gid) == -1) + strerr_die4sys(111,FATAL,"unable to chown ",target.s,": "); + if (chmod(target.s,mode) == -1) + strerr_die4sys(111,FATAL,"unable to chmod ",target.s,": "); +} + +char buf[256]; +substdio in = SUBSTDIO_FDBUF(read,0,buf,sizeof(buf)); +stralloc line = {0}; + +void main(argc,argv) +int argc; +char **argv; +{ + int match; + + umask(077); + + to = argv[1]; + if (!to) strerr_die2x(100,FATAL,"install: usage: install dir"); + + for (;;) { + if (getln(&in,&line,&match,'\n') == -1) + strerr_die2sys(111,FATAL,"unable to read input: "); + doit(&line); + if (!match) + _exit(0); + } +} diff --git a/install=x b/install=x new file mode 100644 index 0000000..6dc960b --- /dev/null +++ b/install=x @@ -0,0 +1,9 @@ +getln.a +strerr.a +substdio.a +stralloc.a +alloc.a +open.a +error.a +str.a +fs.a @@ -0,0 +1,53 @@ +#include "fmt.h" +#include "scan.h" +#include "ip.h" + +unsigned int ip_fmt(s,ip) +char *s; +struct ip_address *ip; +{ + unsigned int len; + unsigned int i; + + len = 0; + i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i; + return len; +} + +unsigned int ip_scan(s,ip) +char *s; +struct ip_address *ip; +{ + unsigned int i; + unsigned int len; + unsigned long u; + + len = 0; + i = scan_ulong(s,&u); if (!i) return 0; ip->d[0] = u; s += i; len += i; + if (*s != '.') return 0; ++s; ++len; + i = scan_ulong(s,&u); if (!i) return 0; ip->d[1] = u; s += i; len += i; + if (*s != '.') return 0; ++s; ++len; + i = scan_ulong(s,&u); if (!i) return 0; ip->d[2] = u; s += i; len += i; + if (*s != '.') return 0; ++s; ++len; + i = scan_ulong(s,&u); if (!i) return 0; ip->d[3] = u; s += i; len += i; + return len; +} + +unsigned int ip_scanbracket(s,ip) +char *s; +struct ip_address *ip; +{ + unsigned int len; + + if (*s != '[') return 0; + len = ip_scan(s + 1,ip); + if (!len) return 0; + if (s[len + 1] != ']') return 0; + return len + 2; +} @@ -0,0 +1,11 @@ +#ifndef IP_H +#define IP_H + +struct ip_address { unsigned char d[4]; } ; + +extern unsigned int ip_fmt(); +#define IPFMT 19 +extern unsigned int ip_scan(); +extern unsigned int ip_scanbracket(); + +#endif diff --git a/ipalloc.c b/ipalloc.c new file mode 100644 index 0000000..81792d5 --- /dev/null +++ b/ipalloc.c @@ -0,0 +1,7 @@ +#include "alloc.h" +#include "gen_allocdefs.h" +#include "ip.h" +#include "ipalloc.h" + +GEN_ALLOC_readyplus(ipalloc,struct ip_mx,ix,len,a,i,n,x,10,ipalloc_readyplus) +GEN_ALLOC_append(ipalloc,struct ip_mx,ix,len,a,i,n,x,10,ipalloc_readyplus,ipalloc_append) diff --git a/ipalloc.h b/ipalloc.h new file mode 100644 index 0000000..ad61475 --- /dev/null +++ b/ipalloc.h @@ -0,0 +1,14 @@ +#ifndef IPALLOC_H +#define IPALLOC_H + +#include "ip.h" + +struct ip_mx { struct ip_address ip; int pref; } ; + +#include "gen_alloc.h" + +GEN_ALLOC_typedef(ipalloc,struct ip_mx,ix,len,a) +extern int ipalloc_readyplus(); +extern int ipalloc_append(); + +#endif @@ -0,0 +1,5 @@ +dependon \ +tcpclient tcpserver tcprules \ +who@ date@ finger@ \ +tcpcat mconnect \ +addcr delcr diff --git a/make-compile.sh b/make-compile.sh new file mode 100644 index 0000000..a1eb501 --- /dev/null +++ b/make-compile.sh @@ -0,0 +1 @@ +echo exec "$CC" -c '${1+"$@"}' diff --git a/make-load.sh b/make-load.sh new file mode 100644 index 0000000..de07d2e --- /dev/null +++ b/make-load.sh @@ -0,0 +1,2 @@ +echo 'main="$1"; shift' +echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}' diff --git a/make-makelib.sh b/make-makelib.sh new file mode 100644 index 0000000..d6b7c8c --- /dev/null +++ b/make-makelib.sh @@ -0,0 +1,16 @@ +echo 'main="$1"; shift' +echo 'rm -f "$main"' +echo 'ar cr "$main" ${1+"$@"}' + +case "$1" in +sunos-5.*) ;; +unix_sv*) ;; +irix64-*) ;; +irix-*) ;; +dgux-*) ;; +hp-ux-*) ;; +sco*) ;; +*) + echo 'ranlib "$main"' + ;; +esac @@ -0,0 +1,5 @@ +dependon \ +tcpclient.0 \ +tcpserver.0 \ +tcprules.0 \ +tcp-environ.0 diff --git a/mconnect.sh b/mconnect.sh new file mode 100644 index 0000000..3d137dd --- /dev/null +++ b/mconnect.sh @@ -0,0 +1,7 @@ +# +# requires multitee +# +BIN/tcpclient -RHl0 -- "${1-0}" "${2-25}" sh -c ' + exec 4>&1 + multitee 0:1 6:4e0 | BIN/addcr >&7 +' | BIN/delcr diff --git a/mconnect=s b/mconnect=s new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/mconnect=s diff --git a/ndelay.c b/ndelay.c new file mode 100644 index 0000000..438d1d8 --- /dev/null +++ b/ndelay.c @@ -0,0 +1,13 @@ +#include <sys/types.h> +#include <fcntl.h> +#include "ndelay.h" + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +int ndelay_on(fd) +int fd; +{ + return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); +} diff --git a/ndelay.h b/ndelay.h new file mode 100644 index 0000000..68c6bce --- /dev/null +++ b/ndelay.h @@ -0,0 +1,7 @@ +#ifndef NDELAY_H +#define NDELAY_H + +extern int ndelay_on(); +extern int ndelay_off(); + +#endif diff --git a/ndelay=l b/ndelay=l new file mode 100644 index 0000000..322dd65 --- /dev/null +++ b/ndelay=l @@ -0,0 +1,2 @@ +ndelay.o +ndelay_off.o diff --git a/ndelay_off.c b/ndelay_off.c new file mode 100644 index 0000000..86f8fbf --- /dev/null +++ b/ndelay_off.c @@ -0,0 +1,13 @@ +#include <sys/types.h> +#include <fcntl.h> +#include "ndelay.h" + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +int ndelay_off(fd) +int fd; +{ + return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); +} @@ -0,0 +1,10 @@ +#ifndef OPEN_H +#define OPEN_H + +extern int open_read(); +extern int open_excl(); +extern int open_append(); +extern int open_trunc(); +extern int open_write(); + +#endif @@ -0,0 +1,2 @@ +open_read.o +open_trunc.o diff --git a/open_read.c b/open_read.c new file mode 100644 index 0000000..f503e48 --- /dev/null +++ b/open_read.c @@ -0,0 +1,6 @@ +#include <sys/types.h> +#include <fcntl.h> +#include "open.h" + +int open_read(fn) char *fn; +{ return open(fn,O_RDONLY | O_NDELAY); } diff --git a/open_trunc.c b/open_trunc.c new file mode 100644 index 0000000..e275085 --- /dev/null +++ b/open_trunc.c @@ -0,0 +1,6 @@ +#include <sys/types.h> +#include <fcntl.h> +#include "open.h" + +int open_trunc(fn) char *fn; +{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } diff --git a/readwrite.h b/readwrite.h new file mode 100644 index 0000000..2a64968 --- /dev/null +++ b/readwrite.h @@ -0,0 +1,7 @@ +#ifndef READWRITE_H +#define READWRITE_H + +extern int read(); +extern int write(); + +#endif diff --git a/remoteinfo.c b/remoteinfo.c new file mode 100644 index 0000000..c7abd70 --- /dev/null +++ b/remoteinfo.c @@ -0,0 +1,77 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <fcntl.h> +#include "byte.h" +#include "substdio.h" +#include "ip.h" +#include "fmt.h" +#include "timeoutconn.h" +#include "timeoutread.h" +#include "timeoutwrite.h" +#include "remoteinfo.h" + +static char line[999]; +static int t; + +static int mywrite(fd,buf,len) int fd; char *buf; int len; +{ + return timeoutwrite(t,fd,buf,len); +} +static int myread(fd,buf,len) int fd; char *buf; int len; +{ + return timeoutread(t,fd,buf,len); +} + +char *remoteinfo_get(ipr,rp,ipl,lp,timeout) +struct ip_address *ipr; +unsigned long rp; +struct ip_address *ipl; +unsigned long lp; +int timeout; +{ + char *x; + int s; + struct sockaddr_in sin; + substdio ss; + char buf[32]; + unsigned int len; + int numcolons; + char ch; + + t = timeout; + + s = socket(AF_INET,SOCK_STREAM,0); + if (s == -1) return 0; + + byte_zero(&sin,sizeof(sin)); + sin.sin_family = AF_INET; + byte_copy(&sin.sin_addr,4,ipl); + sin.sin_port = 0; + if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; } + if (timeoutconn(s,ipr,113,timeout) == -1) { close(s); return 0; } + fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) & ~O_NDELAY); + + len = 0; + len += fmt_ulong(line + len,rp); + len += fmt_str(line + len," , "); + len += fmt_ulong(line + len,lp); + len += fmt_str(line + len,"\r\n"); + + substdio_fdbuf(&ss,mywrite,s,buf,sizeof buf); + if (substdio_putflush(&ss,line,len) == -1) { close(s); return 0; } + + substdio_fdbuf(&ss,myread,s,buf,sizeof buf); + x = line; + numcolons = 0; + for (;;) { + if (substdio_get(&ss,&ch,1) != 1) { close(s); return 0; } + if ((ch == ' ') || (ch == '\t') || (ch == '\r')) continue; + if (ch == '\n') break; + if (numcolons < 3) { if (ch == ':') ++numcolons; } + else { *x++ = ch; if (x == line + sizeof(line) - 1) break; } + } + *x = 0; + close(s); + return line; +} diff --git a/remoteinfo.h b/remoteinfo.h new file mode 100644 index 0000000..d5d9097 --- /dev/null +++ b/remoteinfo.h @@ -0,0 +1,6 @@ +#ifndef REMOTEINFO_H +#define REMOTEINFO_H + +extern char *remoteinfo_get(); + +#endif @@ -0,0 +1,27 @@ +#ifndef SCAN_H +#define SCAN_H + +extern unsigned int scan_uint(); +extern unsigned int scan_xint(); +extern unsigned int scan_nbbint(); +extern unsigned int scan_ushort(); +extern unsigned int scan_xshort(); +extern unsigned int scan_nbbshort(); +extern unsigned int scan_ulong(); +extern unsigned int scan_xlong(); +extern unsigned int scan_nbblong(); + +extern unsigned int scan_plusminus(); +extern unsigned int scan_0x(); + +extern unsigned int scan_whitenskip(); +extern unsigned int scan_nonwhitenskip(); +extern unsigned int scan_charsetnskip(); +extern unsigned int scan_noncharsetnskip(); + +extern unsigned int scan_strncmp(); +extern unsigned int scan_memcmp(); + +extern unsigned int scan_long(); + +#endif diff --git a/scan_8long.c b/scan_8long.c new file mode 100644 index 0000000..8b3a6df --- /dev/null +++ b/scan_8long.c @@ -0,0 +1,11 @@ +#include "scan.h" + +unsigned int scan_8long(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')) < 8) + { result = result * 8 + c; ++pos; } + *u = result; return pos; +} diff --git a/scan_ulong.c b/scan_ulong.c new file mode 100644 index 0000000..27c41ea --- /dev/null +++ b/scan_ulong.c @@ -0,0 +1,11 @@ +#include "scan.h" + +unsigned int scan_ulong(s,u) register char *s; register unsigned long *u; +{ + register unsigned int pos; register unsigned long result; + register unsigned long c; + pos = 0; result = 0; + while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) + { result = result * 10 + c; ++pos; } + *u = result; return pos; +} @@ -0,0 +1,15 @@ +#ifndef SEEK_H +#define SEEK_H + +typedef unsigned long seek_pos; + +extern seek_pos seek_cur(); + +extern int seek_set(); +extern int seek_end(); + +extern int seek_trunc(); + +#define seek_begin(fd) (seek_set((fd),(seek_pos) 0)) + +#endif @@ -0,0 +1,4 @@ +seek_cur.o +seek_end.o +seek_set.o +seek_trunc.o diff --git a/seek_cur.c b/seek_cur.c new file mode 100644 index 0000000..c8a3ee8 --- /dev/null +++ b/seek_cur.c @@ -0,0 +1,7 @@ +#include <sys/types.h> +#include "seek.h" + +#define CUR 1 /* sigh */ + +seek_pos seek_cur(fd) int fd; +{ return lseek(fd,(off_t) 0,CUR); } diff --git a/seek_end.c b/seek_end.c new file mode 100644 index 0000000..8a7b3c5 --- /dev/null +++ b/seek_end.c @@ -0,0 +1,7 @@ +#include <sys/types.h> +#include "seek.h" + +#define END 2 /* sigh */ + +int seek_end(fd) int fd; +{ if (lseek(fd,(off_t) 0,END) == -1) return -1; return 0; } diff --git a/seek_set.c b/seek_set.c new file mode 100644 index 0000000..f540664 --- /dev/null +++ b/seek_set.c @@ -0,0 +1,7 @@ +#include <sys/types.h> +#include "seek.h" + +#define SET 0 /* sigh */ + +int seek_set(fd,pos) int fd; seek_pos pos; +{ if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; } diff --git a/seek_trunc.c b/seek_trunc.c new file mode 100644 index 0000000..6a1a73e --- /dev/null +++ b/seek_trunc.c @@ -0,0 +1,5 @@ +#include <sys/types.h> +#include "seek.h" + +int seek_trunc(fd,pos) int fd; seek_pos pos; +{ return ftruncate(fd,(off_t) pos); } diff --git a/select.h.do b/select.h.do new file mode 100644 index 0000000..5ab38df --- /dev/null +++ b/select.h.do @@ -0,0 +1,6 @@ +dependon compile trysysel.c select.h1 select.h2 +./compile trysysel.c >/dev/null 2>&1 && cat select.h2 || cat select.h1 +rm -f trysysel.o +formake '( ./compile trysysel.c >/dev/null 2>&1 \' +formake '&& cat select.h2 || cat select.h1 ) > select.h' +formake 'rm -f trysysel.o trysysel' diff --git a/select.h1 b/select.h1 new file mode 100644 index 0000000..32d0968 --- /dev/null +++ b/select.h1 @@ -0,0 +1,8 @@ +#ifndef SELECT_H +#define SELECT_H + +#include <sys/types.h> +#include <sys/time.h> +extern int select(); + +#endif diff --git a/select.h2 b/select.h2 new file mode 100644 index 0000000..eb4b8fe --- /dev/null +++ b/select.h2 @@ -0,0 +1,9 @@ +#ifndef SELECT_H +#define SELECT_H + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/select.h> +extern int select(); + +#endif diff --git a/setup.do b/setup.do new file mode 100644 index 0000000..d667234 --- /dev/null +++ b/setup.do @@ -0,0 +1,5 @@ +dependon it man install conf-bin conf-man BIN MAN +formake './install "`head -1 conf-bin`" < BIN' +formake './install "`head -1 conf-man`" < MAN' +./install "`head -1 conf-bin`" < BIN +./install "`head -1 conf-man`" < MAN diff --git a/sgetopt.c b/sgetopt.c new file mode 100644 index 0000000..a8bffc0 --- /dev/null +++ b/sgetopt.c @@ -0,0 +1,54 @@ +/* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer +D. J. Bernstein, djb@pobox.com. +Depends on subgetopt.h, substdio.h, subfd.h. +No system requirements. +19970208: Cleanups. +931201: Baseline. +No known patent problems. + +Documentation in sgetopt.3. +*/ + +#include "substdio.h" +#include "subfd.h" +#define SGETOPTNOSHORT +#include "sgetopt.h" +#define SUBGETOPTNOSHORT +#include "subgetopt.h" + +#define getopt sgetoptmine +#define optind subgetoptind +#define opterr sgetopterr +#define optproblem subgetoptproblem +#define optprogname sgetoptprogname + +int opterr = 1; +char *optprogname = 0; + +int getopt(argc,argv,opts) +int argc; +char **argv; +char *opts; +{ + int c; + char *s; + + if (!optprogname) { + optprogname = *argv; + if (!optprogname) optprogname = ""; + for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1; + } + c = subgetopt(argc,argv,opts); + if (opterr) + if (c == '?') { + char chp[2]; chp[0] = optproblem; chp[1] = '\n'; + substdio_puts(subfderr,optprogname); + if (argv[optind] && (optind < argc)) + substdio_puts(subfderr,": illegal option -- "); + else + substdio_puts(subfderr,": option requires an argument -- "); + substdio_put(subfderr,chp,2); + substdio_flush(subfderr); + } + return c; +} diff --git a/sgetopt.h b/sgetopt.h new file mode 100644 index 0000000..5f89127 --- /dev/null +++ b/sgetopt.h @@ -0,0 +1,21 @@ +#ifndef SGETOPT_H +#define SGETOPT_H + +#ifndef SGETOPTNOSHORT +#define getopt sgetoptmine +#define optarg subgetoptarg +#define optind subgetoptind +#define optpos subgetoptpos +#define opterr sgetopterr +#define optproblem subgetoptproblem +#define optprogname sgetoptprogname +#define opteof subgetoptdone +#endif + +#include "subgetopt.h" + +extern int sgetoptmine(); +extern int sgetopterr; +extern char *sgetoptprogname; + +#endif @@ -0,0 +1,43 @@ +#ifndef SIG_H +#define SIG_H + +extern void sig_catch(); +extern void sig_block(); +extern void sig_unblock(); +extern void sig_blocknone(); +extern void sig_pause(); + +extern void sig_dfl(); + +extern void sig_miscignore(); +extern void sig_bugcatch(); + +extern void sig_pipeignore(); +extern void sig_pipedefault(); + +extern void sig_contblock(); +extern void sig_contunblock(); +extern void sig_contcatch(); +extern void sig_contdefault(); + +extern void sig_termblock(); +extern void sig_termunblock(); +extern void sig_termcatch(); +extern void sig_termdefault(); + +extern void sig_alarmblock(); +extern void sig_alarmunblock(); +extern void sig_alarmcatch(); +extern void sig_alarmdefault(); + +extern void sig_childblock(); +extern void sig_childunblock(); +extern void sig_childcatch(); +extern void sig_childdefault(); + +extern void sig_hangupblock(); +extern void sig_hangupunblock(); +extern void sig_hangupcatch(); +extern void sig_hangupdefault(); + +#endif @@ -0,0 +1,7 @@ +sig_block.o +sig_catch.o +sig_pause.o +sig_dfl.o +sig_pipe.o +sig_child.o +sig_term.o diff --git a/sig_block.c b/sig_block.c new file mode 100644 index 0000000..c6b096a --- /dev/null +++ b/sig_block.c @@ -0,0 +1,40 @@ +#include <signal.h> +#include "sig.h" +#include "hassgprm.h" + +void sig_block(sig) +int sig; +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss,sig); + sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); +#else + sigblock(1 << (sig - 1)); +#endif +} + +void sig_unblock(sig) +int sig; +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss,sig); + sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); +#else + sigsetmask(sigsetmask(~0) & ~(1 << (sig - 1))); +#endif +} + +void sig_blocknone() +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); +#else + sigsetmask(0); +#endif +} diff --git a/sig_catch.c b/sig_catch.c new file mode 100644 index 0000000..1888765 --- /dev/null +++ b/sig_catch.c @@ -0,0 +1,18 @@ +#include <signal.h> +#include "sig.h" +#include "hassgact.h" + +void sig_catch(sig,f) +int sig; +void (*f)(); +{ +#ifdef HASSIGACTION + struct sigaction sa; + sa.sa_handler = f; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(sig,&sa,(struct sigaction *) 0); +#else + signal(sig,f); /* won't work under System V, even nowadays---dorks */ +#endif +} diff --git a/sig_child.c b/sig_child.c new file mode 100644 index 0000000..fd5b39b --- /dev/null +++ b/sig_child.c @@ -0,0 +1,7 @@ +#include <signal.h> +#include "sig.h" + +void sig_childblock() { sig_block(SIGCHLD); } +void sig_childunblock() { sig_unblock(SIGCHLD); } +void sig_childcatch(f) void (*f)(); { sig_catch(SIGCHLD,f); } +void sig_childdefault() { sig_catch(SIGCHLD,SIG_DFL); } diff --git a/sig_cont.c b/sig_cont.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sig_cont.c diff --git a/sig_dfl.c b/sig_dfl.c new file mode 100644 index 0000000..a92bd7b --- /dev/null +++ b/sig_dfl.c @@ -0,0 +1,82 @@ +#include <signal.h> +#include "sig.h" +#include "hassgact.h" +#include "hassgprm.h" + +/* tnx to Chris Torek for some improvements in previous versions */ + +static int flagcont; + +static void sigcont() { flagcont = 1; } + +void sig_dfl(sig) +int sig; +{ +#ifdef HASSIGPROCMASK + sigset_t ssorig; + sigset_t ssnew; +#else + int maskorig; + int masknew; +#endif +#ifdef HASSIGACTION + struct sigaction saorig; + struct sigaction sanew; +#else + struct sigvec svorig; + struct sigvec svnew; +#endif + + if (sig == SIGCONT) return; + +#ifdef HASSIGPROCMASK + sigfillset(&ssnew); + sigprocmask(SIG_SETMASK,&ssnew,&ssorig); +#else + masknew = ~0; + maskorig = sigsetmask(masknew); +#endif + +#ifdef HASSIGACTION + sanew.sa_handler = SIG_DFL; + sanew.sa_flags = 0; + sigemptyset(&sanew.sa_mask); + sigaction(sig,&sanew,&saorig); + sanew.sa_handler = sigcont; + sigaction(SIGCONT,&sanew,(struct sigaction *) 0); +#else + svnew.sv_handler = SIG_DFL; + svnew.sv_flags = 0; + svnew.sv_mask = 0; + sigvec(sig,&svnew,&svorig); + svnew.sv_handler = sigcont; + sigvec(SIGCONT,&svnew,(struct sigvec *) 0); +#endif + + flagcont = 0; + if (kill(getpid(),sig) == 0) { +#ifdef HASSIGPROCMASK + sigdelset(&ssnew,sig); + sigdelset(&ssnew,SIGCONT); + while (!flagcont) + sigsuspend(&ssnew); +#else + masknew &= ~(1 << (sig - 1)); + masknew &= ~(1 << (SIGCONT - 1)); + while (!flagcont) + sigpause(masknew); +#endif + } + +#ifdef HASSIGACTION + sigaction(sig,&saorig,(struct sigaction *) 0); +#else + sigvec(sig,&svorig,(struct sigvec *) 0); +#endif + +#ifdef HASSIGPROCMASK + sigprocmask(SIG_SETMASK,&ssorig,(sigset_t *) 0); +#else + sigsetmask(maskorig); +#endif +} diff --git a/sig_pause.c b/sig_pause.c new file mode 100644 index 0000000..3416734 --- /dev/null +++ b/sig_pause.c @@ -0,0 +1,14 @@ +#include <signal.h> +#include "sig.h" +#include "hassgprm.h" + +void sig_pause() +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigsuspend(&ss); +#else + sigpause(0); +#endif +} diff --git a/sig_pipe.c b/sig_pipe.c new file mode 100644 index 0000000..594ae7d --- /dev/null +++ b/sig_pipe.c @@ -0,0 +1,5 @@ +#include <signal.h> +#include "sig.h" + +void sig_pipeignore() { sig_catch(SIGPIPE,SIG_IGN); } +void sig_pipedefault() { sig_catch(SIGPIPE,SIG_DFL); } diff --git a/sig_term.c b/sig_term.c new file mode 100644 index 0000000..ca72cc3 --- /dev/null +++ b/sig_term.c @@ -0,0 +1,7 @@ +#include <signal.h> +#include "sig.h" + +void sig_termblock() { sig_block(SIGTERM); } +void sig_termunblock() { sig_unblock(SIGTERM); } +void sig_termcatch(f) void (*f)(); { sig_catch(SIGTERM,f); } +void sig_termdefault() { sig_catch(SIGTERM,SIG_DFL); } diff --git a/socket.lib.do b/socket.lib.do new file mode 100644 index 0000000..106c5e8 --- /dev/null +++ b/socket.lib.do @@ -0,0 +1,8 @@ +dependon trylsock.c compile load +( ./compile trylsock.c && ./load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \ +&& echo -lsocket -lnsl +rm -f trylsock.o trylsock +formake '( ( ./compile trylsock.c && \' +formake './load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \' +formake '&& echo -lsocket -lnsl || exit 0 ) > socket.lib' +formake 'rm -f trylsock.o trylsock' @@ -0,0 +1,14 @@ +#ifndef STR_H +#define STR_H + +extern unsigned int str_copy(); +extern int str_diff(); +extern int str_diffn(); +extern unsigned int str_len(); +extern unsigned int str_chr(); +extern unsigned int str_rchr(); +extern int str_start(); + +#define str_equal(s,t) (!str_diff((s),(t))) + +#endif @@ -0,0 +1,10 @@ +str_len.o +str_diff.o +str_diffn.o +str_cpy.o +byte_chr.o +byte_rchr.o +byte_diff.o +byte_copy.o +byte_cr.o +byte_zero.o diff --git a/str_cpy.c b/str_cpy.c new file mode 100644 index 0000000..453d790 --- /dev/null +++ b/str_cpy.c @@ -0,0 +1,16 @@ +#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; + } +} diff --git a/str_diff.c b/str_diff.c new file mode 100644 index 0000000..18f8927 --- /dev/null +++ b/str_diff.c @@ -0,0 +1,17 @@ +#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); +} diff --git a/str_diffn.c b/str_diffn.c new file mode 100644 index 0000000..89142f1 --- /dev/null +++ b/str_diffn.c @@ -0,0 +1,18 @@ +#include "str.h" + +int str_diffn(s,t,len) +register char *s; +register char *t; +unsigned int len; +{ + register char x; + + for (;;) { + if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + } + return ((int)(unsigned int)(unsigned char) x) + - ((int)(unsigned int)(unsigned char) *t); +} diff --git a/str_len.c b/str_len.c new file mode 100644 index 0000000..2d2f88b --- /dev/null +++ b/str_len.c @@ -0,0 +1,15 @@ +#include "str.h" + +unsigned int str_len(s) +register char *s; +{ + register char *t; + + t = s; + for (;;) { + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + } +} diff --git a/stralloc.h b/stralloc.h new file mode 100644 index 0000000..fca496c --- /dev/null +++ b/stralloc.h @@ -0,0 +1,21 @@ +#ifndef STRALLOC_H +#define STRALLOC_H + +#include "gen_alloc.h" + +GEN_ALLOC_typedef(stralloc,char,s,len,a) + +extern int stralloc_ready(); +extern int stralloc_readyplus(); +extern int stralloc_copy(); +extern int stralloc_cat(); +extern int stralloc_copys(); +extern int stralloc_cats(); +extern int stralloc_copyb(); +extern int stralloc_catb(); +extern int stralloc_append(); /* beware: this takes a pointer to 1 char */ +extern int stralloc_starts(); + +#define stralloc_0(sa) stralloc_append(sa,"") + +#endif diff --git a/stralloc=l b/stralloc=l new file mode 100644 index 0000000..e1ebc8d --- /dev/null +++ b/stralloc=l @@ -0,0 +1,8 @@ +stralloc_eady.o +stralloc_pend.o +stralloc_copy.o +stralloc_opys.o +stralloc_opyb.o +stralloc_cat.o +stralloc_cats.o +stralloc_catb.o diff --git a/stralloc_arts.c b/stralloc_arts.c new file mode 100644 index 0000000..1ccb5a4 --- /dev/null +++ b/stralloc_arts.c @@ -0,0 +1,12 @@ +#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); +} diff --git a/stralloc_cat.c b/stralloc_cat.c new file mode 100644 index 0000000..efbb112 --- /dev/null +++ b/stralloc_cat.c @@ -0,0 +1,9 @@ +#include "byte.h" +#include "stralloc.h" + +int stralloc_cat(sato,safrom) +stralloc *sato; +stralloc *safrom; +{ + return stralloc_catb(sato,safrom->s,safrom->len); +} diff --git a/stralloc_catb.c b/stralloc_catb.c new file mode 100644 index 0000000..67dbcc0 --- /dev/null +++ b/stralloc_catb.c @@ -0,0 +1,15 @@ +#include "stralloc.h" +#include "byte.h" + +int stralloc_catb(sa,s,n) +stralloc *sa; +char *s; +unsigned int n; +{ + if (!sa->s) return stralloc_copyb(sa,s,n); + if (!stralloc_readyplus(sa,n + 1)) return 0; + byte_copy(sa->s + sa->len,n,s); + sa->len += n; + sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ + return 1; +} diff --git a/stralloc_cats.c b/stralloc_cats.c new file mode 100644 index 0000000..d300286 --- /dev/null +++ b/stralloc_cats.c @@ -0,0 +1,10 @@ +#include "byte.h" +#include "str.h" +#include "stralloc.h" + +int stralloc_cats(sa,s) +stralloc *sa; +char *s; +{ + return stralloc_catb(sa,s,str_len(s)); +} diff --git a/stralloc_copy.c b/stralloc_copy.c new file mode 100644 index 0000000..652aed6 --- /dev/null +++ b/stralloc_copy.c @@ -0,0 +1,9 @@ +#include "byte.h" +#include "stralloc.h" + +int stralloc_copy(sato,safrom) +stralloc *sato; +stralloc *safrom; +{ + return stralloc_copyb(sato,safrom->s,safrom->len); +} diff --git a/stralloc_eady.c b/stralloc_eady.c new file mode 100644 index 0000000..3a31f4b --- /dev/null +++ b/stralloc_eady.c @@ -0,0 +1,6 @@ +#include "alloc.h" +#include "stralloc.h" +#include "gen_allocdefs.h" + +GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) +GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) diff --git a/stralloc_opyb.c b/stralloc_opyb.c new file mode 100644 index 0000000..ac258b3 --- /dev/null +++ b/stralloc_opyb.c @@ -0,0 +1,14 @@ +#include "stralloc.h" +#include "byte.h" + +int stralloc_copyb(sa,s,n) +stralloc *sa; +char *s; +unsigned int n; +{ + if (!stralloc_ready(sa,n + 1)) return 0; + byte_copy(sa->s,n,s); + sa->len = n; + sa->s[n] = 'Z'; /* ``offensive programming'' */ + return 1; +} diff --git a/stralloc_opys.c b/stralloc_opys.c new file mode 100644 index 0000000..fdd7807 --- /dev/null +++ b/stralloc_opys.c @@ -0,0 +1,10 @@ +#include "byte.h" +#include "str.h" +#include "stralloc.h" + +int stralloc_copys(sa,s) +stralloc *sa; +char *s; +{ + return stralloc_copyb(sa,s,str_len(s)); +} diff --git a/stralloc_pend.c b/stralloc_pend.c new file mode 100644 index 0000000..a3443b8 --- /dev/null +++ b/stralloc_pend.c @@ -0,0 +1,5 @@ +#include "alloc.h" +#include "stralloc.h" +#include "gen_allocdefs.h" + +GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) diff --git a/strerr.h b/strerr.h new file mode 100644 index 0000000..d18e833 --- /dev/null +++ b/strerr.h @@ -0,0 +1,80 @@ +#ifndef STRERR_H +#define STRERR_H + +struct strerr + { + struct strerr *who; + char *x; + char *y; + char *z; + } +; + +extern struct strerr strerr_sys; +extern void strerr_sysinit(); + +extern char *strerr(); +extern void strerr_warn(); +extern void strerr_die(); + +#define STRERR(r,se,a) \ +{ se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } + +#define STRERR_SYS(r,se,a) \ +{ se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } +#define STRERR_SYS3(r,se,a,b,c) \ +{ se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } + +#define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se)) +#define strerr_warn5(x1,x2,x3,x4,x5,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se)) +#define strerr_warn4(x1,x2,x3,x4,se) \ +strerr_warn((x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_warn3(x1,x2,x3,se) \ +strerr_warn((x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_warn2(x1,x2,se) \ +strerr_warn((x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_warn1(x1,se) \ +strerr_warn((x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) + +#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se)) +#define strerr_die5(e,x1,x2,x3,x4,x5,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se)) +#define strerr_die4(e,x1,x2,x3,x4,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_die3(e,x1,x2,x3,se) \ +strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_die2(e,x1,x2,se) \ +strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_die1(e,x1,se) \ +strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) + +#define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) +#define strerr_die5sys(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,&strerr_sys) +#define strerr_die4sys(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,&strerr_sys) +#define strerr_die3sys(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,&strerr_sys) +#define strerr_die2sys(e,x1,x2) \ +strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys) +#define strerr_die1sys(e,x1) \ +strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys) + +#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) 0) +#define strerr_die5x(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) 0) +#define strerr_die4x(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) 0) +#define strerr_die3x(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) +#define strerr_die2x(e,x1,x2) \ +strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) +#define strerr_die1x(e,x1) \ +strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) + +#endif diff --git a/strerr=l b/strerr=l new file mode 100644 index 0000000..5181cee --- /dev/null +++ b/strerr=l @@ -0,0 +1,2 @@ +strerr_sys.o +strerr_die.o diff --git a/strerr_die.c b/strerr_die.c new file mode 100644 index 0000000..6092020 --- /dev/null +++ b/strerr_die.c @@ -0,0 +1,37 @@ +#include "substdio.h" +#include "subfd.h" +#include "exit.h" +#include "strerr.h" + +void strerr_warn(x1,x2,x3,x4,x5,x6,se) +char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; +struct strerr *se; +{ + strerr_sysinit(); + + if (x1) substdio_puts(subfderr,x1); + if (x2) substdio_puts(subfderr,x2); + if (x3) substdio_puts(subfderr,x3); + if (x4) substdio_puts(subfderr,x4); + if (x5) substdio_puts(subfderr,x5); + if (x6) substdio_puts(subfderr,x6); + + while(se) { + if (se->x) substdio_puts(subfderr,se->x); + if (se->y) substdio_puts(subfderr,se->y); + if (se->z) substdio_puts(subfderr,se->z); + se = se->who; + } + + substdio_puts(subfderr,"\n"); + substdio_flush(subfderr); +} + +void strerr_die(e,x1,x2,x3,x4,x5,x6,se) +int e; +char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; +struct strerr *se; +{ + strerr_warn(x1,x2,x3,x4,x5,x6,se); + _exit(e); +} diff --git a/strerr_sys.c b/strerr_sys.c new file mode 100644 index 0000000..198198b --- /dev/null +++ b/strerr_sys.c @@ -0,0 +1,12 @@ +#include "error.h" +#include "strerr.h" + +struct strerr strerr_sys; + +void strerr_sysinit() +{ + strerr_sys.who = 0; + strerr_sys.x = error_str(errno); + strerr_sys.y = ""; + strerr_sys.z = ""; +} @@ -0,0 +1,15 @@ +#ifndef SUBFD_H +#define SUBFD_H + +#include "substdio.h" + +extern substdio *subfdin; +extern substdio *subfdinsmall; +extern substdio *subfdout; +extern substdio *subfdoutsmall; +extern substdio *subfderr; + +extern int subfd_read(); +extern int subfd_readsmall(); + +#endif diff --git a/subfderr.c b/subfderr.c new file mode 100644 index 0000000..011ab0f --- /dev/null +++ b/subfderr.c @@ -0,0 +1,7 @@ +#include "readwrite.h" +#include "substdio.h" +#include "subfd.h" + +char subfd_errbuf[256]; +static substdio it = SUBSTDIO_FDBUF(write,2,subfd_errbuf,256); +substdio *subfderr = ⁢ diff --git a/subfdin.c b/subfdin.c new file mode 100644 index 0000000..a11d323 --- /dev/null +++ b/subfdin.c @@ -0,0 +1,13 @@ +#include "readwrite.h" +#include "substdio.h" +#include "subfd.h" + +int subfd_read(fd,buf,len) int fd; char *buf; int len; +{ + if (substdio_flush(subfdout) == -1) return -1; + return read(fd,buf,len); +} + +char subfd_inbuf[SUBSTDIO_INSIZE]; +static substdio it = SUBSTDIO_FDBUF(subfd_read,0,subfd_inbuf,SUBSTDIO_INSIZE); +substdio *subfdin = ⁢ diff --git a/subfdout.c b/subfdout.c new file mode 100644 index 0000000..0aee102 --- /dev/null +++ b/subfdout.c @@ -0,0 +1,7 @@ +#include "readwrite.h" +#include "substdio.h" +#include "subfd.h" + +char subfd_outbuf[SUBSTDIO_OUTSIZE]; +static substdio it = SUBSTDIO_FDBUF(write,1,subfd_outbuf,SUBSTDIO_OUTSIZE); +substdio *subfdout = ⁢ diff --git a/subgetopt.c b/subgetopt.c new file mode 100644 index 0000000..dacf376 --- /dev/null +++ b/subgetopt.c @@ -0,0 +1,79 @@ +/* subgetopt.c, subgetopt.h: (yet another) improved getopt clone, inner layer +D. J. Bernstein, djb@pobox.com. +No dependencies. +No system requirements. +19970228: Cleanups. +931129: Adapted from getopt.c. +No known patent problems. + +Documentation in subgetopt.3. +*/ + +#define SUBGETOPTNOSHORT +#include "subgetopt.h" + +#define sgopt subgetopt +#define optind subgetoptind +#define optpos subgetoptpos +#define optarg subgetoptarg +#define optproblem subgetoptproblem +#define optdone subgetoptdone + +int optind = 1; +int optpos = 0; +char *optarg = 0; +int optproblem = 0; +int optdone = SUBGETOPTDONE; + +int sgopt(argc,argv,opts) +int argc; +char **argv; +char *opts; +{ + int c; + char *s; + + optarg = 0; + if (!argv || (optind >= argc) || !argv[optind]) return optdone; + if (optpos && !argv[optind][optpos]) { + ++optind; + optpos = 0; + if ((optind >= argc) || !argv[optind]) return optdone; + } + if (!optpos) { + if (argv[optind][0] != '-') return optdone; + ++optpos; + c = argv[optind][1]; + if ((c == '-') || (c == 0)) { + if (c) ++optind; + optpos = 0; + return optdone; + } + /* otherwise c is reassigned below */ + } + c = argv[optind][optpos]; + ++optpos; + s = opts; + while (*s) { + if (c == *s) { + if (s[1] == ':') { + optarg = argv[optind] + optpos; + ++optind; + optpos = 0; + if (!*optarg) { + optarg = argv[optind]; + if ((optind >= argc) || !optarg) { /* argument past end */ + optproblem = c; + return '?'; + } + ++optind; + } + } + return c; + } + ++s; + if (*s == ':') ++s; + } + optproblem = c; + return '?'; +} diff --git a/subgetopt.h b/subgetopt.h new file mode 100644 index 0000000..d26c62a --- /dev/null +++ b/subgetopt.h @@ -0,0 +1,24 @@ +#ifndef SUBGETOPT_H +#define SUBGETOPT_H + +#ifndef SUBGETOPTNOSHORT +#define sgopt subgetopt +#define sgoptarg subgetoptarg +#define sgoptind subgetoptind +#define sgoptpos subgetoptpos +#define sgoptproblem subgetoptproblem +#define sgoptprogname subgetoptprogname +#define sgoptdone subgetoptdone +#endif + +#define SUBGETOPTDONE -1 + +extern int subgetopt(); +extern char *subgetoptarg; +extern int subgetoptind; +extern int subgetoptpos; +extern int subgetoptproblem; +extern char *subgetoptprogname; +extern int subgetoptdone; + +#endif diff --git a/substdi.c b/substdi.c new file mode 100644 index 0000000..42407a1 --- /dev/null +++ b/substdi.c @@ -0,0 +1,91 @@ +#include "substdio.h" +#include "byte.h" +#include "error.h" + +static int oneread(op,fd,buf,len) +register int (*op)(); +register int fd; +register char *buf; +register int len; +{ + register int r; + + for (;;) { + r = op(fd,buf,len); + if (r == -1) if (errno == error_intr) continue; + return r; + } +} + +static int getthis(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int r; + register int q; + + r = s->p; + q = r - len; + if (q > 0) { r = len; s->p = q; } else s->p = 0; + byte_copy(buf,r,s->x + s->n); + s->n += r; + return r; +} + +int substdio_feed(s) +register substdio *s; +{ + register int r; + register int q; + + if (s->p) return s->p; + q = s->n; + r = oneread(s->op,s->fd,s->x,q); + if (r <= 0) return r; + s->p = r; + q -= r; + s->n = q; + if (q > 0) /* damn, gotta shift */ byte_copyr(s->x + q,r,s->x); + return r; +} + +int substdio_bget(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int r; + + if (s->p > 0) return getthis(s,buf,len); + r = s->n; if (r <= len) return oneread(s->op,s->fd,buf,r); + r = substdio_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +int substdio_get(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,len); + r = substdio_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +char *substdio_peek(s) +register substdio *s; +{ + return s->x + s->n; +} + +void substdio_seek(s,len) +register substdio *s; +register int len; +{ + s->n += len; + s->p -= len; +} diff --git a/substdio.c b/substdio.c new file mode 100644 index 0000000..d03dff2 --- /dev/null +++ b/substdio.c @@ -0,0 +1,15 @@ +#include "substdio.h" + +void substdio_fdbuf(s,op,fd,buf,len) +register substdio *s; +register int (*op)(); +register int fd; +register char *buf; +register int len; +{ + s->x = buf; + s->fd = fd; + s->op = op; + s->p = 0; + s->n = len; +} diff --git a/substdio.h b/substdio.h new file mode 100644 index 0000000..c3f7f7d --- /dev/null +++ b/substdio.h @@ -0,0 +1,47 @@ +#ifndef SUBSTDIO_H +#define SUBSTDIO_H + +typedef struct substdio { + char *x; + int p; + int n; + int fd; + int (*op)(); +} substdio; + +#define SUBSTDIO_FDBUF(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } + +extern void substdio_fdbuf(); + +extern int substdio_flush(); +extern int substdio_put(); +extern int substdio_bput(); +extern int substdio_putflush(); +extern int substdio_puts(); +extern int substdio_bputs(); +extern int substdio_putsflush(); + +extern int substdio_get(); +extern int substdio_bget(); +extern int substdio_feed(); + +extern char *substdio_peek(); +extern void substdio_seek(); + +#define substdio_fileno(s) ((s)->fd) + +#define SUBSTDIO_INSIZE 8192 +#define SUBSTDIO_OUTSIZE 8192 + +#define substdio_PEEK(s) ( (s)->x + (s)->n ) +#define substdio_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) + +#define substdio_BPUTC(s,c) \ + ( ((s)->n != (s)->p) \ + ? ( (s)->x[(s)->p++] = (c), 0 ) \ + : substdio_bput((s),&(c),1) \ + ) + +extern int substdio_copy(); + +#endif diff --git a/substdio=l b/substdio=l new file mode 100644 index 0000000..55720b5 --- /dev/null +++ b/substdio=l @@ -0,0 +1,7 @@ +substdio.o +substdi.o +substdo.o +subfderr.o +subfdout.o +subfdin.o +substdio_copy.o diff --git a/substdio_copy.c b/substdio_copy.c new file mode 100644 index 0000000..71cf200 --- /dev/null +++ b/substdio_copy.c @@ -0,0 +1,18 @@ +#include "substdio.h" + +int substdio_copy(ssout,ssin) +register substdio *ssout; +register substdio *ssin; +{ + register int n; + register char *x; + + for (;;) { + n = substdio_feed(ssin); + if (n < 0) return -2; + if (!n) return 0; + x = substdio_PEEK(ssin); + if (substdio_put(ssout,x,n) == -1) return -3; + substdio_SEEK(ssin,n); + } +} diff --git a/substdo.c b/substdo.c new file mode 100644 index 0000000..fb616f7 --- /dev/null +++ b/substdo.c @@ -0,0 +1,108 @@ +#include "substdio.h" +#include "str.h" +#include "byte.h" +#include "error.h" + +static int allwrite(op,fd,buf,len) +register int (*op)(); +register int fd; +register char *buf; +register int len; +{ + register int w; + + while (len) { + w = op(fd,buf,len); + if (w == -1) { + if (errno == error_intr) continue; + return -1; /* note that some data may have been written */ + } + if (w == 0) ; /* luser's fault */ + buf += w; + len -= w; + } + return 0; +} + +int substdio_flush(s) +register substdio *s; +{ + register int p; + + p = s->p; + if (!p) return 0; + s->p = 0; + return allwrite(s->op,s->fd,s->x,p); +} + +int substdio_bput(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int n; + + while (len > (n = s->n - s->p)) { + byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; + if (substdio_flush(s) == -1) return -1; + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int substdio_put(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int n; + + n = s->n; + if (len > n - s->p) { + if (substdio_flush(s) == -1) return -1; + /* now s->p == 0 */ + if (n < SUBSTDIO_OUTSIZE) n = SUBSTDIO_OUTSIZE; + while (len > s->n) { + if (n > len) n = len; + if (allwrite(s->op,s->fd,buf,n) == -1) return -1; + buf += n; + len -= n; + } + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int substdio_putflush(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + if (substdio_flush(s) == -1) return -1; + return allwrite(s->op,s->fd,buf,len); +} + +int substdio_bputs(s,buf) +register substdio *s; +register char *buf; +{ + return substdio_bput(s,buf,str_len(buf)); +} + +int substdio_puts(s,buf) +register substdio *s; +register char *buf; +{ + return substdio_put(s,buf,str_len(buf)); +} + +int substdio_putsflush(s,buf) +register substdio *s; +register char *buf; +{ + return substdio_putflush(s,buf,str_len(buf)); +} diff --git a/tcp-environ.5 b/tcp-environ.5 new file mode 100644 index 0000000..b5cb83b --- /dev/null +++ b/tcp-environ.5 @@ -0,0 +1,62 @@ +.TH tcp-environ 5 +.SH NAME +tcp-environ \- TCP-related environment variables +.SH DESCRIPTION +The following environment variables +describe a TCP connection. +They are set up by +.BR tcp-env , +.BR tcpclient , +and +.BR tcpserver . +Note that +.BR TCPLOCALHOST , +.BR TCPREMOTEHOST , +and +.B TCPREMOTEINFO +can contain arbitrary characters. +.TP 5 +PROTO +The string +.BR TCP . +.TP 5 +TCPLOCALHOST +The domain name of the local host, +with uppercase letters converted to lowercase. +If there is no currently available domain name +for the local IP address, +.B TCPLOCALHOST +is not set. +.TP 5 +TCPLOCALIP +The IP address of the local host, in dotted-decimal form. +.TP 5 +TCPLOCALPORT +The local TCP port number, in decimal. +.TP 5 +TCPREMOTEHOST +The domain name of the remote host, +with uppercase letters converted to lowercase. +If there is no currently available domain name +for the remote IP address, +.B TCPREMOTEHOST +is not set. +.TP 5 +TCPREMOTEINFO +A connection-specific string, perhaps a username, +supplied by the remote host +via 931/1413/IDENT/TAP. +If the remote host did not supply connection information, +.B TCPREMOTEINFO +is not set. +.TP 5 +TCPREMOTEIP +The IP address of the remote host. +.TP 5 +TCPREMOTEPORT +The remote TCP port number. +.SH "SEE ALSO" +tcpclient(1), +tcpserver(1), +tcp-env(1), +tcp(4) diff --git a/tcp-environ=0 b/tcp-environ=0 new file mode 100644 index 0000000..da3c189 --- /dev/null +++ b/tcp-environ=0 @@ -0,0 +1 @@ +tcp-environ.5 diff --git a/tcpcat.sh b/tcpcat.sh new file mode 100644 index 0000000..485cb26 --- /dev/null +++ b/tcpcat.sh @@ -0,0 +1 @@ +exec BIN/tcpclient -RHl0 -- "${1-0}" "${2-17}" sh -c 'exec cat <&6' diff --git a/tcpcat=s b/tcpcat=s new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tcpcat=s diff --git a/tcpclient.1 b/tcpclient.1 new file mode 100644 index 0000000..9c91902 --- /dev/null +++ b/tcpclient.1 @@ -0,0 +1,134 @@ +.TH tcpclient 1 +.SH NAME +tcpclient \- create an outgoing TCP connection +.SH SYNOPSIS +.B tcpclient +[ +.B \-qQvdDhHrR +] +[ +.B \-l\fIlocalname +] +[ +.B \-p\fIlocport +] +[ +.B \-t\fItimeoutinfo +] +[ +.B \-T\fItimeoutconn +] +.I host +.I port +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B tcpclient +is a TCP UCSPI client. +It attempts to connect to a TCP server; +if it is successful, it runs +.I program +with the given arguments, +with descriptor 6 reading from the network +and descriptor 7 writing to the network. + +The server's address is given by +.I host +and +.IR port . +.I host +may be 0, referring to the local machine, +or a dotted-decimal IP address, +or a host name; +if a host has several IP addresses, +.B tcpclient +tries each in turn. +.I port +may be a numeric port number +or a port name. + +.B tcpclient +sets up several environment variables, +as described in +.B tcp-environ(5). +.SH OPTIONS +.TP +.B \-p\fIlocport +Use +.I locport +for the local side of the connection; +quit if +.I locport +is not available. +.TP +.B \-q +Quiet. +Do not print any messages. +.TP +.B \-Q +(Default.) +Print error messages. +.TP +.B \-v +Verbose. +Print all available messages. +.TP +.B \-T\fItimeoutconn +Give up on the +connection attempt +after +.I timeoutconn +seconds. Default: 60. +This timeout applies to each IP address tried. +.TP +.B \-h +(Default.) +Look up the remote host name for +.BR TCPREMOTEHOST . +.TP +.B \-H +Do not look up the remote host name; +unset +.BR TCPREMOTEHOST . +.TP +.B \-l\fIlocalname +Do not look up the local host name; +use +.I localname +for +.BR TCPLOCALHOST . +.TP +.B \-r +(Default.) +Attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-R +Do not attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-t\fItimeoutinfo +Give up on the +.B TCPREMOTEINFO +connection attempt +after +.I timeoutinfo +seconds. Default: 26. +.TP +.B \-d +(Default.) +Delay sending data for a fraction of a second whenever the +remote host is responding slowly, +to make better use of the network. +.TP +.B \-D +Never delay sending data; +enable TCP_NODELAY. +This is appropriate for interactive connections. +.SH "SEE ALSO" +tcpserver(1), +tcp-environ(5) diff --git a/tcpclient.c b/tcpclient.c new file mode 100644 index 0000000..a22a20a --- /dev/null +++ b/tcpclient.c @@ -0,0 +1,236 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> + +#include "substdio.h" +#include "stralloc.h" +#include "str.h" +#include "byte.h" +#include "error.h" +#include "sig.h" +#include "subfd.h" +#include "fd.h" +#include "ip.h" +#include "ipalloc.h" +#include "case.h" +#include "sgetopt.h" +#include "exit.h" +#include "scan.h" +#include "fmt.h" +#include "env.h" +#include "dns.h" +#include "remoteinfo.h" + +int verbosity = 1; +char temp[IPFMT + FMT_ULONG]; + +void out(s) char *s; { if (verbosity) substdio_puts(subfderr,s); } +void flush() { if (verbosity) substdio_flush(subfderr); } + +void usage() +{ out("tcpclient: usage: \ +tcpclient [ -qQvdDrRU ] [ -plocport ] [ -llocalname ] [ -ttimeoutinfo ] \ +[ -Ttimeoutconn ] host port program\n"); flush(); _exit(100); } +void die(s) char *s; +{ out("tcpclient: fatal: "); out(s); out("\n"); flush(); _exit(111); } +void diep(s) char *s; +{ char *x = error_str(errno); + out("tcpclient: fatal: "); out(s); out(": "); + out(x); out("\n"); flush(); _exit(111); } +void nomem() +{ die("out of memory"); } +void warnconnect(ipr) struct ip_address *ipr; +{ + char *x = error_str(errno); + temp[ip_fmt(temp,ipr)] = 0; + out("tcpclient: unable to connect to "); out(temp); out(": "); + out(x); out("\n"); flush(); } +void infoconnected(ipr) struct ip_address *ipr; +{ if (verbosity < 2) return; + temp[ip_fmt(temp,ipr)] = 0; + out("tcpclient: connected to "); out(temp); out("\n"); flush(); } + +int flagdelay = 1; +int flagremoteinfo = 1; +int flagremotehost = 1; +char *forcelocal = 0; +unsigned long timeout = 26; +unsigned long timeout2 = 60; + +stralloc tmp = {0}; +ipalloc ia = {0}; + +struct sockaddr_in salocal; +struct ip_address iplocal; +unsigned long portlocal; +struct sockaddr_in saremote; +struct ip_address ipremote; +unsigned long portremote; + +void main(argc,argv) +int argc; +char **argv; +{ + int s; + int dummy; + int opt; + char *hostname; + char *portname; + struct servent *se; + int j; + + portlocal = 0; + + while ((opt = getopt(argc,argv,"dDvqQLhHrRp:Ut:T:l:")) != opteof) + switch(opt) { + case 'd': flagdelay = 1; break; + case 'D': flagdelay = 0; break; + case 'v': verbosity = 2; break; + case 'q': verbosity = 0; break; + case 'Q': verbosity = 1; break; + case 'l': forcelocal = optarg; break; + case 'H': flagremotehost = 0; break; + case 'h': flagremotehost = 1; break; + case 'R': flagremoteinfo = 0; break; + case 'r': flagremoteinfo = 1; break; + case 'p': scan_ulong(optarg,&portlocal); break; + case 't': scan_ulong(optarg,&timeout); break; + case 'T': scan_ulong(optarg,&timeout2); break; + case 'U': usage(); + default: _exit(100); + } + argc -= optind; + argv += optind; + + hostname = *argv++; + if (!hostname) usage(); + portname = *argv++; + if (!portname) usage(); + if (!*argv) usage(); + + close(6); + close(7); + sig_pipeignore(); + + dns_init(1); + + byte_zero(&salocal,sizeof(salocal)); + salocal.sin_family = AF_INET; + salocal.sin_addr.s_addr = INADDR_ANY; + salocal.sin_port = htons((unsigned short) portlocal); + + byte_zero(&saremote,sizeof(saremote)); + saremote.sin_family = AF_INET; + + if (!portname[scan_ulong(portname,&portremote)]) + ; + else { + se = getservbyname(portname,"tcp"); + if (!se) die("unable to figure out port number"); + portremote = ntohs(se->s_port); + /* i continue to be amazed at the stupidity of the s_port interface */ + } + + if (!str_diff(hostname,"0")) hostname = "0.0.0.0"; + + if (!hostname[ip_scan(hostname,&ipremote)]) { + s = socket(AF_INET,SOCK_STREAM,0); + if (s == -1) diep("unable to create socket"); + if (bind(s,(struct sockaddr *) &salocal,sizeof(salocal)) == -1) + diep("unable to bind"); + if (timeoutconn(s,&ipremote,portremote,(int) timeout2) == -1) { + warnconnect(&ipremote); + _exit(111); + } + } + else { + if (!stralloc_copys(&tmp,hostname)) nomem(); + switch(dns_ip(&ia,&tmp)) { + case DNS_SOFT: die("temporarily unable to figure out host address"); + case DNS_HARD: die("unable to figure out host address"); + case DNS_MEM: nomem(); + } + if (ia.len == 0) die("no IP addresses for that host"); + for (j = 0;j < ia.len;++j) { + s = socket(AF_INET,SOCK_STREAM,0); + if (s == -1) diep("unable to create socket"); + if (bind(s,(struct sockaddr *) &salocal,sizeof(salocal)) == -1) + diep("unable to bind"); + byte_copy(&ipremote,4,&ia.ix[j].ip); + if (timeoutconn(s,&ipremote,portremote,(int) timeout2) == 0) break; + warnconnect(&ipremote); + close(s); + } + if (j == ia.len) _exit(111); + } + + if (!flagdelay) { + int opt = 1; + setsockopt(s,IPPROTO_TCP,1,&opt,sizeof(opt)); /* 1 == TCP_NODELAY */ + /* if it fails, bummer */ + } + + if (!env_init()) nomem(); + if (!env_put("PROTO=TCP")) nomem(); + if (!env_unset("TCPLOCALHOST")) nomem(); + if (!env_unset("TCPREMOTEHOST")) nomem(); + if (!env_unset("TCPREMOTEINFO")) nomem(); + + dummy = sizeof(salocal); + if (getsockname(s,(struct sockaddr *) &salocal,&dummy) == -1) + diep("unable to get local address"); + portlocal = ntohs(salocal.sin_port); + byte_copy(&iplocal,4,&salocal.sin_addr); + + temp[fmt_ulong(temp,portlocal)] = 0; + if (!env_put2("TCPLOCALPORT",temp)) nomem(); + temp[ip_fmt(temp,&iplocal)] = 0; + if (!env_put2("TCPLOCALIP",temp)) nomem(); + if (forcelocal) { + if (!env_put2("TCPLOCALHOST",forcelocal)) nomem(); + } + else + switch(dns_ptr(&tmp,&iplocal)) { + case DNS_MEM: nomem(); + case 0: + if (!stralloc_0(&tmp)) nomem(); + case_lowers(tmp.s); + if (!env_put2("TCPLOCALHOST",tmp.s)) nomem(); + } + + dummy = sizeof(saremote); + if (getpeername(s,(struct sockaddr *) &saremote,&dummy) == -1) + diep("unable to get remote address"); + portremote = ntohs(saremote.sin_port); + byte_copy(&ipremote,4,&saremote.sin_addr); + + infoconnected(&ipremote); + + temp[fmt_ulong(temp,portremote)] = 0; + if (!env_put2("TCPREMOTEPORT",temp)) nomem(); + temp[ip_fmt(temp,&ipremote)] = 0; + if (!env_put2("TCPREMOTEIP",temp)) nomem(); + if (flagremotehost) + switch(dns_ptr(&tmp,&ipremote)) { + case DNS_MEM: nomem(); + case 0: + if (!stralloc_0(&tmp)) nomem(); + case_lowers(tmp.s); + if (!env_put2("TCPREMOTEHOST",tmp.s)) nomem(); + } + if (flagremoteinfo) { + char *rinfo; + rinfo = remoteinfo_get(&ipremote,portremote,&iplocal,portlocal,(int) timeout); + if (rinfo) + if (!env_put2("TCPREMOTEINFO",rinfo)) nomem(); + } + + if (fd_move(6,s) == -1) diep("unable to set up descriptor 6"); + if (fd_copy(7,6) == -1) diep("unable to set up descriptor 7"); + sig_pipedefault(); + + execvp(*argv,argv); + diep("unable to execute"); +} diff --git a/tcpclient=0 b/tcpclient=0 new file mode 100644 index 0000000..cea39bf --- /dev/null +++ b/tcpclient=0 @@ -0,0 +1 @@ +tcpclient.1 diff --git a/tcpclient=x b/tcpclient=x new file mode 100644 index 0000000..569d485 --- /dev/null +++ b/tcpclient=x @@ -0,0 +1,21 @@ +ip.o +ipalloc.o +dns.o +remoteinfo.o +timeoutconn.o +timeoutread.o +timeoutwrite.o +stralloc.a +env.a +alloc.a +ndelay.a +substdio.a +error.a +str.a +sig.a +fd.a +case.a +getopt.a +fs.a +dns.lib +socket.lib diff --git a/tcprules.1 b/tcprules.1 new file mode 100644 index 0000000..6bf8dcc --- /dev/null +++ b/tcprules.1 @@ -0,0 +1,207 @@ +.TH tcprules 1 +.SH NAME +tcprules \- compile rules for tcpserver +.SH SYNOPSIS +.B tcprules +.I rules.cdb +.I rules.tmp +.SH OVERVIEW +.B tcpserver +optionally follows rules to decide whether a TCP connection is acceptable. +For example, a rule of + +.EX + 18.23.0.32:deny +.EE + +prohibits connections from IP address 18.23.0.32. + +.B tcprules +reads rules from its standard input +and writes them into +.I rules.cdb +in a binary format suited +for quick access by +.BR tcpserver . + +.B tcprules +can be used while +.B tcpserver +is running: +it ensures that +.I rules.cdb +is updated atomically. +It does this by first writing the rules to +.I rules.tmp +and then moving +.I rules.tmp +on top of +.IR rules.cdb . +If +.I rules.tmp +already exists, it is destroyed. +The directories containing +.I rules.cdb +and +.I rules.tmp +must be writable to +.BR tcprules ; +they must also be on the same filesystem. + +If there is a problem with the input, +.B tcprules +complains and leaves +.I rules.cdb +alone. + +The binary +.I rules.cdb +format is portable across machines. +.SH "RULE FORMAT" +A rule takes up one line. +A file containing rules +may also contain comments: lines beginning with # are ignored. + +Each rule contains an +.BR address , +a colon, +and a list of +.BR instructions , +with no extra spaces. +When +.B tcpserver +receives a connection from that address, +it follows the instructions. +.SH "ADDRESSES" +.B tcpserver +starts by looking for a rule with address +.IR TCPREMOTEINFO\fB@\fITCPREMOTEIP . +If it doesn't find one, or if +.I TCPREMOTEINFO +is not set, it tries the address +.IR TCPREMOTEIP . +If that doesn't work, it tries shorter and shorter prefixes of +.I TCPREMOTEIP +ending with a dot. +If none of them work, it tries the empty string. + +For example, here are some rules: + +.EX + joe@127.0.0.1:first +.br + 18.23.0.32:second +.br + 127.:third +.br + :fourth +.EE + +If +.I TCPREMOTEIP +is +.BR 10.119.75.38 , +.B tcpserver +will follow the +.B fourth +instructions. + +If +.I TCPREMOTEIP +is +.BR 18.23.0.32 , +.B tcpserver +will follow the +.B second +instructions. + +If +.I TCPREMOTEINFO +is +.B bill +and +.I TCPREMOTEIP +is +.BR 127.0.0.1 , +.B tcpserver +will follow the +.B third +instructions. + +If +.I TCPREMOTEINFO +is +.B joe +and +.I TCPREMOTEIP +is +.BR 127.0.0.1 , +.B tcpserver +will follow the +.B first +instructions. +.SH "ADDRESS RANGES" +.B tcprules +treats +.B 1.2.3.37-53:ins +as an abbreviation +for the rules +.BR 1.2.3.37:ins , +.BR 1.2.3.38:ins , +and so on up through +.BR 1.2.3.53:ins . +Similarly, +.BR 10.2-3.:ins +is an abbreviation for +.B 10.2.:ins +and +.BR 10.3.:ins . +.SH "INSTRUCTIONS" +The instructions in a rule must begin with either +.B allow +or +.BR deny . +.B deny +tells +.B tcpserver +to drop the connection without running anything. +For example, the rule + +.EX + :deny +.EE + +tells +.B tcpserver +to drop all connections that aren't handled by more specific rules. + +The instructions may continue with some environment variables, +in the format +.IR ,VAR="VALUE" . +.B tcpserver +adds +.I VAR=VALUE +to the current environment. +For example, + +.EX + 10.0.:allow,RELAYCLIENT="@fix.me" +.EE + +adds +.B RELAYCLIENT=@fix.me +to the environment. +The quotes here may be replaced by any repeated character: + +.EX + 10.0.:allow,RELAYCLIENT=/@fix.me/ +.EE + +Any number of variables may be listed: + +.EX + 127.0.0.1:allow,RELAYCLIENT="",TCPLOCALHOST="movie.edu" +.EE +.SH "SEE ALSO" +tcpserver(1), +tcp-environ(5) diff --git a/tcprules.c b/tcprules.c new file mode 100644 index 0000000..1264fea --- /dev/null +++ b/tcprules.c @@ -0,0 +1,177 @@ +#include "strerr.h" +#include "stralloc.h" +#include "getln.h" +#include "substdio.h" +#include "subfd.h" +#include "exit.h" +#include "fmt.h" +#include "byte.h" +#include "cdbmss.h" + +#define FATAL "tcprules: fatal: " + +unsigned long linenum = 0; +char *fntemp; +char *fn; + +stralloc line = {0}; +int match = 1; + +stralloc address = {0}; +stralloc data = {0}; +stralloc key = {0}; + +struct cdbmss cdbmss; + +void die_nomem() { + strerr_die2x(111,FATAL,"out of memory"); +} +void usage() { + strerr_die1x(100,"tcprules: usage: tcprules rules.cdb rules.tmp"); +} +void die_bad() { + if (!stralloc_0(&line)) die_nomem(); + strerr_die3x(100,FATAL,"unable to parse this line: ",line.s); +} +void die_write() { + strerr_die4sys(111,FATAL,"unable to write to ",fntemp,": "); +} + +char strnum[FMT_ULONG]; +stralloc sanum = {0}; + +void getnum(buf,len,u) +char *buf; +int len; +unsigned long *u; +{ + if (!stralloc_copyb(&sanum,buf,len)) die_nomem(); + if (!stralloc_0(&sanum)) die_nomem(); + if (sanum.s[scan_ulong(sanum.s,u)]) die_bad(); +} + +void doaddressdata() +{ + int i; + int left; + int right; + unsigned long bot; + unsigned long top; + + if (byte_chr(address.s,address.len,'@') == address.len) { + i = byte_chr(address.s,address.len,'-'); + if (i < address.len) { + left = byte_rchr(address.s,i,'.'); + if (left == i) left = 0; else ++left; + + ++i; + right = i + byte_chr(address.s + i,address.len - i,'.'); + + getnum(address.s + left,i - 1 - left,&bot); + getnum(address.s + i,right - i,&top); + if (top > 255) top = 255; + + while (bot <= top) { + if (!stralloc_copyb(&key,address.s,left)) die_nomem(); + if (!stralloc_catb(&key,strnum,fmt_ulong(strnum,bot))) die_nomem(); + if (!stralloc_catb(&key,address.s + right,address.len - right)) die_nomem(); + if (cdbmss_add(&cdbmss,key.s,key.len,data.s,data.len) == -1) die_write(); + ++bot; + } + + return; + } + } + + if (!stralloc_copy(&key,&address)) die_nomem(); + if (cdbmss_add(&cdbmss,key.s,key.len,data.s,data.len) == -1) die_write(); +} + +void main(argc,argv) +int argc; +char **argv; +{ + int colon; + char *x; + int len; + int fd; + int i; + char ch; + + fn = argv[1]; + if (!fn) usage(); + fntemp = argv[2]; + if (!fntemp) usage(); + + fd = open_trunc(fntemp); + if (fd == -1) + strerr_die4sys(111,FATAL,"unable to create ",fntemp,": "); + if (cdbmss_start(&cdbmss,fd) == -1) die_write(); + + while (match) { + if (getln(subfdin,&line,&match,'\n') == -1) + strerr_die2sys(111,FATAL,"unable to read input: "); + + x = line.s; len = line.len; + + if (!len) break; + if (x[0] == '#') continue; + if (x[0] == '\n') continue; + + while (len) { + ch = x[len - 1]; + if (ch != '\n') if (ch != ' ') if (ch != '\t') break; + --len; + } + line.len = len; /* for die_bad() */ + + colon = byte_chr(x,len,':'); + if (colon == len) continue; + + if (!stralloc_copyb(&address,x,colon)) die_nomem(); + if (!stralloc_copys(&data,"")) die_nomem(); + + x += colon + 1; len -= colon + 1; + + if ((len >= 4) && byte_equal(x,4,"deny")) { + if (!stralloc_catb(&data,"D",2)) die_nomem(); + x += 4; len -= 4; + } + else if ((len >= 5) && byte_equal(x,5,"allow")) { + x += 5; len -= 5; + } + else + die_bad(); + + while (len) + switch(*x) { + case ',': + i = byte_chr(x,len,'='); + if (i == len) die_bad(); + if (!stralloc_catb(&data,"+",1)) die_nomem(); + if (!stralloc_catb(&data,x + 1,i)) die_nomem(); + x += i + 1; len -= i + 1; + if (!len) die_bad(); + ch = *x; + x += 1; len -= 1; + i = byte_chr(x,len,ch); + if (i == len) die_bad(); + if (!stralloc_catb(&data,x,i)) die_nomem(); + if (!stralloc_0(&data)) die_nomem(); + x += i + 1; len -= i + 1; + break; + default: + die_bad(); + } + + doaddressdata(); + } + + if (cdbmss_finish(&cdbmss) == -1) die_write(); + if (fsync(fd) == -1) die_write(); + if (close(fd) == -1) die_write(); /* NFS stupidity */ + if (rename(fntemp,fn)) + strerr_die6sys(111,FATAL,"unable to move ",fntemp," to ",fn,": "); + + _exit(0); +} diff --git a/tcprules=0 b/tcprules=0 new file mode 100644 index 0000000..e12053d --- /dev/null +++ b/tcprules=0 @@ -0,0 +1 @@ +tcprules.1 diff --git a/tcprules=x b/tcprules=x new file mode 100644 index 0000000..b534828 --- /dev/null +++ b/tcprules=x @@ -0,0 +1,12 @@ +cdbmss.o +cdbmake.a +getln.a +strerr.a +stralloc.a +substdio.a +alloc.a +error.a +open.a +seek.a +str.a +fs.a diff --git a/tcpserver.1 b/tcpserver.1 new file mode 100644 index 0000000..77000d6 --- /dev/null +++ b/tcpserver.1 @@ -0,0 +1,220 @@ +.TH tcpserver 1 +.SH NAME +tcpserver \- accept incoming TCP connections +.SH SYNOPSIS +.B tcpserver +[ +.B \-qQvdDoOpPhHrR1 +] +[ +.B \-c\fIlimit +] +[ +.B \-b\fIbacklog +] +[ +.B \-x\fIrules.cdb +] +[ +.B \-g\fIgid +] +[ +.B \-u\fIuid +] +[ +.B \-l\fIlocalname +] +[ +.B \-t\fItimeout +] +.I host +.I port +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B tcpserver +waits for connections from TCP clients. +For each connection, it runs +.I program +with the given arguments, +with descriptor 0 reading from the network +and descriptor 1 writing to the network. + +The server's address is given by +.I host +and +.IR port . +.I host +can be 0, allowing connections from any host; +or a particular IP address, +allowing connections only to that address; +or a host name, allowing connections to the first IP address +for that host. +.I port +may be a numeric port number +or a port name. +If +.I port +is 0, +.B tcpserver +will choose a free port. + +.B tcpserver +sets up several environment variables, +as described in +.B tcp-environ(5). + +.B tcpserver +exits when it receives SIGTERM. +.SH "OPTIONS" +.TP +.B \-c\fIlimit +Do not handle more than +.I limit +simultaneous connections. +If there are +.I limit +simultaneous copies of +.I program +running, defer acceptance of a new connection +until one copy finishes. +.I limit +must be a positive integer. +Default: 40. +.TP +.B \-x\fIrules.cdb +Follow the rules compiled into +.I rules.cdb +by +.BR tcprules . +These rules may specify setting environment variables +or rejecting connections from bad sources. +.B tcpserver +does not read +.I rules.cdb +into memory; +you can rerun +.B tcprules +to change +.BR tcpserver 's +behavior on the fly. +.TP +.B \-g\fIgid +Switch group ID to +.I gid +after preparing to receive connections. +.I gid +must be a positive integer. +.TP +.B \-u\fIuid +Switch user ID to +.I uid +after preparing to receive connections. +.I uid +must be a positive integer. +.TP +.B \-1 +After preparing to receive connections, +print the local port number to standard output. +.TP +.B \-q +Quiet. +Do not print any messages. +.TP +.B \-Q +(Default.) +Print error messages. +.TP +.B \-v +Verbose. +Print all available messages. +.TP +.B \-b\fIbacklog +Allow up to +.I backlog +simultaneous SYN_RECEIVEDs. +Default: 20. +On some systems, +.I backlog +is silently limited to 5. +See +.BR listen (2) +for more details. +.TP +.B \-o +Leave IP options alone. +If the client is sending packets along an IP source route, +send packets back along the same route. +.TP +.B \-O +(Default.) +Kill IP options. +A client can still use source routing to connect and to send data, +but packets will be sent back along the default route. +.TP +.B \-d +(Default.) +Delay sending data for a fraction of a second whenever the +remote host is responding slowly, +to make better use of the network. +.TP +.B \-D +Never delay sending data; +enable TCP_NODELAY. +This is appropriate for interactive connections. +.SH "DATA-GATHERING OPTIONS" +.TP +.B \-p +Paranoid. +After looking up the remote host name, +look up the IP addresses for that name, +and make sure one of them matches +.BR TCPREMOTEIP . +If none of them do, +unset +.BR TCPREMOTEHOST . +.TP +.B \-P +(Default.) +Not paranoid. +.TP +.B \-h +(Default.) +Look up the remote host name and set +.BR TCPREMOTEHOST . +.TP +.B \-H +Do not look up the remote host name. +.TP +.B \-l\fIlocalname +Do not look up the local host name; +use +.I localname +for +.BR TCPLOCALHOST . +.TP +.B \-r +(Default.) +Attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-R +Do not attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-t\fItimeout +Give up on the +.B TCPREMOTEINFO +connection attempt +after +.I timeout +seconds. Default: 26. +.SH "SEE ALSO" +tcpclient(1), +tcprules(1), +listen(2), +tcp-environ(5) diff --git a/tcpserver.c b/tcpserver.c new file mode 100644 index 0000000..3aa6f4e --- /dev/null +++ b/tcpserver.c @@ -0,0 +1,475 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> + +#include "strerr.h" +#include "substdio.h" +#include "stralloc.h" +#include "alloc.h" +#include "readwrite.h" +#include "fd.h" +#include "sig.h" +#include "wait.h" +#include "ip.h" +#include "ipalloc.h" +#include "dns.h" +#include "str.h" +#include "case.h" +#include "byte.h" +#include "sgetopt.h" +#include "remoteinfo.h" +#include "exit.h" +#include "open.h" +#include "scan.h" +#include "fmt.h" +#include "env.h" +#include "cdb.h" + +#define FATAL "tcpserver: fatal: " +#define DROP "tcpserver: warning: dropping connection, " +int verbosity = 1; + +void die_nomem() +{ + if (verbosity) strerr_warn2(FATAL,"out of memory",0); + _exit(111); +} +void drop_nomem() +{ + if (verbosity) strerr_warn2(DROP,"out of memory",0); + _exit(111); +} +void usage() +{ + if (verbosity) strerr_warn1("\ +tcpserver: usage: \ +tcpserver [ -qQvdDoOpPhHrR1 ] \ +[ -xrules.cdb ] \ +[ -bbacklog ] [ -climit ] [ -ttimeout ] [ -llocalname ] [ -ggid ] [ -uuid ] \ +host port program",0); + _exit(100); +} + +void safeappend(sa,s) +stralloc *sa; +char *s; +{ + char ch; + while (ch = *s++) { + if (ch < 33) ch = '?'; + if (ch > 126) ch = '?'; + if (ch == '%') ch = '?'; /* logger stupidity */ + if (ch == ':') ch = '?'; + if (!stralloc_append(sa,&ch)) drop_nomem(); + } +} + +char strnum[FMT_ULONG]; +char strnum2[FMT_ULONG]; +stralloc tmp = {0}; +ipalloc ia = {0}; + +unsigned long numchildren = 0; + +char tcpremoteip[IPFMT]; +char tcpremoteport[IPFMT]; +char *tcpremoteinfo; +struct sockaddr_in saremote; +struct ip_address ipremote; +unsigned long portremote; + +char tcplocalip[IPFMT]; +char tcplocalport[IPFMT]; +struct sockaddr_in salocal; +struct ip_address iplocal; +unsigned long portlocal; + +int fdrules; +char *fnrules = 0; +int flagdeny = 0; + +void printenv() +{ + char *tcplocalhost; + char *tcpremotehost; + + if (verbosity < 2) return; + + tcplocalhost = env_get("TCPLOCALHOST"); + tcpremotehost = env_get("TCPREMOTEHOST"); + + if (!tcplocalhost) tcplocalhost = ""; + if (!tcpremotehost) tcpremotehost = ""; + + if (!stralloc_copys(&tmp,"tcpserver: ")) drop_nomem(); + if (!stralloc_cats(&tmp,flagdeny ? "deny " : "ok ")) drop_nomem(); + if (!stralloc_catb(&tmp,strnum,fmt_ulong(strnum,getpid()))) drop_nomem(); + if (!stralloc_cats(&tmp," ")) drop_nomem(); + safeappend(&tmp,tcplocalhost); + if (!stralloc_cats(&tmp,":")) drop_nomem(); + safeappend(&tmp,tcplocalip); + if (!stralloc_cats(&tmp,":")) drop_nomem(); + safeappend(&tmp,tcplocalport); + if (!stralloc_cats(&tmp," ")) drop_nomem(); + safeappend(&tmp,tcpremotehost); + if (!stralloc_cats(&tmp,":")) drop_nomem(); + safeappend(&tmp,tcpremoteip); + if (!stralloc_cats(&tmp,":")) drop_nomem(); + safeappend(&tmp,tcpremoteinfo ? tcpremoteinfo : ""); + if (!stralloc_cats(&tmp,":")) drop_nomem(); + safeappend(&tmp,tcpremoteport); + if (!stralloc_0(&tmp)) drop_nomem(); + + strerr_warn1(tmp.s,0); +} + +void printpid() +{ + if (verbosity < 2) return; + strnum[fmt_ulong(strnum,(unsigned long) getpid())] = 0; + strnum2[fmt_ulong(strnum2,numchildren)] = 0; + strerr_warn6("tcpserver: pid ",strnum," num ",strnum2," from ",tcpremoteip,0); +} + +char printbuf[16]; +struct substdio print = SUBSTDIO_FDBUF(write,1,printbuf,sizeof(printbuf)); +void printlocalport() +{ + substdio_puts(&print,tcplocalport); + substdio_puts(&print,"\n"); + substdio_flush(&print); +} + +void sigterm() { _exit(0); } + +void sigchld() +{ + int wstat; + int pid; + + while ((pid = wait_nohang(&wstat)) > 0) { + if (numchildren) --numchildren; + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,(unsigned long) pid)] = 0; + strnum2[fmt_ulong(strnum2,(unsigned long) wstat)] = 0; + strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0); + } + } +} + +void drop_rules() +{ + if (verbosity) strerr_warn4(DROP,"unable to read ",fnrules,": ",&strerr_sys); + _exit(111); +} + +int dorule() +{ + char *data; + uint32 dlen32; + unsigned int datalen; + unsigned int next0; + + switch(cdb_seek(fdrules,tmp.s,tmp.len,&dlen32)) { + case -1: drop_rules(); + case 0: return 0; + } + + datalen = dlen32; + data = alloc(datalen); + if (!data) drop_nomem(); + if (cdb_bread(fdrules,data,datalen) != 0) drop_rules(); + + while ((next0 = byte_chr(data,datalen,0)) < datalen) { + switch(data[0]) { + case 'D': flagdeny = 1; break; + case '+': if (!env_put(data + 1)) drop_nomem(); break; + } + data += next0 + 1; datalen -= next0 + 1; + } + return 1; +} + +void rules() +{ + if (!fnrules) return; + + fdrules = open_read(fnrules); + if (fdrules == -1) drop_rules(); + + if (tcpremoteinfo) { + if (!stralloc_copys(&tmp,tcpremoteinfo)) drop_nomem(); + if (!stralloc_cats(&tmp,"@")) drop_nomem(); + if (!stralloc_cats(&tmp,tcpremoteip)) drop_nomem(); + if (dorule()) goto done; + } + + if (!stralloc_copys(&tmp,tcpremoteip)) drop_nomem(); + if (dorule()) goto done; + while (tmp.len > 0) { + if (tcpremoteip[tmp.len - 1] == '.') + if (dorule()) goto done; + --tmp.len; + } + + dorule(); + + done: + close(fdrules); +} + +int flagkillopts = 1; +int flagdelay = 1; +int flagremoteinfo = 1; +int flagremotehost = 1; +int flagparanoid = 0; +int flag1 = 0; +unsigned long backlog = 20; +unsigned long timeout = 26; +unsigned long uid = 0; +unsigned long gid = 0; +char *forcelocal = 0; +unsigned long limit = 40; + +void main(argc,argv) +int argc; +char **argv; +{ + int s; + int t; + int dummy; + int opt; + char *hostname; + char *portname; + struct servent *se; + int j; + + while ((opt = getopt(argc,argv,"dDvqQhHrR1x:t:u:g:l:b:c:pPoO")) != opteof) + switch(opt) { + case 'b': scan_ulong(optarg,&backlog); break; + case 'c': scan_ulong(optarg,&limit); break; + case 'x': fnrules = optarg; break; + case 'd': flagdelay = 1; break; + case 'D': flagdelay = 0; break; + case 'v': verbosity = 2; break; + case 'q': verbosity = 0; break; + case 'Q': verbosity = 1; break; + case 'P': flagparanoid = 0; break; + case 'p': flagparanoid = 1; break; + case 'O': flagkillopts = 1; break; + case 'o': flagkillopts = 0; break; + case 'H': flagremotehost = 0; break; + case 'h': flagremotehost = 1; break; + case 'R': flagremoteinfo = 0; break; + case 'r': flagremoteinfo = 1; break; + case 't': scan_ulong(optarg,&timeout); break; + case 'g': scan_ulong(optarg,&gid); break; + case 'u': scan_ulong(optarg,&uid); break; + case '1': flag1 = 1; break; + case 'l': forcelocal = optarg; break; + default: usage(); + } + argc -= optind; + argv += optind; + + hostname = *argv++; + if (!hostname) usage(); + portname = *argv++; + if (!portname) usage(); + if (!*argv) usage(); + + sig_pipeignore(); + sig_termcatch(sigterm); + sig_childcatch(sigchld); + + dns_init(1); + + byte_zero(&salocal,sizeof(salocal)); + salocal.sin_family = AF_INET; + + if (!portname[scan_ulong(portname,&portlocal)]) + salocal.sin_port = htons((unsigned short) portlocal); + else { + se = getservbyname(portname,"tcp"); + if (!se) { + if (verbosity) strerr_warn3(FATAL,"unable to figure out number for port ",portname,0); + _exit(111); + } + salocal.sin_port = se->s_port; + } + + if (str_equal(hostname,"")) hostname = "0.0.0.0"; + if (str_equal(hostname,"0")) hostname = "0.0.0.0"; + + if (hostname[ip_scan(hostname,&iplocal)]) { + if (!stralloc_copys(&tmp,hostname)) die_nomem(); + switch(dns_ip(&ia,&tmp)) { + case DNS_MEM: + die_nomem(); + case DNS_HARD: + if (verbosity) strerr_warn3(FATAL,"unable to figure out address for host ",hostname,0); + _exit(111); + case DNS_SOFT: + if (verbosity) strerr_warn3(FATAL,"temporarily unable to figure out address for host ",hostname,0); + _exit(111); + } + if (!ia.len) { + if (verbosity) strerr_warn3(FATAL,"no IP addresses for host ",hostname,0); + _exit(111); + } + byte_copy(&iplocal,4,&ia.ix[0].ip); + } + + byte_copy(&salocal.sin_addr,4,&iplocal); + s = socket(AF_INET,SOCK_STREAM,0); + if (s == -1) { + if (verbosity) strerr_warn2(FATAL,"unable to create socket: ",&strerr_sys); + _exit(111); + } + + { + int opt = 1; + setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); + } + + if (bind(s,(struct sockaddr *) &salocal,sizeof(salocal)) == -1) { + if (verbosity) strerr_warn2(FATAL,"unable to bind: ",&strerr_sys); + _exit(111); + } + dummy = sizeof(salocal); + if (getsockname(s,(struct sockaddr *) &salocal,&dummy) == -1) { + if (verbosity) strerr_warn2(FATAL,"unable to get local address: ",&strerr_sys); + _exit(111); + } + if (listen(s,backlog) == -1) { + if (verbosity) strerr_warn2(FATAL,"unable to listen: ",&strerr_sys); + _exit(111); + } + + if (gid) if (setgid(gid) == -1) { + if (verbosity) strerr_warn2(FATAL,"unable to set gid: ",&strerr_sys); + _exit(100); + } + if (uid) if (setuid(uid) == -1) { + if (verbosity) strerr_warn2(FATAL,"unable to set uid: ",&strerr_sys); + _exit(100); + } + + if (!env_init()) die_nomem(); + if (!env_put("PROTO=TCP")) die_nomem(); + if (!env_unset("TCPLOCALHOST")) die_nomem(); + if (!env_unset("TCPREMOTEHOST")) die_nomem(); + if (!env_unset("TCPREMOTEINFO")) die_nomem(); + + if (forcelocal) + if (!env_put2("TCPLOCALHOST",forcelocal)) die_nomem(); + + portlocal = ntohs(salocal.sin_port); + tcplocalport[fmt_ulong(tcplocalport,portlocal)] = 0; + if (!env_put2("TCPLOCALPORT",tcplocalport)) die_nomem(); + if (flag1) printlocalport(); + + close(0); + close(1); + sig_childblock(); + + for (;;) { + while (numchildren >= limit) sig_pause(); + sig_childunblock(); + + dummy = sizeof(saremote); + t = accept(s,(struct sockaddr *) &saremote,&dummy); + if (t == -1) continue; + portremote = ntohs(saremote.sin_port); + byte_copy(&ipremote,4,&saremote.sin_addr); + + sig_childblock(); + + switch(fork()) { + default: + ++numchildren; + break; + case -1: + if (verbosity) strerr_warn2(DROP,"unable to fork: ",&strerr_sys); + break; + case 0: + tcpremoteip[ip_fmt(tcpremoteip,&ipremote)] = 0; + printpid(); + + close(s); + if (flagkillopts) { + setsockopt(t,IPPROTO_IP,1,(char *) 0,0); /* 1 == IP_OPTIONS */ + /* if it fails, bummer */ + } + if (!flagdelay) { + int opt = 1; + setsockopt(t,IPPROTO_TCP,1,&opt,sizeof(opt)); /* 1 == TCP_NODELAY */ + /* if it fails, bummer */ + } + + dummy = sizeof(salocal); + if (getsockname(t,(struct sockaddr *) &salocal,&dummy) == -1) { + if (verbosity) strerr_warn2(DROP,"unable to get local address",&strerr_sys); + _exit(111); + } + byte_copy(&iplocal,4,&salocal.sin_addr); + + tcplocalip[ip_fmt(tcplocalip,&iplocal)] = 0; + tcpremoteport[fmt_ulong(tcpremoteport,portremote)] = 0; + + if (!env_put2("TCPREMOTEIP",tcpremoteip)) drop_nomem(); + if (!env_put2("TCPLOCALIP",tcplocalip)) drop_nomem(); + if (!env_put2("TCPREMOTEPORT",tcpremoteport)) drop_nomem(); + + if (!forcelocal) + switch(dns_ptr(&tmp,&iplocal)) { + case DNS_MEM: drop_nomem(); + case 0: + if (!stralloc_0(&tmp)) drop_nomem(); + case_lowers(tmp.s); + if (!env_put2("TCPLOCALHOST",tmp.s)) drop_nomem(); + } + + if (flagremotehost) + switch(dns_ptr(&tmp,&ipremote)) { + case DNS_MEM: drop_nomem(); + case 0: + if (flagparanoid) { + if (dns_ip(&ia,&tmp) != 0) break; + for (j = 0;j < ia.len;++j) + if (!byte_diff(&ipremote,4,&ia.ix[j].ip)) + break; + if (j == ia.len) + break; + } + if (!stralloc_0(&tmp)) drop_nomem(); + case_lowers(tmp.s); + if (!env_put2("TCPREMOTEHOST",tmp.s)) drop_nomem(); + } + if (flagremoteinfo) { + tcpremoteinfo = remoteinfo_get(&ipremote,portremote,&iplocal,portlocal,(int) timeout); + if (tcpremoteinfo) + if (!env_put2("TCPREMOTEINFO",tcpremoteinfo)) drop_nomem(); + } + + rules(); + printenv(); + if (flagdeny) _exit(100); + + if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1)) { + if (verbosity) strerr_warn2(DROP,"unable to set up descriptors: ",&strerr_sys); + _exit(111); + } + sig_childunblock(); + sig_childdefault(); + sig_termdefault(); + sig_pipedefault(); + execvp(*argv,argv); + if (verbosity) strerr_warn4(DROP,"unable to run ",*argv,": ",&strerr_sys); + _exit(111); + } + close(t); + } +} diff --git a/tcpserver=0 b/tcpserver=0 new file mode 100644 index 0000000..6dc8469 --- /dev/null +++ b/tcpserver=0 @@ -0,0 +1 @@ +tcpserver.1 diff --git a/tcpserver=x b/tcpserver=x new file mode 100644 index 0000000..c1eaae9 --- /dev/null +++ b/tcpserver=x @@ -0,0 +1,25 @@ +ip.o +ipalloc.o +dns.o +remoteinfo.o +timeoutconn.o +timeoutread.o +timeoutwrite.o +cdb.a +open.a +wait.a +strerr.a +stralloc.a +env.a +ndelay.a +alloc.a +getopt.a +substdio.a +error.a +str.a +sig.a +fd.a +case.a +fs.a +dns.lib +socket.lib diff --git a/timeoutconn.c b/timeoutconn.c new file mode 100644 index 0000000..33a16d9 --- /dev/null +++ b/timeoutconn.c @@ -0,0 +1,59 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "ndelay.h" +#include "select.h" +#include "error.h" +#include "readwrite.h" +#include "ip.h" +#include "byte.h" +#include "timeoutconn.h" + +int timeoutconn(s,ip,port,timeout) +int s; +struct ip_address *ip; +unsigned int port; +int timeout; +{ + char ch; + struct sockaddr_in sin; + char *x; + fd_set wfds; + struct timeval tv; + + byte_zero(&sin,sizeof(sin)); + byte_copy(&sin.sin_addr,4,ip); + x = (char *) &sin.sin_port; + x[1] = port; port >>= 8; x[0] = port; + sin.sin_family = AF_INET; + + if (ndelay_on(s) == -1) return -1; + + /* XXX: could bind s */ + + if (connect(s,(struct sockaddr *) &sin,sizeof(sin)) == 0) { + ndelay_off(s); + return 0; + } + if ((errno != error_inprogress) && (errno != error_wouldblock)) return -1; + + FD_ZERO(&wfds); + FD_SET(s,&wfds); + tv.tv_sec = timeout; tv.tv_usec = 0; + + if (select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1; + if (FD_ISSET(s,&wfds)) { + int dummy; + dummy = sizeof(sin); + if (getpeername(s,(struct sockaddr *) &sin,&dummy) == -1) { + read(s,&ch,1); + return -1; + } + ndelay_off(s); + return 0; + } + + errno = error_timeout; /* note that connect attempt is continuing */ + return -1; +} diff --git a/timeoutconn.h b/timeoutconn.h new file mode 100644 index 0000000..88aab06 --- /dev/null +++ b/timeoutconn.h @@ -0,0 +1,6 @@ +#ifndef TIMEOUTCONN_H +#define TIMEOUTCONN_H + +extern int timeoutconn(); + +#endif diff --git a/timeoutread.c b/timeoutread.c new file mode 100644 index 0000000..c75e29c --- /dev/null +++ b/timeoutread.c @@ -0,0 +1,22 @@ +#include "timeoutread.h" +#include "select.h" +#include "error.h" +#include "readwrite.h" + +int timeoutread(t,fd,buf,len) int t; int fd; char *buf; int len; +{ + fd_set rfds; + struct timeval tv; + + tv.tv_sec = t; + tv.tv_usec = 0; + + FD_ZERO(&rfds); + FD_SET(fd,&rfds); + + if (select(fd + 1,&rfds,(fd_set *) 0,(fd_set *) 0,&tv) == -1) return -1; + if (FD_ISSET(fd,&rfds)) return read(fd,buf,len); + + errno = error_timeout; + return -1; +} diff --git a/timeoutread.h b/timeoutread.h new file mode 100644 index 0000000..20d3bfc --- /dev/null +++ b/timeoutread.h @@ -0,0 +1,6 @@ +#ifndef TIMEOUTREAD_H +#define TIMEOUTREAD_H + +extern int timeoutread(); + +#endif diff --git a/timeoutwrite.c b/timeoutwrite.c new file mode 100644 index 0000000..516d283 --- /dev/null +++ b/timeoutwrite.c @@ -0,0 +1,22 @@ +#include "timeoutwrite.h" +#include "select.h" +#include "error.h" +#include "readwrite.h" + +int timeoutwrite(t,fd,buf,len) int t; int fd; char *buf; int len; +{ + fd_set wfds; + struct timeval tv; + + tv.tv_sec = t; + tv.tv_usec = 0; + + FD_ZERO(&wfds); + FD_SET(fd,&wfds); + + if (select(fd + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1; + if (FD_ISSET(fd,&wfds)) return write(fd,buf,len); + + errno = error_timeout; + return -1; +} diff --git a/timeoutwrite.h b/timeoutwrite.h new file mode 100644 index 0000000..4725861 --- /dev/null +++ b/timeoutwrite.h @@ -0,0 +1,6 @@ +#ifndef TIMEOUTWRITE_H +#define TIMEOUTWRITE_H + +extern int timeoutwrite(); + +#endif diff --git a/trycpp.c b/trycpp.c new file mode 100644 index 0000000..d7d83ad --- /dev/null +++ b/trycpp.c @@ -0,0 +1,7 @@ +void main() +{ +#ifdef NeXT + printf("nextstep\n"); exit(0); +#endif + printf("unknown\n"); exit(0); +} diff --git a/trylsock.c b/trylsock.c new file mode 100644 index 0000000..fbce408 --- /dev/null +++ b/trylsock.c @@ -0,0 +1,4 @@ +main() +{ + ; +} diff --git a/tryrsolv.c b/tryrsolv.c new file mode 100644 index 0000000..fbce408 --- /dev/null +++ b/tryrsolv.c @@ -0,0 +1,4 @@ +main() +{ + ; +} diff --git a/trysgact.c b/trysgact.c new file mode 100644 index 0000000..263cb21 --- /dev/null +++ b/trysgact.c @@ -0,0 +1,10 @@ +#include <signal.h> + +void main() +{ + struct sigaction sa; + sa.sa_handler = 0; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(0,&sa,(struct sigaction *) 0); +} diff --git a/trysgprm.c b/trysgprm.c new file mode 100644 index 0000000..ed28857 --- /dev/null +++ b/trysgprm.c @@ -0,0 +1,10 @@ +#include <signal.h> + +void main() +{ + sigset_t ss; + + sigemptyset(&ss); + sigaddset(&ss,SIGCHLD); + sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); +} diff --git a/trysysel.c b/trysysel.c new file mode 100644 index 0000000..f6ed055 --- /dev/null +++ b/trysysel.c @@ -0,0 +1,8 @@ +#include <sys/types.h> +#include <sys/time.h> +#include <sys/select.h> /* SVR4 silliness */ + +void foo() +{ + ; +} diff --git a/tryulong32.c b/tryulong32.c new file mode 100644 index 0000000..a108076 --- /dev/null +++ b/tryulong32.c @@ -0,0 +1,11 @@ +void 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); +} diff --git a/trywaitp.c b/trywaitp.c new file mode 100644 index 0000000..7e73bfa --- /dev/null +++ b/trywaitp.c @@ -0,0 +1,7 @@ +#include <sys/types.h> +#include <sys/wait.h> + +void main() +{ + waitpid(0,0,0); +} diff --git a/uint32.h.do b/uint32.h.do new file mode 100644 index 0000000..b87401d --- /dev/null +++ b/uint32.h.do @@ -0,0 +1,7 @@ +dependon tryulong32.c compile load uint32.h1 uint32.h2 +( ./compile tryulong32.c && ./load tryulong32 && ./tryulong32 ) >/dev/null 2>&1 \ +&& cat uint32.h2 || cat uint32.h1 +rm -f tryulong32.o tryulong32 +formake '( ( ./compile tryulong32.c && ./load tryulong32 && ./tryulong32 ) >/dev/null 2>&1 \' +formake '&& cat uint32.h2 || cat uint32.h1 ) > uint32.h' +formake 'rm -f tryulong32.o tryulong32' diff --git a/uint32.h1 b/uint32.h1 new file mode 100644 index 0000000..6599aa0 --- /dev/null +++ b/uint32.h1 @@ -0,0 +1,6 @@ +#ifndef UINT32_H +#define UINT32_H + +typedef unsigned int uint32; + +#endif diff --git a/uint32.h2 b/uint32.h2 new file mode 100644 index 0000000..716430d --- /dev/null +++ b/uint32.h2 @@ -0,0 +1,6 @@ +#ifndef UINT32_H +#define UINT32_H + +typedef unsigned long uint32; + +#endif @@ -0,0 +1,14 @@ +#ifndef WAIT_H +#define WAIT_H + +extern int wait_pid(); +extern int wait_nohang(); +extern int wait_stop(); +extern int wait_stopnohang(); + +#define wait_crashed(w) ((w) & 127) +#define wait_exitcode(w) ((w) >> 8) +#define wait_stopsig(w) ((w) >> 8) +#define wait_stopped(w) (((w) & 127) == 127) + +#endif @@ -0,0 +1 @@ +wait_nohang.o diff --git a/wait_nohang.c b/wait_nohang.c new file mode 100644 index 0000000..bea2774 --- /dev/null +++ b/wait_nohang.c @@ -0,0 +1,12 @@ +#include <sys/types.h> +#include <sys/wait.h> +#include "haswaitp.h" + +int wait_nohang(wstat) int *wstat; +{ +#ifdef HASWAITPID + return waitpid(-1,wstat,WNOHANG); +#else + return wait3(wstat,WNOHANG,(struct rusage *) 0); +#endif +} diff --git a/warn-auto.sh b/warn-auto.sh new file mode 100644 index 0000000..36d2313 --- /dev/null +++ b/warn-auto.sh @@ -0,0 +1,2 @@ +#!/bin/sh +# WARNING: This file was auto-generated. Do not edit! @@ -0,0 +1 @@ +BIN/tcpclient -RHl0 -- "${1-0}" 11 sh -c 'exec BIN/delcr <&6' | cat -v |