summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ucspi-tcp-0.88/CHANGES148
-rw-r--r--ucspi-tcp-0.88/FILES218
-rw-r--r--ucspi-tcp-0.88/Makefile837
-rw-r--r--ucspi-tcp-0.88/README7
-rw-r--r--ucspi-tcp-0.88/SYSDEPS12
-rw-r--r--ucspi-tcp-0.88/TARGETS171
-rw-r--r--ucspi-tcp-0.88/TODO3
-rw-r--r--ucspi-tcp-0.88/VERSION1
-rw-r--r--ucspi-tcp-0.88/addcr.c22
-rw-r--r--ucspi-tcp-0.88/alloc.c32
-rw-r--r--ucspi-tcp-0.88/alloc.h8
-rw-r--r--ucspi-tcp-0.88/alloc_re.c17
-rw-r--r--ucspi-tcp-0.88/argv0.c10
-rw-r--r--ucspi-tcp-0.88/auto-str.c41
-rw-r--r--ucspi-tcp-0.88/auto_home.h6
-rw-r--r--ucspi-tcp-0.88/buffer.c10
-rw-r--r--ucspi-tcp-0.88/buffer.h56
-rw-r--r--ucspi-tcp-0.88/buffer_0.c12
-rw-r--r--ucspi-tcp-0.88/buffer_1.c6
-rw-r--r--ucspi-tcp-0.88/buffer_2.c6
-rw-r--r--ucspi-tcp-0.88/buffer_copy.c16
-rw-r--r--ucspi-tcp-0.88/buffer_get.c67
-rw-r--r--ucspi-tcp-0.88/buffer_put.c88
-rw-r--r--ucspi-tcp-0.88/byte.h13
-rw-r--r--ucspi-tcp-0.88/byte_chr.c20
-rw-r--r--ucspi-tcp-0.88/byte_copy.c14
-rw-r--r--ucspi-tcp-0.88/byte_cr.c16
-rw-r--r--ucspi-tcp-0.88/byte_diff.c16
-rw-r--r--ucspi-tcp-0.88/byte_rchr.c23
-rw-r--r--ucspi-tcp-0.88/byte_zero.c13
-rw-r--r--ucspi-tcp-0.88/case.h13
-rw-r--r--ucspi-tcp-0.88/case_diffb.c18
-rw-r--r--ucspi-tcp-0.88/case_diffs.c17
-rw-r--r--ucspi-tcp-0.88/cdb.c136
-rw-r--r--ucspi-tcp-0.88/cdb.h37
-rw-r--r--ucspi-tcp-0.88/cdb_hash.c21
-rw-r--r--ucspi-tcp-0.88/cdb_make.c153
-rw-r--r--ucspi-tcp-0.88/cdb_make.h39
-rw-r--r--ucspi-tcp-0.88/chkshsgr.c10
-rw-r--r--ucspi-tcp-0.88/choose.sh18
-rw-r--r--ucspi-tcp-0.88/commands.c39
-rw-r--r--ucspi-tcp-0.88/commands.h12
-rw-r--r--ucspi-tcp-0.88/conf-cc3
-rw-r--r--ucspi-tcp-0.88/conf-home4
-rw-r--r--ucspi-tcp-0.88/conf-ld3
-rw-r--r--ucspi-tcp-0.88/date@.sh1
-rw-r--r--ucspi-tcp-0.88/delcr.c37
-rw-r--r--ucspi-tcp-0.88/dns.h84
-rw-r--r--ucspi-tcp-0.88/dns_dfd.c69
-rw-r--r--ucspi-tcp-0.88/dns_domain.c61
-rw-r--r--ucspi-tcp-0.88/dns_dtda.c35
-rw-r--r--ucspi-tcp-0.88/dns_ip.c75
-rw-r--r--ucspi-tcp-0.88/dns_ipq.c71
-rw-r--r--ucspi-tcp-0.88/dns_name.c48
-rw-r--r--ucspi-tcp-0.88/dns_nd.c24
-rw-r--r--ucspi-tcp-0.88/dns_packet.c77
-rw-r--r--ucspi-tcp-0.88/dns_random.c62
-rw-r--r--ucspi-tcp-0.88/dns_rcip.c82
-rw-r--r--ucspi-tcp-0.88/dns_rcrw.c130
-rw-r--r--ucspi-tcp-0.88/dns_resolve.c29
-rw-r--r--ucspi-tcp-0.88/dns_sortip.c20
-rw-r--r--ucspi-tcp-0.88/dns_transmit.c364
-rw-r--r--ucspi-tcp-0.88/dns_txt.c59
-rw-r--r--ucspi-tcp-0.88/env.c15
-rw-r--r--ucspi-tcp-0.88/env.h8
-rw-r--r--ucspi-tcp-0.88/error.c116
-rw-r--r--ucspi-tcp-0.88/error.h26
-rw-r--r--ucspi-tcp-0.88/error_str.c269
-rw-r--r--ucspi-tcp-0.88/exit.h6
-rw-r--r--ucspi-tcp-0.88/fd.h7
-rw-r--r--ucspi-tcp-0.88/fd_copy.c11
-rw-r--r--ucspi-tcp-0.88/fd_move.c9
-rw-r--r--ucspi-tcp-0.88/find-systype.sh159
-rw-r--r--ucspi-tcp-0.88/finger@.sh4
-rw-r--r--ucspi-tcp-0.88/fixcrio.c161
-rw-r--r--ucspi-tcp-0.88/fmt.h25
-rw-r--r--ucspi-tcp-0.88/fmt_ulong.c13
-rw-r--r--ucspi-tcp-0.88/fork.h19
-rw-r--r--ucspi-tcp-0.88/fork.h29
-rw-r--r--ucspi-tcp-0.88/gen_alloc.h7
-rw-r--r--ucspi-tcp-0.88/gen_allocdefs.h34
-rw-r--r--ucspi-tcp-0.88/getln.c14
-rw-r--r--ucspi-tcp-0.88/getln.h10
-rw-r--r--ucspi-tcp-0.88/getln2.c24
-rw-r--r--ucspi-tcp-0.88/hassgact.h11
-rw-r--r--ucspi-tcp-0.88/hassgact.h22
-rw-r--r--ucspi-tcp-0.88/hassgprm.h11
-rw-r--r--ucspi-tcp-0.88/hassgprm.h22
-rw-r--r--ucspi-tcp-0.88/hasshsgr.h11
-rw-r--r--ucspi-tcp-0.88/hasshsgr.h22
-rw-r--r--ucspi-tcp-0.88/haswaitp.h11
-rw-r--r--ucspi-tcp-0.88/haswaitp.h22
-rw-r--r--ucspi-tcp-0.88/hier.c25
-rw-r--r--ucspi-tcp-0.88/http@.sh6
-rw-r--r--ucspi-tcp-0.88/install.c149
-rw-r--r--ucspi-tcp-0.88/instcheck.c108
-rw-r--r--ucspi-tcp-0.88/iopause.c76
-rw-r--r--ucspi-tcp-0.88/iopause.h119
-rw-r--r--ucspi-tcp-0.88/iopause.h218
-rw-r--r--ucspi-tcp-0.88/ip4.h9
-rw-r--r--ucspi-tcp-0.88/ip4_fmt.c18
-rw-r--r--ucspi-tcp-0.88/ip4_scan.c19
-rw-r--r--ucspi-tcp-0.88/mconnect-io.c53
-rw-r--r--ucspi-tcp-0.88/mconnect.sh1
-rw-r--r--ucspi-tcp-0.88/ndelay.h7
-rw-r--r--ucspi-tcp-0.88/ndelay_off.c12
-rw-r--r--ucspi-tcp-0.88/ndelay_on.c12
-rw-r--r--ucspi-tcp-0.88/open.h10
-rw-r--r--ucspi-tcp-0.88/open_read.c6
-rw-r--r--ucspi-tcp-0.88/open_trunc.c6
-rw-r--r--ucspi-tcp-0.88/open_write.c6
-rw-r--r--ucspi-tcp-0.88/openreadclose.c16
-rw-r--r--ucspi-tcp-0.88/openreadclose.h8
-rw-r--r--ucspi-tcp-0.88/pathexec.h8
-rw-r--r--ucspi-tcp-0.88/pathexec_env.c68
-rw-r--r--ucspi-tcp-0.88/pathexec_run.c46
-rw-r--r--ucspi-tcp-0.88/prot.c19
-rw-r--r--ucspi-tcp-0.88/prot.h7
-rw-r--r--ucspi-tcp-0.88/rblsmtpd.c198
-rw-r--r--ucspi-tcp-0.88/readclose.c21
-rw-r--r--ucspi-tcp-0.88/readclose.h9
-rw-r--r--ucspi-tcp-0.88/readwrite.h7
-rw-r--r--ucspi-tcp-0.88/recordio.c178
-rw-r--r--ucspi-tcp-0.88/remoteinfo.c98
-rw-r--r--ucspi-tcp-0.88/remoteinfo.h9
-rw-r--r--ucspi-tcp-0.88/rts.exp435
-rw-r--r--ucspi-tcp-0.88/rts.sh1
-rw-r--r--ucspi-tcp-0.88/rts.tests347
-rw-r--r--ucspi-tcp-0.88/rules.c100
-rw-r--r--ucspi-tcp-0.88/rules.h9
-rw-r--r--ucspi-tcp-0.88/scan.h28
-rw-r--r--ucspi-tcp-0.88/scan_ulong.c14
-rw-r--r--ucspi-tcp-0.88/seek.h15
-rw-r--r--ucspi-tcp-0.88/seek_set.c7
-rw-r--r--ucspi-tcp-0.88/select.h110
-rw-r--r--ucspi-tcp-0.88/select.h211
-rw-r--r--ucspi-tcp-0.88/sgetopt.c51
-rw-r--r--ucspi-tcp-0.88/sgetopt.h21
-rw-r--r--ucspi-tcp-0.88/sig.c12
-rw-r--r--ucspi-tcp-0.88/sig.h25
-rw-r--r--ucspi-tcp-0.88/sig_block.c38
-rw-r--r--ucspi-tcp-0.88/sig_catch.c16
-rw-r--r--ucspi-tcp-0.88/sig_pause.c14
-rw-r--r--ucspi-tcp-0.88/socket.h22
-rw-r--r--ucspi-tcp-0.88/socket_accept.c21
-rw-r--r--ucspi-tcp-0.88/socket_bind.c33
-rw-r--r--ucspi-tcp-0.88/socket_conn.c33
-rw-r--r--ucspi-tcp-0.88/socket_delay.c11
-rw-r--r--ucspi-tcp-0.88/socket_listen.c10
-rw-r--r--ucspi-tcp-0.88/socket_local.c17
-rw-r--r--ucspi-tcp-0.88/socket_opts.c10
-rw-r--r--ucspi-tcp-0.88/socket_remote.c17
-rw-r--r--ucspi-tcp-0.88/socket_tcp.c16
-rw-r--r--ucspi-tcp-0.88/socket_udp.c16
-rw-r--r--ucspi-tcp-0.88/str.h14
-rw-r--r--ucspi-tcp-0.88/str_chr.c17
-rw-r--r--ucspi-tcp-0.88/str_diff.c15
-rw-r--r--ucspi-tcp-0.88/str_len.c14
-rw-r--r--ucspi-tcp-0.88/str_start.c13
-rw-r--r--ucspi-tcp-0.88/stralloc.h29
-rw-r--r--ucspi-tcp-0.88/stralloc_cat.c7
-rw-r--r--ucspi-tcp-0.88/stralloc_catb.c12
-rw-r--r--ucspi-tcp-0.88/stralloc_cats.c8
-rw-r--r--ucspi-tcp-0.88/stralloc_copy.c7
-rw-r--r--ucspi-tcp-0.88/stralloc_eady.c6
-rw-r--r--ucspi-tcp-0.88/stralloc_opyb.c11
-rw-r--r--ucspi-tcp-0.88/stralloc_opys.c8
-rw-r--r--ucspi-tcp-0.88/stralloc_pend.c5
-rw-r--r--ucspi-tcp-0.88/strerr.h78
-rw-r--r--ucspi-tcp-0.88/strerr_die.c31
-rw-r--r--ucspi-tcp-0.88/strerr_sys.c12
-rw-r--r--ucspi-tcp-0.88/subgetopt.c65
-rw-r--r--ucspi-tcp-0.88/subgetopt.h24
-rw-r--r--ucspi-tcp-0.88/tai.h26
-rw-r--r--ucspi-tcp-0.88/tai_pack.c16
-rw-r--r--ucspi-tcp-0.88/taia.h33
-rw-r--r--ucspi-tcp-0.88/taia_add.c18
-rw-r--r--ucspi-tcp-0.88/taia_approx.c6
-rw-r--r--ucspi-tcp-0.88/taia_frac.c6
-rw-r--r--ucspi-tcp-0.88/taia_less.c12
-rw-r--r--ucspi-tcp-0.88/taia_now.c12
-rw-r--r--ucspi-tcp-0.88/taia_pack.c20
-rw-r--r--ucspi-tcp-0.88/taia_sub.c21
-rw-r--r--ucspi-tcp-0.88/taia_uint.c10
-rw-r--r--ucspi-tcp-0.88/tcpcat.sh1
-rw-r--r--ucspi-tcp-0.88/tcpclient.c224
-rw-r--r--ucspi-tcp-0.88/tcprules.c175
-rw-r--r--ucspi-tcp-0.88/tcprulescheck.c57
-rw-r--r--ucspi-tcp-0.88/tcpserver.c426
-rw-r--r--ucspi-tcp-0.88/timeoutconn.c34
-rw-r--r--ucspi-tcp-0.88/timeoutconn.h8
-rw-r--r--ucspi-tcp-0.88/trycpp.c7
-rw-r--r--ucspi-tcp-0.88/trylsock.c4
-rw-r--r--ucspi-tcp-0.88/trypoll.c18
-rw-r--r--ucspi-tcp-0.88/trysgact.c10
-rw-r--r--ucspi-tcp-0.88/trysgprm.c10
-rw-r--r--ucspi-tcp-0.88/tryshsgr.c14
-rw-r--r--ucspi-tcp-0.88/trysysel.c8
-rw-r--r--ucspi-tcp-0.88/tryulong32.c11
-rw-r--r--ucspi-tcp-0.88/tryulong64.c11
-rw-r--r--ucspi-tcp-0.88/tryvfork.c4
-rw-r--r--ucspi-tcp-0.88/trywaitp.c7
-rw-r--r--ucspi-tcp-0.88/uint16.h11
-rw-r--r--ucspi-tcp-0.88/uint16_pack.c13
-rw-r--r--ucspi-tcp-0.88/uint16_unpack.c23
-rw-r--r--ucspi-tcp-0.88/uint32.h111
-rw-r--r--ucspi-tcp-0.88/uint32.h211
-rw-r--r--ucspi-tcp-0.88/uint32_pack.c21
-rw-r--r--ucspi-tcp-0.88/uint32_unpack.c31
-rw-r--r--ucspi-tcp-0.88/uint64.h18
-rw-r--r--ucspi-tcp-0.88/uint64.h28
-rw-r--r--ucspi-tcp-0.88/wait.h14
-rw-r--r--ucspi-tcp-0.88/wait_nohang.c12
-rw-r--r--ucspi-tcp-0.88/wait_pid.c39
-rw-r--r--ucspi-tcp-0.88/warn-auto.sh2
-rw-r--r--ucspi-tcp-0.88/warn-shsgr3
-rw-r--r--ucspi-tcp-0.88/who@.sh1
-rw-r--r--ucspi-tcp-0.88/x86cpuid.c38
218 files changed, 9151 insertions, 0 deletions
diff --git a/ucspi-tcp-0.88/CHANGES b/ucspi-tcp-0.88/CHANGES
new file mode 100644
index 0000000..f21a528
--- /dev/null
+++ b/ucspi-tcp-0.88/CHANGES
@@ -0,0 +1,148 @@
+19960311
+ version: ucspi-tcp 0.50, alpha.
+19960803
+ version: ucspi-tcp 0.60, alpha.
+19960903
+ version: ucspi-tcp 0.70, beta.
+19960914
+ version: ucspi-tcp 0.71, beta.
+19960922
+ version: ucspi-tcp 0.72, beta.
+19970410
+ version: ucspi-tcp 0.73, beta.
+19980118
+ version: ucspi-tcp 0.80, beta.
+19981107
+ code: switched to new install system.
+ code: eliminated tcpclient -U; moved usage() to default.
+ code: switched to strerr in tcpclient.
+ code: switched to str_equal in tcpclient.
+ portability problem: OpenBSD connect() prohibits 0.0.0.0.
+ impact: tcpclient 0 fails. fix: interpret 0 as
+ 127.0.0.1. hopefully nobody needs 0 to mean primary
+ interface.
+ code: tcpclient now interprets empty host name as 0.
+ doc: added addcr.0, delcr.0.
+ doc: added who@.0, date@.0, finger@.0.
+ doc: added tcpcat.0, mconnect.0.
+ code: added printstatus() in tcpserver.
+ code: eliminated numchildren in printpid() in tcpserver.
+ code: unblocked SIGCHLD after setting SIGCHLD to SIG_DFL in
+ tcpserver, instead of before, to avoid confusion if
+ someone sends SIGCHLD manually.
+ code: moved printstatus() before fork in tcpserver.
+ code: added mconnect-io.
+ code: added argv0.
+ code: added fixcr.
+ doc: revamped BLURB.
+ code: added recordio.
+ doc: cleaned up tcpclient.0.
+ code: added http@.
+ code: stopped after 100 bytes in safeappend() in tcpserver.
+19981108
+ code: added tcpserver -B.
+ code: added a few regression tests.
+ version: ucspi-tcp 0.83, beta.
+19981109
+ doc: added http@ to BLURB.
+19981110
+ code: added exec to mconnect.
+ code: tcpclient now ignores port results from getpeername() in
+ favor of the port it tried connecting to.
+ code: added strport to tcpclient.
+ doc: reorganized tcpclient.0.
+ doc: reorganized tcpserver.0.
+ code: revamped tcpserver messages.
+ code: revamped tcpclient messages.
+ code: added a few more regression tests.
+ code: rewrote recordio for instant output and other features.
+ doc: added references in tcpserver.0 and tcpclient.0.
+ code: added tcpclient -i option.
+ code: added tcprulescheck.
+ code: added some tcprules regression tests.
+19981111
+ code: avoided ndelay in recordio.
+ version: ucspi-tcp 0.84, beta.
+19981212
+ doc: improved description of host 0 in tcpserver.0. tnx to
+ several people.
+19981218
+ doc: reordered sample rules in tcprules.0.
+ tnx Harald Hanche-Olsen.
+20000120
+ internal: revamped packaging.
+ internal: massive rewrite. tnx to everyone for bug reports and
+ other comments on various versions of tcpclient,
+ tcpserver, tcpcontrol, and rblsmtpd: Akihiro Iijima,
+ Akihiro Terasaki, Albert J. deVera, Alex Vostrikov,
+ Amos Shapira, Anand R. Buddhdev, Andrea Paolini,
+ Andrew Pam, Araki Yasuhiro, Arne Wichmann,
+ Ayamura Kikuchi, Bart B. B. Hanssens, Bert Gijsbers,
+ Bradford M. Shelton, Brendan Kehoe, Brian J. Reichert,
+ Brian M. Fisk, Brian O'Reilly, Bruno Wolff,
+ Chris Garrigues, Chris Johnson, Christian Wettergren,
+ Dale N. Woolridge, Dan M. Vogel, Daniel C. Mahoney,
+ Darren Hall, Darren W. Rees, Dave Sill, David J. Walton,
+ David P. Smith, David Pool, Dax Kelson, Dirk Jaeckel,
+ Dirk Vluegels, Donald E. Blais, Ed Weinberg,
+ Edward S. Marshall, Eric A. Perlman, Erik Wallin,
+ Faried Nawaz, Fred B. Ringel, Frederik P. Lindberg,
+ Gerry Boudreaux, Giles Lean, Grant Holliday,
+ Greg D. Patterson, Harald Barth, Harald Fritzsche,
+ Harald Hanche-Olsen, Hirofumi Ukawa, Hiroshi Yamashita,
+ Hitesh Patel, Ingmar Hupp, J. B. Keith Humphreys,
+ Jakub K. Boguslaw, Janos Farkas, Jason R. Mastaler,
+ Jeff Hayward, Jeremy Wohl, Jim Littlefield,
+ Johan Holmberg, John Bolhuis, John D. Mitchell,
+ Jos Backus, Jose Monteiro, Joshua J. Ellis,
+ Julie L. Baumler, Karl Lehenbauer, Karsten Thygesen,
+ Keith Burdis, Kenny Elliott, Kikuchi Kousuke,
+ Kris Kennaway, Lars Balker Rasmussen, Louis S. Theran,
+ Lyndon F. Bartels, Mads E. Eilertsen, Mark Delany,
+ Martin Mersberger, Matt P. Simerson, Matthew A. Zahorik,
+ Michael B. Scher, Michael Handler, Michael Hirohama,
+ Michael R. Gile, Michael Salmon, Mikael Suokas,
+ Nobuhiro Murata, Patrick M. Kane, Paul R. Rotering,
+ Peter Rye, Peter Wilkinson, Petr Novotny,
+ Petri Kaukasoina, Raul D. Miller, Richard A. Soderberg,
+ Robert W. Luce, Roberto A. Lumbreras, Russ Allbery,
+ Russell Nelson, Sean Reifschneider, Shawn A. Clifford,
+ Shin Ohira, Shinya O'Hira, Stan Norton,
+ Stathy G. Touloumis, Stefan M. Linnemann, Sudish Joseph,
+ Thomas E. Erskine, Thomas Kuerten, Tim Goodwin,
+ Timothy L. Mayo, Todd Underwood, Tomoaki Terazawa,
+ Tomoki Yoshioka, Toshinori Maeno, Uwe Ohse, Vern Hart,
+ Vince Vielhaber, Waskita Adijarto, William E. Baxter,
+ Wolfgang Rufeger, Wu Ching-hong, Yoshitatsu Takeshita.
+20000307
+ internal: switched to various new libraries.
+ ui: tcpserver prints status on startup, before first connection.
+20000309
+ ui: incorporated rblsmtpd.
+ ui: tcpserver -X allows nonexistent rules file.
+ ui: http@ uses HTTP/1.0, sends Host, removes header.
+ ui: added fixcrio.
+ ui: delcr leaves CR alone at the end of a partial final line.
+20000311
+ ui: switched to prot; so setgid() is preceded by setgroups().
+ ui: tcpserver supports -U.
+ ui: tcpserver supports hostname rules.
+ ui: tcprulescheck now uses environment variables.
+20000312
+ version: ucspi-tcp 0.86, beta.
+20000314
+ portability problem: the poll() emulation in RedHat 5.1 doesn't
+ clear revents when select() returns 0. tnx Petr Novotny.
+ impact: dns lookups busy-loop when they should time out.
+ fix: new iopause from DNScache.
+20000315
+ version: ucspi-tcp 0.87, beta.
+20000318
+ internal: split rules() out of tcpserver and tcprulescheck.
+ bug: didn't always clear rule length when $TCPREMOTEHOST was
+ set. impact: empty rule could be ignored. fix: obvious.
+ tnx Toshinori Maeno, Takashi Takizawa, Yuichi Katoh.
+ ui: check for lone = rule if $TCPREMOTEHOST is set.
+ ui: tcpclient supports fast+slow timeouts, 2+58 by default.
+ ui: tcpclient randomizes order of addresses.
+ version: ucspi-tcp 0.88, beta.
diff --git a/ucspi-tcp-0.88/FILES b/ucspi-tcp-0.88/FILES
new file mode 100644
index 0000000..cfb38a5
--- /dev/null
+++ b/ucspi-tcp-0.88/FILES
@@ -0,0 +1,218 @@
+README
+TODO
+CHANGES
+VERSION
+FILES
+SYSDEPS
+TARGETS
+Makefile
+conf-cc
+conf-ld
+conf-home
+tcpserver.c
+tcprules.c
+tcprulescheck.c
+recordio.c
+argv0.c
+tcpclient.c
+date@.sh
+finger@.sh
+http@.sh
+who@.sh
+tcpcat.sh
+mconnect.sh
+mconnect-io.c
+addcr.c
+delcr.c
+fixcrio.c
+rblsmtpd.c
+remoteinfo.h
+remoteinfo.c
+timeoutconn.h
+timeoutconn.c
+rules.h
+rules.c
+rts.sh
+rts.tests
+rts.exp
+alloc.c
+alloc.h
+alloc_re.c
+auto-str.c
+auto_home.h
+buffer.c
+buffer.h
+buffer_0.c
+buffer_1.c
+buffer_2.c
+buffer_copy.c
+buffer_get.c
+buffer_put.c
+byte.h
+byte_chr.c
+byte_copy.c
+byte_cr.c
+byte_diff.c
+byte_rchr.c
+byte_zero.c
+case.h
+case_diffb.c
+case_diffs.c
+cdb.c
+cdb.h
+cdb_hash.c
+cdb_make.c
+cdb_make.h
+chkshsgr.c
+choose.sh
+commands.c
+commands.h
+dns.h
+dns_dfd.c
+dns_domain.c
+dns_dtda.c
+dns_ip.c
+dns_ipq.c
+dns_name.c
+dns_nd.c
+dns_packet.c
+dns_random.c
+dns_rcip.c
+dns_rcrw.c
+dns_resolve.c
+dns_sortip.c
+dns_transmit.c
+dns_txt.c
+env.c
+env.h
+error.c
+error.h
+error_str.c
+exit.h
+fd.h
+fd_copy.c
+fd_move.c
+find-systype.sh
+fmt.h
+fmt_ulong.c
+fork.h1
+fork.h2
+gen_alloc.h
+gen_allocdefs.h
+getln.c
+getln.h
+getln2.c
+hassgact.h1
+hassgact.h2
+hassgprm.h1
+hassgprm.h2
+hasshsgr.h1
+hasshsgr.h2
+haswaitp.h1
+haswaitp.h2
+hier.c
+install.c
+instcheck.c
+iopause.c
+iopause.h1
+iopause.h2
+ip4.h
+ip4_fmt.c
+ip4_scan.c
+ndelay.h
+ndelay_off.c
+ndelay_on.c
+open.h
+open_read.c
+open_trunc.c
+open_write.c
+openreadclose.c
+openreadclose.h
+pathexec.h
+pathexec_env.c
+pathexec_run.c
+prot.c
+prot.h
+readclose.c
+readclose.h
+readwrite.h
+scan.h
+scan_ulong.c
+seek.h
+seek_set.c
+select.h1
+select.h2
+sgetopt.c
+sgetopt.h
+sig.c
+sig.h
+sig_block.c
+sig_catch.c
+sig_pause.c
+socket.h
+socket_accept.c
+socket_bind.c
+socket_conn.c
+socket_delay.c
+socket_listen.c
+socket_local.c
+socket_opts.c
+socket_remote.c
+socket_tcp.c
+socket_udp.c
+str.h
+str_chr.c
+str_diff.c
+str_len.c
+str_start.c
+stralloc.h
+stralloc_cat.c
+stralloc_catb.c
+stralloc_cats.c
+stralloc_copy.c
+stralloc_eady.c
+stralloc_opyb.c
+stralloc_opys.c
+stralloc_pend.c
+strerr.h
+strerr_die.c
+strerr_sys.c
+subgetopt.c
+subgetopt.h
+tai.h
+tai_pack.c
+taia.h
+taia_add.c
+taia_approx.c
+taia_frac.c
+taia_less.c
+taia_now.c
+taia_pack.c
+taia_sub.c
+taia_uint.c
+trycpp.c
+trylsock.c
+trypoll.c
+trysgact.c
+trysgprm.c
+tryshsgr.c
+trysysel.c
+tryulong32.c
+tryulong64.c
+tryvfork.c
+trywaitp.c
+uint16.h
+uint16_pack.c
+uint16_unpack.c
+uint32.h1
+uint32.h2
+uint32_pack.c
+uint32_unpack.c
+uint64.h1
+uint64.h2
+wait.h
+wait_nohang.c
+wait_pid.c
+warn-auto.sh
+warn-shsgr
+x86cpuid.c
diff --git a/ucspi-tcp-0.88/Makefile b/ucspi-tcp-0.88/Makefile
new file mode 100644
index 0000000..a67b0cb
--- /dev/null
+++ b/ucspi-tcp-0.88/Makefile
@@ -0,0 +1,837 @@
+# Don't edit Makefile! Use conf-* for configuration.
+
+SHELL=/bin/sh
+
+default: it
+
+addcr: \
+load addcr.o unix.a byte.a
+ ./load addcr unix.a byte.a
+
+addcr.o: \
+compile addcr.c buffer.h exit.h
+ ./compile addcr.c
+
+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
+
+argv0: \
+load argv0.o unix.a byte.a
+ ./load argv0 unix.a byte.a
+
+argv0.o: \
+compile argv0.c pathexec.h strerr.h
+ ./compile argv0.c
+
+auto-str: \
+load auto-str.o unix.a byte.a
+ ./load auto-str unix.a byte.a
+
+auto-str.o: \
+compile auto-str.c buffer.h readwrite.h exit.h
+ ./compile auto-str.c
+
+auto_home.c: \
+auto-str conf-home
+ ./auto-str auto_home `head -1 conf-home` > auto_home.c
+
+auto_home.o: \
+compile auto_home.c
+ ./compile auto_home.c
+
+buffer.o: \
+compile buffer.c buffer.h
+ ./compile buffer.c
+
+buffer_0.o: \
+compile buffer_0.c readwrite.h buffer.h
+ ./compile buffer_0.c
+
+buffer_1.o: \
+compile buffer_1.c readwrite.h buffer.h
+ ./compile buffer_1.c
+
+buffer_2.o: \
+compile buffer_2.c readwrite.h buffer.h
+ ./compile buffer_2.c
+
+buffer_copy.o: \
+compile buffer_copy.c buffer.h
+ ./compile buffer_copy.c
+
+buffer_get.o: \
+compile buffer_get.c buffer.h byte.h error.h
+ ./compile buffer_get.c
+
+buffer_put.o: \
+compile buffer_put.c buffer.h str.h byte.h error.h
+ ./compile buffer_put.c
+
+byte.a: \
+makelib byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_rchr.o \
+byte_zero.o case_diffb.o case_diffs.o fmt_ulong.o ip4_fmt.o \
+ip4_scan.o scan_ulong.o str_chr.o str_diff.o str_len.o str_start.o \
+uint16_pack.o uint16_unpack.o uint32_pack.o uint32_unpack.o
+ ./makelib byte.a byte_chr.o byte_copy.o byte_cr.o \
+ byte_diff.o byte_rchr.o byte_zero.o case_diffb.o \
+ case_diffs.o fmt_ulong.o ip4_fmt.o ip4_scan.o scan_ulong.o \
+ str_chr.o str_diff.o str_len.o str_start.o uint16_pack.o \
+ uint16_unpack.o uint32_pack.o uint32_unpack.o
+
+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_diffb.o: \
+compile case_diffb.c case.h
+ ./compile case_diffb.c
+
+case_diffs.o: \
+compile case_diffs.c case.h
+ ./compile case_diffs.c
+
+cdb.a: \
+makelib cdb.o cdb_hash.o cdb_make.o
+ ./makelib cdb.a cdb.o cdb_hash.o cdb_make.o
+
+cdb.o: \
+compile cdb.c readwrite.h error.h seek.h byte.h cdb.h uint32.h
+ ./compile cdb.c
+
+cdb_hash.o: \
+compile cdb_hash.c cdb.h uint32.h
+ ./compile cdb_hash.c
+
+cdb_make.o: \
+compile cdb_make.c readwrite.h seek.h error.h alloc.h cdb.h uint32.h \
+cdb_make.h buffer.h uint32.h
+ ./compile cdb_make.c
+
+check: \
+it instcheck
+ ./instcheck
+
+chkshsgr: \
+load chkshsgr.o
+ ./load chkshsgr
+
+chkshsgr.o: \
+compile chkshsgr.c exit.h
+ ./compile chkshsgr.c
+
+choose: \
+warn-auto.sh choose.sh conf-home
+ cat warn-auto.sh choose.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > choose
+ chmod 755 choose
+
+commands.o: \
+compile commands.c buffer.h stralloc.h gen_alloc.h str.h case.h \
+commands.h
+ ./compile commands.c
+
+compile: \
+warn-auto.sh conf-cc
+ ( cat warn-auto.sh; \
+ echo exec "`head -1 conf-cc`" '-c $${1+"$$@"}' \
+ ) > compile
+ chmod 755 compile
+
+date@: \
+warn-auto.sh date@.sh conf-home
+ cat warn-auto.sh date@.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > date@
+ chmod 755 date@
+
+delcr: \
+load delcr.o unix.a byte.a
+ ./load delcr unix.a byte.a
+
+delcr.o: \
+compile delcr.c buffer.h exit.h
+ ./compile delcr.c
+
+dns.a: \
+makelib dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o \
+dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o \
+dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o
+ ./makelib dns.a dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o \
+ dns_ipq.o dns_name.o dns_nd.o dns_packet.o dns_random.o \
+ dns_rcip.o dns_rcrw.o dns_resolve.o dns_sortip.o \
+ dns_transmit.o dns_txt.o
+
+dns_dfd.o: \
+compile dns_dfd.c error.h alloc.h byte.h dns.h stralloc.h gen_alloc.h \
+iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dns_dfd.c
+
+dns_domain.o: \
+compile dns_domain.c error.h alloc.h case.h byte.h dns.h stralloc.h \
+gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dns_domain.c
+
+dns_dtda.o: \
+compile dns_dtda.c stralloc.h gen_alloc.h dns.h stralloc.h iopause.h \
+taia.h tai.h uint64.h taia.h
+ ./compile dns_dtda.c
+
+dns_ip.o: \
+compile dns_ip.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
+stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dns_ip.c
+
+dns_ipq.o: \
+compile dns_ipq.c stralloc.h gen_alloc.h case.h byte.h str.h dns.h \
+stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dns_ipq.c
+
+dns_name.o: \
+compile dns_name.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
+stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dns_name.c
+
+dns_nd.o: \
+compile dns_nd.c byte.h fmt.h dns.h stralloc.h gen_alloc.h iopause.h \
+taia.h tai.h uint64.h taia.h
+ ./compile dns_nd.c
+
+dns_packet.o: \
+compile dns_packet.c error.h dns.h stralloc.h gen_alloc.h iopause.h \
+taia.h tai.h uint64.h taia.h
+ ./compile dns_packet.c
+
+dns_random.o: \
+compile dns_random.c dns.h stralloc.h gen_alloc.h iopause.h taia.h \
+tai.h uint64.h taia.h taia.h uint32.h
+ ./compile dns_random.c
+
+dns_rcip.o: \
+compile dns_rcip.c taia.h tai.h uint64.h openreadclose.h stralloc.h \
+gen_alloc.h byte.h ip4.h env.h dns.h stralloc.h iopause.h taia.h \
+taia.h
+ ./compile dns_rcip.c
+
+dns_rcrw.o: \
+compile dns_rcrw.c taia.h tai.h uint64.h env.h byte.h str.h \
+openreadclose.h stralloc.h gen_alloc.h dns.h stralloc.h iopause.h \
+taia.h taia.h
+ ./compile dns_rcrw.c
+
+dns_resolve.o: \
+compile dns_resolve.c iopause.h taia.h tai.h uint64.h taia.h byte.h \
+dns.h stralloc.h gen_alloc.h iopause.h taia.h
+ ./compile dns_resolve.c
+
+dns_sortip.o: \
+compile dns_sortip.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \
+taia.h tai.h uint64.h taia.h
+ ./compile dns_sortip.c
+
+dns_transmit.o: \
+compile dns_transmit.c socket.h uint16.h alloc.h error.h byte.h \
+readwrite.h uint16.h dns.h stralloc.h gen_alloc.h iopause.h taia.h \
+tai.h uint64.h taia.h
+ ./compile dns_transmit.c
+
+dns_txt.o: \
+compile dns_txt.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
+stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dns_txt.c
+
+env.o: \
+compile env.c str.h env.h
+ ./compile env.c
+
+error.o: \
+compile error.c error.h
+ ./compile error.c
+
+error_str.o: \
+compile error_str.c error.h
+ ./compile error_str.c
+
+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
+
+finger@: \
+warn-auto.sh finger@.sh conf-home
+ cat warn-auto.sh finger@.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > finger@
+ chmod 755 finger@
+
+fixcrio: \
+load fixcrio.o time.a unix.a byte.a
+ ./load fixcrio time.a unix.a byte.a
+
+fixcrio.o: \
+compile fixcrio.c sig.h buffer.h strerr.h byte.h readwrite.h exit.h \
+iopause.h taia.h tai.h uint64.h pathexec.h
+ ./compile fixcrio.c
+
+fmt_ulong.o: \
+compile fmt_ulong.c fmt.h
+ ./compile fmt_ulong.c
+
+fork.h: \
+choose compile load tryvfork.c fork.h1 fork.h2
+ ./choose cl tryvfork fork.h1 fork.h2 > fork.h
+
+getln.o: \
+compile getln.c byte.h getln.h buffer.h stralloc.h gen_alloc.h
+ ./compile getln.c
+
+getln2.o: \
+compile getln2.c byte.h getln.h buffer.h stralloc.h gen_alloc.h
+ ./compile getln2.c
+
+hassgact.h: \
+choose compile load trysgact.c hassgact.h1 hassgact.h2
+ ./choose cl trysgact hassgact.h1 hassgact.h2 > hassgact.h
+
+hassgprm.h: \
+choose compile load trysgprm.c hassgprm.h1 hassgprm.h2
+ ./choose cl trysgprm hassgprm.h1 hassgprm.h2 > hassgprm.h
+
+hasshsgr.h: \
+choose compile load tryshsgr.c hasshsgr.h1 hasshsgr.h2 chkshsgr \
+warn-shsgr
+ ./chkshsgr || ( cat warn-shsgr; exit 1 )
+ ./choose clr tryshsgr hasshsgr.h1 hasshsgr.h2 > hasshsgr.h
+
+haswaitp.h: \
+choose compile load trywaitp.c haswaitp.h1 haswaitp.h2
+ ./choose cl trywaitp haswaitp.h1 haswaitp.h2 > haswaitp.h
+
+hier.o: \
+compile hier.c auto_home.h
+ ./compile hier.c
+
+http@: \
+warn-auto.sh http@.sh conf-home
+ cat warn-auto.sh http@.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > http@
+ chmod 755 http@
+
+install: \
+load install.o hier.o auto_home.o unix.a byte.a
+ ./load install hier.o auto_home.o unix.a byte.a
+
+install.o: \
+compile install.c buffer.h strerr.h error.h open.h readwrite.h exit.h
+ ./compile install.c
+
+instcheck: \
+load instcheck.o hier.o auto_home.o unix.a byte.a
+ ./load instcheck hier.o auto_home.o unix.a byte.a
+
+instcheck.o: \
+compile instcheck.c strerr.h error.h readwrite.h exit.h
+ ./compile instcheck.c
+
+iopause.h: \
+choose compile trypoll.c iopause.h1 iopause.h2
+ ./choose clr trypoll iopause.h1 iopause.h2 > iopause.h
+
+iopause.o: \
+compile iopause.c taia.h tai.h uint64.h select.h iopause.h taia.h
+ ./compile iopause.c
+
+ip4_fmt.o: \
+compile ip4_fmt.c fmt.h ip4.h
+ ./compile ip4_fmt.c
+
+ip4_scan.o: \
+compile ip4_scan.c scan.h ip4.h
+ ./compile ip4_scan.c
+
+it: \
+prog install instcheck
+
+load: \
+warn-auto.sh conf-ld
+ ( cat warn-auto.sh; \
+ echo 'main="$$1"; shift'; \
+ echo exec "`head -1 conf-ld`" \
+ '-o "$$main" "$$main".o $${1+"$$@"}' \
+ ) > load
+ chmod 755 load
+
+makelib: \
+warn-auto.sh systype
+ ( cat warn-auto.sh; \
+ echo 'main="$$1"; shift'; \
+ echo 'rm -f "$$main"'; \
+ echo 'ar cr "$$main" $${1+"$$@"}'; \
+ case "`cat systype`" in \
+ sunos-5.*) ;; \
+ unix_sv*) ;; \
+ irix64-*) ;; \
+ irix-*) ;; \
+ dgux-*) ;; \
+ hp-ux-*) ;; \
+ sco*) ;; \
+ *) echo 'ranlib "$$main"' ;; \
+ esac \
+ ) > makelib
+ chmod 755 makelib
+
+mconnect: \
+warn-auto.sh mconnect.sh conf-home
+ cat warn-auto.sh mconnect.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > mconnect
+ chmod 755 mconnect
+
+mconnect-io: \
+load mconnect-io.o unix.a byte.a
+ ./load mconnect-io unix.a byte.a
+
+mconnect-io.o: \
+compile mconnect-io.c sig.h wait.h fork.h buffer.h strerr.h \
+readwrite.h exit.h
+ ./compile mconnect-io.c
+
+ndelay_off.o: \
+compile ndelay_off.c ndelay.h
+ ./compile ndelay_off.c
+
+ndelay_on.o: \
+compile ndelay_on.c ndelay.h
+ ./compile ndelay_on.c
+
+open_read.o: \
+compile open_read.c open.h
+ ./compile open_read.c
+
+open_trunc.o: \
+compile open_trunc.c open.h
+ ./compile open_trunc.c
+
+open_write.o: \
+compile open_write.c open.h
+ ./compile open_write.c
+
+openreadclose.o: \
+compile openreadclose.c error.h open.h readclose.h stralloc.h \
+gen_alloc.h openreadclose.h stralloc.h
+ ./compile openreadclose.c
+
+pathexec_env.o: \
+compile pathexec_env.c stralloc.h gen_alloc.h alloc.h str.h byte.h \
+env.h pathexec.h
+ ./compile pathexec_env.c
+
+pathexec_run.o: \
+compile pathexec_run.c error.h stralloc.h gen_alloc.h str.h env.h \
+pathexec.h
+ ./compile pathexec_run.c
+
+prog: \
+tcpserver tcprules tcprulescheck argv0 recordio tcpclient who@ date@ \
+finger@ http@ tcpcat mconnect mconnect-io addcr delcr fixcrio \
+rblsmtpd rts
+
+prot.o: \
+compile prot.c hasshsgr.h prot.h
+ ./compile prot.c
+
+rblsmtpd: \
+load rblsmtpd.o commands.o dns.a time.a unix.a byte.a socket.lib
+ ./load rblsmtpd commands.o dns.a time.a unix.a byte.a \
+ `cat socket.lib`
+
+rblsmtpd.o: \
+compile rblsmtpd.c byte.h str.h scan.h fmt.h env.h exit.h sig.h \
+buffer.h readwrite.h sgetopt.h subgetopt.h strerr.h stralloc.h \
+gen_alloc.h commands.h pathexec.h dns.h stralloc.h iopause.h taia.h \
+tai.h uint64.h taia.h
+ ./compile rblsmtpd.c
+
+readclose.o: \
+compile readclose.c readwrite.h error.h readclose.h stralloc.h \
+gen_alloc.h
+ ./compile readclose.c
+
+recordio: \
+load recordio.o time.a unix.a byte.a
+ ./load recordio time.a unix.a byte.a
+
+recordio.o: \
+compile recordio.c sig.h buffer.h strerr.h str.h byte.h readwrite.h \
+exit.h fmt.h iopause.h taia.h tai.h uint64.h pathexec.h
+ ./compile recordio.c
+
+remoteinfo.o: \
+compile remoteinfo.c fmt.h buffer.h socket.h uint16.h error.h \
+iopause.h taia.h tai.h uint64.h timeoutconn.h uint16.h remoteinfo.h \
+stralloc.h gen_alloc.h uint16.h
+ ./compile remoteinfo.c
+
+rts: \
+warn-auto.sh rts.sh conf-home
+ cat warn-auto.sh rts.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > rts
+ chmod 755 rts
+
+rules.o: \
+compile rules.c alloc.h stralloc.h gen_alloc.h open.h cdb.h uint32.h \
+rules.h stralloc.h
+ ./compile rules.c
+
+scan_ulong.o: \
+compile scan_ulong.c scan.h
+ ./compile scan_ulong.c
+
+seek_set.o: \
+compile seek_set.c seek.h
+ ./compile seek_set.c
+
+select.h: \
+choose compile trysysel.c select.h1 select.h2
+ ./choose c trysysel select.h1 select.h2 > select.h
+
+setup: \
+it install
+ ./install
+
+sgetopt.o: \
+compile sgetopt.c buffer.h sgetopt.h subgetopt.h subgetopt.h
+ ./compile sgetopt.c
+
+sig.o: \
+compile sig.c sig.h
+ ./compile sig.c
+
+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_pause.o: \
+compile sig_pause.c sig.h hassgprm.h
+ ./compile sig_pause.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
+
+socket_accept.o: \
+compile socket_accept.c byte.h socket.h uint16.h
+ ./compile socket_accept.c
+
+socket_bind.o: \
+compile socket_bind.c byte.h socket.h uint16.h
+ ./compile socket_bind.c
+
+socket_conn.o: \
+compile socket_conn.c readwrite.h byte.h socket.h uint16.h
+ ./compile socket_conn.c
+
+socket_delay.o: \
+compile socket_delay.c socket.h uint16.h
+ ./compile socket_delay.c
+
+socket_listen.o: \
+compile socket_listen.c socket.h uint16.h
+ ./compile socket_listen.c
+
+socket_local.o: \
+compile socket_local.c byte.h socket.h uint16.h
+ ./compile socket_local.c
+
+socket_opts.o: \
+compile socket_opts.c socket.h uint16.h
+ ./compile socket_opts.c
+
+socket_remote.o: \
+compile socket_remote.c byte.h socket.h uint16.h
+ ./compile socket_remote.c
+
+socket_tcp.o: \
+compile socket_tcp.c ndelay.h socket.h uint16.h
+ ./compile socket_tcp.c
+
+socket_udp.o: \
+compile socket_udp.c ndelay.h socket.h uint16.h
+ ./compile socket_udp.c
+
+str_chr.o: \
+compile str_chr.c str.h
+ ./compile str_chr.c
+
+str_diff.o: \
+compile str_diff.c str.h
+ ./compile str_diff.c
+
+str_len.o: \
+compile str_len.c str.h
+ ./compile str_len.c
+
+str_start.o: \
+compile str_start.c str.h
+ ./compile str_start.c
+
+stralloc_cat.o: \
+compile stralloc_cat.c byte.h stralloc.h gen_alloc.h
+ ./compile stralloc_cat.c
+
+stralloc_catb.o: \
+compile stralloc_catb.c stralloc.h gen_alloc.h byte.h
+ ./compile stralloc_catb.c
+
+stralloc_cats.o: \
+compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h
+ ./compile stralloc_cats.c
+
+stralloc_copy.o: \
+compile stralloc_copy.c byte.h stralloc.h gen_alloc.h
+ ./compile stralloc_copy.c
+
+stralloc_eady.o: \
+compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \
+gen_allocdefs.h
+ ./compile stralloc_eady.c
+
+stralloc_opyb.o: \
+compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h
+ ./compile stralloc_opyb.c
+
+stralloc_opys.o: \
+compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h
+ ./compile stralloc_opys.c
+
+stralloc_pend.o: \
+compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \
+gen_allocdefs.h
+ ./compile stralloc_pend.c
+
+strerr_die.o: \
+compile strerr_die.c buffer.h exit.h strerr.h
+ ./compile strerr_die.c
+
+strerr_sys.o: \
+compile strerr_sys.c error.h strerr.h
+ ./compile strerr_sys.c
+
+subgetopt.o: \
+compile subgetopt.c subgetopt.h
+ ./compile subgetopt.c
+
+systype: \
+find-systype.sh conf-cc conf-ld trycpp.c x86cpuid.c
+ ( cat warn-auto.sh; \
+ echo CC=\'`head -1 conf-cc`\'; \
+ echo LD=\'`head -1 conf-ld`\'; \
+ cat find-systype.sh; \
+ ) | sh > systype
+
+tai_pack.o: \
+compile tai_pack.c tai.h uint64.h
+ ./compile tai_pack.c
+
+taia_add.o: \
+compile taia_add.c taia.h tai.h uint64.h
+ ./compile taia_add.c
+
+taia_approx.o: \
+compile taia_approx.c taia.h tai.h uint64.h
+ ./compile taia_approx.c
+
+taia_frac.o: \
+compile taia_frac.c taia.h tai.h uint64.h
+ ./compile taia_frac.c
+
+taia_less.o: \
+compile taia_less.c taia.h tai.h uint64.h
+ ./compile taia_less.c
+
+taia_now.o: \
+compile taia_now.c taia.h tai.h uint64.h
+ ./compile taia_now.c
+
+taia_pack.o: \
+compile taia_pack.c taia.h tai.h uint64.h
+ ./compile taia_pack.c
+
+taia_sub.o: \
+compile taia_sub.c taia.h tai.h uint64.h
+ ./compile taia_sub.c
+
+taia_uint.o: \
+compile taia_uint.c taia.h tai.h uint64.h
+ ./compile taia_uint.c
+
+tcpcat: \
+warn-auto.sh tcpcat.sh conf-home
+ cat warn-auto.sh tcpcat.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > tcpcat
+ chmod 755 tcpcat
+
+tcpclient: \
+load tcpclient.o remoteinfo.o timeoutconn.o dns.a time.a unix.a \
+byte.a socket.lib
+ ./load tcpclient remoteinfo.o timeoutconn.o dns.a time.a \
+ unix.a byte.a `cat socket.lib`
+
+tcpclient.o: \
+compile tcpclient.c sig.h exit.h sgetopt.h subgetopt.h uint16.h fmt.h \
+scan.h str.h ip4.h uint16.h socket.h uint16.h fd.h stralloc.h \
+gen_alloc.h buffer.h error.h strerr.h pathexec.h timeoutconn.h \
+uint16.h remoteinfo.h stralloc.h uint16.h dns.h stralloc.h iopause.h \
+taia.h tai.h uint64.h taia.h
+ ./compile tcpclient.c
+
+tcprules: \
+load tcprules.o cdb.a unix.a byte.a
+ ./load tcprules cdb.a unix.a byte.a
+
+tcprules.o: \
+compile tcprules.c strerr.h stralloc.h gen_alloc.h getln.h buffer.h \
+stralloc.h buffer.h exit.h fmt.h byte.h cdb_make.h buffer.h uint32.h
+ ./compile tcprules.c
+
+tcprulescheck: \
+load tcprulescheck.o rules.o cdb.a unix.a byte.a
+ ./load tcprulescheck rules.o cdb.a unix.a byte.a
+
+tcprulescheck.o: \
+compile tcprulescheck.c byte.h buffer.h strerr.h env.h rules.h \
+stralloc.h gen_alloc.h
+ ./compile tcprulescheck.c
+
+tcpserver: \
+load tcpserver.o rules.o remoteinfo.o timeoutconn.o cdb.a dns.a \
+time.a unix.a byte.a socket.lib
+ ./load tcpserver rules.o remoteinfo.o timeoutconn.o cdb.a \
+ dns.a time.a unix.a byte.a `cat socket.lib`
+
+tcpserver.o: \
+compile tcpserver.c uint16.h str.h byte.h fmt.h scan.h ip4.h fd.h \
+exit.h env.h prot.h open.h wait.h readwrite.h stralloc.h gen_alloc.h \
+alloc.h buffer.h error.h strerr.h sgetopt.h subgetopt.h pathexec.h \
+socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h \
+stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h \
+taia.h
+ ./compile tcpserver.c
+
+time.a: \
+makelib iopause.o tai_pack.o taia_add.o taia_approx.o taia_frac.o \
+taia_less.o taia_now.o taia_pack.o taia_sub.o taia_uint.o
+ ./makelib time.a iopause.o tai_pack.o taia_add.o \
+ taia_approx.o taia_frac.o taia_less.o taia_now.o \
+ taia_pack.o taia_sub.o taia_uint.o
+
+timeoutconn.o: \
+compile timeoutconn.c ndelay.h socket.h uint16.h iopause.h taia.h \
+tai.h uint64.h error.h timeoutconn.h uint16.h
+ ./compile timeoutconn.c
+
+uint16_pack.o: \
+compile uint16_pack.c uint16.h
+ ./compile uint16_pack.c
+
+uint16_unpack.o: \
+compile uint16_unpack.c uint16.h
+ ./compile uint16_unpack.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
+
+uint32_pack.o: \
+compile uint32_pack.c uint32.h
+ ./compile uint32_pack.c
+
+uint32_unpack.o: \
+compile uint32_unpack.c uint32.h
+ ./compile uint32_unpack.c
+
+uint64.h: \
+choose compile load tryulong64.c uint64.h1 uint64.h2
+ ./choose clr tryulong64 uint64.h1 uint64.h2 > uint64.h
+
+unix.a: \
+makelib alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \
+buffer_copy.o buffer_get.o buffer_put.o env.o error.o error_str.o \
+fd_copy.o fd_move.o getln.o getln2.o ndelay_off.o ndelay_on.o \
+open_read.o open_trunc.o open_write.o openreadclose.o pathexec_env.o \
+pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o sig.o \
+sig_block.o sig_catch.o sig_pause.o socket_accept.o socket_bind.o \
+socket_conn.o socket_delay.o socket_listen.o socket_local.o \
+socket_opts.o socket_remote.o socket_tcp.o socket_udp.o \
+stralloc_cat.o stralloc_catb.o stralloc_cats.o stralloc_copy.o \
+stralloc_eady.o stralloc_opyb.o stralloc_opys.o stralloc_pend.o \
+strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o wait_pid.o
+ ./makelib unix.a alloc.o alloc_re.o buffer.o buffer_0.o \
+ buffer_1.o buffer_2.o buffer_copy.o buffer_get.o \
+ buffer_put.o env.o error.o error_str.o fd_copy.o fd_move.o \
+ getln.o getln2.o ndelay_off.o ndelay_on.o open_read.o \
+ open_trunc.o open_write.o openreadclose.o pathexec_env.o \
+ pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o \
+ sig.o sig_block.o sig_catch.o sig_pause.o socket_accept.o \
+ socket_bind.o socket_conn.o socket_delay.o socket_listen.o \
+ socket_local.o socket_opts.o socket_remote.o socket_tcp.o \
+ socket_udp.o stralloc_cat.o stralloc_catb.o stralloc_cats.o \
+ stralloc_copy.o stralloc_eady.o stralloc_opyb.o \
+ stralloc_opys.o stralloc_pend.o strerr_die.o strerr_sys.o \
+ subgetopt.o wait_nohang.o wait_pid.o
+
+wait_nohang.o: \
+compile wait_nohang.c haswaitp.h
+ ./compile wait_nohang.c
+
+wait_pid.o: \
+compile wait_pid.c error.h haswaitp.h
+ ./compile wait_pid.c
+
+who@: \
+warn-auto.sh who@.sh conf-home
+ cat warn-auto.sh who@.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > who@
+ chmod 755 who@
diff --git a/ucspi-tcp-0.88/README b/ucspi-tcp-0.88/README
new file mode 100644
index 0000000..2d6ab86
--- /dev/null
+++ b/ucspi-tcp-0.88/README
@@ -0,0 +1,7 @@
+ucspi-tcp 0.88, beta.
+20000318
+Copyright 2000
+D. J. Bernstein
+
+ucspi-tcp home page: http://cr.yp.to/ucspi-tcp.html
+Installation instructions: http://cr.yp.to/ucspi-tcp/install.html
diff --git a/ucspi-tcp-0.88/SYSDEPS b/ucspi-tcp-0.88/SYSDEPS
new file mode 100644
index 0000000..e024e62
--- /dev/null
+++ b/ucspi-tcp-0.88/SYSDEPS
@@ -0,0 +1,12 @@
+VERSION
+systype
+fork.h
+hassgact.h
+hassgprm.h
+hasshsgr.h
+haswaitp.h
+iopause.h
+select.h
+socket.lib
+uint32.h
+uint64.h
diff --git a/ucspi-tcp-0.88/TARGETS b/ucspi-tcp-0.88/TARGETS
new file mode 100644
index 0000000..4d1f2a0
--- /dev/null
+++ b/ucspi-tcp-0.88/TARGETS
@@ -0,0 +1,171 @@
+load
+compile
+choose
+iopause.h
+uint64.h
+tcpserver.o
+uint32.h
+rules.o
+remoteinfo.o
+timeoutconn.o
+systype
+makelib
+cdb.o
+cdb_hash.o
+cdb_make.o
+cdb.a
+dns_dfd.o
+dns_domain.o
+dns_dtda.o
+dns_ip.o
+dns_ipq.o
+dns_name.o
+dns_nd.o
+dns_packet.o
+dns_random.o
+dns_rcip.o
+dns_rcrw.o
+dns_resolve.o
+dns_sortip.o
+dns_transmit.o
+dns_txt.o
+dns.a
+select.h
+iopause.o
+tai_pack.o
+taia_add.o
+taia_approx.o
+taia_frac.o
+taia_less.o
+taia_now.o
+taia_pack.o
+taia_sub.o
+taia_uint.o
+time.a
+alloc.o
+alloc_re.o
+buffer.o
+buffer_0.o
+buffer_1.o
+buffer_2.o
+buffer_copy.o
+buffer_get.o
+buffer_put.o
+env.o
+error.o
+error_str.o
+fd_copy.o
+fd_move.o
+getln.o
+getln2.o
+ndelay_off.o
+ndelay_on.o
+open_read.o
+open_trunc.o
+open_write.o
+openreadclose.o
+pathexec_env.o
+pathexec_run.o
+chkshsgr.o
+chkshsgr
+hasshsgr.h
+prot.o
+readclose.o
+seek_set.o
+sgetopt.o
+sig.o
+hassgprm.h
+sig_block.o
+hassgact.h
+sig_catch.o
+sig_pause.o
+socket_accept.o
+socket_bind.o
+socket_conn.o
+socket_delay.o
+socket_listen.o
+socket_local.o
+socket_opts.o
+socket_remote.o
+socket_tcp.o
+socket_udp.o
+stralloc_cat.o
+stralloc_catb.o
+stralloc_cats.o
+stralloc_copy.o
+stralloc_eady.o
+stralloc_opyb.o
+stralloc_opys.o
+stralloc_pend.o
+strerr_die.o
+strerr_sys.o
+subgetopt.o
+haswaitp.h
+wait_nohang.o
+wait_pid.o
+unix.a
+byte_chr.o
+byte_copy.o
+byte_cr.o
+byte_diff.o
+byte_rchr.o
+byte_zero.o
+case_diffb.o
+case_diffs.o
+fmt_ulong.o
+ip4_fmt.o
+ip4_scan.o
+scan_ulong.o
+str_chr.o
+str_diff.o
+str_len.o
+str_start.o
+uint16_pack.o
+uint16_unpack.o
+uint32_pack.o
+uint32_unpack.o
+byte.a
+socket.lib
+tcpserver
+tcprules.o
+tcprules
+tcprulescheck.o
+tcprulescheck
+argv0.o
+argv0
+recordio.o
+recordio
+tcpclient.o
+tcpclient
+who@
+date@
+finger@
+http@
+tcpcat
+mconnect
+fork.h
+mconnect-io.o
+mconnect-io
+addcr.o
+addcr
+delcr.o
+delcr
+fixcrio.o
+fixcrio
+rblsmtpd.o
+commands.o
+rblsmtpd
+rts
+prog
+install.o
+hier.o
+auto-str.o
+auto-str
+auto_home.c
+auto_home.o
+install
+instcheck.o
+instcheck
+it
+setup
+check
diff --git a/ucspi-tcp-0.88/TODO b/ucspi-tcp-0.88/TODO
new file mode 100644
index 0000000..f620416
--- /dev/null
+++ b/ucspi-tcp-0.88/TODO
@@ -0,0 +1,3 @@
+inetd.conf conversion tools
+pre-forking version of tcpserver?
+rule directory in tcpserver?
diff --git a/ucspi-tcp-0.88/VERSION b/ucspi-tcp-0.88/VERSION
new file mode 100644
index 0000000..2b47df0
--- /dev/null
+++ b/ucspi-tcp-0.88/VERSION
@@ -0,0 +1 @@
+ucspi-tcp 0.88
diff --git a/ucspi-tcp-0.88/addcr.c b/ucspi-tcp-0.88/addcr.c
new file mode 100644
index 0000000..e8b69e3
--- /dev/null
+++ b/ucspi-tcp-0.88/addcr.c
@@ -0,0 +1,22 @@
+#include "buffer.h"
+#include "exit.h"
+
+main()
+{
+ register int n;
+ register char *x;
+ char ch;
+
+ for (;;) {
+ n = buffer_feed(buffer_0);
+ if (n < 0) _exit(111);
+ if (!n) _exit(0);
+ x = buffer_PEEK(buffer_0);
+ buffer_SEEK(buffer_0,n);
+ while (n > 0) {
+ ch = *x++; --n;
+ if (ch == '\n') buffer_PUTC(buffer_1,"\r"[0]);
+ buffer_PUTC(buffer_1,ch);
+ }
+ }
+}
diff --git a/ucspi-tcp-0.88/alloc.c b/ucspi-tcp-0.88/alloc.c
new file mode 100644
index 0000000..0e2d4cd
--- /dev/null
+++ b/ucspi-tcp-0.88/alloc.c
@@ -0,0 +1,32 @@
+#include "alloc.h"
+#include "error.h"
+extern char *malloc();
+extern void free();
+
+#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */
+#define SPACE 2048 /* must be multiple of ALIGNMENT */
+
+typedef union { char irrelevant[ALIGNMENT]; double d; } aligned;
+static aligned realspace[SPACE / ALIGNMENT];
+#define space ((char *) realspace)
+static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */
+
+/*@null@*//*@out@*/char *alloc(n)
+unsigned int n;
+{
+ char *x;
+ n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */
+ if (n <= avail) { avail -= n; return space + avail; }
+ x = malloc(n);
+ if (!x) errno = error_nomem;
+ return x;
+}
+
+void alloc_free(x)
+char *x;
+{
+ if (x >= space)
+ if (x < space + SPACE)
+ return; /* XXX: assuming that pointers are flat */
+ free(x);
+}
diff --git a/ucspi-tcp-0.88/alloc.h b/ucspi-tcp-0.88/alloc.h
new file mode 100644
index 0000000..1b1d893
--- /dev/null
+++ b/ucspi-tcp-0.88/alloc.h
@@ -0,0 +1,8 @@
+#ifndef ALLOC_H
+#define ALLOC_H
+
+extern /*@null@*//*@out@*/char *alloc();
+extern void alloc_free();
+extern int alloc_re();
+
+#endif
diff --git a/ucspi-tcp-0.88/alloc_re.c b/ucspi-tcp-0.88/alloc_re.c
new file mode 100644
index 0000000..feb8b49
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/argv0.c b/ucspi-tcp-0.88/argv0.c
new file mode 100644
index 0000000..2a0e936
--- /dev/null
+++ b/ucspi-tcp-0.88/argv0.c
@@ -0,0 +1,10 @@
+#include "pathexec.h"
+#include "strerr.h"
+
+main(int argc,char **argv,char **envp)
+{
+ if (argc < 3)
+ strerr_die1x(100,"argv0: usage: argv0 realname program [ arg ... ]");
+ pathexec_run(argv[1],argv + 2,envp);
+ strerr_die4sys(111,"argv0: fatal: ","unable to run ",argv[1],": ");
+}
diff --git a/ucspi-tcp-0.88/auto-str.c b/ucspi-tcp-0.88/auto-str.c
new file mode 100644
index 0000000..0e793a2
--- /dev/null
+++ b/ucspi-tcp-0.88/auto-str.c
@@ -0,0 +1,41 @@
+#include "buffer.h"
+#include "readwrite.h"
+#include "exit.h"
+
+char bspace[256];
+buffer b = BUFFER_INIT(write,1,bspace,sizeof bspace);
+
+void puts(char *s)
+{
+ if (buffer_puts(&b,s) == -1) _exit(111);
+}
+
+main(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 (buffer_flush(&b) == -1) _exit(111);
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/auto_home.h b/ucspi-tcp-0.88/auto_home.h
new file mode 100644
index 0000000..a756cd0
--- /dev/null
+++ b/ucspi-tcp-0.88/auto_home.h
@@ -0,0 +1,6 @@
+#ifndef AUTO_HOME_H
+#define AUTO_HOME_H
+
+extern char auto_home[];
+
+#endif
diff --git a/ucspi-tcp-0.88/buffer.c b/ucspi-tcp-0.88/buffer.c
new file mode 100644
index 0000000..f44a697
--- /dev/null
+++ b/ucspi-tcp-0.88/buffer.c
@@ -0,0 +1,10 @@
+#include "buffer.h"
+
+void buffer_init(buffer *s,int (*op)(),int fd,char *buf,unsigned int len)
+{
+ s->x = buf;
+ s->fd = fd;
+ s->op = op;
+ s->p = 0;
+ s->n = len;
+}
diff --git a/ucspi-tcp-0.88/buffer.h b/ucspi-tcp-0.88/buffer.h
new file mode 100644
index 0000000..12539b3
--- /dev/null
+++ b/ucspi-tcp-0.88/buffer.h
@@ -0,0 +1,56 @@
+#ifndef BUFFER_H
+#define BUFFER_H
+
+typedef struct buffer {
+ char *x;
+ unsigned int p;
+ unsigned int n;
+ int fd;
+ int (*op)();
+} buffer;
+
+#define BUFFER_INIT(op,fd,buf,len) { (buf), 0, (len), (fd), (op) }
+#define BUFFER_INSIZE 8192
+#define BUFFER_OUTSIZE 8192
+
+extern void buffer_init(buffer *,int (*)(),int,char *,unsigned int);
+
+extern int buffer_flush(buffer *);
+extern int buffer_put(buffer *,char *,unsigned int);
+extern int buffer_putalign(buffer *,char *,unsigned int);
+extern int buffer_putflush(buffer *,char *,unsigned int);
+extern int buffer_puts(buffer *,char *);
+extern int buffer_putsalign(buffer *,char *);
+extern int buffer_putsflush(buffer *,char *);
+
+#define buffer_PUTC(s,c) \
+ ( ((s)->n != (s)->p) \
+ ? ( (s)->x[(s)->p++] = (c), 0 ) \
+ : buffer_put((s),&(c),1) \
+ )
+
+extern int buffer_get(buffer *,char *,unsigned int);
+extern int buffer_bget(buffer *,char *,unsigned int);
+extern int buffer_feed(buffer *);
+
+extern char *buffer_peek(buffer *);
+extern void buffer_seek(buffer *,unsigned int);
+
+#define buffer_PEEK(s) ( (s)->x + (s)->n )
+#define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) )
+
+#define buffer_GETC(s,c) \
+ ( ((s)->p > 0) \
+ ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \
+ : buffer_get((s),(c),1) \
+ )
+
+extern int buffer_copy(buffer *,buffer *);
+
+extern buffer *buffer_0;
+extern buffer *buffer_0small;
+extern buffer *buffer_1;
+extern buffer *buffer_1small;
+extern buffer *buffer_2;
+
+#endif
diff --git a/ucspi-tcp-0.88/buffer_0.c b/ucspi-tcp-0.88/buffer_0.c
new file mode 100644
index 0000000..6c5365a
--- /dev/null
+++ b/ucspi-tcp-0.88/buffer_0.c
@@ -0,0 +1,12 @@
+#include "readwrite.h"
+#include "buffer.h"
+
+int buffer_0_read(fd,buf,len) int fd; char *buf; int len;
+{
+ if (buffer_flush(buffer_1) == -1) return -1;
+ return read(fd,buf,len);
+}
+
+char buffer_0_space[BUFFER_INSIZE];
+static buffer it = BUFFER_INIT(buffer_0_read,0,buffer_0_space,sizeof buffer_0_space);
+buffer *buffer_0 = &it;
diff --git a/ucspi-tcp-0.88/buffer_1.c b/ucspi-tcp-0.88/buffer_1.c
new file mode 100644
index 0000000..3104e22
--- /dev/null
+++ b/ucspi-tcp-0.88/buffer_1.c
@@ -0,0 +1,6 @@
+#include "readwrite.h"
+#include "buffer.h"
+
+char buffer_1_space[BUFFER_OUTSIZE];
+static buffer it = BUFFER_INIT(write,1,buffer_1_space,sizeof buffer_1_space);
+buffer *buffer_1 = &it;
diff --git a/ucspi-tcp-0.88/buffer_2.c b/ucspi-tcp-0.88/buffer_2.c
new file mode 100644
index 0000000..297825c
--- /dev/null
+++ b/ucspi-tcp-0.88/buffer_2.c
@@ -0,0 +1,6 @@
+#include "readwrite.h"
+#include "buffer.h"
+
+char buffer_2_space[256];
+static buffer it = BUFFER_INIT(write,2,buffer_2_space,sizeof buffer_2_space);
+buffer *buffer_2 = &it;
diff --git a/ucspi-tcp-0.88/buffer_copy.c b/ucspi-tcp-0.88/buffer_copy.c
new file mode 100644
index 0000000..dc4d4b1
--- /dev/null
+++ b/ucspi-tcp-0.88/buffer_copy.c
@@ -0,0 +1,16 @@
+#include "buffer.h"
+
+int buffer_copy(buffer *bout,buffer *bin)
+{
+ int n;
+ char *x;
+
+ for (;;) {
+ n = buffer_feed(bin);
+ if (n < 0) return -2;
+ if (!n) return 0;
+ x = buffer_PEEK(bin);
+ if (buffer_put(bout,x,n) == -1) return -3;
+ buffer_SEEK(bin,n);
+ }
+}
diff --git a/ucspi-tcp-0.88/buffer_get.c b/ucspi-tcp-0.88/buffer_get.c
new file mode 100644
index 0000000..937b75e
--- /dev/null
+++ b/ucspi-tcp-0.88/buffer_get.c
@@ -0,0 +1,67 @@
+#include "buffer.h"
+#include "byte.h"
+#include "error.h"
+
+static int oneread(int (*op)(),int fd,char *buf,unsigned int len)
+{
+ int r;
+
+ for (;;) {
+ r = op(fd,buf,len);
+ if (r == -1) if (errno == error_intr) continue;
+ return r;
+ }
+}
+
+static int getthis(buffer *s,char *buf,unsigned int len)
+{
+ if (len > s->p) len = s->p;
+ s->p -= len;
+ byte_copy(buf,len,s->x + s->n);
+ s->n += len;
+ return len;
+}
+
+int buffer_feed(buffer *s)
+{
+ int r;
+
+ if (s->p) return s->p;
+ r = oneread(s->op,s->fd,s->x,s->n);
+ if (r <= 0) return r;
+ s->p = r;
+ s->n -= r;
+ if (s->n > 0) byte_copyr(s->x + s->n,r,s->x);
+ return r;
+}
+
+int buffer_bget(buffer *s,char *buf,unsigned int len)
+{
+ int r;
+
+ if (s->p > 0) return getthis(s,buf,len);
+ if (s->n <= len) return oneread(s->op,s->fd,buf,s->n);
+ r = buffer_feed(s); if (r <= 0) return r;
+ return getthis(s,buf,len);
+}
+
+int buffer_get(buffer *s,char *buf,unsigned int len)
+{
+ int r;
+
+ if (s->p > 0) return getthis(s,buf,len);
+ if (s->n <= len) return oneread(s->op,s->fd,buf,len);
+ r = buffer_feed(s); if (r <= 0) return r;
+ return getthis(s,buf,len);
+}
+
+char *buffer_peek(buffer *s)
+{
+ return s->x + s->n;
+}
+
+void buffer_seek(buffer *s,unsigned int len)
+{
+ s->n += len;
+ s->p -= len;
+}
diff --git a/ucspi-tcp-0.88/buffer_put.c b/ucspi-tcp-0.88/buffer_put.c
new file mode 100644
index 0000000..a05e1f5
--- /dev/null
+++ b/ucspi-tcp-0.88/buffer_put.c
@@ -0,0 +1,88 @@
+#include "buffer.h"
+#include "str.h"
+#include "byte.h"
+#include "error.h"
+
+static int allwrite(int (*op)(),int fd,char *buf,unsigned int len)
+{
+ 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 buffer_flush(buffer *s)
+{
+ int p;
+
+ p = s->p;
+ if (!p) return 0;
+ s->p = 0;
+ return allwrite(s->op,s->fd,s->x,p);
+}
+
+int buffer_putalign(buffer *s,char *buf,unsigned int len)
+{
+ unsigned 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 (buffer_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 buffer_put(buffer *s,char *buf,unsigned int len)
+{
+ unsigned int n;
+
+ n = s->n;
+ if (len > n - s->p) {
+ if (buffer_flush(s) == -1) return -1;
+ /* now s->p == 0 */
+ if (n < BUFFER_OUTSIZE) n = BUFFER_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 buffer_putflush(buffer *s,char *buf,unsigned int len)
+{
+ if (buffer_flush(s) == -1) return -1;
+ return allwrite(s->op,s->fd,buf,len);
+}
+
+int buffer_putsalign(buffer *s,char *buf)
+{
+ return buffer_putalign(s,buf,str_len(buf));
+}
+
+int buffer_puts(buffer *s,char *buf)
+{
+ return buffer_put(s,buf,str_len(buf));
+}
+
+int buffer_putsflush(buffer *s,char *buf)
+{
+ return buffer_putflush(s,buf,str_len(buf));
+}
diff --git a/ucspi-tcp-0.88/byte.h b/ucspi-tcp-0.88/byte.h
new file mode 100644
index 0000000..de06c69
--- /dev/null
+++ b/ucspi-tcp-0.88/byte.h
@@ -0,0 +1,13 @@
+#ifndef BYTE_H
+#define BYTE_H
+
+extern unsigned int byte_chr();
+extern unsigned int byte_rchr();
+extern void byte_copy();
+extern void byte_copyr();
+extern int byte_diff();
+extern void byte_zero();
+
+#define byte_equal(s,n,t) (!byte_diff((s),(n),(t)))
+
+#endif
diff --git a/ucspi-tcp-0.88/byte_chr.c b/ucspi-tcp-0.88/byte_chr.c
new file mode 100644
index 0000000..f81dde8
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/byte_copy.c b/ucspi-tcp-0.88/byte_copy.c
new file mode 100644
index 0000000..eaad11b
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/byte_cr.c b/ucspi-tcp-0.88/byte_cr.c
new file mode 100644
index 0000000..3e7a1d5
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/byte_diff.c b/ucspi-tcp-0.88/byte_diff.c
new file mode 100644
index 0000000..cdbd760
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/byte_rchr.c b/ucspi-tcp-0.88/byte_rchr.c
new file mode 100644
index 0000000..476bc22
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/byte_zero.c b/ucspi-tcp-0.88/byte_zero.c
new file mode 100644
index 0000000..92009ba
--- /dev/null
+++ b/ucspi-tcp-0.88/byte_zero.c
@@ -0,0 +1,13 @@
+#include "byte.h"
+
+void byte_zero(s,n)
+char *s;
+register unsigned int n;
+{
+ for (;;) {
+ if (!n) break; *s++ = 0; --n;
+ if (!n) break; *s++ = 0; --n;
+ if (!n) break; *s++ = 0; --n;
+ if (!n) break; *s++ = 0; --n;
+ }
+}
diff --git a/ucspi-tcp-0.88/case.h b/ucspi-tcp-0.88/case.h
new file mode 100644
index 0000000..93458d7
--- /dev/null
+++ b/ucspi-tcp-0.88/case.h
@@ -0,0 +1,13 @@
+#ifndef CASE_H
+#define CASE_H
+
+extern void case_lowers(char *);
+extern void case_lowerb(char *,unsigned int);
+extern int case_diffs(char *,char *);
+extern int case_diffb(char *,unsigned int,char *);
+extern int case_starts(char *,char *);
+extern int case_startb(char *,unsigned int,char *);
+
+#define case_equals(s,t) (!case_diffs((s),(t)))
+
+#endif
diff --git a/ucspi-tcp-0.88/case_diffb.c b/ucspi-tcp-0.88/case_diffb.c
new file mode 100644
index 0000000..967af56
--- /dev/null
+++ b/ucspi-tcp-0.88/case_diffb.c
@@ -0,0 +1,18 @@
+#include "case.h"
+
+int case_diffb(register char *s,register unsigned int len,register char *t)
+{
+ register unsigned char x;
+ register unsigned char y;
+
+ while (len > 0) {
+ --len;
+ x = *s++ - 'A';
+ if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+ y = *t++ - 'A';
+ if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+ if (x != y)
+ return ((int)(unsigned int) x) - ((int)(unsigned int) y);
+ }
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/case_diffs.c b/ucspi-tcp-0.88/case_diffs.c
new file mode 100644
index 0000000..2575184
--- /dev/null
+++ b/ucspi-tcp-0.88/case_diffs.c
@@ -0,0 +1,17 @@
+#include "case.h"
+
+int case_diffs(register char *s,register char *t)
+{
+ register unsigned char x;
+ register unsigned char y;
+
+ for (;;) {
+ x = *s++ - 'A';
+ if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+ y = *t++ - 'A';
+ if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+ if (x != y) break;
+ if (!x) break;
+ }
+ return ((int)(unsigned int) x) - ((int)(unsigned int) y);
+}
diff --git a/ucspi-tcp-0.88/cdb.c b/ucspi-tcp-0.88/cdb.c
new file mode 100644
index 0000000..b09d3a5
--- /dev/null
+++ b/ucspi-tcp-0.88/cdb.c
@@ -0,0 +1,136 @@
+/* Public domain. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include "readwrite.h"
+#include "error.h"
+#include "seek.h"
+#include "byte.h"
+#include "cdb.h"
+
+void cdb_free(struct cdb *c)
+{
+ if (c->map) {
+ munmap(c->map,c->size);
+ c->map = 0;
+ }
+}
+
+void cdb_findstart(struct cdb *c)
+{
+ c->loop = 0;
+}
+
+void cdb_init(struct cdb *c,int fd)
+{
+ struct stat st;
+ char *x;
+
+ cdb_free(c);
+ cdb_findstart(c);
+ c->fd = fd;
+
+ if (fstat(fd,&st) == 0)
+ if (st.st_size <= 0xffffffff) {
+ x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0);
+ if (x + 1) {
+ c->size = st.st_size;
+ c->map = x;
+ }
+ }
+}
+
+int cdb_read(struct cdb *c,char *buf,unsigned int len,uint32 pos)
+{
+ if (c->map) {
+ if ((pos > c->size) || (c->size - pos < len)) goto FORMAT;
+ byte_copy(buf,len,c->map + pos);
+ }
+ else {
+ if (seek_set(c->fd,pos) == -1) return -1;
+ while (len > 0) {
+ int r;
+ do
+ r = read(c->fd,buf,len);
+ while ((r == -1) && (errno == error_intr));
+ if (r == -1) return -1;
+ if (r == 0) goto FORMAT;
+ buf += r;
+ len -= r;
+ }
+ }
+ return 0;
+
+ FORMAT:
+ errno = error_proto;
+ return -1;
+}
+
+static int match(struct cdb *c,char *key,unsigned int len,uint32 pos)
+{
+ char buf[32];
+ int n;
+
+ while (len > 0) {
+ n = sizeof buf;
+ if (n > len) n = len;
+ if (cdb_read(c,buf,n,pos) == -1) return -1;
+ if (byte_diff(buf,n,key)) return 0;
+ pos += n;
+ key += n;
+ len -= n;
+ }
+ return 1;
+}
+
+int cdb_findnext(struct cdb *c,char *key,unsigned int len)
+{
+ char buf[8];
+ uint32 pos;
+ uint32 u;
+
+ if (!c->loop) {
+ u = cdb_hash(key,len);
+ if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1;
+ uint32_unpack(buf + 4,&c->hslots);
+ if (!c->hslots) return 0;
+ uint32_unpack(buf,&c->hpos);
+ c->khash = u;
+ u >>= 8;
+ u %= c->hslots;
+ u <<= 3;
+ c->kpos = c->hpos + u;
+ }
+
+ while (c->loop < c->hslots) {
+ if (cdb_read(c,buf,8,c->kpos) == -1) return -1;
+ uint32_unpack(buf + 4,&pos);
+ if (!pos) return 0;
+ c->loop += 1;
+ c->kpos += 8;
+ if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos;
+ uint32_unpack(buf,&u);
+ if (u == c->khash) {
+ if (cdb_read(c,buf,8,pos) == -1) return -1;
+ uint32_unpack(buf,&u);
+ if (u == len)
+ switch(match(c,key,len,pos + 8)) {
+ case -1:
+ return -1;
+ case 1:
+ uint32_unpack(buf + 4,&c->dlen);
+ c->dpos = pos + 8 + len;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int cdb_find(struct cdb *c,char *key,unsigned int len)
+{
+ cdb_findstart(c);
+ return cdb_findnext(c,key,len);
+}
diff --git a/ucspi-tcp-0.88/cdb.h b/ucspi-tcp-0.88/cdb.h
new file mode 100644
index 0000000..ff99810
--- /dev/null
+++ b/ucspi-tcp-0.88/cdb.h
@@ -0,0 +1,37 @@
+/* Public domain. */
+
+#ifndef CDB_H
+#define CDB_H
+
+#include "uint32.h"
+
+#define CDB_HASHSTART 5381
+extern uint32 cdb_hashadd(uint32,unsigned char);
+extern uint32 cdb_hash(char *,unsigned int);
+
+struct cdb {
+ char *map; /* 0 if no map is available */
+ int fd;
+ uint32 size; /* initialized if map is nonzero */
+ uint32 loop; /* number of hash slots searched under this key */
+ uint32 khash; /* initialized if loop is nonzero */
+ uint32 kpos; /* initialized if loop is nonzero */
+ uint32 hpos; /* initialized if loop is nonzero */
+ uint32 hslots; /* initialized if loop is nonzero */
+ uint32 dpos; /* initialized if cdb_findnext() returns 1 */
+ uint32 dlen; /* initialized if cdb_findnext() returns 1 */
+} ;
+
+extern void cdb_free(struct cdb *);
+extern void cdb_init(struct cdb *,int fd);
+
+extern int cdb_read(struct cdb *,char *,unsigned int,uint32);
+
+extern void cdb_findstart(struct cdb *);
+extern int cdb_findnext(struct cdb *,char *,unsigned int);
+extern int cdb_find(struct cdb *,char *,unsigned int);
+
+#define cdb_datapos(c) ((c)->dpos)
+#define cdb_datalen(c) ((c)->dlen)
+
+#endif
diff --git a/ucspi-tcp-0.88/cdb_hash.c b/ucspi-tcp-0.88/cdb_hash.c
new file mode 100644
index 0000000..d8e3cb8
--- /dev/null
+++ b/ucspi-tcp-0.88/cdb_hash.c
@@ -0,0 +1,21 @@
+/* Public domain. */
+
+#include "cdb.h"
+
+uint32 cdb_hashadd(uint32 h,unsigned char c)
+{
+ h += (h << 5);
+ return h ^ c;
+}
+
+uint32 cdb_hash(char *buf,unsigned int len)
+{
+ uint32 h;
+
+ h = CDB_HASHSTART;
+ while (len) {
+ h = cdb_hashadd(h,*buf++);
+ --len;
+ }
+ return h;
+}
diff --git a/ucspi-tcp-0.88/cdb_make.c b/ucspi-tcp-0.88/cdb_make.c
new file mode 100644
index 0000000..6d1bd03
--- /dev/null
+++ b/ucspi-tcp-0.88/cdb_make.c
@@ -0,0 +1,153 @@
+/* Public domain. */
+
+#include "readwrite.h"
+#include "seek.h"
+#include "error.h"
+#include "alloc.h"
+#include "cdb.h"
+#include "cdb_make.h"
+
+int cdb_make_start(struct cdb_make *c,int fd)
+{
+ c->head = 0;
+ c->split = 0;
+ c->hash = 0;
+ c->numentries = 0;
+ c->fd = fd;
+ c->pos = sizeof c->final;
+ buffer_init(&c->b,write,fd,c->bspace,sizeof c->bspace);
+ return seek_set(fd,c->pos);
+}
+
+static int posplus(struct cdb_make *c,uint32 len)
+{
+ uint32 newpos = c->pos + len;
+ if (newpos < len) { errno = error_nomem; return -1; }
+ c->pos = newpos;
+ return 0;
+}
+
+int cdb_make_addend(struct cdb_make *c,unsigned int keylen,unsigned int datalen,uint32 h)
+{
+ struct cdb_hplist *head;
+
+ head = c->head;
+ if (!head || (head->num >= CDB_HPLIST)) {
+ head = (struct cdb_hplist *) alloc(sizeof(struct cdb_hplist));
+ if (!head) return -1;
+ head->num = 0;
+ head->next = c->head;
+ c->head = head;
+ }
+ head->hp[head->num].h = h;
+ head->hp[head->num].p = c->pos;
+ ++head->num;
+ ++c->numentries;
+ if (posplus(c,8) == -1) return -1;
+ if (posplus(c,keylen) == -1) return -1;
+ if (posplus(c,datalen) == -1) return -1;
+ return 0;
+}
+
+int cdb_make_addbegin(struct cdb_make *c,unsigned int keylen,unsigned int datalen)
+{
+ char buf[8];
+
+ if (keylen > 0xffffffff) { errno = error_nomem; return -1; }
+ if (datalen > 0xffffffff) { errno = error_nomem; return -1; }
+
+ uint32_pack(buf,keylen);
+ uint32_pack(buf + 4,datalen);
+ if (buffer_putalign(&c->b,buf,8) == -1) return -1;
+ return 0;
+}
+
+int cdb_make_add(struct cdb_make *c,char *key,unsigned int keylen,char *data,unsigned int datalen)
+{
+ if (cdb_make_addbegin(c,keylen,datalen) == -1) return -1;
+ if (buffer_putalign(&c->b,key,keylen) == -1) return -1;
+ if (buffer_putalign(&c->b,data,datalen) == -1) return -1;
+ return cdb_make_addend(c,keylen,datalen,cdb_hash(key,keylen));
+}
+
+int cdb_make_finish(struct cdb_make *c)
+{
+ char buf[8];
+ int i;
+ uint32 len;
+ uint32 u;
+ uint32 memsize;
+ uint32 count;
+ uint32 where;
+ struct cdb_hplist *x;
+ struct cdb_hp *hp;
+
+ for (i = 0;i < 256;++i)
+ c->count[i] = 0;
+
+ for (x = c->head;x;x = x->next) {
+ i = x->num;
+ while (i--)
+ ++c->count[255 & x->hp[i].h];
+ }
+
+ memsize = 1;
+ for (i = 0;i < 256;++i) {
+ u = c->count[i] * 2;
+ if (u > memsize)
+ memsize = u;
+ }
+
+ memsize += c->numentries; /* no overflow possible up to now */
+ u = (uint32) 0 - (uint32) 1;
+ u /= sizeof(struct cdb_hp);
+ if (memsize > u) { errno = error_nomem; return -1; }
+
+ c->split = (struct cdb_hp *) alloc(memsize * sizeof(struct cdb_hp));
+ if (!c->split) return -1;
+
+ c->hash = c->split + c->numentries;
+
+ u = 0;
+ for (i = 0;i < 256;++i) {
+ u += c->count[i]; /* bounded by numentries, so no overflow */
+ c->start[i] = u;
+ }
+
+ for (x = c->head;x;x = x->next) {
+ i = x->num;
+ while (i--)
+ c->split[--c->start[255 & x->hp[i].h]] = x->hp[i];
+ }
+
+ for (i = 0;i < 256;++i) {
+ count = c->count[i];
+
+ len = count + count; /* no overflow possible */
+ uint32_pack(c->final + 8 * i,c->pos);
+ uint32_pack(c->final + 8 * i + 4,len);
+
+ for (u = 0;u < len;++u)
+ c->hash[u].h = c->hash[u].p = 0;
+
+ hp = c->split + c->start[i];
+ for (u = 0;u < count;++u) {
+ where = (hp->h >> 8) % len;
+ while (c->hash[where].p)
+ if (++where == len)
+ where = 0;
+ c->hash[where] = *hp++;
+ }
+
+ for (u = 0;u < len;++u) {
+ uint32_pack(buf,c->hash[u].h);
+ uint32_pack(buf + 4,c->hash[u].p);
+ if (buffer_putalign(&c->b,buf,8) == -1) return -1;
+ if (posplus(c,8) == -1) return -1;
+ }
+ }
+
+ if (buffer_flush(&c->b) == -1) return -1;
+ if (seek_begin(c->fd) == -1) return -1;
+ return buffer_putflush(&c->b,c->final,sizeof c->final);
+}
diff --git a/ucspi-tcp-0.88/cdb_make.h b/ucspi-tcp-0.88/cdb_make.h
new file mode 100644
index 0000000..b8bbe4d
--- /dev/null
+++ b/ucspi-tcp-0.88/cdb_make.h
@@ -0,0 +1,39 @@
+/* Public domain. */
+
+#ifndef CDB_MAKE_H
+#define CDB_MAKE_H
+
+#include "buffer.h"
+#include "uint32.h"
+
+#define CDB_HPLIST 1000
+
+struct cdb_hp { uint32 h; uint32 p; } ;
+
+struct cdb_hplist {
+ struct cdb_hp hp[CDB_HPLIST];
+ struct cdb_hplist *next;
+ int num;
+} ;
+
+struct cdb_make {
+ char bspace[8192];
+ char final[2048];
+ uint32 count[256];
+ uint32 start[256];
+ struct cdb_hplist *head;
+ struct cdb_hp *split; /* includes space for hash */
+ struct cdb_hp *hash;
+ uint32 numentries;
+ buffer b;
+ uint32 pos;
+ int fd;
+} ;
+
+extern int cdb_make_start(struct cdb_make *,int);
+extern int cdb_make_addbegin(struct cdb_make *,unsigned int,unsigned int);
+extern int cdb_make_addend(struct cdb_make *,unsigned int,unsigned int,uint32);
+extern int cdb_make_add(struct cdb_make *,char *,unsigned int,char *,unsigned int);
+extern int cdb_make_finish(struct cdb_make *);
+
+#endif
diff --git a/ucspi-tcp-0.88/chkshsgr.c b/ucspi-tcp-0.88/chkshsgr.c
new file mode 100644
index 0000000..4c7fc83
--- /dev/null
+++ b/ucspi-tcp-0.88/chkshsgr.c
@@ -0,0 +1,10 @@
+#include "exit.h"
+
+main()
+{
+ short x[4];
+
+ x[0] = x[1] = 0;
+ if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1);
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/choose.sh b/ucspi-tcp-0.88/choose.sh
new file mode 100644
index 0000000..feff2da
--- /dev/null
+++ b/ucspi-tcp-0.88/choose.sh
@@ -0,0 +1,18 @@
+
+result="$4"
+
+case "$1" in
+ *c*) ./compile $2.c >/dev/null 2>&1 || result="$3" ;;
+esac
+
+case "$1" in
+ *l*) ./load $2 >/dev/null 2>&1 || result="$3" ;;
+esac
+
+case "$1" in
+ *r*) ./$2 >/dev/null 2>&1 || result="$3" ;;
+esac
+
+rm -f $2.o $2
+
+exec cat "$result"
diff --git a/ucspi-tcp-0.88/commands.c b/ucspi-tcp-0.88/commands.c
new file mode 100644
index 0000000..b2dc77d
--- /dev/null
+++ b/ucspi-tcp-0.88/commands.c
@@ -0,0 +1,39 @@
+#include "buffer.h"
+#include "stralloc.h"
+#include "str.h"
+#include "case.h"
+#include "commands.h"
+
+static stralloc cmd = {0};
+
+int commands(buffer *ss,struct commands *c)
+{
+ int i;
+ char *arg;
+ char ch;
+
+ for (;;) {
+ if (!stralloc_copys(&cmd,"")) return -1;
+
+ for (;;) {
+ i = buffer_get(ss,&ch,1);
+ if (i != 1) return i;
+ if (ch == '\n') break;
+ if (!ch) ch = '\n';
+ if (!stralloc_append(&cmd,&ch)) return -1;
+ }
+
+ if (cmd.len > 0) if (cmd.s[cmd.len - 1] == '\r') --cmd.len;
+
+ if (!stralloc_0(&cmd)) return -1;
+
+ i = str_chr(cmd.s,' ');
+ arg = cmd.s + i;
+ while (*arg == ' ') ++arg;
+ cmd.s[i] = 0;
+
+ for (i = 0;c[i].verb;++i) if (case_equals(c[i].verb,cmd.s)) break;
+ c[i].action(arg);
+ if (c[i].flush) c[i].flush();
+ }
+}
diff --git a/ucspi-tcp-0.88/commands.h b/ucspi-tcp-0.88/commands.h
new file mode 100644
index 0000000..f5fb8fb
--- /dev/null
+++ b/ucspi-tcp-0.88/commands.h
@@ -0,0 +1,12 @@
+#ifndef COMMANDS_H
+#define COMMANDS_H
+
+struct commands {
+ char *verb;
+ void (*action)(char *);
+ void (*flush)(void);
+} ;
+
+extern int commands(buffer *,struct commands *);
+
+#endif
diff --git a/ucspi-tcp-0.88/conf-cc b/ucspi-tcp-0.88/conf-cc
new file mode 100644
index 0000000..7f41e18
--- /dev/null
+++ b/ucspi-tcp-0.88/conf-cc
@@ -0,0 +1,3 @@
+gcc -O2
+
+This will be used to compile .c files.
diff --git a/ucspi-tcp-0.88/conf-home b/ucspi-tcp-0.88/conf-home
new file mode 100644
index 0000000..5b6b574
--- /dev/null
+++ b/ucspi-tcp-0.88/conf-home
@@ -0,0 +1,4 @@
+/usr/local
+
+This is the ucspi-tcp home directory. Programs will be installed in
+.../bin.
diff --git a/ucspi-tcp-0.88/conf-ld b/ucspi-tcp-0.88/conf-ld
new file mode 100644
index 0000000..59a0de7
--- /dev/null
+++ b/ucspi-tcp-0.88/conf-ld
@@ -0,0 +1,3 @@
+gcc -s
+
+This will be used to link .o files into an executable.
diff --git a/ucspi-tcp-0.88/date@.sh b/ucspi-tcp-0.88/date@.sh
new file mode 100644
index 0000000..79bbe0c
--- /dev/null
+++ b/ucspi-tcp-0.88/date@.sh
@@ -0,0 +1 @@
+HOME/bin/tcpclient -RHl0 -- "${1-0}" 13 sh -c 'exec HOME/bin/delcr <&6' | cat -v
diff --git a/ucspi-tcp-0.88/delcr.c b/ucspi-tcp-0.88/delcr.c
new file mode 100644
index 0000000..ab47860
--- /dev/null
+++ b/ucspi-tcp-0.88/delcr.c
@@ -0,0 +1,37 @@
+#include "buffer.h"
+#include "exit.h"
+
+main()
+{
+ register int n;
+ register char *x;
+ char ch;
+ register int flagcr = 0;
+
+ for (;;) {
+ n = buffer_feed(buffer_0);
+ if (n < 0) _exit(111);
+ if (!n) {
+ if (flagcr) buffer_PUTC(buffer_1,"\r"[0]);
+ buffer_flush(buffer_1);
+ _exit(0);
+ }
+ x = buffer_PEEK(buffer_0);
+ buffer_SEEK(buffer_0,n);
+
+ while (n > 0) {
+ ch = *x++; --n;
+ if (!flagcr) {
+ if (ch == '\r') { flagcr = 1; continue; }
+ buffer_PUTC(buffer_1,ch);
+ continue;
+ }
+ if (ch != '\n') {
+ buffer_PUTC(buffer_1,"\r"[0]);
+ if (ch == '\r') continue;
+ }
+ flagcr = 0;
+ buffer_PUTC(buffer_1,ch);
+ }
+ }
+}
diff --git a/ucspi-tcp-0.88/dns.h b/ucspi-tcp-0.88/dns.h
new file mode 100644
index 0000000..0948b1a
--- /dev/null
+++ b/ucspi-tcp-0.88/dns.h
@@ -0,0 +1,84 @@
+#ifndef DNS_H
+#define DNS_H
+
+#include "stralloc.h"
+#include "iopause.h"
+#include "taia.h"
+
+#define DNS_C_IN "\0\1"
+#define DNS_C_ANY "\0\377"
+
+#define DNS_T_A "\0\1"
+#define DNS_T_NS "\0\2"
+#define DNS_T_CNAME "\0\5"
+#define DNS_T_SOA "\0\6"
+#define DNS_T_PTR "\0\14"
+#define DNS_T_HINFO "\0\15"
+#define DNS_T_MX "\0\17"
+#define DNS_T_TXT "\0\20"
+#define DNS_T_RP "\0\21"
+#define DNS_T_SIG "\0\30"
+#define DNS_T_KEY "\0\31"
+#define DNS_T_AAAA "\0\34"
+#define DNS_T_AXFR "\0\374"
+#define DNS_T_ANY "\0\377"
+
+struct dns_transmit {
+ char *query; /* 0, or dynamically allocated */
+ unsigned int querylen;
+ char *packet; /* 0, or dynamically allocated */
+ unsigned int packetlen;
+ int s1; /* 0, or 1 + an open file descriptor */
+ int tcpstate;
+ unsigned int udploop;
+ unsigned int curserver;
+ struct taia deadline;
+ unsigned int pos;
+ char *servers;
+ char localip[4];
+ char qtype[2];
+} ;
+
+extern void dns_random_init(char *);
+extern unsigned int dns_random(unsigned int);
+
+extern void dns_sortip(char *,unsigned int);
+
+extern void dns_domain_free(char **);
+extern int dns_domain_copy(char **,char *);
+extern unsigned int dns_domain_length(char *);
+extern int dns_domain_equal(char *,char *);
+extern char *dns_domain_suffix(char *,char *);
+extern int dns_domain_fromdot(char **,char *,unsigned int);
+extern int dns_domain_todot_cat(stralloc *,char *);
+
+extern unsigned int dns_packet_copy(char *,unsigned int,unsigned int,char *,unsigned int);
+extern unsigned int dns_packet_getname(char *,unsigned int,unsigned int,char **);
+extern unsigned int dns_packet_skipname(char *,unsigned int,unsigned int);
+extern int dns_packet_nameequal(char *,unsigned int,unsigned int,char *,unsigned int,unsigned int);
+
+extern int dns_transmit_start(struct dns_transmit *,char *,int,char *,char *,char *);
+extern void dns_transmit_free(struct dns_transmit *);
+extern void dns_transmit_io(struct dns_transmit *,iopause_fd *,struct taia *);
+extern int dns_transmit_get(struct dns_transmit *,iopause_fd *,struct taia *);
+
+extern int dns_resolvconfip(char *);
+extern int dns_resolve(char *,char *);
+extern struct dns_transmit dns_resolve_tx;
+
+extern int dns_ip4_packet(stralloc *,char *,unsigned int);
+extern int dns_ip4(stralloc *,stralloc *);
+extern int dns_name_packet(stralloc *,char *,unsigned int);
+extern void dns_name4_domain(char *,char *);
+#define DNS_NAME4_DOMAIN 31
+extern int dns_name4(stralloc *,char *);
+extern int dns_txt_packet(stralloc *,char *,unsigned int);
+extern int dns_txt(stralloc *,stralloc *);
+extern int dns_mx_packet(stralloc *,char *,unsigned int);
+extern int dns_mx(stralloc *,stralloc *);
+
+extern int dns_resolvconfrewrite(stralloc *);
+extern int dns_ip4_qualify_rules(stralloc *,stralloc *,stralloc *,stralloc *);
+extern int dns_ip4_qualify(stralloc *,stralloc *,stralloc *);
+
+#endif
diff --git a/ucspi-tcp-0.88/dns_dfd.c b/ucspi-tcp-0.88/dns_dfd.c
new file mode 100644
index 0000000..14a29d8
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_dfd.c
@@ -0,0 +1,69 @@
+#include "error.h"
+#include "alloc.h"
+#include "byte.h"
+#include "dns.h"
+
+int dns_domain_fromdot(char **out,char *buf,unsigned int n)
+{
+ char label[63];
+ unsigned int labellen = 0; /* <= sizeof label */
+ char name[255];
+ unsigned int namelen = 0; /* <= sizeof name */
+ char ch;
+ char *x;
+
+ errno = error_proto;
+
+ for (;;) {
+ if (!n) break;
+ ch = *buf++; --n;
+ if (ch == '.') {
+ if (labellen) {
+ if (namelen + labellen + 1 > sizeof name) return 0;
+ name[namelen++] = labellen;
+ byte_copy(name + namelen,labellen,label);
+ namelen += labellen;
+ labellen = 0;
+ }
+ continue;
+ }
+ if (ch == '\\') {
+ if (!n) break;
+ ch = *buf++; --n;
+ if ((ch >= '0') && (ch <= '7')) {
+ ch -= '0';
+ if (n && (*buf >= '0') && (*buf <= '7')) {
+ ch <<= 3;
+ ch += *buf - '0';
+ ++buf; --n;
+ if (n && (*buf >= '0') && (*buf <= '7')) {
+ ch <<= 3;
+ ch += *buf - '0';
+ ++buf; --n;
+ }
+ }
+ }
+ }
+ if (labellen >= sizeof label) return 0;
+ label[labellen++] = ch;
+ }
+
+ if (labellen) {
+ if (namelen + labellen + 1 > sizeof name) return 0;
+ name[namelen++] = labellen;
+ byte_copy(name + namelen,labellen,label);
+ namelen += labellen;
+ labellen = 0;
+ }
+
+ if (namelen + 1 > sizeof name) return 0;
+ name[namelen++] = 0;
+
+ x = alloc(namelen);
+ if (!x) return 0;
+ byte_copy(x,namelen,name);
+
+ if (*out) alloc_free(*out);
+ *out = x;
+ return 1;
+}
diff --git a/ucspi-tcp-0.88/dns_domain.c b/ucspi-tcp-0.88/dns_domain.c
new file mode 100644
index 0000000..f898485
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_domain.c
@@ -0,0 +1,61 @@
+#include "error.h"
+#include "alloc.h"
+#include "case.h"
+#include "byte.h"
+#include "dns.h"
+
+unsigned int dns_domain_length(char *dn)
+{
+ char *x;
+ unsigned char c;
+
+ x = dn;
+ while (c = *x++)
+ x += (unsigned int) c;
+ return x - dn;
+}
+
+void dns_domain_free(char **out)
+{
+ if (*out) {
+ alloc_free(*out);
+ *out = 0;
+ }
+}
+
+int dns_domain_copy(char **out,char *in)
+{
+ unsigned int len;
+ char *x;
+
+ len = dns_domain_length(in);
+ x = alloc(len);
+ if (!x) return 0;
+ byte_copy(x,len,in);
+ if (*out) alloc_free(*out);
+ *out = x;
+ return 1;
+}
+
+int dns_domain_equal(char *dn1,char *dn2)
+{
+ unsigned int len;
+
+ len = dns_domain_length(dn1);
+ if (len != dns_domain_length(dn2)) return 0;
+
+ if (case_diffb(dn1,len,dn2)) return 0; /* safe since 63 < 'A' */
+ return 1;
+}
+
+char *dns_domain_suffix(char *big,char *little)
+{
+ unsigned char c;
+
+ for (;;) {
+ if (dns_domain_equal(big,little)) return big;
+ c = *big++;
+ if (!c) return 0;
+ big += c;
+ }
+}
diff --git a/ucspi-tcp-0.88/dns_dtda.c b/ucspi-tcp-0.88/dns_dtda.c
new file mode 100644
index 0000000..00b41a1
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_dtda.c
@@ -0,0 +1,35 @@
+#include "stralloc.h"
+#include "dns.h"
+
+int dns_domain_todot_cat(stralloc *out,char *d)
+{
+ char ch;
+ char ch2;
+ unsigned char ch3;
+ char buf[4];
+
+ if (!*d)
+ return stralloc_append(out,".");
+
+ for (;;) {
+ ch = *d++;
+ while (ch--) {
+ ch2 = *d++;
+ if ((ch2 >= 'A') && (ch2 <= 'Z'))
+ ch2 += 32;
+ if (((ch2 >= 'a') && (ch2 <= 'z')) || ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_')) {
+ if (!stralloc_append(out,&ch2)) return 0;
+ }
+ else {
+ ch3 = ch2;
+ buf[3] = '0' + (ch3 & 7); ch3 >>= 3;
+ buf[2] = '0' + (ch3 & 7); ch3 >>= 3;
+ buf[1] = '0' + (ch3 & 7);
+ buf[0] = '\\';
+ if (!stralloc_catb(out,buf,4)) return 0;
+ }
+ }
+ if (!*d) return 1;
+ if (!stralloc_append(out,".")) return 0;
+ }
+}
diff --git a/ucspi-tcp-0.88/dns_ip.c b/ucspi-tcp-0.88/dns_ip.c
new file mode 100644
index 0000000..fb0526c
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_ip.c
@@ -0,0 +1,75 @@
+#include "stralloc.h"
+#include "uint16.h"
+#include "byte.h"
+#include "dns.h"
+
+int dns_ip4_packet(stralloc *out,char *buf,unsigned int len)
+{
+ unsigned int pos;
+ char header[12];
+ uint16 numanswers;
+ uint16 datalen;
+
+ if (!stralloc_copys(out,"")) return -1;
+
+ pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
+ uint16_unpack_big(header + 6,&numanswers);
+ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
+ pos += 4;
+
+ while (numanswers--) {
+ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
+ pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
+ uint16_unpack_big(header + 8,&datalen);
+ if (byte_equal(header,2,DNS_T_A))
+ if (byte_equal(header + 2,2,DNS_C_IN))
+ if (datalen == 4) {
+ if (!dns_packet_copy(buf,len,pos,header,4)) return -1;
+ if (!stralloc_catb(out,header,4)) return -1;
+ }
+ pos += datalen;
+ }
+
+ dns_sortip(out->s,out->len);
+ return 0;
+}
+
+static char *q = 0;
+
+int dns_ip4(stralloc *out,stralloc *fqdn)
+{
+ unsigned int i;
+ char code;
+ char ch;
+
+ if (!stralloc_copys(out,"")) return -1;
+ code = 0;
+ for (i = 0;i <= fqdn->len;++i) {
+ if (i < fqdn->len)
+ ch = fqdn->s[i];
+ else
+ ch = '.';
+
+ if ((ch == '[') || (ch == ']')) continue;
+ if (ch == '.') {
+ if (!stralloc_append(out,&code)) return -1;
+ code = 0;
+ continue;
+ }
+ if ((ch >= '0') && (ch <= '9')) {
+ code *= 10;
+ code += ch - '0';
+ continue;
+ }
+
+ if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
+ if (dns_resolve(q,DNS_T_A) == -1) return -1;
+ if (dns_ip4_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
+ dns_transmit_free(&dns_resolve_tx);
+ dns_domain_free(&q);
+ return 0;
+ }
+
+ out->len &= ~3;
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/dns_ipq.c b/ucspi-tcp-0.88/dns_ipq.c
new file mode 100644
index 0000000..8181ab7
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_ipq.c
@@ -0,0 +1,71 @@
+#include "stralloc.h"
+#include "case.h"
+#include "byte.h"
+#include "str.h"
+#include "dns.h"
+
+static int doit(stralloc *work,char *rule)
+{
+ char ch;
+ unsigned int colon;
+ unsigned int prefixlen;
+
+ ch = *rule++;
+ if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1;
+ colon = str_chr(rule,':');
+ if (!rule[colon]) return 1;
+
+ if (work->len < colon) return 1;
+ prefixlen = work->len - colon;
+ if ((ch == '=') && prefixlen) return 1;
+ if (case_diffb(rule,colon,work->s + prefixlen)) return 1;
+ if (ch == '?') {
+ if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1;
+ if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1;
+ if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1;
+ }
+
+ work->len = prefixlen;
+ if (ch == '-') work->len = 0;
+ return stralloc_cats(work,rule + colon + 1);
+}
+
+int dns_ip4_qualify_rules(stralloc *out,stralloc *fqdn,stralloc *in,stralloc *rules)
+{
+ unsigned int i;
+ unsigned int j;
+ unsigned int plus;
+ unsigned int fqdnlen;
+
+ if (!stralloc_copy(fqdn,in)) return -1;
+
+ for (j = i = 0;j < rules->len;++j)
+ if (!rules->s[j]) {
+ if (!doit(fqdn,rules->s + i)) return -1;
+ i = j + 1;
+ }
+
+ fqdnlen = fqdn->len;
+ plus = byte_chr(fqdn->s,fqdnlen,'+');
+ if (plus >= fqdnlen)
+ return dns_ip4(out,fqdn);
+
+ i = plus + 1;
+ for (;;) {
+ j = byte_chr(fqdn->s + i,fqdnlen - i,'+');
+ byte_copy(fqdn->s + plus,j,fqdn->s + i);
+ fqdn->len = plus + j;
+ if (dns_ip4(out,fqdn) == -1) return -1;
+ if (out->len) return 0;
+ i += j;
+ if (i >= fqdnlen) return 0;
+ ++i;
+ }
+}
+
+int dns_ip4_qualify(stralloc *out,stralloc *fqdn,stralloc *in)
+{
+ static stralloc rules;
+ if (dns_resolvconfrewrite(&rules) == -1) return -1;
+ return dns_ip4_qualify_rules(out,fqdn,in,&rules);
+}
diff --git a/ucspi-tcp-0.88/dns_name.c b/ucspi-tcp-0.88/dns_name.c
new file mode 100644
index 0000000..dcb10c7
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_name.c
@@ -0,0 +1,48 @@
+#include "stralloc.h"
+#include "uint16.h"
+#include "byte.h"
+#include "dns.h"
+
+static char *q = 0;
+
+int dns_name_packet(stralloc *out,char *buf,unsigned int len)
+{
+ unsigned int pos;
+ char header[12];
+ uint16 numanswers;
+ uint16 datalen;
+
+ if (!stralloc_copys(out,"")) return -1;
+
+ pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
+ uint16_unpack_big(header + 6,&numanswers);
+ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
+ pos += 4;
+
+ while (numanswers--) {
+ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
+ pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
+ uint16_unpack_big(header + 8,&datalen);
+ if (byte_equal(header,2,DNS_T_PTR))
+ if (byte_equal(header + 2,2,DNS_C_IN)) {
+ if (!dns_packet_getname(buf,len,pos,&q)) return -1;
+ if (!dns_domain_todot_cat(out,q)) return -1;
+ return 0;
+ }
+ pos += datalen;
+ }
+
+ return 0;
+}
+
+int dns_name4(stralloc *out,char ip[4])
+{
+ char name[DNS_NAME4_DOMAIN];
+
+ dns_name4_domain(name,ip);
+ if (dns_resolve(name,DNS_T_PTR) == -1) return -1;
+ if (dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
+ dns_transmit_free(&dns_resolve_tx);
+ dns_domain_free(&q);
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/dns_nd.c b/ucspi-tcp-0.88/dns_nd.c
new file mode 100644
index 0000000..279d74d
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_nd.c
@@ -0,0 +1,24 @@
+#include "byte.h"
+#include "fmt.h"
+#include "dns.h"
+
+void dns_name4_domain(char name[DNS_NAME4_DOMAIN],char ip[4])
+{
+ unsigned int namelen;
+ unsigned int i;
+
+ namelen = 0;
+ i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[3]);
+ name[namelen++] = i;
+ namelen += i;
+ i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[2]);
+ name[namelen++] = i;
+ namelen += i;
+ i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[1]);
+ name[namelen++] = i;
+ namelen += i;
+ i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[0]);
+ name[namelen++] = i;
+ namelen += i;
+ byte_copy(name + namelen,14,"\7in-addr\4arpa\0");
+}
diff --git a/ucspi-tcp-0.88/dns_packet.c b/ucspi-tcp-0.88/dns_packet.c
new file mode 100644
index 0000000..04a2cc8
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_packet.c
@@ -0,0 +1,77 @@
+/*
+DNS should have used LZ77 instead of its own sophomoric compression algorithm.
+*/
+
+#include "error.h"
+#include "dns.h"
+
+unsigned int dns_packet_copy(char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen)
+{
+ while (outlen) {
+ if (pos >= len) { errno = error_proto; return 0; }
+ *out = buf[pos++];
+ ++out; --outlen;
+ }
+ return pos;
+}
+
+unsigned int dns_packet_skipname(char *buf,unsigned int len,unsigned int pos)
+{
+ unsigned char ch;
+
+ for (;;) {
+ if (pos >= len) break;
+ ch = buf[pos++];
+ if (ch >= 192) return pos + 1;
+ if (ch >= 64) break;
+ if (!ch) return pos;
+ pos += ch;
+ }
+
+ errno = error_proto;
+ return 0;
+}
+
+unsigned int dns_packet_getname(char *buf,unsigned int len,unsigned int pos,char **d)
+{
+ unsigned int loop = 0;
+ unsigned int state = 0;
+ unsigned int firstcompress = 0;
+ unsigned int where;
+ unsigned char ch;
+ char name[255];
+ unsigned int namelen = 0;
+
+ for (;;) {
+ if (pos >= len) goto PROTO; ch = buf[pos++];
+ if (++loop >= 1000) goto PROTO;
+
+ if (state) {
+ if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch;
+ --state;
+ }
+ else {
+ while (ch >= 192) {
+ where = ch; where -= 192; where <<= 8;
+ if (pos >= len) goto PROTO; ch = buf[pos++];
+ if (!firstcompress) firstcompress = pos;
+ pos = where + ch;
+ if (pos >= len) goto PROTO; ch = buf[pos++];
+ if (++loop >= 1000) goto PROTO;
+ }
+ if (ch >= 64) goto PROTO;
+ if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch;
+ if (!ch) break;
+ state = ch;
+ }
+ }
+
+ if (!dns_domain_copy(d,name)) return 0;
+
+ if (firstcompress) return firstcompress;
+ return pos;
+
+ PROTO:
+ errno = error_proto;
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/dns_random.c b/ucspi-tcp-0.88/dns_random.c
new file mode 100644
index 0000000..b9892b4
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_random.c
@@ -0,0 +1,62 @@
+#include "dns.h"
+#include "taia.h"
+#include "uint32.h"
+
+static uint32 seed[32];
+static uint32 in[12];
+static uint32 out[8];
+static int outleft = 0;
+
+#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
+#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
+
+static void surf(void)
+{
+ uint32 t[12]; uint32 x; uint32 sum = 0;
+ int r; int i; int loop;
+
+ for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i];
+ for (i = 0;i < 8;++i) out[i] = seed[24 + i];
+ x = t[11];
+ for (loop = 0;loop < 2;++loop) {
+ for (r = 0;r < 16;++r) {
+ sum += 0x9e3779b9;
+ MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13)
+ MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13)
+ MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13)
+ }
+ for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
+ }
+}
+
+void dns_random_init(char data[128])
+{
+ int i;
+ struct taia t;
+ char tpack[16];
+
+ for (i = 0;i < 32;++i)
+ uint32_unpack(data + 4 * i,seed + i);
+
+ taia_now(&t);
+ taia_pack(tpack,&t);
+ for (i = 0;i < 4;++i)
+ uint32_unpack(tpack + 4 * i,in + 4 + i);
+
+ in[8] = getpid();
+ in[9] = getppid();
+ /* more space in 10 and 11, but this is probably enough */
+}
+
+unsigned int dns_random(unsigned int n)
+{
+ if (!n) return 0;
+
+ if (!outleft) {
+ if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
+ surf();
+ outleft = 8;
+ }
+
+ return out[--outleft] % n;
+}
diff --git a/ucspi-tcp-0.88/dns_rcip.c b/ucspi-tcp-0.88/dns_rcip.c
new file mode 100644
index 0000000..2356c8b
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_rcip.c
@@ -0,0 +1,82 @@
+#include "taia.h"
+#include "openreadclose.h"
+#include "byte.h"
+#include "ip4.h"
+#include "env.h"
+#include "dns.h"
+
+static stralloc data = {0};
+
+static int init(char ip[64])
+{
+ int i;
+ int j;
+ int iplen = 0;
+ char *x;
+
+ x = env_get("DNSCACHEIP");
+ if (x)
+ while (iplen <= 60)
+ if (*x == '.')
+ ++x;
+ else {
+ i = ip4_scan(x,ip + iplen);
+ if (!i) break;
+ x += i;
+ iplen += 4;
+ }
+
+ if (!iplen) {
+ i = openreadclose("/etc/resolv.conf",&data,64);
+ if (i == -1) return -1;
+ if (i) {
+ if (!stralloc_append(&data,"\n")) return -1;
+ i = 0;
+ for (j = 0;j < data.len;++j)
+ if (data.s[j] == '\n') {
+ if (byte_equal("nameserver ",11,data.s + i) || byte_equal("nameserver\t",11,data.s + i)) {
+ i += 10;
+ while ((data.s[i] == ' ') || (data.s[i] == '\t'))
+ ++i;
+ if (iplen <= 60)
+ if (ip4_scan(data.s + i,ip + iplen))
+ iplen += 4;
+ }
+ i = j + 1;
+ }
+ }
+ }
+
+ if (!iplen) {
+ byte_copy(ip,4,"\177\0\0\1");
+ iplen = 4;
+ }
+ byte_zero(ip + iplen,64 - iplen);
+ return 0;
+}
+
+static int ok = 0;
+static unsigned int uses;
+static struct taia deadline;
+static char ip[64]; /* defined if ok */
+
+int dns_resolvconfip(char s[64])
+{
+ struct taia now;
+
+ taia_now(&now);
+ if (taia_less(&deadline,&now)) ok = 0;
+ if (!uses) ok = 0;
+
+ if (!ok) {
+ if (init(ip) == -1) return -1;
+ taia_uint(&deadline,600);
+ taia_add(&deadline,&now,&deadline);
+ uses = 10000;
+ ok = 1;
+ }
+
+ --uses;
+ byte_copy(s,64,ip);
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/dns_rcrw.c b/ucspi-tcp-0.88/dns_rcrw.c
new file mode 100644
index 0000000..6f215ac
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_rcrw.c
@@ -0,0 +1,130 @@
+#include "taia.h"
+#include "env.h"
+#include "byte.h"
+#include "str.h"
+#include "openreadclose.h"
+#include "dns.h"
+
+static stralloc data = {0};
+
+static int init(stralloc *rules)
+{
+ char host[256];
+ char *x;
+ int i;
+ int j;
+ int k;
+
+ if (!stralloc_copys(rules,"")) return -1;
+
+ x = env_get("DNSREWRITEFILE");
+ if (!x) x = "/etc/dnsrewrite";
+
+ i = openreadclose(x,&data,64);
+ if (i == -1) return -1;
+
+ if (i) {
+ if (!stralloc_append(&data,"\n")) return -1;
+ i = 0;
+ for (j = 0;j < data.len;++j)
+ if (data.s[j] == '\n') {
+ if (!stralloc_catb(rules,data.s + i,j - i)) return -1;
+ while (rules->len) {
+ if (rules->s[rules->len - 1] != ' ')
+ if (rules->s[rules->len - 1] != '\t')
+ if (rules->s[rules->len - 1] != '\r')
+ break;
+ --rules->len;
+ }
+ if (!stralloc_0(rules)) return -1;
+ i = j + 1;
+ }
+ return 0;
+ }
+
+ x = env_get("LOCALDOMAIN");
+ if (x) {
+ if (!stralloc_copys(&data,x)) return -1;
+ if (!stralloc_append(&data," ")) return -1;
+ if (!stralloc_copys(rules,"?:")) return -1;
+ i = 0;
+ for (j = 0;j < data.len;++j)
+ if (data.s[j] == ' ') {
+ if (!stralloc_cats(rules,"+.")) return -1;
+ if (!stralloc_catb(rules,data.s + i,j - i)) return -1;
+ i = j + 1;
+ }
+ if (!stralloc_0(rules)) return -1;
+ if (!stralloc_cats(rules,"*.:")) return -1;
+ if (!stralloc_0(rules)) return -1;
+ return 0;
+ }
+
+ i = openreadclose("/etc/resolv.conf",&data,64);
+ if (i == -1) return -1;
+
+ if (i) {
+ if (!stralloc_append(&data,"\n")) return -1;
+ i = 0;
+ for (j = 0;j < data.len;++j)
+ if (data.s[j] == '\n') {
+ if (byte_equal("search ",7,data.s + i) || byte_equal("search\t",7,data.s + i) || byte_equal("domain ",7,data.s + i) || byte_equal("domain\t",7,data.s + i)) {
+ if (!stralloc_copys(rules,"?:")) return -1;
+ i += 7;
+ while (i < j) {
+ k = byte_chr(data.s + i,j - i,' ');
+ k = byte_chr(data.s + i,k,'\t');
+ if (!k) { ++i; continue; }
+ if (!stralloc_cats(rules,"+.")) return -1;
+ if (!stralloc_catb(rules,data.s + i,k)) return -1;
+ i += k;
+ }
+ if (!stralloc_0(rules)) return -1;
+ if (!stralloc_cats(rules,"*.:")) return -1;
+ if (!stralloc_0(rules)) return -1;
+ return 0;
+ }
+ i = j + 1;
+ }
+ }
+
+ host[0] = 0;
+ if (gethostname(host,sizeof host) == -1) return -1;
+ host[(sizeof host) - 1] = 0;
+ i = str_chr(host,'.');
+ if (host[i]) {
+ if (!stralloc_copys(rules,"?:")) return -1;
+ if (!stralloc_cats(rules,host + i)) return -1;
+ if (!stralloc_0(rules)) return -1;
+ }
+ if (!stralloc_cats(rules,"*.:")) return -1;
+ if (!stralloc_0(rules)) return -1;
+
+ return 0;
+}
+
+static int ok = 0;
+static unsigned int uses;
+static struct taia deadline;
+static stralloc rules = {0}; /* defined if ok */
+
+int dns_resolvconfrewrite(stralloc *out)
+{
+ struct taia now;
+
+ taia_now(&now);
+ if (taia_less(&deadline,&now)) ok = 0;
+ if (!uses) ok = 0;
+
+ if (!ok) {
+ if (init(&rules) == -1) return -1;
+ taia_uint(&deadline,600);
+ taia_add(&deadline,&now,&deadline);
+ uses = 10000;
+ ok = 1;
+ }
+
+ --uses;
+ if (!stralloc_copy(out,&rules)) return -1;
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/dns_resolve.c b/ucspi-tcp-0.88/dns_resolve.c
new file mode 100644
index 0000000..3365c00
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_resolve.c
@@ -0,0 +1,29 @@
+#include "iopause.h"
+#include "taia.h"
+#include "byte.h"
+#include "dns.h"
+
+struct dns_transmit dns_resolve_tx = {0};
+
+int dns_resolve(char *q,char qtype[2])
+{
+ struct taia stamp;
+ struct taia deadline;
+ char servers[64];
+ iopause_fd x[1];
+ int r;
+
+ if (dns_resolvconfip(servers) == -1) return -1;
+ if (dns_transmit_start(&dns_resolve_tx,servers,1,q,qtype,"\0\0\0\0") == -1) return -1;
+
+ for (;;) {
+ taia_now(&stamp);
+ taia_uint(&deadline,120);
+ taia_add(&deadline,&deadline,&stamp);
+ dns_transmit_io(&dns_resolve_tx,x,&deadline);
+ iopause(x,1,&deadline,&stamp);
+ r = dns_transmit_get(&dns_resolve_tx,x,&stamp);
+ if (r == -1) return -1;
+ if (r == 1) return 0;
+ }
+}
diff --git a/ucspi-tcp-0.88/dns_sortip.c b/ucspi-tcp-0.88/dns_sortip.c
new file mode 100644
index 0000000..af9b235
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_sortip.c
@@ -0,0 +1,20 @@
+#include "byte.h"
+#include "dns.h"
+
+/* XXX: sort servers by configurable notion of closeness? */
+/* XXX: pay attention to competence of each server? */
+
+void dns_sortip(char *s,unsigned int n)
+{
+ unsigned int i;
+ char tmp[4];
+
+ n >>= 2;
+ while (n > 1) {
+ i = dns_random(n);
+ --n;
+ byte_copy(tmp,4,s + (i << 2));
+ byte_copy(s + (i << 2),4,s + (n << 2));
+ byte_copy(s + (n << 2),4,tmp);
+ }
+}
diff --git a/ucspi-tcp-0.88/dns_transmit.c b/ucspi-tcp-0.88/dns_transmit.c
new file mode 100644
index 0000000..df12826
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_transmit.c
@@ -0,0 +1,364 @@
+#include "socket.h"
+#include "alloc.h"
+#include "error.h"
+#include "byte.h"
+#include "readwrite.h"
+#include "uint16.h"
+#include "dns.h"
+
+static int serverwantstcp(char *buf,unsigned int len)
+{
+ char out[12];
+
+ if (!dns_packet_copy(buf,len,0,out,12)) return 1;
+ if (out[2] & 2) return 1;
+ return 0;
+}
+
+static int serverfailed(char *buf,unsigned int len)
+{
+ char out[12];
+ unsigned int rcode;
+
+ if (!dns_packet_copy(buf,len,0,out,12)) return 1;
+ rcode = out[3];
+ rcode &= 15;
+ if (rcode && (rcode != 3)) { errno = error_again; return 1; }
+ return 0;
+}
+
+static int irrelevant(struct dns_transmit *d,char *buf,unsigned int len)
+{
+ char out[12];
+ char *dn;
+ unsigned int pos;
+
+ pos = dns_packet_copy(buf,len,0,out,12); if (!pos) return 1;
+ if (byte_diff(out,2,d->query + 2)) return 1;
+ if (out[4] != 0) return 1;
+ if (out[5] != 1) return 1;
+
+ dn = 0;
+ pos = dns_packet_getname(buf,len,pos,&dn); if (!pos) return 1;
+ if (!dns_domain_equal(dn,d->query + 14)) { alloc_free(dn); return 1; }
+ alloc_free(dn);
+
+ pos = dns_packet_copy(buf,len,pos,out,4); if (!pos) return 1;
+ if (byte_diff(out,2,d->qtype)) return 1;
+ if (byte_diff(out + 2,2,DNS_C_IN)) return 1;
+
+ return 0;
+}
+
+static void packetfree(struct dns_transmit *d)
+{
+ if (!d->packet) return;
+ alloc_free(d->packet);
+ d->packet = 0;
+}
+
+static void queryfree(struct dns_transmit *d)
+{
+ if (!d->query) return;
+ alloc_free(d->query);
+ d->query = 0;
+}
+
+static void socketfree(struct dns_transmit *d)
+{
+ if (!d->s1) return;
+ close(d->s1 - 1);
+ d->s1 = 0;
+}
+
+void dns_transmit_free(struct dns_transmit *d)
+{
+ queryfree(d);
+ socketfree(d);
+ packetfree(d);
+}
+
+static int randombind(struct dns_transmit *d)
+{
+ int j;
+
+ for (j = 0;j < 10;++j)
+ if (socket_bind4(d->s1 - 1,d->localip,1025 + dns_random(64510)) == 0)
+ return 0;
+ if (socket_bind4(d->s1 - 1,d->localip,0) == 0)
+ return 0;
+ return -1;
+}
+
+static const int timeouts[4] = { 1, 3, 11, 45 };
+
+static int thisudp(struct dns_transmit *d)
+{
+ char *ip;
+
+ socketfree(d);
+
+ while (d->udploop < 4) {
+ for (;d->curserver < 16;++d->curserver) {
+ ip = d->servers + 4 * d->curserver;
+ if (byte_diff(ip,4,"\0\0\0\0")) {
+ d->query[2] = dns_random(256);
+ d->query[3] = dns_random(256);
+
+ d->s1 = 1 + socket_udp();
+ if (!d->s1) { dns_transmit_free(d); return -1; }
+ if (randombind(d) == -1) { dns_transmit_free(d); return -1; }
+
+ if (socket_connect4(d->s1 - 1,ip,53) == 0)
+ if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) {
+ struct taia now;
+ taia_now(&now);
+ taia_uint(&d->deadline,timeouts[d->udploop]);
+ taia_add(&d->deadline,&d->deadline,&now);
+ d->tcpstate = 0;
+ return 0;
+ }
+
+ socketfree(d);
+ }
+ }
+
+ ++d->udploop;
+ d->curserver = 0;
+ }
+
+ dns_transmit_free(d); return -1;
+}
+
+static int firstudp(struct dns_transmit *d)
+{
+ d->curserver = 0;
+ return thisudp(d);
+}
+
+static int nextudp(struct dns_transmit *d)
+{
+ ++d->curserver;
+ return thisudp(d);
+}
+
+static int thistcp(struct dns_transmit *d)
+{
+ struct taia now;
+ char *ip;
+
+ socketfree(d);
+ packetfree(d);
+
+ for (;d->curserver < 16;++d->curserver) {
+ ip = d->servers + 4 * d->curserver;
+ if (byte_diff(ip,4,"\0\0\0\0")) {
+ d->query[2] = dns_random(256);
+ d->query[3] = dns_random(256);
+
+ d->s1 = 1 + socket_tcp();
+ if (!d->s1) { dns_transmit_free(d); return -1; }
+ if (randombind(d) == -1) { dns_transmit_free(d); return -1; }
+
+ taia_now(&now);
+ taia_uint(&d->deadline,10);
+ taia_add(&d->deadline,&d->deadline,&now);
+ if (socket_connect4(d->s1 - 1,ip,53) == 0) {
+ d->tcpstate = 2;
+ return 0;
+ }
+ if ((errno == error_inprogress) || (errno == error_wouldblock)) {
+ d->tcpstate = 1;
+ return 0;
+ }
+
+ socketfree(d);
+ }
+ }
+
+ dns_transmit_free(d); return -1;
+}
+
+static int firsttcp(struct dns_transmit *d)
+{
+ d->curserver = 0;
+ return thistcp(d);
+}
+
+static int nexttcp(struct dns_transmit *d)
+{
+ ++d->curserver;
+ return thistcp(d);
+}
+
+int dns_transmit_start(struct dns_transmit *d,char servers[64],int flagrecursive,char *q,char qtype[2],char localip[4])
+{
+ unsigned int len;
+
+ dns_transmit_free(d);
+ errno = error_io;
+
+ len = dns_domain_length(q);
+ d->querylen = len + 18;
+ d->query = alloc(d->querylen);
+ if (!d->query) return -1;
+
+ uint16_pack_big(d->query,len + 16);
+ byte_copy(d->query + 2,12,flagrecursive ? "\0\0\1\0\0\1\0\0\0\0\0\0" : "\0\0\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround");
+ byte_copy(d->query + 14,len,q);
+ byte_copy(d->query + 14 + len,2,qtype);
+ byte_copy(d->query + 16 + len,2,DNS_C_IN);
+
+ byte_copy(d->qtype,2,qtype);
+ d->servers = servers;
+ byte_copy(d->localip,4,localip);
+
+ d->udploop = flagrecursive ? 1 : 0;
+
+ if (len + 16 > 512) return firsttcp(d);
+ return firstudp(d);
+}
+
+void dns_transmit_io(struct dns_transmit *d,iopause_fd *x,struct taia *deadline)
+{
+ x->fd = d->s1 - 1;
+
+ switch(d->tcpstate) {
+ case 0: case 3: case 4: case 5:
+ x->events = IOPAUSE_READ;
+ break;
+ case 1: case 2:
+ x->events = IOPAUSE_WRITE;
+ break;
+ }
+
+ if (taia_less(&d->deadline,deadline))
+ *deadline = d->deadline;
+}
+
+int dns_transmit_get(struct dns_transmit *d,iopause_fd *x,struct taia *when)
+{
+ char udpbuf[513];
+ unsigned char ch;
+ int r;
+ int fd;
+
+ errno = error_io;
+ fd = d->s1 - 1;
+
+ if (!x->revents) {
+ if (taia_less(when,&d->deadline)) return 0;
+ errno = error_timeout;
+ if (d->tcpstate == 0) return nextudp(d);
+ return nexttcp(d);
+ }
+
+ if (d->tcpstate == 0) {
+/*
+have attempted to send UDP query to each server udploop times
+have sent query to curserver on UDP socket s
+*/
+ r = recv(fd,udpbuf,sizeof udpbuf,0);
+ if (r <= 0) {
+ if (d->udploop == 2) return 0;
+ return nextudp(d);
+ }
+ if (r + 1 > sizeof udpbuf) return 0;
+
+ if (irrelevant(d,udpbuf,r)) return 0;
+ if (serverwantstcp(udpbuf,r)) return firsttcp(d);
+ if (serverfailed(udpbuf,r)) {
+ if (d->udploop == 2) return 0;
+ return nextudp(d);
+ }
+ socketfree(d);
+
+ d->packetlen = r;
+ d->packet = alloc(d->packetlen);
+ if (!d->packet) { dns_transmit_free(d); return -1; }
+ byte_copy(d->packet,d->packetlen,udpbuf);
+ queryfree(d);
+ return 1;
+ }
+
+ if (d->tcpstate == 1) {
+/*
+have sent connection attempt to curserver on TCP socket s
+pos not defined
+*/
+ if (!socket_connected(fd)) return nexttcp(d);
+ d->pos = 0;
+ d->tcpstate = 2;
+ return 0;
+ }
+
+ if (d->tcpstate == 2) {
+/*
+have connection to curserver on TCP socket s
+have sent pos bytes of query
+*/
+ r = write(fd,d->query + d->pos,d->querylen - d->pos);
+ if (r <= 0) return nexttcp(d);
+ d->pos += r;
+ if (d->pos == d->querylen) {
+ struct taia now;
+ taia_now(&now);
+ taia_uint(&d->deadline,10);
+ taia_add(&d->deadline,&d->deadline,&now);
+ d->tcpstate = 3;
+ }
+ return 0;
+ }
+
+ if (d->tcpstate == 3) {
+/*
+have sent entire query to curserver on TCP socket s
+pos not defined
+*/
+ r = read(fd,&ch,1);
+ if (r <= 0) return nexttcp(d);
+ d->packetlen = ch;
+ d->tcpstate = 4;
+ return 0;
+ }
+
+ if (d->tcpstate == 4) {
+/*
+have sent entire query to curserver on TCP socket s
+pos not defined
+have received one byte of packet length into packetlen
+*/
+ r = read(fd,&ch,1);
+ if (r <= 0) return nexttcp(d);
+ d->packetlen <<= 8;
+ d->packetlen += ch;
+ d->tcpstate = 5;
+ d->pos = 0;
+ d->packet = alloc(d->packetlen);
+ if (!d->packet) { dns_transmit_free(d); return -1; }
+ return 0;
+ }
+
+ if (d->tcpstate == 5) {
+/*
+have sent entire query to curserver on TCP socket s
+have received entire packet length into packetlen
+packet is allocated
+have received pos bytes of packet
+*/
+ r = read(fd,d->packet + d->pos,d->packetlen - d->pos);
+ if (r <= 0) return nexttcp(d);
+ d->pos += r;
+ if (d->pos < d->packetlen) return 0;
+
+ socketfree(d);
+ if (irrelevant(d,d->packet,d->packetlen)) return nexttcp(d);
+ if (serverwantstcp(d->packet,d->packetlen)) return nexttcp(d);
+ if (serverfailed(d->packet,d->packetlen)) return nexttcp(d);
+
+ queryfree(d);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/dns_txt.c b/ucspi-tcp-0.88/dns_txt.c
new file mode 100644
index 0000000..263b641
--- /dev/null
+++ b/ucspi-tcp-0.88/dns_txt.c
@@ -0,0 +1,59 @@
+#include "stralloc.h"
+#include "uint16.h"
+#include "byte.h"
+#include "dns.h"
+
+int dns_txt_packet(stralloc *out,char *buf,unsigned int len)
+{
+ unsigned int pos;
+ char header[12];
+ uint16 numanswers;
+ uint16 datalen;
+ char ch;
+ unsigned int txtlen;
+ int i;
+
+ if (!stralloc_copys(out,"")) return -1;
+
+ pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
+ uint16_unpack_big(header + 6,&numanswers);
+ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
+ pos += 4;
+
+ while (numanswers--) {
+ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
+ pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
+ uint16_unpack_big(header + 8,&datalen);
+ if (byte_equal(header,2,DNS_T_TXT))
+ if (byte_equal(header + 2,2,DNS_C_IN)) {
+ if (pos + datalen > len) return -1;
+ txtlen = 0;
+ for (i = 0;i < datalen;++i) {
+ ch = buf[pos + i];
+ if (!txtlen)
+ txtlen = (unsigned char) ch;
+ else {
+ --txtlen;
+ if (ch < 32) ch = '?';
+ if (ch > 126) ch = '?';
+ if (!stralloc_append(out,&ch)) return -1;
+ }
+ }
+ }
+ pos += datalen;
+ }
+
+ return 0;
+}
+
+static char *q = 0;
+
+int dns_txt(stralloc *out,stralloc *fqdn)
+{
+ if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
+ if (dns_resolve(q,DNS_T_TXT) == -1) return -1;
+ if (dns_txt_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
+ dns_transmit_free(&dns_resolve_tx);
+ dns_domain_free(&q);
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/env.c b/ucspi-tcp-0.88/env.c
new file mode 100644
index 0000000..430203e
--- /dev/null
+++ b/ucspi-tcp-0.88/env.c
@@ -0,0 +1,15 @@
+#include "str.h"
+#include "env.h"
+
+extern /*@null@*/char *env_get(char *s)
+{
+ int i;
+ unsigned int len;
+
+ if (!s) return 0;
+ len = str_len(s);
+ for (i = 0;environ[i];++i)
+ if (str_start(environ[i],s) && (environ[i][len] == '='))
+ return environ[i] + len + 1;
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/env.h b/ucspi-tcp-0.88/env.h
new file mode 100644
index 0000000..777873a
--- /dev/null
+++ b/ucspi-tcp-0.88/env.h
@@ -0,0 +1,8 @@
+#ifndef ENV_H
+#define ENV_H
+
+extern char **environ;
+
+extern /*@null@*/char *env_get(char *);
+
+#endif
diff --git a/ucspi-tcp-0.88/error.c b/ucspi-tcp-0.88/error.c
new file mode 100644
index 0000000..ea16ff9
--- /dev/null
+++ b/ucspi-tcp-0.88/error.c
@@ -0,0 +1,116 @@
+#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
+
+int error_nodevice =
+#ifdef ENXIO
+ENXIO;
+#else
+-14;
+#endif
+
+int error_proto =
+#ifdef EPROTO
+EPROTO;
+#else
+-15;
+#endif
+
+int error_isdir =
+#ifdef EISDIR
+EISDIR;
+#else
+-16;
+#endif
diff --git a/ucspi-tcp-0.88/error.h b/ucspi-tcp-0.88/error.h
new file mode 100644
index 0000000..d5f3c7e
--- /dev/null
+++ b/ucspi-tcp-0.88/error.h
@@ -0,0 +1,26 @@
+#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 int error_nodevice;
+extern int error_proto;
+extern int error_isdir;
+
+extern char *error_str(int);
+extern int error_temp(int);
+
+#endif
diff --git a/ucspi-tcp-0.88/error_str.c b/ucspi-tcp-0.88/error_str.c
new file mode 100644
index 0000000..c999ab0
--- /dev/null
+++ b/ucspi-tcp-0.88/error_str.c
@@ -0,0 +1,269 @@
+#include <errno.h>
+#include "error.h"
+
+#define X(e,s) if (i == e) return s;
+
+char *error_str(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")
+ X(error_nodevice,"device not configured")
+ X(error_proto,"protocol error")
+ X(error_isdir,"is a directory")
+#ifdef ESRCH
+ X(ESRCH,"no such process")
+#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 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 EMULTIHOP
+ X(EMULTIHOP,"multihop attempted")
+#endif
+#ifdef EREMCHG
+ X(EREMCHG,"remote address changed")
+#endif
+ return "unknown error";
+}
diff --git a/ucspi-tcp-0.88/exit.h b/ucspi-tcp-0.88/exit.h
new file mode 100644
index 0000000..39011c8
--- /dev/null
+++ b/ucspi-tcp-0.88/exit.h
@@ -0,0 +1,6 @@
+#ifndef EXIT_H
+#define EXIT_H
+
+extern void _exit();
+
+#endif
diff --git a/ucspi-tcp-0.88/fd.h b/ucspi-tcp-0.88/fd.h
new file mode 100644
index 0000000..e9c08d6
--- /dev/null
+++ b/ucspi-tcp-0.88/fd.h
@@ -0,0 +1,7 @@
+#ifndef FD_H
+#define FD_H
+
+extern int fd_copy(int,int);
+extern int fd_move(int,int);
+
+#endif
diff --git a/ucspi-tcp-0.88/fd_copy.c b/ucspi-tcp-0.88/fd_copy.c
new file mode 100644
index 0000000..aa5e55e
--- /dev/null
+++ b/ucspi-tcp-0.88/fd_copy.c
@@ -0,0 +1,11 @@
+#include <fcntl.h>
+#include "fd.h"
+
+int fd_copy(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/ucspi-tcp-0.88/fd_move.c b/ucspi-tcp-0.88/fd_move.c
new file mode 100644
index 0000000..821ee95
--- /dev/null
+++ b/ucspi-tcp-0.88/fd_move.c
@@ -0,0 +1,9 @@
+#include "fd.h"
+
+int fd_move(int to,int from)
+{
+ if (to == from) return 0;
+ if (fd_copy(to,from) == -1) return -1;
+ close(from);
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/find-systype.sh b/ucspi-tcp-0.88/find-systype.sh
new file mode 100644
index 0000000..0955c32
--- /dev/null
+++ b/ucspi-tcp-0.88/find-systype.sh
@@ -0,0 +1,159 @@
+# 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
+
+if $CC -c x86cpuid.c
+then
+ if $LD -o x86cpuid x86cpuid.o
+ then
+ x86cpuid="`./x86cpuid | tr /: ..`"
+ case "$x86cpuid" in
+ ?*)
+ chip="$x86cpuid"
+ ;;
+ esac
+ fi
+fi
+rm -f x86cpuid x86cpuid.o
+
+echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]'
diff --git a/ucspi-tcp-0.88/finger@.sh b/ucspi-tcp-0.88/finger@.sh
new file mode 100644
index 0000000..ea8bf79
--- /dev/null
+++ b/ucspi-tcp-0.88/finger@.sh
@@ -0,0 +1,4 @@
+echo "${2-}" | HOME/bin/tcpclient -RHl0 -- "${1-0}" 79 sh -c '
+ HOME/bin/addcr >&7
+ exec HOME/bin/delcr <&6
+' | cat -v
diff --git a/ucspi-tcp-0.88/fixcrio.c b/ucspi-tcp-0.88/fixcrio.c
new file mode 100644
index 0000000..dbd4fa4
--- /dev/null
+++ b/ucspi-tcp-0.88/fixcrio.c
@@ -0,0 +1,161 @@
+#include "sig.h"
+#include "buffer.h"
+#include "strerr.h"
+#include "byte.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "iopause.h"
+#include "pathexec.h"
+
+#define FATAL "fixcrio: fatal: "
+
+char prebuf[256];
+
+int leftstatus = 0;
+char leftbuf[512];
+int leftlen;
+int leftpos;
+int leftflagcr = 0;
+
+int rightstatus = 0;
+char rightbuf[512];
+int rightlen;
+int rightpos;
+int rightflagcr = 0;
+
+void doit(int fdleft,int fdright)
+{
+ struct taia stamp;
+ struct taia deadline;
+ iopause_fd x[4];
+ int xlen;
+ iopause_fd *io0;
+ iopause_fd *ioleft;
+ iopause_fd *io1;
+ iopause_fd *ioright;
+ int r;
+ int i;
+ char ch;
+
+ for (;;) {
+ xlen = 0;
+
+ io0 = 0;
+ if (leftstatus == 0) {
+ io0 = &x[xlen++];
+ io0->fd = 0;
+ io0->events = IOPAUSE_READ;
+ }
+ ioleft = 0;
+ if (leftstatus == 1) {
+ ioleft = &x[xlen++];
+ ioleft->fd = fdleft;
+ ioleft->events = IOPAUSE_WRITE;
+ }
+
+ ioright = 0;
+ if (rightstatus == 0) {
+ ioright = &x[xlen++];
+ ioright->fd = fdright;
+ ioright->events = IOPAUSE_READ;
+ }
+ io1 = 0;
+ if (rightstatus == 1) {
+ io1 = &x[xlen++];
+ io1->fd = 1;
+ io1->events = IOPAUSE_WRITE;
+ }
+
+ taia_now(&stamp);
+ taia_uint(&deadline,3600);
+ taia_add(&deadline,&stamp,&deadline);
+ iopause(x,xlen,&deadline,&stamp);
+
+ if (io0 && io0->revents) {
+ r = read(0,prebuf,sizeof prebuf);
+ if (r <= 0) {
+ leftstatus = -1;
+ close(fdleft);
+ }
+ else {
+ leftstatus = 1;
+ leftpos = 0;
+ leftlen = 0;
+ for (i = 0;i < r;++i) {
+ ch = prebuf[i];
+ if (ch == '\n')
+ if (!leftflagcr)
+ leftbuf[leftlen++] = '\r';
+ leftbuf[leftlen++] = ch;
+ leftflagcr = (ch == '\r');
+ }
+ }
+ }
+
+ if (ioleft && ioleft->revents) {
+ r = write(fdleft,leftbuf + leftpos,leftlen - leftpos);
+ if (r == -1) break;
+ leftpos += r;
+ if (leftpos == leftlen) leftstatus = 0;
+ }
+
+ if (ioright && ioright->revents) {
+ r = read(fdright,prebuf,sizeof prebuf);
+ if (r <= 0) break;
+ rightstatus = 1;
+ rightpos = 0;
+ rightlen = 0;
+ for (i = 0;i < r;++i) {
+ ch = prebuf[i];
+ if (ch == '\n')
+ if (!rightflagcr)
+ rightbuf[rightlen++] = '\r';
+ rightbuf[rightlen++] = ch;
+ rightflagcr = (ch == '\r');
+ }
+ }
+
+ if (io1 && io1->revents) {
+ r = write(1,rightbuf + rightpos,rightlen - rightpos);
+ if (r == -1) break;
+ rightpos += r;
+ if (rightpos == rightlen) rightstatus = 0;
+ }
+ }
+
+ _exit(0);
+}
+
+main(int argc,char **argv,char **envp)
+{
+ int piin[2];
+ int piout[2];
+
+ if (argc < 2)
+ strerr_die1x(100,"fixcrio: usage: fixcrio program [ arg ... ]");
+
+ if (pipe(piin) == -1)
+ strerr_die2sys(111,FATAL,"unable to create pipe: ");
+ if (pipe(piout) == -1)
+ strerr_die2sys(111,FATAL,"unable to create pipe: ");
+
+ switch(fork()) {
+ case -1:
+ strerr_die2sys(111,FATAL,"unable to fork: ");
+ case 0:
+ sig_ignore(sig_pipe);
+ close(piin[0]);
+ close(piout[1]);
+ doit(piin[1],piout[0]);
+ }
+
+ close(piin[1]);
+ close(piout[0]);
+ if (fd_move(0,piin[0]) == -1)
+ strerr_die2sys(111,FATAL,"unable to move descriptors: ");
+ if (fd_move(1,piout[1]) == -1)
+ strerr_die2sys(111,FATAL,"unable to move descriptors: ");
+
+ pathexec_run(argv[1],argv + 1,envp);
+ strerr_die4sys(111,FATAL,"unable to run ",argv[1],": ");
+}
diff --git a/ucspi-tcp-0.88/fmt.h b/ucspi-tcp-0.88/fmt.h
new file mode 100644
index 0000000..6fd8fef
--- /dev/null
+++ b/ucspi-tcp-0.88/fmt.h
@@ -0,0 +1,25 @@
+#ifndef FMT_H
+#define FMT_H
+
+#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */
+#define FMT_LEN ((char *) 0) /* convenient abbreviation */
+
+extern unsigned int fmt_uint(char *,unsigned int);
+extern unsigned int fmt_uint0(char *,unsigned int,unsigned int);
+extern unsigned int fmt_xint(char *,unsigned int);
+extern unsigned int fmt_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int);
+extern unsigned int fmt_ushort(char *,unsigned short);
+extern unsigned int fmt_xshort(char *,unsigned short);
+extern unsigned int fmt_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short);
+extern unsigned int fmt_ulong(char *,unsigned long);
+extern unsigned int fmt_xlong(char *,unsigned long);
+extern unsigned int fmt_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long);
+
+extern unsigned int fmt_plusminus(char *,int);
+extern unsigned int fmt_minus(char *,int);
+extern unsigned int fmt_0x(char *,int);
+
+extern unsigned int fmt_str(char *,char *);
+extern unsigned int fmt_strn(char *,char *,unsigned int);
+
+#endif
diff --git a/ucspi-tcp-0.88/fmt_ulong.c b/ucspi-tcp-0.88/fmt_ulong.c
new file mode 100644
index 0000000..db48bfd
--- /dev/null
+++ b/ucspi-tcp-0.88/fmt_ulong.c
@@ -0,0 +1,13 @@
+#include "fmt.h"
+
+unsigned int fmt_ulong(register char *s,register unsigned long u)
+{
+ register unsigned int len; register unsigned long q;
+ len = 1; q = u;
+ while (q > 9) { ++len; q /= 10; }
+ if (s) {
+ s += len;
+ do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */
+ }
+ return len;
+}
diff --git a/ucspi-tcp-0.88/fork.h1 b/ucspi-tcp-0.88/fork.h1
new file mode 100644
index 0000000..ddd589d
--- /dev/null
+++ b/ucspi-tcp-0.88/fork.h1
@@ -0,0 +1,9 @@
+#ifndef FORK_H
+#define FORK_H
+
+/* sysdep: -vfork */
+
+extern int fork();
+#define vfork fork
+
+#endif
diff --git a/ucspi-tcp-0.88/fork.h2 b/ucspi-tcp-0.88/fork.h2
new file mode 100644
index 0000000..7c1b0b9
--- /dev/null
+++ b/ucspi-tcp-0.88/fork.h2
@@ -0,0 +1,9 @@
+#ifndef FORK_H
+#define FORK_H
+
+/* sysdep: +vfork */
+
+extern int fork();
+extern int vfork();
+
+#endif
diff --git a/ucspi-tcp-0.88/gen_alloc.h b/ucspi-tcp-0.88/gen_alloc.h
new file mode 100644
index 0000000..b94a956
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/gen_allocdefs.h b/ucspi-tcp-0.88/gen_allocdefs.h
new file mode 100644
index 0000000..d025b27
--- /dev/null
+++ b/ucspi-tcp-0.88/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(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(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(register ta *x,register type *i) \
+{ if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; }
+
+#endif
diff --git a/ucspi-tcp-0.88/getln.c b/ucspi-tcp-0.88/getln.c
new file mode 100644
index 0000000..489621c
--- /dev/null
+++ b/ucspi-tcp-0.88/getln.c
@@ -0,0 +1,14 @@
+#include "byte.h"
+#include "getln.h"
+
+int getln(buffer *ss,stralloc *sa,int *match,int sep)
+{
+ char *cont;
+ unsigned int clen;
+
+ if (getln2(ss,sa,&cont,&clen,sep) == -1) return -1;
+ if (!clen) { *match = 0; return 0; }
+ if (!stralloc_catb(sa,cont,clen)) return -1;
+ *match = 1;
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/getln.h b/ucspi-tcp-0.88/getln.h
new file mode 100644
index 0000000..3cae45f
--- /dev/null
+++ b/ucspi-tcp-0.88/getln.h
@@ -0,0 +1,10 @@
+#ifndef GETLN_H
+#define GETLN_H
+
+#include "buffer.h"
+#include "stralloc.h"
+
+extern int getln(buffer *,stralloc *,int *,int);
+extern int getln2(buffer *,stralloc *,char **,unsigned int *,int);
+
+#endif
diff --git a/ucspi-tcp-0.88/getln2.c b/ucspi-tcp-0.88/getln2.c
new file mode 100644
index 0000000..bf622a4
--- /dev/null
+++ b/ucspi-tcp-0.88/getln2.c
@@ -0,0 +1,24 @@
+#include "byte.h"
+#include "getln.h"
+
+int getln2(buffer *ss,stralloc *sa,char **cont,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 = buffer_feed(ss);
+ if (n < 0) return -1;
+ if (n == 0) { *clen = 0; return 0; }
+ x = buffer_PEEK(ss);
+ i = byte_chr(x,n,sep);
+ if (i < n) { buffer_SEEK(ss,*clen = i + 1); *cont = x; return 0; }
+ if (!stralloc_readyplus(sa,n)) return -1;
+ i = sa->len;
+ sa->len = i + buffer_get(ss,sa->s + i,n);
+ }
+}
diff --git a/ucspi-tcp-0.88/hassgact.h1 b/ucspi-tcp-0.88/hassgact.h1
new file mode 100644
index 0000000..03c7a9f
--- /dev/null
+++ b/ucspi-tcp-0.88/hassgact.h1
@@ -0,0 +1 @@
+/* sysdep: -sigaction */
diff --git a/ucspi-tcp-0.88/hassgact.h2 b/ucspi-tcp-0.88/hassgact.h2
new file mode 100644
index 0000000..594d486
--- /dev/null
+++ b/ucspi-tcp-0.88/hassgact.h2
@@ -0,0 +1,2 @@
+/* sysdep: +sigaction */
+#define HASSIGACTION 1
diff --git a/ucspi-tcp-0.88/hassgprm.h1 b/ucspi-tcp-0.88/hassgprm.h1
new file mode 100644
index 0000000..4c05fd1
--- /dev/null
+++ b/ucspi-tcp-0.88/hassgprm.h1
@@ -0,0 +1 @@
+/* sysdep: -sigprocmask */
diff --git a/ucspi-tcp-0.88/hassgprm.h2 b/ucspi-tcp-0.88/hassgprm.h2
new file mode 100644
index 0000000..d959bc7
--- /dev/null
+++ b/ucspi-tcp-0.88/hassgprm.h2
@@ -0,0 +1,2 @@
+/* sysdep: +sigprocmask */
+#define HASSIGPROCMASK 1
diff --git a/ucspi-tcp-0.88/hasshsgr.h1 b/ucspi-tcp-0.88/hasshsgr.h1
new file mode 100644
index 0000000..d11c988
--- /dev/null
+++ b/ucspi-tcp-0.88/hasshsgr.h1
@@ -0,0 +1 @@
+/* sysdep: -shortsetgroups */
diff --git a/ucspi-tcp-0.88/hasshsgr.h2 b/ucspi-tcp-0.88/hasshsgr.h2
new file mode 100644
index 0000000..db6a830
--- /dev/null
+++ b/ucspi-tcp-0.88/hasshsgr.h2
@@ -0,0 +1,2 @@
+/* sysdep: +shortsetgroups */
+#define HASSHORTSETGROUPS 1
diff --git a/ucspi-tcp-0.88/haswaitp.h1 b/ucspi-tcp-0.88/haswaitp.h1
new file mode 100644
index 0000000..469a7ad
--- /dev/null
+++ b/ucspi-tcp-0.88/haswaitp.h1
@@ -0,0 +1 @@
+/* sysdep: -waitpid */
diff --git a/ucspi-tcp-0.88/haswaitp.h2 b/ucspi-tcp-0.88/haswaitp.h2
new file mode 100644
index 0000000..a75823a
--- /dev/null
+++ b/ucspi-tcp-0.88/haswaitp.h2
@@ -0,0 +1,2 @@
+/* sysdep: +waitpid */
+#define HASWAITPID 1
diff --git a/ucspi-tcp-0.88/hier.c b/ucspi-tcp-0.88/hier.c
new file mode 100644
index 0000000..5663ada
--- /dev/null
+++ b/ucspi-tcp-0.88/hier.c
@@ -0,0 +1,25 @@
+#include "auto_home.h"
+
+void hier()
+{
+ h(auto_home,-1,-1,02755);
+ d(auto_home,"bin",-1,-1,02755);
+
+ c(auto_home,"bin","tcpserver",-1,-1,0755);
+ c(auto_home,"bin","tcprules",-1,-1,0755);
+ c(auto_home,"bin","tcprulescheck",-1,-1,0755);
+ c(auto_home,"bin","argv0",-1,-1,0755);
+ c(auto_home,"bin","recordio",-1,-1,0755);
+ c(auto_home,"bin","tcpclient",-1,-1,0755);
+ c(auto_home,"bin","who@",-1,-1,0755);
+ c(auto_home,"bin","date@",-1,-1,0755);
+ c(auto_home,"bin","finger@",-1,-1,0755);
+ c(auto_home,"bin","http@",-1,-1,0755);
+ c(auto_home,"bin","tcpcat",-1,-1,0755);
+ c(auto_home,"bin","mconnect",-1,-1,0755);
+ c(auto_home,"bin","mconnect-io",-1,-1,0755);
+ c(auto_home,"bin","addcr",-1,-1,0755);
+ c(auto_home,"bin","delcr",-1,-1,0755);
+ c(auto_home,"bin","fixcrio",-1,-1,0755);
+ c(auto_home,"bin","rblsmtpd",-1,-1,0755);
+}
diff --git a/ucspi-tcp-0.88/http@.sh b/ucspi-tcp-0.88/http@.sh
new file mode 100644
index 0000000..039be03
--- /dev/null
+++ b/ucspi-tcp-0.88/http@.sh
@@ -0,0 +1,6 @@
+echo "GET /${2-} HTTP/1.0
+Host: ${1-0}:${3-80}
+" | HOME/bin/tcpclient -RHl0 -- "${1-0}" "${3-80}" sh -c '
+ HOME/bin/addcr >&7
+ exec HOME/bin/delcr <&6
+' | awk '/^$/ { body=1; next } { if (body) print }'
diff --git a/ucspi-tcp-0.88/install.c b/ucspi-tcp-0.88/install.c
new file mode 100644
index 0000000..605fed3
--- /dev/null
+++ b/ucspi-tcp-0.88/install.c
@@ -0,0 +1,149 @@
+#include "buffer.h"
+#include "strerr.h"
+#include "error.h"
+#include "open.h"
+#include "readwrite.h"
+#include "exit.h"
+
+extern void hier();
+
+#define FATAL "install: fatal: "
+
+int fdsourcedir = -1;
+
+void h(home,uid,gid,mode)
+char *home;
+int uid;
+int gid;
+int mode;
+{
+ if (mkdir(home,0700) == -1)
+ if (errno != error_exist)
+ strerr_die4sys(111,FATAL,"unable to mkdir ",home,": ");
+ if (chown(home,uid,gid) == -1)
+ strerr_die4sys(111,FATAL,"unable to chown ",home,": ");
+ if (chmod(home,mode) == -1)
+ strerr_die4sys(111,FATAL,"unable to chmod ",home,": ");
+}
+
+void d(home,subdir,uid,gid,mode)
+char *home;
+char *subdir;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ if (mkdir(subdir,0700) == -1)
+ if (errno != error_exist)
+ strerr_die6sys(111,FATAL,"unable to mkdir ",home,"/",subdir,": ");
+ if (chown(subdir,uid,gid) == -1)
+ strerr_die6sys(111,FATAL,"unable to chown ",home,"/",subdir,": ");
+ if (chmod(subdir,mode) == -1)
+ strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",subdir,": ");
+}
+
+char inbuf[BUFFER_INSIZE];
+char outbuf[BUFFER_OUTSIZE];
+buffer ssin;
+buffer ssout;
+
+void c(home,subdir,file,uid,gid,mode)
+char *home;
+char *subdir;
+char *file;
+int uid;
+int gid;
+int mode;
+{
+ int fdin;
+ int fdout;
+
+ if (fchdir(fdsourcedir) == -1)
+ strerr_die2sys(111,FATAL,"unable to switch back to source directory: ");
+
+ fdin = open_read(file);
+ if (fdin == -1)
+ strerr_die4sys(111,FATAL,"unable to read ",file,": ");
+ buffer_init(&ssin,read,fdin,inbuf,sizeof inbuf);
+
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ if (chdir(subdir) == -1)
+ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+
+ fdout = open_trunc(file);
+ if (fdout == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ buffer_init(&ssout,write,fdout,outbuf,sizeof outbuf);
+
+ switch(buffer_copy(&ssout,&ssin)) {
+ case -2:
+ strerr_die4sys(111,FATAL,"unable to read ",file,": ");
+ case -3:
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ }
+
+ close(fdin);
+ if (buffer_flush(&ssout) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ if (fsync(fdout) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ if (close(fdout) == -1) /* NFS silliness */
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+
+ if (chown(file,uid,gid) == -1)
+ strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": ");
+ if (chmod(file,mode) == -1)
+ strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": ");
+}
+
+void z(home,subdir,file,len,uid,gid,mode)
+char *home;
+char *subdir;
+char *file;
+int len;
+int uid;
+int gid;
+int mode;
+{
+ int fdout;
+
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ if (chdir(subdir) == -1)
+ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+
+ fdout = open_trunc(file);
+ if (fdout == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ buffer_init(&ssout,write,fdout,outbuf,sizeof outbuf);
+
+ while (len-- > 0)
+ if (buffer_put(&ssout,"",1) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+
+ if (buffer_flush(&ssout) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ if (fsync(fdout) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ if (close(fdout) == -1) /* NFS silliness */
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+
+ if (chown(file,uid,gid) == -1)
+ strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": ");
+ if (chmod(file,mode) == -1)
+ strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": ");
+}
+
+main()
+{
+ fdsourcedir = open_read(".");
+ if (fdsourcedir == -1)
+ strerr_die2sys(111,FATAL,"unable to open current directory: ");
+
+ umask(077);
+ hier();
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/instcheck.c b/ucspi-tcp-0.88/instcheck.c
new file mode 100644
index 0000000..c945e67
--- /dev/null
+++ b/ucspi-tcp-0.88/instcheck.c
@@ -0,0 +1,108 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "strerr.h"
+#include "error.h"
+#include "readwrite.h"
+#include "exit.h"
+
+extern void hier();
+
+#define FATAL "instcheck: fatal: "
+#define WARNING "instcheck: warning: "
+
+void perm(prefix1,prefix2,prefix3,file,type,uid,gid,mode)
+char *prefix1;
+char *prefix2;
+char *prefix3;
+char *file;
+int type;
+int uid;
+int gid;
+int mode;
+{
+ struct stat st;
+
+ if (stat(file,&st) == -1) {
+ if (errno == error_noent)
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," does not exist",0);
+ else
+ strerr_warn4(WARNING,"unable to stat .../",file,": ",&strerr_sys);
+ return;
+ }
+
+ if ((uid != -1) && (st.st_uid != uid))
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong owner",0);
+ if ((gid != -1) && (st.st_gid != gid))
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong group",0);
+ if ((st.st_mode & 07777) != mode)
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong permissions",0);
+ if ((st.st_mode & S_IFMT) != type)
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong type",0);
+}
+
+void h(home,uid,gid,mode)
+char *home;
+int uid;
+int gid;
+int mode;
+{
+ perm("","","",home,S_IFDIR,uid,gid,mode);
+}
+
+void d(home,subdir,uid,gid,mode)
+char *home;
+char *subdir;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ perm("",home,"/",subdir,S_IFDIR,uid,gid,mode);
+}
+
+void p(home,fifo,uid,gid,mode)
+char *home;
+char *fifo;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ perm("",home,"/",fifo,S_IFIFO,uid,gid,mode);
+}
+
+void c(home,subdir,file,uid,gid,mode)
+char *home;
+char *subdir;
+char *file;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ if (chdir(subdir) == -1)
+ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+ perm(".../",subdir,"/",file,S_IFREG,uid,gid,mode);
+}
+
+void z(home,file,len,uid,gid,mode)
+char *home;
+char *file;
+int len;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ perm("",home,"/",file,S_IFREG,uid,gid,mode);
+}
+
+main()
+{
+ hier();
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/iopause.c b/ucspi-tcp-0.88/iopause.c
new file mode 100644
index 0000000..b8034de
--- /dev/null
+++ b/ucspi-tcp-0.88/iopause.c
@@ -0,0 +1,76 @@
+#include "taia.h"
+#include "select.h"
+#include "iopause.h"
+
+void iopause(iopause_fd *x,unsigned int len,struct taia *deadline,struct taia *stamp)
+{
+ struct taia t;
+ int millisecs;
+ double d;
+ int i;
+
+ if (taia_less(deadline,stamp))
+ millisecs = 0;
+ else {
+ t = *stamp;
+ taia_sub(&t,deadline,&t);
+ d = taia_approx(&t);
+ if (d > 1000.0) d = 1000.0;
+ millisecs = d * 1000.0 + 20.0;
+ }
+
+ for (i = 0;i < len;++i)
+ x[i].revents = 0;
+
+#ifdef IOPAUSE_POLL
+
+ poll(x,len,millisecs);
+ /* XXX: some kernels apparently need x[0] even if len is 0 */
+ /* XXX: how to handle EAGAIN? are kernels really this dumb? */
+ /* XXX: how to handle EINVAL? when exactly can this happen? */
+
+#else
+{
+
+ struct timeval tv;
+ fd_set rfds;
+ fd_set wfds;
+ int nfds;
+ int fd;
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+
+ nfds = 1;
+ for (i = 0;i < len;++i) {
+ fd = x[i].fd;
+ if (fd < 0) continue;
+ if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/
+
+ if (fd >= nfds) nfds = fd + 1;
+ if (x[i].events & IOPAUSE_READ) FD_SET(fd,&rfds);
+ if (x[i].events & IOPAUSE_WRITE) FD_SET(fd,&wfds);
+ }
+
+ tv.tv_sec = millisecs / 1000;
+ tv.tv_usec = 1000 * (millisecs % 1000);
+
+ if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) <= 0)
+ return;
+ /* XXX: for EBADF, could seek out and destroy the bad descriptor */
+
+ for (i = 0;i < len;++i) {
+ fd = x[i].fd;
+ if (fd < 0) continue;
+ if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/
+
+ if (x[i].events & IOPAUSE_READ)
+ if (FD_ISSET(fd,&rfds)) x[i].revents |= IOPAUSE_READ;
+ if (x[i].events & IOPAUSE_WRITE)
+ if (FD_ISSET(fd,&wfds)) x[i].revents |= IOPAUSE_WRITE;
+ }
+
+}
+#endif
+
+}
diff --git a/ucspi-tcp-0.88/iopause.h1 b/ucspi-tcp-0.88/iopause.h1
new file mode 100644
index 0000000..dae0a33
--- /dev/null
+++ b/ucspi-tcp-0.88/iopause.h1
@@ -0,0 +1,19 @@
+#ifndef IOPAUSE_H
+#define IOPAUSE_H
+
+/* sysdep: -poll */
+
+typedef struct {
+ int fd;
+ short events;
+ short revents;
+} iopause_fd;
+
+#define IOPAUSE_READ 1
+#define IOPAUSE_WRITE 4
+
+#include "taia.h"
+
+extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *);
+
+#endif
diff --git a/ucspi-tcp-0.88/iopause.h2 b/ucspi-tcp-0.88/iopause.h2
new file mode 100644
index 0000000..2cf5cf8
--- /dev/null
+++ b/ucspi-tcp-0.88/iopause.h2
@@ -0,0 +1,18 @@
+#ifndef IOPAUSE_H
+#define IOPAUSE_H
+
+/* sysdep: +poll */
+#define IOPAUSE_POLL
+
+#include <sys/types.h>
+#include <poll.h>
+
+typedef struct pollfd iopause_fd;
+#define IOPAUSE_READ POLLIN
+#define IOPAUSE_WRITE POLLOUT
+
+#include "taia.h"
+
+extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *);
+
+#endif
diff --git a/ucspi-tcp-0.88/ip4.h b/ucspi-tcp-0.88/ip4.h
new file mode 100644
index 0000000..64a7c1e
--- /dev/null
+++ b/ucspi-tcp-0.88/ip4.h
@@ -0,0 +1,9 @@
+#ifndef IP4_H
+#define IP4_H
+
+extern unsigned int ip4_scan(char *,char *);
+extern unsigned int ip4_fmt(char *,char *);
+
+#define IP4_FMT 20
+
+#endif
diff --git a/ucspi-tcp-0.88/ip4_fmt.c b/ucspi-tcp-0.88/ip4_fmt.c
new file mode 100644
index 0000000..c605634
--- /dev/null
+++ b/ucspi-tcp-0.88/ip4_fmt.c
@@ -0,0 +1,18 @@
+#include "fmt.h"
+#include "ip4.h"
+
+unsigned int ip4_fmt(char *s,char ip[4])
+{
+ unsigned int len;
+ unsigned int i;
+
+ len = 0;
+ i = fmt_ulong(s,(unsigned long) (unsigned char) ip[0]); len += i; if (s) s += i;
+ if (s) *s++ = '.'; ++len;
+ i = fmt_ulong(s,(unsigned long) (unsigned char) ip[1]); len += i; if (s) s += i;
+ if (s) *s++ = '.'; ++len;
+ i = fmt_ulong(s,(unsigned long) (unsigned char) ip[2]); len += i; if (s) s += i;
+ if (s) *s++ = '.'; ++len;
+ i = fmt_ulong(s,(unsigned long) (unsigned char) ip[3]); len += i; if (s) s += i;
+ return len;
+}
diff --git a/ucspi-tcp-0.88/ip4_scan.c b/ucspi-tcp-0.88/ip4_scan.c
new file mode 100644
index 0000000..7a61371
--- /dev/null
+++ b/ucspi-tcp-0.88/ip4_scan.c
@@ -0,0 +1,19 @@
+#include "scan.h"
+#include "ip4.h"
+
+unsigned int ip4_scan(char *s,char ip[4])
+{
+ unsigned int i;
+ unsigned int len;
+ unsigned long u;
+
+ len = 0;
+ i = scan_ulong(s,&u); if (!i) return 0; ip[0] = u; s += i; len += i;
+ if (*s != '.') return 0; ++s; ++len;
+ i = scan_ulong(s,&u); if (!i) return 0; ip[1] = u; s += i; len += i;
+ if (*s != '.') return 0; ++s; ++len;
+ i = scan_ulong(s,&u); if (!i) return 0; ip[2] = u; s += i; len += i;
+ if (*s != '.') return 0; ++s; ++len;
+ i = scan_ulong(s,&u); if (!i) return 0; ip[3] = u; s += i; len += i;
+ return len;
+}
diff --git a/ucspi-tcp-0.88/mconnect-io.c b/ucspi-tcp-0.88/mconnect-io.c
new file mode 100644
index 0000000..5cd4ada
--- /dev/null
+++ b/ucspi-tcp-0.88/mconnect-io.c
@@ -0,0 +1,53 @@
+#include "sig.h"
+#include "wait.h"
+#include "fork.h"
+#include "buffer.h"
+#include "strerr.h"
+#include "readwrite.h"
+#include "exit.h"
+
+char outbuf[512];
+buffer bout;
+
+char inbuf[512];
+buffer bin;
+
+int myread(int fd,char *buf,int len)
+{
+ buffer_flush(&bout);
+ return read(fd,buf,len);
+}
+
+main()
+{
+ int pid;
+ int wstat;
+ char ch;
+
+ sig_ignore(sig_pipe);
+
+ pid = fork();
+ if (pid == -1) strerr_die2sys(111,"mconnect-io: fatal: ","unable to fork: ");
+
+ if (!pid) {
+ buffer_init(&bin,myread,0,inbuf,sizeof inbuf);
+ buffer_init(&bout,write,7,outbuf,sizeof outbuf);
+
+ while (buffer_get(&bin,&ch,1) == 1) {
+ if (ch == '\n') buffer_put(&bout,"\r",1);
+ buffer_put(&bout,&ch,1);
+ }
+ _exit(0);
+ }
+
+ buffer_init(&bin,myread,6,inbuf,sizeof inbuf);
+ buffer_init(&bout,write,1,outbuf,sizeof outbuf);
+
+ while (buffer_get(&bin,&ch,1) == 1)
+ buffer_put(&bout,&ch,1);
+
+ kill(pid,sig_term);
+ wait_pid(&wstat,pid);
+
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/mconnect.sh b/ucspi-tcp-0.88/mconnect.sh
new file mode 100644
index 0000000..9629b90
--- /dev/null
+++ b/ucspi-tcp-0.88/mconnect.sh
@@ -0,0 +1 @@
+exec HOME/bin/tcpclient -RHl0 -- "${1-0}" "${2-25}" HOME/bin/mconnect-io
diff --git a/ucspi-tcp-0.88/ndelay.h b/ucspi-tcp-0.88/ndelay.h
new file mode 100644
index 0000000..60b788c
--- /dev/null
+++ b/ucspi-tcp-0.88/ndelay.h
@@ -0,0 +1,7 @@
+#ifndef NDELAY_H
+#define NDELAY_H
+
+extern int ndelay_on(int);
+extern int ndelay_off(int);
+
+#endif
diff --git a/ucspi-tcp-0.88/ndelay_off.c b/ucspi-tcp-0.88/ndelay_off.c
new file mode 100644
index 0000000..9daa8cd
--- /dev/null
+++ b/ucspi-tcp-0.88/ndelay_off.c
@@ -0,0 +1,12 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "ndelay.h"
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+int ndelay_off(int fd)
+{
+ return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);
+}
diff --git a/ucspi-tcp-0.88/ndelay_on.c b/ucspi-tcp-0.88/ndelay_on.c
new file mode 100644
index 0000000..eccd8c8
--- /dev/null
+++ b/ucspi-tcp-0.88/ndelay_on.c
@@ -0,0 +1,12 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "ndelay.h"
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+int ndelay_on(int fd)
+{
+ return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);
+}
diff --git a/ucspi-tcp-0.88/open.h b/ucspi-tcp-0.88/open.h
new file mode 100644
index 0000000..2963fa7
--- /dev/null
+++ b/ucspi-tcp-0.88/open.h
@@ -0,0 +1,10 @@
+#ifndef OPEN_H
+#define OPEN_H
+
+extern int open_read(char *);
+extern int open_excl(char *);
+extern int open_append(char *);
+extern int open_trunc(char *);
+extern int open_write(char *);
+
+#endif
diff --git a/ucspi-tcp-0.88/open_read.c b/ucspi-tcp-0.88/open_read.c
new file mode 100644
index 0000000..7f5ec8b
--- /dev/null
+++ b/ucspi-tcp-0.88/open_read.c
@@ -0,0 +1,6 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "open.h"
+
+int open_read(char *fn)
+{ return open(fn,O_RDONLY | O_NDELAY); }
diff --git a/ucspi-tcp-0.88/open_trunc.c b/ucspi-tcp-0.88/open_trunc.c
new file mode 100644
index 0000000..77b99ef
--- /dev/null
+++ b/ucspi-tcp-0.88/open_trunc.c
@@ -0,0 +1,6 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "open.h"
+
+int open_trunc(char *fn)
+{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); }
diff --git a/ucspi-tcp-0.88/open_write.c b/ucspi-tcp-0.88/open_write.c
new file mode 100644
index 0000000..531b8fe
--- /dev/null
+++ b/ucspi-tcp-0.88/open_write.c
@@ -0,0 +1,6 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "open.h"
+
+int open_write(char *fn)
+{ return open(fn,O_WRONLY | O_NDELAY); }
diff --git a/ucspi-tcp-0.88/openreadclose.c b/ucspi-tcp-0.88/openreadclose.c
new file mode 100644
index 0000000..d1e2086
--- /dev/null
+++ b/ucspi-tcp-0.88/openreadclose.c
@@ -0,0 +1,16 @@
+#include "error.h"
+#include "open.h"
+#include "readclose.h"
+#include "openreadclose.h"
+
+int openreadclose(char *fn,stralloc *sa,unsigned int bufsize)
+{
+ int fd;
+ fd = open_read(fn);
+ if (fd == -1) {
+ if (errno == error_noent) return 0;
+ return -1;
+ }
+ if (readclose(fd,sa,bufsize) == -1) return -1;
+ return 1;
+}
diff --git a/ucspi-tcp-0.88/openreadclose.h b/ucspi-tcp-0.88/openreadclose.h
new file mode 100644
index 0000000..99688f4
--- /dev/null
+++ b/ucspi-tcp-0.88/openreadclose.h
@@ -0,0 +1,8 @@
+#ifndef OPENREADCLOSE_H
+#define OPENREADCLOSE_H
+
+#include "stralloc.h"
+
+extern int openreadclose(char *,stralloc *,unsigned int);
+
+#endif
diff --git a/ucspi-tcp-0.88/pathexec.h b/ucspi-tcp-0.88/pathexec.h
new file mode 100644
index 0000000..6fcbb89
--- /dev/null
+++ b/ucspi-tcp-0.88/pathexec.h
@@ -0,0 +1,8 @@
+#ifndef PATHEXEC_H
+#define PATHEXEC_H
+
+extern void pathexec_run(char *,char **,char **);
+extern int pathexec_env(char *,char *);
+extern void pathexec(char **);
+
+#endif
diff --git a/ucspi-tcp-0.88/pathexec_env.c b/ucspi-tcp-0.88/pathexec_env.c
new file mode 100644
index 0000000..48bba7e
--- /dev/null
+++ b/ucspi-tcp-0.88/pathexec_env.c
@@ -0,0 +1,68 @@
+#include "stralloc.h"
+#include "alloc.h"
+#include "str.h"
+#include "byte.h"
+#include "env.h"
+#include "pathexec.h"
+
+static stralloc plus;
+static stralloc tmp;
+
+int pathexec_env(char *s,char *t)
+{
+ if (!s) return 1;
+ if (!stralloc_copys(&tmp,s)) return 0;
+ if (t) {
+ if (!stralloc_cats(&tmp,"=")) return 0;
+ if (!stralloc_cats(&tmp,t)) return 0;
+ }
+ if (!stralloc_0(&tmp)) return 0;
+ return stralloc_cat(&plus,&tmp);
+}
+
+void pathexec(char **argv)
+{
+ char *path;
+ char **e;
+ unsigned int elen;
+ unsigned int i;
+ unsigned int j;
+ unsigned int split;
+ unsigned int t;
+
+ if (!stralloc_cats(&plus,"")) return;
+
+ elen = 0;
+ for (i = 0;environ[i];++i)
+ ++elen;
+ for (i = 0;i < plus.len;++i)
+ if (!plus.s[i])
+ ++elen;
+
+ e = (char **) alloc((elen + 1) * sizeof(char *));
+ if (!e) return;
+
+ elen = 0;
+ for (i = 0;environ[i];++i)
+ e[elen++] = environ[i];
+
+ j = 0;
+ for (i = 0;i < plus.len;++i)
+ if (!plus.s[i]) {
+ split = str_chr(plus.s + j,'=');
+ for (t = 0;t < elen;++t)
+ if (byte_equal(plus.s + j,split,e[t]))
+ if (e[t][split] == '=') {
+ --elen;
+ e[t] = e[elen];
+ break;
+ }
+ if (plus.s[j + split])
+ e[elen++] = plus.s + j;
+ j = i + 1;
+ }
+ e[elen] = 0;
+
+ pathexec_run(*argv,argv,e);
+ alloc_free(e);
+}
diff --git a/ucspi-tcp-0.88/pathexec_run.c b/ucspi-tcp-0.88/pathexec_run.c
new file mode 100644
index 0000000..17837eb
--- /dev/null
+++ b/ucspi-tcp-0.88/pathexec_run.c
@@ -0,0 +1,46 @@
+#include "error.h"
+#include "stralloc.h"
+#include "str.h"
+#include "env.h"
+#include "pathexec.h"
+
+static stralloc tmp;
+
+void pathexec_run(char *file,char **argv,char **envp)
+{
+ char *path;
+ unsigned int split;
+ int savederrno;
+
+ if (file[str_chr(file,'/')]) {
+ execve(file,argv,envp);
+ return;
+ }
+
+ path = env_get("PATH");
+ if (!path) path = "/bin:/usr/bin";
+
+ savederrno = 0;
+ for (;;) {
+ split = str_chr(path,':');
+ if (!stralloc_copyb(&tmp,path,split)) return;
+ if (!split)
+ if (!stralloc_cats(&tmp,".")) return;
+ if (!stralloc_cats(&tmp,"/")) return;
+ if (!stralloc_cats(&tmp,file)) return;
+ if (!stralloc_0(&tmp)) return;
+
+ execve(tmp.s,argv,envp);
+ if (errno != error_noent) {
+ savederrno = errno;
+ if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return;
+ }
+
+ if (!path[split]) {
+ if (savederrno) errno = savederrno;
+ return;
+ }
+ path += split;
+ path += 1;
+ }
+}
diff --git a/ucspi-tcp-0.88/prot.c b/ucspi-tcp-0.88/prot.c
new file mode 100644
index 0000000..0a8a373
--- /dev/null
+++ b/ucspi-tcp-0.88/prot.c
@@ -0,0 +1,19 @@
+#include "hasshsgr.h"
+#include "prot.h"
+
+int prot_gid(int gid)
+{
+#ifdef HASSHORTSETGROUPS
+ short x[2];
+ x[0] = gid; x[1] = 73; /* catch errors */
+ if (setgroups(1,x) == -1) return -1;
+#else
+ if (setgroups(1,&gid) == -1) return -1;
+#endif
+ return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
+}
+
+int prot_uid(int uid)
+{
+ return setuid(uid);
+}
diff --git a/ucspi-tcp-0.88/prot.h b/ucspi-tcp-0.88/prot.h
new file mode 100644
index 0000000..7dd0503
--- /dev/null
+++ b/ucspi-tcp-0.88/prot.h
@@ -0,0 +1,7 @@
+#ifndef PROT_H
+#define PROT_H
+
+extern int prot_gid(int);
+extern int prot_uid(int);
+
+#endif
diff --git a/ucspi-tcp-0.88/rblsmtpd.c b/ucspi-tcp-0.88/rblsmtpd.c
new file mode 100644
index 0000000..cc8ba2e
--- /dev/null
+++ b/ucspi-tcp-0.88/rblsmtpd.c
@@ -0,0 +1,198 @@
+#include "byte.h"
+#include "str.h"
+#include "scan.h"
+#include "fmt.h"
+#include "env.h"
+#include "exit.h"
+#include "sig.h"
+#include "buffer.h"
+#include "readwrite.h"
+#include "sgetopt.h"
+#include "strerr.h"
+#include "stralloc.h"
+#include "commands.h"
+#include "pathexec.h"
+#include "dns.h"
+
+#define FATAL "rblsmtpd: fatal: "
+
+void nomem(void)
+{
+ strerr_die2x(111,FATAL,"out of memory");
+}
+void usage(void)
+{
+ strerr_die1x(100,"rblsmtpd: usage: rblsmtpd [ -b ] [ -R ] [ -t timeout ] [ -r base ] [ -a base ] smtpd [ arg ... ]");
+}
+
+char *ip_env;
+static stralloc ip_reverse;
+
+void ip_init(void)
+{
+ unsigned int i;
+ unsigned int j;
+
+ ip_env = env_get("TCPREMOTEIP");
+ if (!ip_env) ip_env = "";
+
+ if (!stralloc_copys(&ip_reverse,"")) nomem();
+
+ i = str_len(ip_env);
+ while (i) {
+ for (j = i;j > 0;--j) if (ip_env[j - 1] == '.') break;
+ if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) nomem();
+ if (!stralloc_cats(&ip_reverse,".")) nomem();
+ if (!j) break;
+ i = j - 1;
+ }
+}
+
+unsigned long timeout = 60;
+int flagrblbounce = 0;
+int flagfailclosed = 0;
+int flagmustnotbounce = 0;
+
+int decision = 0; /* 0 undecided, 1 accept, 2 reject, 3 bounce */
+static stralloc text; /* defined if decision is 2 or 3 */
+
+static stralloc tmp;
+
+void rbl(char *base)
+{
+ if (decision) return;
+ if (!stralloc_copy(&tmp,&ip_reverse)) nomem();
+ if (!stralloc_cats(&tmp,base)) nomem();
+ if (dns_txt(&text,&tmp) == -1) {
+ flagmustnotbounce = 1;
+ if (flagfailclosed) {
+ if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem();
+ decision = 2;
+ }
+ return;
+ }
+ if (text.len)
+ if (flagrblbounce)
+ decision = 3;
+ else
+ decision = 2;
+}
+
+void antirbl(char *base)
+{
+ if (decision) return;
+ if (!stralloc_copy(&tmp,&ip_reverse)) nomem();
+ if (!stralloc_cats(&tmp,base)) nomem();
+ if (dns_ip4(&text,&tmp) == -1) {
+ flagmustnotbounce = 1;
+ if (!flagfailclosed)
+ decision = 1;
+ return;
+ }
+ if (text.len)
+ decision = 1;
+}
+
+char strnum[FMT_ULONG];
+static stralloc message;
+
+char inspace[64]; buffer in = BUFFER_INIT(read,0,inspace,sizeof inspace);
+char outspace[1]; buffer out = BUFFER_INIT(write,1,outspace,sizeof outspace);
+
+void reject() { buffer_putflush(&out,message.s,message.len); }
+void accept() { buffer_putsflush(&out,"250 rblsmtpd.local\r\n"); }
+void greet() { buffer_putsflush(&out,"220 rblsmtpd.local\r\n"); }
+void quit() { buffer_putsflush(&out,"221 rblsmtpd.local\r\n"); _exit(0); }
+void drop() { _exit(0); }
+
+struct commands smtpcommands[] = {
+ { "quit", quit, 0 }
+, { "helo", accept, 0 }
+, { "ehlo", accept, 0 }
+, { "mail", accept, 0 }
+, { "rset", accept, 0 }
+, { "noop", accept, 0 }
+, { 0, reject, 0 }
+} ;
+
+void rblsmtpd(void)
+{
+ int i;
+
+ if (flagmustnotbounce || (decision == 2)) {
+ if (!stralloc_copys(&message,"451 ")) nomem();
+ }
+ else
+ if (!stralloc_copys(&message,"553 ")) nomem();
+
+ if (text.len > 200) text.len = 200;
+ if (!stralloc_cat(&message,&text)) nomem();
+ for (i = 0;i < message.len;++i)
+ if ((message.s[i] < 32) || (message.s[i] > 126))
+ message.s[i] = '?';
+
+ buffer_puts(buffer_2,"rblsmtpd: ");
+ buffer_puts(buffer_2,ip_env);
+ buffer_puts(buffer_2," pid ");
+ buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
+ buffer_puts(buffer_2,": ");
+ buffer_put(buffer_2,message.s,message.len);
+ buffer_puts(buffer_2,"\n");
+ buffer_flush(buffer_2);
+
+ if (!stralloc_cats(&message,"\r\n")) nomem();
+
+ if (!timeout)
+ reject();
+ else {
+ sig_catch(sig_alarm,drop);
+ alarm(timeout);
+ greet();
+ commands(&in,smtpcommands);
+ }
+ _exit(0);
+}
+
+main(int argc,char **argv,char **envp)
+{
+ int flagwantdefaultrbl = 1;
+ char *x;
+ int opt;
+
+ ip_init();
+
+ x = env_get("RBLSMTPD");
+ if (x) {
+ if (!*x)
+ decision = 1;
+ else if (*x == '-') {
+ if (!stralloc_copys(&text,x + 1)) nomem();
+ decision = 3;
+ }
+ else {
+ if (!stralloc_copys(&text,x)) nomem();
+ decision = 2;
+ }
+ }
+
+ while ((opt = getopt(argc,argv,"bBcCt:r:a:")) != opteof)
+ switch(opt) {
+ case 'b': flagrblbounce = 1; break;
+ case 'B': flagrblbounce = 0; break;
+ case 'c': flagfailclosed = 1; break;
+ case 'C': flagfailclosed = 0; break;
+ case 't': scan_ulong(optarg,&timeout); break;
+ case 'r': rbl(optarg); flagwantdefaultrbl = 0; break;
+ case 'a': antirbl(optarg); break;
+ default: usage();
+ }
+
+ argv += optind;
+ if (!*argv) usage();
+
+ if (flagwantdefaultrbl) rbl("rbl.maps.vix.com");
+ if (decision >= 2) rblsmtpd();
+
+ pathexec_run(*argv,argv,envp);
+ strerr_die4sys(111,FATAL,"unable to run ",*argv,": ");
+}
diff --git a/ucspi-tcp-0.88/readclose.c b/ucspi-tcp-0.88/readclose.c
new file mode 100644
index 0000000..4265c06
--- /dev/null
+++ b/ucspi-tcp-0.88/readclose.c
@@ -0,0 +1,21 @@
+#include "readwrite.h"
+#include "error.h"
+#include "readclose.h"
+
+int readclose_append(int fd,stralloc *sa,unsigned int bufsize)
+{
+ int r;
+ for (;;) {
+ if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
+ r = read(fd,sa->s + sa->len,bufsize);
+ if (r == -1) if (errno == error_intr) continue;
+ if (r <= 0) { close(fd); return r; }
+ sa->len += r;
+ }
+}
+
+int readclose(int fd,stralloc *sa,unsigned int bufsize)
+{
+ if (!stralloc_copys(sa,"")) { close(fd); return -1; }
+ return readclose_append(fd,sa,bufsize);
+}
diff --git a/ucspi-tcp-0.88/readclose.h b/ucspi-tcp-0.88/readclose.h
new file mode 100644
index 0000000..49afd6c
--- /dev/null
+++ b/ucspi-tcp-0.88/readclose.h
@@ -0,0 +1,9 @@
+#ifndef READCLOSE_H
+#define READCLOSE_H
+
+#include "stralloc.h"
+
+extern int readclose_append(int,stralloc *,unsigned int);
+extern int readclose(int,stralloc *,unsigned int);
+
+#endif
diff --git a/ucspi-tcp-0.88/readwrite.h b/ucspi-tcp-0.88/readwrite.h
new file mode 100644
index 0000000..2a64968
--- /dev/null
+++ b/ucspi-tcp-0.88/readwrite.h
@@ -0,0 +1,7 @@
+#ifndef READWRITE_H
+#define READWRITE_H
+
+extern int read();
+extern int write();
+
+#endif
diff --git a/ucspi-tcp-0.88/recordio.c b/ucspi-tcp-0.88/recordio.c
new file mode 100644
index 0000000..a3ee03c
--- /dev/null
+++ b/ucspi-tcp-0.88/recordio.c
@@ -0,0 +1,178 @@
+#include "sig.h"
+#include "buffer.h"
+#include "strerr.h"
+#include "str.h"
+#include "byte.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "fmt.h"
+#include "iopause.h"
+#include "pathexec.h"
+
+#define FATAL "recordio: fatal: "
+
+char pid[FMT_ULONG];
+
+char recordbuf[512];
+buffer ssrecord = BUFFER_INIT(write,2,recordbuf,sizeof recordbuf);
+
+void record(char *buf,int len,char *direction) /* 1 <= len <= 256 */
+{
+ int i;
+
+ while (len) {
+ buffer_puts(&ssrecord,pid);
+ buffer_puts(&ssrecord,direction);
+
+ i = byte_chr(buf,len,'\n');
+ buffer_put(&ssrecord,buf,i);
+
+ if (i == len) {
+ buffer_puts(&ssrecord,"+\n");
+ buffer_flush(&ssrecord);
+ return;
+ }
+
+ buffer_puts(&ssrecord," \n");
+ buffer_flush(&ssrecord);
+ buf += i + 1;
+ len -= i + 1;
+ }
+}
+
+int leftstatus = 0;
+char leftbuf[256];
+int leftlen;
+int leftpos;
+
+int rightstatus = 0;
+char rightbuf[256];
+int rightlen;
+int rightpos;
+
+void doit(int fdleft,int fdright) /* copy 0 -> fdleft, copy fdright -> 1 */
+{
+ struct taia stamp;
+ struct taia deadline;
+ iopause_fd x[4];
+ int xlen;
+ iopause_fd *io0;
+ iopause_fd *ioleft;
+ iopause_fd *io1;
+ iopause_fd *ioright;
+ int r;
+
+ for (;;) {
+ xlen = 0;
+
+ io0 = 0;
+ if (leftstatus == 0) {
+ io0 = &x[xlen++];
+ io0->fd = 0;
+ io0->events = IOPAUSE_READ;
+ }
+ ioleft = 0;
+ if (leftstatus == 1) {
+ ioleft = &x[xlen++];
+ ioleft->fd = fdleft;
+ ioleft->events = IOPAUSE_WRITE;
+ }
+
+ ioright = 0;
+ if (rightstatus == 0) {
+ ioright = &x[xlen++];
+ ioright->fd = fdright;
+ ioright->events = IOPAUSE_READ;
+ }
+ io1 = 0;
+ if (rightstatus == 1) {
+ io1 = &x[xlen++];
+ io1->fd = 1;
+ io1->events = IOPAUSE_WRITE;
+ }
+
+ taia_now(&stamp);
+ taia_uint(&deadline,3600);
+ taia_add(&deadline,&stamp,&deadline);
+ iopause(x,xlen,&deadline,&stamp);
+
+ if (io0 && io0->revents) {
+ r = read(0,leftbuf,sizeof leftbuf);
+ if (r <= 0) {
+ leftstatus = -1;
+ close(fdleft);
+ buffer_puts(&ssrecord,pid);
+ buffer_puts(&ssrecord," < [EOF]\n");
+ buffer_flush(&ssrecord);
+ }
+ else {
+ leftstatus = 1; leftpos = 0; leftlen = r;
+ record(leftbuf,r," < ");
+ }
+ }
+
+ if (ioleft && ioleft->revents) {
+ r = write(fdleft,leftbuf + leftpos,leftlen - leftpos);
+ if (r == -1) break;
+ leftpos += r;
+ if (leftpos == leftlen) leftstatus = 0;
+ }
+
+ if (ioright && ioright->revents) {
+ r = read(fdright,rightbuf,sizeof rightbuf);
+ if (r <= 0) {
+ buffer_puts(&ssrecord,pid);
+ buffer_puts(&ssrecord," > [EOF]\n");
+ buffer_flush(&ssrecord);
+ break;
+ }
+ rightstatus = 1; rightpos = 0; rightlen = r;
+ record(rightbuf,r," > ");
+ }
+
+ if (io1 && io1->revents) {
+ r = write(1,rightbuf + rightpos,rightlen - rightpos);
+ if (r == -1) break;
+ rightpos += r;
+ if (rightpos == rightlen) rightstatus = 0;
+ }
+ }
+
+ _exit(0);
+}
+
+main(int argc,char **argv,char **envp)
+{
+ int piin[2];
+ int piout[2];
+
+ pid[fmt_ulong(pid,getpid())] = 0;
+
+ if (argc < 2)
+ strerr_die1x(100,"recordio: usage: recordio program [ arg ... ]");
+
+ if (pipe(piin) == -1)
+ strerr_die2sys(111,FATAL,"unable to create pipe: ");
+ if (pipe(piout) == -1)
+ strerr_die2sys(111,FATAL,"unable to create pipe: ");
+
+ switch(fork()) {
+ case -1:
+ strerr_die2sys(111,FATAL,"unable to fork: ");
+ case 0:
+ sig_ignore(sig_pipe);
+ close(piin[0]);
+ close(piout[1]);
+ doit(piin[1],piout[0]);
+ }
+
+ close(piin[1]);
+ close(piout[0]);
+ if (fd_move(0,piin[0]) == -1)
+ strerr_die2sys(111,FATAL,"unable to move descriptors: ");
+ if (fd_move(1,piout[1]) == -1)
+ strerr_die2sys(111,FATAL,"unable to move descriptors: ");
+
+ pathexec_run(argv[1],argv + 1,envp);
+ strerr_die4sys(111,FATAL,"unable to run ",argv[1],": ");
+}
diff --git a/ucspi-tcp-0.88/remoteinfo.c b/ucspi-tcp-0.88/remoteinfo.c
new file mode 100644
index 0000000..6c437c0
--- /dev/null
+++ b/ucspi-tcp-0.88/remoteinfo.c
@@ -0,0 +1,98 @@
+#include "fmt.h"
+#include "buffer.h"
+#include "socket.h"
+#include "error.h"
+#include "iopause.h"
+#include "timeoutconn.h"
+#include "remoteinfo.h"
+
+static struct taia now;
+static struct taia deadline;
+
+static int mywrite(int fd,char *buf,int len)
+{
+ iopause_fd x;
+
+ x.fd = fd;
+ x.events = IOPAUSE_WRITE;
+ for (;;) {
+ taia_now(&now);
+ iopause(&x,1,&deadline,&now);
+ if (x.revents) break;
+ if (taia_less(&deadline,&now)) {
+ errno = error_timeout;
+ return -1;
+ }
+ }
+ return write(fd,buf,len);
+}
+
+static int myread(int fd,char *buf,int len)
+{
+ iopause_fd x;
+
+ x.fd = fd;
+ x.events = IOPAUSE_READ;
+ for (;;) {
+ taia_now(&now);
+ iopause(&x,1,&deadline,&now);
+ if (x.revents) break;
+ if (taia_less(&deadline,&now)) {
+ errno = error_timeout;
+ return -1;
+ }
+ }
+ return read(fd,buf,len);
+}
+
+static int doit(stralloc *out,int s,char ipremote[4],uint16 portremote,char iplocal[4],uint16 portlocal,unsigned int timeout)
+{
+ buffer b;
+ char bspace[128];
+ char strnum[FMT_ULONG];
+ int numcolons;
+ char ch;
+
+ if (socket_bind4(s,iplocal,0) == -1) return -1;
+ if (timeoutconn(s,ipremote,113,timeout) == -1) return -1;
+
+ buffer_init(&b,mywrite,s,bspace,sizeof bspace);
+ buffer_put(&b,strnum,fmt_ulong(strnum,portremote));
+ buffer_put(&b," , ",3);
+ buffer_put(&b,strnum,fmt_ulong(strnum,portlocal));
+ buffer_put(&b,"\r\n",2);
+ if (buffer_flush(&b) == -1) return -1;
+
+ buffer_init(&b,myread,s,bspace,sizeof bspace);
+ numcolons = 0;
+ for (;;) {
+ if (buffer_get(&b,&ch,1) != 1) return -1;
+ if ((ch == ' ') || (ch == '\t') || (ch == '\r')) continue;
+ if (ch == '\n') return 0;
+ if (numcolons < 3) {
+ if (ch == ':') ++numcolons;
+ }
+ else {
+ if (!stralloc_append(out,&ch)) return -1;
+ if (out->len > 256) return 0;
+ }
+ }
+}
+
+int remoteinfo(stralloc *out,char ipremote[4],uint16 portremote,char iplocal[4],uint16 portlocal,unsigned int timeout)
+{
+ int s;
+ int r;
+
+ if (!stralloc_copys(out,"")) return -1;
+
+ taia_now(&now);
+ taia_uint(&deadline,timeout);
+ taia_add(&deadline,&now,&deadline);
+
+ s = socket_tcp();
+ if (s == -1) return -1;
+ r = doit(out,s,ipremote,portremote,iplocal,portlocal,timeout);
+ close(s);
+ return r;
+}
diff --git a/ucspi-tcp-0.88/remoteinfo.h b/ucspi-tcp-0.88/remoteinfo.h
new file mode 100644
index 0000000..2ca779d
--- /dev/null
+++ b/ucspi-tcp-0.88/remoteinfo.h
@@ -0,0 +1,9 @@
+#ifndef REMOTEINFO_H
+#define REMOTEINFO_H
+
+#include "stralloc.h"
+#include "uint16.h"
+
+extern int remoteinfo(stralloc *,char *,uint16,char *,uint16,unsigned int);
+
+#endif
diff --git a/ucspi-tcp-0.88/rts.exp b/ucspi-tcp-0.88/rts.exp
new file mode 100644
index 0000000..242d7cf
--- /dev/null
+++ b/ucspi-tcp-0.88/rts.exp
@@ -0,0 +1,435 @@
+--- tcpclient prints usage message without enough arguments
+tcpclient: usage: tcpclient [ -hHrRdDqQv ] [ -i localip ] [ -p localport ] [ -T timeoutconn ] [ -l localname ] [ -t timeoutinfo ] host port program
+100
+--- tcpclient prints error message with unknown port name
+tcpclient: fatal: unable to figure out port number for nonexistentport
+111
+--- tcpclient prints error message when connection fails
+tcpclient: unable to connect to 127.0.0.1 port 16: connection refused
+111
+--- tcpclient -q does not print error message when connection fails
+111
+--- tcpclient understands empty host name as synonym for 0
+tcpclient: unable to connect to 127.0.0.1 port 16: connection refused
+111
+--- tcpclient understands unbracketed IP address
+tcpclient: unable to connect to 127.0.0.1 port 16: connection refused
+111
+--- tcpclient understands bracketed IP address
+tcpclient: unable to connect to 127.0.0.1 port 16: connection refused
+111
+--- tcpclient prints error message with unknown host name
+tcpclient: fatal: no IP address for nonexistent.local.
+111
+--- tcpclient prints error message with unresolvable host name
+tcpclient: fatal: temporarily unable to figure out IP address for thislabelistoolongbecausednshasalimitof63charactersinasinglelabel.: protocol error
+111
+--- tcpserver prints usage message without enough arguments
+tcpserver: usage: tcpserver [ -1UXpPhHrRoOdDqQv ] [ -c limit ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] [ -u uid ] [ -b backlog ] [ -l localname ] [ -t timeout ] host port program
+100
+--- tcpserver -u 1 attempts to set uid to 1
+tcpserver: fatal: unable to set uid: permission denied
+111
+--- tcpserver -U reads $UID
+tcpserver: fatal: unable to set uid: permission denied
+111
+--- tcpserver -g 2 attempts to set gid to 2
+tcpserver: fatal: unable to set gid: permission denied
+111
+--- tcpserver -U reads $GID
+tcpserver: fatal: unable to set gid: permission denied
+111
+--- tcpserver prints error message with unknown port name
+tcpserver: fatal: unable to figure out port number for nonexistentport
+111
+--- tcpserver prints error message with unknown host name
+tcpserver: fatal: no IP address for nonexistent.local.
+111
+--- tcpserver prints error message with unresolvable host name
+tcpserver: fatal: temporarily unable to figure out IP address for thislabelistoolongbecausednshasalimitof63charactersinasinglelabel.: protocol error
+111
+--- tcpserver prints error message with non-local host name
+tcpserver: fatal: unable to bind: address not available
+111
+--- tcpserver sets basic environment variables
+bannerPROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=127.0.0.1
+TCPLOCALPORT=50016
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=127.0.0.1
+TCPREMOTEPORT=50017
+TCPREMOTEINFO=unset
+0
+--- tcpclient recognizes -D, -i, -r, -h, -t
+bannerPROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=127.0.0.1
+TCPLOCALPORT=50016
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=127.0.0.1
+TCPREMOTEPORT=50018
+TCPREMOTEINFO=unset
+0
+--- tcpclient sets basic environment variables
+PROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=127.0.0.1
+TCPLOCALPORT=50019
+TCPREMOTEHOST=unset
+TCPREMOTEIP=127.0.0.1
+TCPREMOTEPORT=50016
+TCPREMOTEINFO=unset
+0
+--- tcpclient looks up host names properly
+PROTO=TCP
+TCPLOCALHOST=localhost
+TCPLOCALIP=127.0.0.1
+TCPLOCALPORT=50020
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=127.0.0.1
+TCPREMOTEPORT=50016
+TCPREMOTEINFO=unset
+0
+--- tcpclient -v works
+tcpclient: connected to 127.0.0.1 port 50016
+ok
+0
+--- tcpserver prints error message with used port
+tcpserver: fatal: unable to bind: address already used
+111
+--- tcpcat works
+bannerPROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=127.0.0.1
+TCPLOCALPORT=50016
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=127.0.0.1
+TCPREMOTEINFO=unset
+0
+--- mconnect works
+bannerPROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=127.0.0.1
+TCPLOCALPORT=50016
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=127.0.0.1
+TCPREMOTEINFO=unset
+0
+--- tcprules prints usage message without enough arguments
+tcprules: usage: tcprules rules.cdb rules.tmp
+100
+--- tcprules prints error message if it cannot create tmp
+tcprules: fatal: unable to create /dev/nonexistent/tmp: file does not exist
+111
+--- tcprules prints error message if it cannot move tmp to cdb
+tcprules: fatal: unable to move test.tmp to /dev/nonexistent/cdb: file does not exist
+111
+--- tcprules creates a cdb file
+0
+--- tcprulescheck sees deny
+rule 1.2.3.4:
+deny connection
+0
+--- tcprulescheck does not apply deny to another host
+default:
+allow connection
+0
+--- tcprules replaces a cdb file
+0
+--- tcprulescheck finds rule with address and info
+rule joe@127.0.0.1:
+set environment variable which=first
+allow connection
+0
+--- tcprulescheck finds rule with address
+rule 18.23.0.32:
+set environment variable which=second
+allow connection
+0
+--- tcprulescheck finds one-dot wildcard
+rule 127.:
+set environment variable which=third
+allow connection
+0
+--- tcprulescheck finds zero-dot wildcard
+rule :
+set environment variable which=fourth
+allow connection
+0
+--- tcprules handles comments, address ranges, multiple variables
+0
+rule 127.0.:
+set environment variable which=first
+set environment variable where=whatever
+allow connection
+rule 127.1.:
+set environment variable which=first
+set environment variable where=whatever
+allow connection
+rule 127.2.:
+set environment variable which=first
+set environment variable where=whatever
+allow connection
+rule 127.3.:
+set environment variable which=first
+set environment variable where=whatever
+allow connection
+rule 127.4.:
+set environment variable which=first
+set environment variable where=whatever
+allow connection
+rule 127.5.:
+set environment variable which=first
+set environment variable where=whatever
+allow connection
+default:
+allow connection
+default:
+allow connection
+default:
+allow connection
+default:
+allow connection
+default:
+allow connection
+--- tcprules handles host names
+0
+rule =known.edu:
+set environment variable which=known
+allow connection
+rule :
+set environment variable which=anybody
+allow connection
+rule :
+set environment variable which=anybody
+allow connection
+rule =.abuser.edu:
+deny connection
+rule =.abuser.edu:
+deny connection
+--- tcprulescheck searches for rules in the proper order
+0
+rule xyz@86.75.30.9:
+set environment variable which=first
+allow connection
+rule xyz@86.75.30.9:
+set environment variable which=first
+allow connection
+rule xyz@=one.two.three:
+set environment variable which=second
+allow connection
+rule 86.75.30.9:
+set environment variable which=third
+allow connection
+rule 86.75.30.9:
+set environment variable which=third
+allow connection
+rule 86.75.30.9:
+set environment variable which=third
+allow connection
+rule 86.75.30.9:
+set environment variable which=third
+allow connection
+rule =one.two.three:
+set environment variable which=fourth
+allow connection
+rule =one.two.three:
+set environment variable which=fourth
+allow connection
+rule 86.75.30.:
+set environment variable which=fifth
+allow connection
+rule 86.75.30.:
+set environment variable which=fifth
+allow connection
+rule 86.75.:
+set environment variable which=sixth
+allow connection
+rule 86.75.:
+set environment variable which=sixth
+allow connection
+rule 86.75.:
+set environment variable which=sixth
+allow connection
+rule 86.75.:
+set environment variable which=sixth
+allow connection
+rule 86.:
+set environment variable which=seventh
+allow connection
+rule 86.:
+set environment variable which=seventh
+allow connection
+rule 86.:
+set environment variable which=seventh
+allow connection
+rule 86.:
+set environment variable which=seventh
+allow connection
+rule =.two.three:
+set environment variable which=eighth
+allow connection
+rule =.two.three:
+set environment variable which=eighth
+allow connection
+rule =.three:
+set environment variable which=ninth
+allow connection
+rule =.three:
+set environment variable which=ninth
+allow connection
+rule =:
+set environment variable which=tenth
+allow connection
+rule =:
+set environment variable which=tenth
+allow connection
+rule :
+set environment variable which=eleventh
+allow connection
+rule :
+set environment variable which=eleventh
+allow connection
+--- addcr leaves an empty file alone
+0
+--- addcr leaves a partial final line alone
+test0
+--- addcr adds CR after the first line
+test^M
+0
+--- addcr adds CR after the second line
+test^M
+test2^M
+0
+--- addcr handles nulls
+t^@st^M
+0
+--- delcr leaves an empty file alone
+0
+--- delcr leaves a non-CR line alone
+test
+0
+--- delcr removes CR if a line has it
+test
+0
+--- delcr converts CR CR LF to CR LF
+test^M
+0
+--- delcr does not remove CR from a partial final line
+test^M0
+--- delcr handles a non-CR partial final line
+test0
+--- delcr handles nulls
+t^@st
+0
+--- fixcrio works
+^M
+hi^M
+there^M
+bye^M
+--- recordio works
+... < test $
+... > test $
+... < [EOF]$
+... > [EOF]$
+--- recordio handles multiple-line packets
+... < test $
+... < test2 $
+... > test $
+... > test2 $
+... < [EOF]$
+... > [EOF]$
+--- recordio handles partial final lines
+... < test+$
+... > test+$
+... < [EOF]$
+... > [EOF]$
+--- argv0 works
+zero
+0
+--- argv0 requires arguments
+argv0: usage: argv0 realname program [ arg ... ]
+100
+--- rblsmtpd does not find 127.0.0.1 on the RBL
+ok
+0
+--- rblsmtpd finds 127.0.0.2 on the RBL
+rblsmtpd: 127.0.0.2 pid x: 451 Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+220 rblsmtpd.local^M
+451 Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>^M
+221 rblsmtpd.local^M
+0
+--- rblsmtpd -b uses a permanent error code
+rblsmtpd: 127.0.0.2 pid x: 553 Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+220 rblsmtpd.local^M
+553 Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>^M
+221 rblsmtpd.local^M
+0
+--- rblsmtpd quits after a timeout
+rblsmtpd: 127.0.0.2 pid x: 451 Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+220 rblsmtpd.local^M
+0
+--- rblsmtpd prints an immediate error message with -t0
+rblsmtpd: 127.0.0.2 pid x: 451 Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+451 Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>^M
+0
+--- rblsmtpd understands an empty $RBLSMTPD
+ok
+0
+--- rblsmtpd understands a nonempty $RBLSMTPD
+rblsmtpd: 127.0.0.2 pid x: 451 Error
+220 rblsmtpd.local^M
+451 Error^M
+221 rblsmtpd.local^M
+0
+--- rblsmtpd understands a permanent $RBLSMTPD
+rblsmtpd: 127.0.0.2 pid x: 553 Error
+220 rblsmtpd.local^M
+553 Error^M
+221 rblsmtpd.local^M
+0
+--- rblsmtpd understands -r
+ok
+0
+--- rblsmtpd understands -a
+ok
+0
+--- tcpserver -1v prints proper messages
+50016
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from 127.0.0.1
+tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from 127.0.0.1
+tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from 127.0.0.1
+tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from 127.0.0.1
+tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from 127.0.0.1
+tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from 127.0.0.1
+tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from 127.0.0.1
+tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
diff --git a/ucspi-tcp-0.88/rts.sh b/ucspi-tcp-0.88/rts.sh
new file mode 100644
index 0000000..c71e839
--- /dev/null
+++ b/ucspi-tcp-0.88/rts.sh
@@ -0,0 +1 @@
+env - PATH="`pwd`:$PATH" sh rts.tests 2>&1 | cat -v
diff --git a/ucspi-tcp-0.88/rts.tests b/ucspi-tcp-0.88/rts.tests
new file mode 100644
index 0000000..8c23929
--- /dev/null
+++ b/ucspi-tcp-0.88/rts.tests
@@ -0,0 +1,347 @@
+# Assumptions:
+# We're not running with uid 0 or 1.
+# We're not running with gid 0 or 2.
+# supervise is installed.
+# The DNS cache translates 127.0.0.1<->localhost.
+# There is no listener for TCP port 16.
+# There is no listener for TCP port 50016.
+# There is no use of TCP ports 50017, 50018, 50019, 50020.
+
+
+rm -rf rts-tmp
+mkdir rts-tmp
+cd rts-tmp
+
+
+echo '#!/bin/sh
+ trap "" 13
+ echo PROTO="$PROTO"
+ echo TCPLOCALHOST="${TCPLOCALHOST-unset}"
+ echo TCPLOCALIP="${TCPLOCALIP-unset}"
+ echo TCPLOCALPORT="${TCPLOCALPORT-unset}"
+ echo TCPREMOTEHOST="${TCPREMOTEHOST-unset}"
+ echo TCPREMOTEIP="${TCPREMOTEIP-unset}"
+ echo TCPREMOTEPORT="${TCPREMOTEPORT-unset}"
+ echo TCPREMOTEINFO="${TCPREMOTEINFO-unset}"
+' > print
+chmod 755 print
+
+mkdir 50016
+echo '#!/bin/sh
+exec tcpserver \
+-c 2 -Bbanner -vo -D -1 -Xx rules.cdb -Rt5 -hp -l Local -b 2 \
+127.0.0.1 50016 ../print
+' > 50016/run
+chmod 755 50016/run
+
+supervise 50016 >log 2>&1 &
+
+echo '--- tcpclient prints usage message without enough arguments'
+tcpclient 0 0; echo $?
+
+echo '--- tcpclient prints error message with unknown port name'
+tcpclient 0 nonexistentport echo wrong; echo $?
+
+echo '--- tcpclient prints error message when connection fails'
+tcpclient 0 016 echo wrong; echo $?
+
+echo '--- tcpclient -q does not print error message when connection fails'
+tcpclient -q 0 016 echo wrong; echo $?
+
+echo '--- tcpclient understands empty host name as synonym for 0'
+tcpclient '' 016 echo wrong; echo $?
+
+echo '--- tcpclient understands unbracketed IP address'
+tcpclient '127.000.000.001' 016 echo wrong; echo $?
+
+echo '--- tcpclient understands bracketed IP address'
+tcpclient '[127.000.000.001]' 016 echo wrong; echo $?
+
+echo '--- tcpclient prints error message with unknown host name'
+tcpclient nonexistent.local. 016 echo wrong; echo $?
+
+echo '--- tcpclient prints error message with unresolvable host name'
+tcpclient thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 016 echo wrong; echo $?
+
+echo '--- tcpserver prints usage message without enough arguments'
+tcpserver 0 0; echo $?
+
+echo '--- tcpserver -u 1 attempts to set uid to 1'
+tcpserver -u 1 0 0 echo wrong; echo $?
+
+echo '--- tcpserver -U reads $UID'
+env UID=1 tcpserver -U 0 0 echo wrong; echo $?
+
+echo '--- tcpserver -g 2 attempts to set gid to 2'
+tcpserver -g 2 0 0 echo wrong; echo $?
+
+echo '--- tcpserver -U reads $GID'
+env GID=2 tcpserver -U 0 0 echo wrong; echo $?
+
+echo '--- tcpserver prints error message with unknown port name'
+tcpserver 0 nonexistentport echo wrong; echo $?
+
+echo '--- tcpserver prints error message with unknown host name'
+tcpserver nonexistent.local. 016 echo wrong; echo $?
+
+echo '--- tcpserver prints error message with unresolvable host name'
+tcpserver thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 016 echo wrong; echo $?
+
+echo '--- tcpserver prints error message with non-local host name'
+tcpserver 1.2.3.4 016 echo wrong; echo $?
+
+echo '--- tcpserver sets basic environment variables'
+tcpclient -p 50017 -R -H -T 10 -l Local 0 50016 sh -c 'cat <&6'
+echo $?
+
+echo '--- tcpclient recognizes -D, -i, -r, -h, -t'
+tcpclient -Di 127.0.0.1 -p 50018 -hrt1 -l Local \
+127.0.0.1 50016 sh -c 'cat <&6'
+echo $?
+
+echo '--- tcpclient sets basic environment variables'
+tcpclient -p 50019 -R -H -l Local 0 50016 ./print
+echo $?
+
+echo '--- tcpclient looks up host names properly'
+tcpclient -p 50020 -R 0 50016 ./print
+echo $?
+
+echo '--- tcpclient -v works'
+tcpclient -v -R -H -l Local 0 50016 echo ok
+echo $?
+
+echo '--- tcpserver prints error message with used port'
+tcpserver -R -H -l Local 127.0.0.1 50016 echo wrong
+echo $?
+
+echo '--- tcpcat works'
+tcpcat 0 50016 | grep -v TCPREMOTEPORT
+echo $?
+
+echo '--- mconnect works'
+mconnect 0 50016 </dev/null | grep -v TCPREMOTEPORT
+echo $?
+
+echo '--- tcprules prints usage message without enough arguments'
+tcprules test.cdb; echo $?
+
+echo '--- tcprules prints error message if it cannot create tmp'
+echo 1.2.3.4:deny | tcprules test.cdb /dev/nonexistent/tmp; echo $?
+
+echo '--- tcprules prints error message if it cannot move tmp to cdb'
+echo 1.2.3.4:deny | tcprules /dev/nonexistent/cdb test.tmp; echo $?
+
+echo '--- tcprules creates a cdb file'
+echo 1.2.3.4:deny | tcprules test.cdb test.tmp; echo $?
+
+echo '--- tcprulescheck sees deny'
+env TCPREMOTEIP=1.2.3.4 tcprulescheck test.cdb; echo $?
+
+echo '--- tcprulescheck does not apply deny to another host'
+env TCPREMOTEIP=1.2.3.5 tcprulescheck test.cdb; echo $?
+
+echo '--- tcprules replaces a cdb file'
+echo 'joe@127.0.0.1:allow,which=/first/
+18.23.0.32:allow,which="second"
+127.:allow,which=+third+
+:allow,which==fourth=' | tcprules test.cdb test.tmp; echo $?
+
+echo '--- tcprulescheck finds rule with address and info'
+env TCPREMOTEIP=127.0.0.1 TCPREMOTEINFO=joe tcprulescheck test.cdb; echo $?
+
+echo '--- tcprulescheck finds rule with address'
+env TCPREMOTEIP=18.23.0.32 TCPREMOTEINFO=joe tcprulescheck test.cdb; echo $?
+
+echo '--- tcprulescheck finds one-dot wildcard'
+env TCPREMOTEIP=127.0.0.1 TCPREMOTEINFO=bill tcprulescheck test.cdb; echo $?
+
+echo '--- tcprulescheck finds zero-dot wildcard'
+env TCPREMOTEIP=10.119.75.39 TCPREMOTEINFO=bill tcprulescheck test.cdb; echo $?
+
+echo '--- tcprules handles comments, address ranges, multiple variables'
+echo '127.0-5.:allow,which=/first/,where=/whatever/
+# comment' | tcprules test.cdb test.tmp; echo $?
+env TCPREMOTEIP=127.0.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.1.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.2.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.3.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.4.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.5.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.6.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.7.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.8.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.9.0.1 tcprulescheck test.cdb
+env TCPREMOTEIP=127.10.0.1 tcprulescheck test.cdb
+
+echo '--- tcprules handles host names'
+echo '=known.edu:allow,which=/known/
+=.abuser.edu:deny
+:allow,which=/anybody/' | tcprules test.cdb test.tmp; echo $?
+env TCPREMOTEIP=1.2.3.4 TCPREMOTEHOST=known.edu tcprulescheck test.cdb
+env TCPREMOTEIP=1.2.3.4 TCPREMOTEHOST=random.edu tcprulescheck test.cdb
+env TCPREMOTEIP=1.2.3.4 TCPREMOTEHOST=abuser.edu tcprulescheck test.cdb
+env TCPREMOTEIP=1.2.3.4 TCPREMOTEHOST=x.abuser.edu tcprulescheck test.cdb
+env TCPREMOTEIP=1.2.3.4 TCPREMOTEHOST=x.y.abuser.edu tcprulescheck test.cdb
+
+echo '--- tcprulescheck searches for rules in the proper order'
+echo 'xyz@86.75.30.9:allow,which=/first/
+xyz@=one.two.three:allow,which=/second/
+86.75.30.9:allow,which=/third/
+=one.two.three:allow,which=/fourth/
+86.75.30.:allow,which=/fifth/
+86.75.:allow,which=/sixth/
+86.:allow,which=/seventh/
+=.two.three:allow,which=/eighth/
+=.three:allow,which=/ninth/
+=:allow,which=/tenth/
+:allow,which=/eleventh/
+' | tcprules test.cdb test.tmp; echo $?
+env TCPREMOTEIP=86.75.30.9 TCPREMOTEHOST=one.two.three TCPREMOTEINFO=xyz tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.9 TCPREMOTEINFO=xyz tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.10 TCPREMOTEHOST=one.two.three TCPREMOTEINFO=xyz tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.9 TCPREMOTEHOST=one.two.three TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.9 TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.9 TCPREMOTEHOST=one.two.three tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.9 tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.10 TCPREMOTEHOST=one.two.three TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.10 TCPREMOTEHOST=one.two.three tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.10 TCPREMOTEHOST=four.two.three tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.30.10 tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.20.10 TCPREMOTEHOST=four.two.three TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.20.10 TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.20.10 TCPREMOTEHOST=four.two.three tcprulescheck test.cdb
+env TCPREMOTEIP=86.75.20.10 tcprulescheck test.cdb
+env TCPREMOTEIP=86.85.20.10 TCPREMOTEHOST=four.two.three TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=86.85.20.10 TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=86.85.20.10 TCPREMOTEHOST=four.two.three tcprulescheck test.cdb
+env TCPREMOTEIP=86.85.20.10 tcprulescheck test.cdb
+env TCPREMOTEIP=96.85.20.10 TCPREMOTEHOST=four.two.three TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=96.85.20.10 TCPREMOTEHOST=four.two.three tcprulescheck test.cdb
+env TCPREMOTEIP=96.85.20.10 TCPREMOTEHOST=four.three TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=96.85.20.10 TCPREMOTEHOST=four.three tcprulescheck test.cdb
+env TCPREMOTEIP=96.85.20.10 TCPREMOTEHOST=four TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=96.85.20.10 TCPREMOTEHOST=four tcprulescheck test.cdb
+env TCPREMOTEIP=96.85.20.10 TCPREMOTEINFO=abc tcprulescheck test.cdb
+env TCPREMOTEIP=96.85.20.10 tcprulescheck test.cdb
+
+
+echo '--- addcr leaves an empty file alone'
+echo '' | tr -d '\012' | addcr; echo $?
+
+echo '--- addcr leaves a partial final line alone'
+echo test | tr -d '\012' | addcr; echo $?
+
+echo '--- addcr adds CR after the first line'
+echo test | addcr; echo $?
+
+echo '--- addcr adds CR after the second line'
+( echo test; echo test2 ) | addcr; echo $?
+
+echo '--- addcr handles nulls'
+echo test | tr e '\0' | addcr; echo $?
+
+echo '--- delcr leaves an empty file alone'
+echo '' | tr -d '\012' | delcr; echo $?
+
+echo '--- delcr leaves a non-CR line alone'
+echo test | delcr; echo $?
+
+echo '--- delcr removes CR if a line has it'
+echo testx | tr x '\015' | delcr; echo $?
+
+echo '--- delcr converts CR CR LF to CR LF'
+echo testxx | tr x '\015' | delcr; echo $?
+
+echo '--- delcr does not remove CR from a partial final line'
+echo testx | tr -d '\012' | tr x '\015' | delcr; echo $?
+
+echo '--- delcr handles a non-CR partial final line'
+echo test | tr -d '\012' | delcr; echo $?
+
+echo '--- delcr handles nulls'
+echo test | tr e '\0' | delcr; echo $?
+
+echo '--- fixcrio works'
+( echo ''; echo hi; echo therex ) | tr x '\015' \
+| fixcrio sh -c 'cat; echo bye' | cat
+
+echo '--- recordio works'
+( echo test; sleep 1 ) | recordio cat 2>&1 >/dev/null \
+| sed 's/^[0-9]*/.../' | sed 's/$/$/'
+
+echo '--- recordio handles multiple-line packets'
+( echo 'test
+test2'; sleep 1 ) | recordio cat 2>&1 >/dev/null \
+| sed 's/^[0-9]*/.../' | sed 's/$/$/'
+
+echo '--- recordio handles partial final lines'
+( echo test | tr -d '\012'; sleep 1 ) | recordio cat 2>&1 >/dev/null \
+| sed 's/^[0-9]*/.../' | sed 's/$/$/'
+
+echo '--- argv0 works'
+argv0 sh zero -c 'echo $0'; echo $?
+
+echo '--- argv0 requires arguments'
+argv0 sh; echo $?
+
+
+echo '--- rblsmtpd does not find 127.0.0.1 on the RBL'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=127.0.0.1 rblsmtpd echo ok 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd finds 127.0.0.2 on the RBL'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=127.0.0.2 rblsmtpd echo whoops 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd -b uses a permanent error code'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=127.0.0.2 rblsmtpd -b echo whoops 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd quits after a timeout'
+sleep 2 \
+| ( TCPREMOTEIP=127.0.0.2 rblsmtpd -cBt1 echo whoops 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd prints an immediate error message with -t0'
+sleep 2 \
+| ( TCPREMOTEIP=127.0.0.2 rblsmtpd -Ct0 echo whoops 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd understands an empty $RBLSMTPD'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=127.0.0.2 RBLSMTPD= rblsmtpd echo ok 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd understands a nonempty $RBLSMTPD'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=127.0.0.2 RBLSMTPD=Error rblsmtpd echo whoops 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd understands a permanent $RBLSMTPD'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=127.0.0.2 RBLSMTPD=-Error rblsmtpd echo whoops 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd understands -r'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=127.0.0.2 rblsmtpd -r nonexistent.local echo ok 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd understands -a'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=127.0.0.2 rblsmtpd -a rbl.maps.vix.com echo ok 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+
+svc -dx 50016
+wait
+
+echo '--- tcpserver -1v prints proper messages'
+sed -e 's/::.*/::x/' -e 's/ [0-9]* / x /' < log
+
+
+exit 0
diff --git a/ucspi-tcp-0.88/rules.c b/ucspi-tcp-0.88/rules.c
new file mode 100644
index 0000000..1840360
--- /dev/null
+++ b/ucspi-tcp-0.88/rules.c
@@ -0,0 +1,100 @@
+#include "alloc.h"
+#include "stralloc.h"
+#include "open.h"
+#include "cdb.h"
+#include "rules.h"
+
+stralloc rules_name = {0};
+
+static struct cdb c;
+
+static int dorule(void (*callback)(char *,unsigned int))
+{
+ char *data;
+ unsigned int datalen;
+
+ switch(cdb_find(&c,rules_name.s,rules_name.len)) {
+ case -1: return -1;
+ case 0: return 0;
+ }
+
+ datalen = cdb_datalen(&c);
+ data = alloc(datalen);
+ if (!data) return -1;
+ if (cdb_read(&c,data,datalen,cdb_datapos(&c)) == -1) {
+ alloc_free(data);
+ return -1;
+ }
+
+ callback(data,datalen);
+ alloc_free(data);
+ return 1;
+}
+
+static int doit(void (*callback)(char *,unsigned int),char *ip,char *host,char *info)
+{
+ int r;
+
+ if (info) {
+ if (!stralloc_copys(&rules_name,info)) return -1;
+ if (!stralloc_cats(&rules_name,"@")) return -1;
+ if (!stralloc_cats(&rules_name,ip)) return -1;
+ r = dorule(callback);
+ if (r) return r;
+
+ if (host) {
+ if (!stralloc_copys(&rules_name,info)) return -1;
+ if (!stralloc_cats(&rules_name,"@=")) return -1;
+ if (!stralloc_cats(&rules_name,host)) return -1;
+ r = dorule(callback);
+ if (r) return r;
+ }
+ }
+
+ if (!stralloc_copys(&rules_name,ip)) return -1;
+ r = dorule(callback);
+ if (r) return r;
+
+ if (host) {
+ if (!stralloc_copys(&rules_name,"=")) return -1;
+ if (!stralloc_cats(&rules_name,host)) return -1;
+ r = dorule(callback);
+ if (r) return r;
+ }
+
+ if (!stralloc_copys(&rules_name,ip)) return -1;
+ while (rules_name.len > 0) {
+ if (ip[rules_name.len - 1] == '.') {
+ r = dorule(callback);
+ if (r) return r;
+ }
+ --rules_name.len;
+ }
+
+ if (host) {
+ while (*host) {
+ if (*host == '.') {
+ if (!stralloc_copys(&rules_name,"=")) return -1;
+ if (!stralloc_cats(&rules_name,host)) return -1;
+ r = dorule(callback);
+ if (r) return r;
+ }
+ ++host;
+ }
+ if (!stralloc_copys(&rules_name,"=")) return -1;
+ r = dorule(callback);
+ if (r) return r;
+ }
+
+ rules_name.len = 0;
+ return dorule(callback);
+}
+
+int rules(void (*callback)(char *,unsigned int),int fd,char *ip,char *host,char *info)
+{
+ int r;
+ cdb_init(&c,fd);
+ r = doit(callback,ip,host,info);
+ cdb_free(&c);
+ return r;
+}
diff --git a/ucspi-tcp-0.88/rules.h b/ucspi-tcp-0.88/rules.h
new file mode 100644
index 0000000..15d9b90
--- /dev/null
+++ b/ucspi-tcp-0.88/rules.h
@@ -0,0 +1,9 @@
+#ifndef RULES_H
+#define RULES_H
+
+#include "stralloc.h"
+
+extern stralloc rules_name;
+extern int rules(void (*)(char *,unsigned int),int,char *,char *,char *);
+
+#endif
diff --git a/ucspi-tcp-0.88/scan.h b/ucspi-tcp-0.88/scan.h
new file mode 100644
index 0000000..758138c
--- /dev/null
+++ b/ucspi-tcp-0.88/scan.h
@@ -0,0 +1,28 @@
+#ifndef SCAN_H
+#define SCAN_H
+
+extern unsigned int scan_uint(char *,unsigned int *);
+extern unsigned int scan_xint(char *,unsigned int *);
+extern unsigned int scan_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int *);
+extern unsigned int scan_ushort(char *,unsigned short *);
+extern unsigned int scan_xshort(char *,unsigned short *);
+extern unsigned int scan_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short *);
+extern unsigned int scan_ulong(char *,unsigned long *);
+extern unsigned int scan_xlong(char *,unsigned long *);
+extern unsigned int scan_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long *);
+
+extern unsigned int scan_plusminus(char *,int *);
+extern unsigned int scan_0x(char *,unsigned int *);
+
+extern unsigned int scan_whitenskip(char *,unsigned int);
+extern unsigned int scan_nonwhitenskip(char *,unsigned int);
+extern unsigned int scan_charsetnskip(char *,char *,unsigned int);
+extern unsigned int scan_noncharsetnskip(char *,char *,unsigned int);
+
+extern unsigned int scan_strncmp(char *,char *,unsigned int);
+extern unsigned int scan_memcmp(char *,char *,unsigned int);
+
+extern unsigned int scan_long(char *,long *);
+extern unsigned int scan_8long(char *,unsigned long *);
+
+#endif
diff --git a/ucspi-tcp-0.88/scan_ulong.c b/ucspi-tcp-0.88/scan_ulong.c
new file mode 100644
index 0000000..69bc3d4
--- /dev/null
+++ b/ucspi-tcp-0.88/scan_ulong.c
@@ -0,0 +1,14 @@
+#include "scan.h"
+
+unsigned int scan_ulong(register char *s,register unsigned long *u)
+{
+ register unsigned int pos = 0;
+ register unsigned long result = 0;
+ register unsigned long c;
+ while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
+ result = result * 10 + c;
+ ++pos;
+ }
+ *u = result;
+ return pos;
+}
diff --git a/ucspi-tcp-0.88/seek.h b/ucspi-tcp-0.88/seek.h
new file mode 100644
index 0000000..06aad97
--- /dev/null
+++ b/ucspi-tcp-0.88/seek.h
@@ -0,0 +1,15 @@
+#ifndef SEEK_H
+#define SEEK_H
+
+typedef unsigned long seek_pos;
+
+extern seek_pos seek_cur(int);
+
+extern int seek_set(int,seek_pos);
+extern int seek_end(int);
+
+extern int seek_trunc(int,seek_pos);
+
+#define seek_begin(fd) (seek_set((fd),(seek_pos) 0))
+
+#endif
diff --git a/ucspi-tcp-0.88/seek_set.c b/ucspi-tcp-0.88/seek_set.c
new file mode 100644
index 0000000..d08d4f3
--- /dev/null
+++ b/ucspi-tcp-0.88/seek_set.c
@@ -0,0 +1,7 @@
+#include <sys/types.h>
+#include "seek.h"
+
+#define SET 0 /* sigh */
+
+int seek_set(int fd,seek_pos pos)
+{ if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; }
diff --git a/ucspi-tcp-0.88/select.h1 b/ucspi-tcp-0.88/select.h1
new file mode 100644
index 0000000..fe725b6
--- /dev/null
+++ b/ucspi-tcp-0.88/select.h1
@@ -0,0 +1,10 @@
+#ifndef SELECT_H
+#define SELECT_H
+
+/* sysdep: -sysselect */
+
+#include <sys/types.h>
+#include <sys/time.h>
+extern int select();
+
+#endif
diff --git a/ucspi-tcp-0.88/select.h2 b/ucspi-tcp-0.88/select.h2
new file mode 100644
index 0000000..2bc2044
--- /dev/null
+++ b/ucspi-tcp-0.88/select.h2
@@ -0,0 +1,11 @@
+#ifndef SELECT_H
+#define SELECT_H
+
+/* sysdep: +sysselect */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>
+extern int select();
+
+#endif
diff --git a/ucspi-tcp-0.88/sgetopt.c b/ucspi-tcp-0.88/sgetopt.c
new file mode 100644
index 0000000..bdd0f14
--- /dev/null
+++ b/ucspi-tcp-0.88/sgetopt.c
@@ -0,0 +1,51 @@
+/* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer
+D. J. Bernstein, djb@pobox.com.
+Depends on subgetopt.h, buffer.h.
+No system requirements.
+19991219: Switched to buffer.h.
+19970208: Cleanups.
+931201: Baseline.
+No known patent problems.
+
+Documentation in sgetopt.3.
+*/
+
+#include "buffer.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(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';
+ buffer_puts(buffer_2,optprogname);
+ if (argv[optind] && (optind < argc))
+ buffer_puts(buffer_2,": illegal option -- ");
+ else
+ buffer_puts(buffer_2,": option requires an argument -- ");
+ buffer_put(buffer_2,chp,2);
+ buffer_flush(buffer_2);
+ }
+ return c;
+}
diff --git a/ucspi-tcp-0.88/sgetopt.h b/ucspi-tcp-0.88/sgetopt.h
new file mode 100644
index 0000000..739203c
--- /dev/null
+++ b/ucspi-tcp-0.88/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(int,char **,char *);
+extern int sgetopterr;
+extern char *sgetoptprogname;
+
+#endif
diff --git a/ucspi-tcp-0.88/sig.c b/ucspi-tcp-0.88/sig.c
new file mode 100644
index 0000000..0368bcc
--- /dev/null
+++ b/ucspi-tcp-0.88/sig.c
@@ -0,0 +1,12 @@
+#include <signal.h>
+#include "sig.h"
+
+int sig_alarm = SIGALRM;
+int sig_child = SIGCHLD;
+int sig_cont = SIGCONT;
+int sig_hangup = SIGHUP;
+int sig_pipe = SIGPIPE;
+int sig_term = SIGTERM;
+
+void (*sig_defaulthandler)() = SIG_DFL;
+void (*sig_ignorehandler)() = SIG_IGN;
diff --git a/ucspi-tcp-0.88/sig.h b/ucspi-tcp-0.88/sig.h
new file mode 100644
index 0000000..bc522e4
--- /dev/null
+++ b/ucspi-tcp-0.88/sig.h
@@ -0,0 +1,25 @@
+#ifndef SIG_H
+#define SIG_H
+
+extern int sig_alarm;
+extern int sig_child;
+extern int sig_cont;
+extern int sig_hangup;
+extern int sig_pipe;
+extern int sig_term;
+
+extern void (*sig_defaulthandler)();
+extern void (*sig_ignorehandler)();
+
+extern void sig_catch(int,void (*)());
+#define sig_ignore(s) (sig_catch((s),sig_ignorehandler))
+#define sig_uncatch(s) (sig_catch((s),sig_defaulthandler))
+
+extern void sig_block(int);
+extern void sig_unblock(int);
+extern void sig_blocknone(void);
+extern void sig_pause(void);
+
+extern void sig_dfl(int);
+
+#endif
diff --git a/ucspi-tcp-0.88/sig_block.c b/ucspi-tcp-0.88/sig_block.c
new file mode 100644
index 0000000..57be036
--- /dev/null
+++ b/ucspi-tcp-0.88/sig_block.c
@@ -0,0 +1,38 @@
+#include <signal.h>
+#include "sig.h"
+#include "hassgprm.h"
+
+void sig_block(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(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(void)
+{
+#ifdef HASSIGPROCMASK
+ sigset_t ss;
+ sigemptyset(&ss);
+ sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
+#else
+ sigsetmask(0);
+#endif
+}
diff --git a/ucspi-tcp-0.88/sig_catch.c b/ucspi-tcp-0.88/sig_catch.c
new file mode 100644
index 0000000..bdb2bfb
--- /dev/null
+++ b/ucspi-tcp-0.88/sig_catch.c
@@ -0,0 +1,16 @@
+#include <signal.h>
+#include "sig.h"
+#include "hassgact.h"
+
+void sig_catch(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/ucspi-tcp-0.88/sig_pause.c b/ucspi-tcp-0.88/sig_pause.c
new file mode 100644
index 0000000..3dcc7b6
--- /dev/null
+++ b/ucspi-tcp-0.88/sig_pause.c
@@ -0,0 +1,14 @@
+#include <signal.h>
+#include "sig.h"
+#include "hassgprm.h"
+
+void sig_pause(void)
+{
+#ifdef HASSIGPROCMASK
+ sigset_t ss;
+ sigemptyset(&ss);
+ sigsuspend(&ss);
+#else
+ sigpause(0);
+#endif
+}
diff --git a/ucspi-tcp-0.88/socket.h b/ucspi-tcp-0.88/socket.h
new file mode 100644
index 0000000..80fb260
--- /dev/null
+++ b/ucspi-tcp-0.88/socket.h
@@ -0,0 +1,22 @@
+#ifndef SOCKET_H
+#define SOCKET_H
+
+#include "uint16.h"
+
+extern int socket_tcp(void);
+extern int socket_udp(void);
+
+extern int socket_connect4(int,char *,uint16);
+extern int socket_connected(int);
+extern int socket_bind4(int,char *,uint16);
+extern int socket_bind4_reuse(int,char *,uint16);
+extern int socket_listen(int,int);
+extern int socket_accept4(int,char *,uint16 *);
+extern int socket_recv4(int,char *,int,char *,uint16 *);
+extern int socket_send4(int,char *,int,char *,uint16);
+extern int socket_local4(int,char *,uint16 *);
+extern int socket_remote4(int,char *,uint16 *);
+
+extern void socket_tryreservein(int,int);
+
+#endif
diff --git a/ucspi-tcp-0.88/socket_accept.c b/ucspi-tcp-0.88/socket_accept.c
new file mode 100644
index 0000000..22c44d4
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_accept.c
@@ -0,0 +1,21 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "byte.h"
+#include "socket.h"
+
+int socket_accept4(int s,char ip[4],uint16 *port)
+{
+ struct sockaddr_in sa;
+ int dummy = sizeof sa;
+ int fd;
+
+ fd = accept(s,(struct sockaddr *) &sa,&dummy);
+ if (fd == -1) return -1;
+
+ byte_copy(ip,4,(char *) &sa.sin_addr);
+ uint16_unpack_big((char *) &sa.sin_port,port);
+
+ return fd;
+}
diff --git a/ucspi-tcp-0.88/socket_bind.c b/ucspi-tcp-0.88/socket_bind.c
new file mode 100644
index 0000000..20830a4
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_bind.c
@@ -0,0 +1,33 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "byte.h"
+#include "socket.h"
+
+int socket_bind4(int s,char ip[4],uint16 port)
+{
+ struct sockaddr_in sa;
+
+ byte_zero(&sa,sizeof sa);
+ sa.sin_family = AF_INET;
+ uint16_pack_big((char *) &sa.sin_port,port);
+ byte_copy((char *) &sa.sin_addr,4,ip);
+
+ return bind(s,(struct sockaddr *) &sa,sizeof sa);
+}
+
+int socket_bind4_reuse(int s,char ip[4],uint16 port)
+{
+ int opt = 1;
+ setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);
+ return socket_bind4(s,ip,port);
+}
+
+void socket_tryreservein(int s,int size)
+{
+ while (size >= 1024) {
+ if (setsockopt(s,SOL_SOCKET,SO_RCVBUF,&size,sizeof size) == 0) return;
+ size -= (size >> 5);
+ }
+}
diff --git a/ucspi-tcp-0.88/socket_conn.c b/ucspi-tcp-0.88/socket_conn.c
new file mode 100644
index 0000000..35adac4
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_conn.c
@@ -0,0 +1,33 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "readwrite.h"
+#include "byte.h"
+#include "socket.h"
+
+int socket_connect4(int s,char ip[4],uint16 port)
+{
+ struct sockaddr_in sa;
+
+ byte_zero(&sa,sizeof sa);
+ sa.sin_family = AF_INET;
+ uint16_pack_big((char *) &sa.sin_port,port);
+ byte_copy((char *) &sa.sin_addr,4,ip);
+
+ return connect(s,(struct sockaddr *) &sa,sizeof sa);
+}
+
+int socket_connected(int s)
+{
+ struct sockaddr_in sa;
+ int dummy;
+ char ch;
+
+ dummy = sizeof sa;
+ if (getpeername(s,(struct sockaddr *) &sa,&dummy) == -1) {
+ read(s,&ch,1); /* sets errno */
+ return 0;
+ }
+ return 1;
+}
diff --git a/ucspi-tcp-0.88/socket_delay.c b/ucspi-tcp-0.88/socket_delay.c
new file mode 100644
index 0000000..0e8c860
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_delay.c
@@ -0,0 +1,11 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "socket.h"
+
+int socket_tcpnodelay(int s)
+{
+ int opt = 1;
+ return setsockopt(s,IPPROTO_TCP,1,&opt,sizeof opt); /* 1 == TCP_NODELAY */
+}
diff --git a/ucspi-tcp-0.88/socket_listen.c b/ucspi-tcp-0.88/socket_listen.c
new file mode 100644
index 0000000..abdb483
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_listen.c
@@ -0,0 +1,10 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "socket.h"
+
+int socket_listen(int s,int backlog)
+{
+ return listen(s,backlog);
+}
diff --git a/ucspi-tcp-0.88/socket_local.c b/ucspi-tcp-0.88/socket_local.c
new file mode 100644
index 0000000..1473d91
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_local.c
@@ -0,0 +1,17 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "byte.h"
+#include "socket.h"
+
+int socket_local4(int s,char ip[4],uint16 *port)
+{
+ struct sockaddr_in sa;
+ int dummy = sizeof sa;
+
+ if (getsockname(s,(struct sockaddr *) &sa,&dummy) == -1) return -1;
+ byte_copy(ip,4,(char *) &sa.sin_addr);
+ uint16_unpack_big((char *) &sa.sin_port,port);
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/socket_opts.c b/ucspi-tcp-0.88/socket_opts.c
new file mode 100644
index 0000000..ce5d170
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_opts.c
@@ -0,0 +1,10 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "socket.h"
+
+int socket_ipoptionskill(int s)
+{
+ return setsockopt(s,IPPROTO_IP,1,(char *) 0,0); /* 1 == IP_OPTIONS */
+}
diff --git a/ucspi-tcp-0.88/socket_remote.c b/ucspi-tcp-0.88/socket_remote.c
new file mode 100644
index 0000000..d65d9f8
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_remote.c
@@ -0,0 +1,17 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "byte.h"
+#include "socket.h"
+
+int socket_remote4(int s,char ip[4],uint16 *port)
+{
+ struct sockaddr_in sa;
+ int dummy = sizeof sa;
+
+ if (getpeername(s,(struct sockaddr *) &sa,&dummy) == -1) return -1;
+ byte_copy(ip,4,(char *) &sa.sin_addr);
+ uint16_unpack_big((char *) &sa.sin_port,port);
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/socket_tcp.c b/ucspi-tcp-0.88/socket_tcp.c
new file mode 100644
index 0000000..aada07d
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_tcp.c
@@ -0,0 +1,16 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "ndelay.h"
+#include "socket.h"
+
+int socket_tcp(void)
+{
+ int s;
+
+ s = socket(AF_INET,SOCK_STREAM,0);
+ if (s == -1) return -1;
+ if (ndelay_on(s) == -1) { close(s); return -1; }
+ return s;
+}
diff --git a/ucspi-tcp-0.88/socket_udp.c b/ucspi-tcp-0.88/socket_udp.c
new file mode 100644
index 0000000..bda4494
--- /dev/null
+++ b/ucspi-tcp-0.88/socket_udp.c
@@ -0,0 +1,16 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "ndelay.h"
+#include "socket.h"
+
+int socket_udp(void)
+{
+ int s;
+
+ s = socket(AF_INET,SOCK_DGRAM,0);
+ if (s == -1) return -1;
+ if (ndelay_on(s) == -1) { close(s); return -1; }
+ return s;
+}
diff --git a/ucspi-tcp-0.88/str.h b/ucspi-tcp-0.88/str.h
new file mode 100644
index 0000000..ab4aedd
--- /dev/null
+++ b/ucspi-tcp-0.88/str.h
@@ -0,0 +1,14 @@
+#ifndef STR_H
+#define STR_H
+
+extern unsigned int str_copy(char *,char *);
+extern int str_diff(char *,char *);
+extern int str_diffn(char *,char *,unsigned int);
+extern unsigned int str_len(char *);
+extern unsigned int str_chr(char *,int);
+extern unsigned int str_rchr(char *,int);
+extern int str_start(char *,char *);
+
+#define str_equal(s,t) (!str_diff((s),(t)))
+
+#endif
diff --git a/ucspi-tcp-0.88/str_chr.c b/ucspi-tcp-0.88/str_chr.c
new file mode 100644
index 0000000..886d6b6
--- /dev/null
+++ b/ucspi-tcp-0.88/str_chr.c
@@ -0,0 +1,17 @@
+#include "str.h"
+
+unsigned int str_chr(register char *s,int c)
+{
+ register char ch;
+ register char *t;
+
+ ch = c;
+ t = s;
+ for (;;) {
+ if (!*t) break; if (*t == ch) break; ++t;
+ if (!*t) break; if (*t == ch) break; ++t;
+ if (!*t) break; if (*t == ch) break; ++t;
+ if (!*t) break; if (*t == ch) break; ++t;
+ }
+ return t - s;
+}
diff --git a/ucspi-tcp-0.88/str_diff.c b/ucspi-tcp-0.88/str_diff.c
new file mode 100644
index 0000000..037dcdf
--- /dev/null
+++ b/ucspi-tcp-0.88/str_diff.c
@@ -0,0 +1,15 @@
+#include "str.h"
+
+int str_diff(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/ucspi-tcp-0.88/str_len.c b/ucspi-tcp-0.88/str_len.c
new file mode 100644
index 0000000..5bd3f62
--- /dev/null
+++ b/ucspi-tcp-0.88/str_len.c
@@ -0,0 +1,14 @@
+#include "str.h"
+
+unsigned int str_len(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/ucspi-tcp-0.88/str_start.c b/ucspi-tcp-0.88/str_start.c
new file mode 100644
index 0000000..43430bb
--- /dev/null
+++ b/ucspi-tcp-0.88/str_start.c
@@ -0,0 +1,13 @@
+#include "str.h"
+
+int str_start(register char *s,register char *t)
+{
+ register char x;
+
+ for (;;) {
+ x = *t++; if (!x) return 1; if (x != *s++) return 0;
+ x = *t++; if (!x) return 1; if (x != *s++) return 0;
+ x = *t++; if (!x) return 1; if (x != *s++) return 0;
+ x = *t++; if (!x) return 1; if (x != *s++) return 0;
+ }
+}
diff --git a/ucspi-tcp-0.88/stralloc.h b/ucspi-tcp-0.88/stralloc.h
new file mode 100644
index 0000000..7866812
--- /dev/null
+++ b/ucspi-tcp-0.88/stralloc.h
@@ -0,0 +1,29 @@
+#ifndef STRALLOC_H
+#define STRALLOC_H
+
+#include "gen_alloc.h"
+
+GEN_ALLOC_typedef(stralloc,char,s,len,a)
+
+extern int stralloc_ready(stralloc *,unsigned int);
+extern int stralloc_readyplus(stralloc *,unsigned int);
+extern int stralloc_copy(stralloc *,stralloc *);
+extern int stralloc_cat(stralloc *,stralloc *);
+extern int stralloc_copys(stralloc *,char *);
+extern int stralloc_cats(stralloc *,char *);
+extern int stralloc_copyb(stralloc *,char *,unsigned int);
+extern int stralloc_catb(stralloc *,char *,unsigned int);
+extern int stralloc_append(stralloc *,char *); /* beware: this takes a pointer to 1 char */
+extern int stralloc_starts(stralloc *,char *);
+
+#define stralloc_0(sa) stralloc_append(sa,"")
+
+extern int stralloc_catulong0(stralloc *,unsigned long,unsigned int);
+extern int stralloc_catlong0(stralloc *,long,unsigned int);
+
+#define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0))
+#define stralloc_catuint0(sa,i,n) (stralloc_catulong0((sa),(i),(n)))
+#define stralloc_catint0(sa,i,n) (stralloc_catlong0((sa),(i),(n)))
+#define stralloc_catint(sa,i) (stralloc_catlong0((sa),(i),0))
+
+#endif
diff --git a/ucspi-tcp-0.88/stralloc_cat.c b/ucspi-tcp-0.88/stralloc_cat.c
new file mode 100644
index 0000000..dd08548
--- /dev/null
+++ b/ucspi-tcp-0.88/stralloc_cat.c
@@ -0,0 +1,7 @@
+#include "byte.h"
+#include "stralloc.h"
+
+int stralloc_cat(stralloc *sato,stralloc *safrom)
+{
+ return stralloc_catb(sato,safrom->s,safrom->len);
+}
diff --git a/ucspi-tcp-0.88/stralloc_catb.c b/ucspi-tcp-0.88/stralloc_catb.c
new file mode 100644
index 0000000..b739bed
--- /dev/null
+++ b/ucspi-tcp-0.88/stralloc_catb.c
@@ -0,0 +1,12 @@
+#include "stralloc.h"
+#include "byte.h"
+
+int stralloc_catb(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/ucspi-tcp-0.88/stralloc_cats.c b/ucspi-tcp-0.88/stralloc_cats.c
new file mode 100644
index 0000000..8b11e94
--- /dev/null
+++ b/ucspi-tcp-0.88/stralloc_cats.c
@@ -0,0 +1,8 @@
+#include "byte.h"
+#include "str.h"
+#include "stralloc.h"
+
+int stralloc_cats(stralloc *sa,char *s)
+{
+ return stralloc_catb(sa,s,str_len(s));
+}
diff --git a/ucspi-tcp-0.88/stralloc_copy.c b/ucspi-tcp-0.88/stralloc_copy.c
new file mode 100644
index 0000000..02f8c47
--- /dev/null
+++ b/ucspi-tcp-0.88/stralloc_copy.c
@@ -0,0 +1,7 @@
+#include "byte.h"
+#include "stralloc.h"
+
+int stralloc_copy(stralloc *sato,stralloc *safrom)
+{
+ return stralloc_copyb(sato,safrom->s,safrom->len);
+}
diff --git a/ucspi-tcp-0.88/stralloc_eady.c b/ucspi-tcp-0.88/stralloc_eady.c
new file mode 100644
index 0000000..3a31f4b
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/stralloc_opyb.c b/ucspi-tcp-0.88/stralloc_opyb.c
new file mode 100644
index 0000000..46b99fc
--- /dev/null
+++ b/ucspi-tcp-0.88/stralloc_opyb.c
@@ -0,0 +1,11 @@
+#include "stralloc.h"
+#include "byte.h"
+
+int stralloc_copyb(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/ucspi-tcp-0.88/stralloc_opys.c b/ucspi-tcp-0.88/stralloc_opys.c
new file mode 100644
index 0000000..78594b0
--- /dev/null
+++ b/ucspi-tcp-0.88/stralloc_opys.c
@@ -0,0 +1,8 @@
+#include "byte.h"
+#include "str.h"
+#include "stralloc.h"
+
+int stralloc_copys(stralloc *sa,char *s)
+{
+ return stralloc_copyb(sa,s,str_len(s));
+}
diff --git a/ucspi-tcp-0.88/stralloc_pend.c b/ucspi-tcp-0.88/stralloc_pend.c
new file mode 100644
index 0000000..a3443b8
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/strerr.h b/ucspi-tcp-0.88/strerr.h
new file mode 100644
index 0000000..702f588
--- /dev/null
+++ b/ucspi-tcp-0.88/strerr.h
@@ -0,0 +1,78 @@
+#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(void);
+
+extern char *strerr(struct strerr *);
+extern void strerr_warn(char *,char *,char *,char *,char *,char *,struct strerr *);
+extern void strerr_die(int,char *,char *,char *,char *,char *,char *,struct strerr *);
+
+#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),(se))
+#define strerr_warn5(x1,x2,x3,x4,x5,se) \
+strerr_warn((x1),(x2),(x3),(x4),(x5),0,(se))
+#define strerr_warn4(x1,x2,x3,x4,se) \
+strerr_warn((x1),(x2),(x3),(x4),0,0,(se))
+#define strerr_warn3(x1,x2,x3,se) \
+strerr_warn((x1),(x2),(x3),0,0,0,(se))
+#define strerr_warn2(x1,x2,se) \
+strerr_warn((x1),(x2),0,0,0,0,(se))
+#define strerr_warn1(x1,se) \
+strerr_warn((x1),0,0,0,0,0,(se))
+
+#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(se))
+#define strerr_die5(e,x1,x2,x3,x4,x5,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,(se))
+#define strerr_die4(e,x1,x2,x3,x4,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),0,0,(se))
+#define strerr_die3(e,x1,x2,x3,se) \
+strerr_die((e),(x1),(x2),(x3),0,0,0,(se))
+#define strerr_die2(e,x1,x2,se) \
+strerr_die((e),(x1),(x2),0,0,0,0,(se))
+#define strerr_die1(e,x1,se) \
+strerr_die((e),(x1),0,0,0,0,0,(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),0,&strerr_sys)
+#define strerr_die4sys(e,x1,x2,x3,x4) \
+strerr_die((e),(x1),(x2),(x3),(x4),0,0,&strerr_sys)
+#define strerr_die3sys(e,x1,x2,x3) \
+strerr_die((e),(x1),(x2),(x3),0,0,0,&strerr_sys)
+#define strerr_die2sys(e,x1,x2) \
+strerr_die((e),(x1),(x2),0,0,0,0,&strerr_sys)
+#define strerr_die1sys(e,x1) \
+strerr_die((e),(x1),0,0,0,0,0,&strerr_sys)
+
+#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),0)
+#define strerr_die5x(e,x1,x2,x3,x4,x5) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,0)
+#define strerr_die4x(e,x1,x2,x3,x4) \
+strerr_die((e),(x1),(x2),(x3),(x4),0,0,0)
+#define strerr_die3x(e,x1,x2,x3) \
+strerr_die((e),(x1),(x2),(x3),0,0,0,0)
+#define strerr_die2x(e,x1,x2) \
+strerr_die((e),(x1),(x2),0,0,0,0,0)
+#define strerr_die1x(e,x1) \
+strerr_die((e),(x1),0,0,0,0,0,0)
+
+#endif
diff --git a/ucspi-tcp-0.88/strerr_die.c b/ucspi-tcp-0.88/strerr_die.c
new file mode 100644
index 0000000..850028b
--- /dev/null
+++ b/ucspi-tcp-0.88/strerr_die.c
@@ -0,0 +1,31 @@
+#include "buffer.h"
+#include "exit.h"
+#include "strerr.h"
+
+void strerr_warn(char *x1,char *x2,char *x3,char *x4,char *x5,char *x6,struct strerr *se)
+{
+ strerr_sysinit();
+
+ if (x1) buffer_puts(buffer_2,x1);
+ if (x2) buffer_puts(buffer_2,x2);
+ if (x3) buffer_puts(buffer_2,x3);
+ if (x4) buffer_puts(buffer_2,x4);
+ if (x5) buffer_puts(buffer_2,x5);
+ if (x6) buffer_puts(buffer_2,x6);
+
+ while(se) {
+ if (se->x) buffer_puts(buffer_2,se->x);
+ if (se->y) buffer_puts(buffer_2,se->y);
+ if (se->z) buffer_puts(buffer_2,se->z);
+ se = se->who;
+ }
+
+ buffer_puts(buffer_2,"\n");
+ buffer_flush(buffer_2);
+}
+
+void strerr_die(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/ucspi-tcp-0.88/strerr_sys.c b/ucspi-tcp-0.88/strerr_sys.c
new file mode 100644
index 0000000..b484197
--- /dev/null
+++ b/ucspi-tcp-0.88/strerr_sys.c
@@ -0,0 +1,12 @@
+#include "error.h"
+#include "strerr.h"
+
+struct strerr strerr_sys;
+
+void strerr_sysinit(void)
+{
+ strerr_sys.who = 0;
+ strerr_sys.x = error_str(errno);
+ strerr_sys.y = "";
+ strerr_sys.z = "";
+}
diff --git a/ucspi-tcp-0.88/subgetopt.c b/ucspi-tcp-0.88/subgetopt.c
new file mode 100644
index 0000000..552c4de
--- /dev/null
+++ b/ucspi-tcp-0.88/subgetopt.c
@@ -0,0 +1,65 @@
+#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(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/ucspi-tcp-0.88/subgetopt.h b/ucspi-tcp-0.88/subgetopt.h
new file mode 100644
index 0000000..b4b63e1
--- /dev/null
+++ b/ucspi-tcp-0.88/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(int,char **,char *);
+extern char *subgetoptarg;
+extern int subgetoptind;
+extern int subgetoptpos;
+extern int subgetoptproblem;
+extern char *subgetoptprogname;
+extern int subgetoptdone;
+
+#endif
diff --git a/ucspi-tcp-0.88/tai.h b/ucspi-tcp-0.88/tai.h
new file mode 100644
index 0000000..28ee9e6
--- /dev/null
+++ b/ucspi-tcp-0.88/tai.h
@@ -0,0 +1,26 @@
+#ifndef TAI_H
+#define TAI_H
+
+#include "uint64.h"
+
+struct tai {
+ uint64 x;
+} ;
+
+#define tai_unix(t,u) ((void) ((t)->x = 4611686018427387914ULL + (uint64) (u)))
+
+extern void tai_now(struct tai *);
+
+#define tai_approx(t) ((double) ((t)->x))
+
+extern void tai_add(struct tai *,struct tai *,struct tai *);
+extern void tai_sub(struct tai *,struct tai *,struct tai *);
+#define tai_less(t,u) ((t)->x < (u)->x)
+
+#define TAI_PACK 8
+extern void tai_pack(char *,struct tai *);
+extern void tai_unpack(char *,struct tai *);
+
+extern void tai_uint(struct tai *,unsigned int);
+
+#endif
diff --git a/ucspi-tcp-0.88/tai_pack.c b/ucspi-tcp-0.88/tai_pack.c
new file mode 100644
index 0000000..5e662cf
--- /dev/null
+++ b/ucspi-tcp-0.88/tai_pack.c
@@ -0,0 +1,16 @@
+#include "tai.h"
+
+void tai_pack(char *s,struct tai *t)
+{
+ uint64 x;
+
+ x = t->x;
+ s[7] = x & 255; x >>= 8;
+ s[6] = x & 255; x >>= 8;
+ s[5] = x & 255; x >>= 8;
+ s[4] = x & 255; x >>= 8;
+ s[3] = x & 255; x >>= 8;
+ s[2] = x & 255; x >>= 8;
+ s[1] = x & 255; x >>= 8;
+ s[0] = x;
+}
diff --git a/ucspi-tcp-0.88/taia.h b/ucspi-tcp-0.88/taia.h
new file mode 100644
index 0000000..f4c0ca7
--- /dev/null
+++ b/ucspi-tcp-0.88/taia.h
@@ -0,0 +1,33 @@
+#ifndef TAIA_H
+#define TAIA_H
+
+#include "tai.h"
+
+struct taia {
+ struct tai sec;
+ unsigned long nano; /* 0...999999999 */
+ unsigned long atto; /* 0...999999999 */
+} ;
+
+extern void taia_tai(struct taia *,struct tai *);
+
+extern void taia_now(struct taia *);
+
+extern double taia_approx(struct taia *);
+extern double taia_frac(struct taia *);
+
+extern void taia_add(struct taia *,struct taia *,struct taia *);
+extern void taia_sub(struct taia *,struct taia *,struct taia *);
+extern void taia_half(struct taia *,struct taia *);
+extern int taia_less(struct taia *,struct taia *);
+
+#define TAIA_PACK 16
+extern void taia_pack(char *,struct taia *);
+extern void taia_unpack(char *,struct taia *);
+
+#define TAIA_FMTFRAC 19
+extern unsigned int taia_fmtfrac(char *,struct taia *);
+
+extern void taia_uint(struct taia *,unsigned int);
+
+#endif
diff --git a/ucspi-tcp-0.88/taia_add.c b/ucspi-tcp-0.88/taia_add.c
new file mode 100644
index 0000000..a596cc8
--- /dev/null
+++ b/ucspi-tcp-0.88/taia_add.c
@@ -0,0 +1,18 @@
+#include "taia.h"
+
+/* XXX: breaks tai encapsulation */
+
+void taia_add(struct taia *t,struct taia *u,struct taia *v)
+{
+ t->sec.x = u->sec.x + v->sec.x;
+ t->nano = u->nano + v->nano;
+ t->atto = u->atto + v->atto;
+ if (t->atto > 999999999UL) {
+ t->atto -= 1000000000UL;
+ ++t->nano;
+ }
+ if (t->nano > 999999999UL) {
+ t->nano -= 1000000000UL;
+ ++t->sec.x;
+ }
+}
diff --git a/ucspi-tcp-0.88/taia_approx.c b/ucspi-tcp-0.88/taia_approx.c
new file mode 100644
index 0000000..0c4d0de
--- /dev/null
+++ b/ucspi-tcp-0.88/taia_approx.c
@@ -0,0 +1,6 @@
+#include "taia.h"
+
+double taia_approx(struct taia *t)
+{
+ return tai_approx(&t->sec) + taia_frac(t);
+}
diff --git a/ucspi-tcp-0.88/taia_frac.c b/ucspi-tcp-0.88/taia_frac.c
new file mode 100644
index 0000000..89a1aac
--- /dev/null
+++ b/ucspi-tcp-0.88/taia_frac.c
@@ -0,0 +1,6 @@
+#include "taia.h"
+
+double taia_frac(struct taia *t)
+{
+ return (t->atto * 0.000000001 + t->nano) * 0.000000001;
+}
diff --git a/ucspi-tcp-0.88/taia_less.c b/ucspi-tcp-0.88/taia_less.c
new file mode 100644
index 0000000..13b7288
--- /dev/null
+++ b/ucspi-tcp-0.88/taia_less.c
@@ -0,0 +1,12 @@
+#include "taia.h"
+
+/* XXX: breaks tai encapsulation */
+
+int taia_less(struct taia *t,struct taia *u)
+{
+ if (t->sec.x < u->sec.x) return 1;
+ if (t->sec.x > u->sec.x) return 0;
+ if (t->nano < u->nano) return 1;
+ if (t->nano > u->nano) return 0;
+ return t->atto < u->atto;
+}
diff --git a/ucspi-tcp-0.88/taia_now.c b/ucspi-tcp-0.88/taia_now.c
new file mode 100644
index 0000000..ccc260d
--- /dev/null
+++ b/ucspi-tcp-0.88/taia_now.c
@@ -0,0 +1,12 @@
+#include <sys/types.h>
+#include <sys/time.h>
+#include "taia.h"
+
+void taia_now(struct taia *t)
+{
+ struct timeval now;
+ gettimeofday(&now,(struct timezone *) 0);
+ tai_unix(&t->sec,now.tv_sec);
+ t->nano = 1000 * now.tv_usec + 500;
+ t->atto = 0;
+}
diff --git a/ucspi-tcp-0.88/taia_pack.c b/ucspi-tcp-0.88/taia_pack.c
new file mode 100644
index 0000000..1f1b051
--- /dev/null
+++ b/ucspi-tcp-0.88/taia_pack.c
@@ -0,0 +1,20 @@
+#include "taia.h"
+
+void taia_pack(char *s,struct taia *t)
+{
+ unsigned long x;
+
+ tai_pack(s,&t->sec);
+ s += 8;
+
+ x = t->atto;
+ s[7] = x & 255; x >>= 8;
+ s[6] = x & 255; x >>= 8;
+ s[5] = x & 255; x >>= 8;
+ s[4] = x;
+ x = t->nano;
+ s[3] = x & 255; x >>= 8;
+ s[2] = x & 255; x >>= 8;
+ s[1] = x & 255; x >>= 8;
+ s[0] = x;
+}
diff --git a/ucspi-tcp-0.88/taia_sub.c b/ucspi-tcp-0.88/taia_sub.c
new file mode 100644
index 0000000..7956647
--- /dev/null
+++ b/ucspi-tcp-0.88/taia_sub.c
@@ -0,0 +1,21 @@
+#include "taia.h"
+
+/* XXX: breaks tai encapsulation */
+
+void taia_sub(struct taia *t,struct taia *u,struct taia *v)
+{
+ unsigned long unano = u->nano;
+ unsigned long uatto = u->atto;
+
+ t->sec.x = u->sec.x - v->sec.x;
+ t->nano = unano - v->nano;
+ t->atto = uatto - v->atto;
+ if (t->atto > uatto) {
+ t->atto += 1000000000UL;
+ --t->nano;
+ }
+ if (t->nano > unano) {
+ t->nano += 1000000000UL;
+ --t->sec.x;
+ }
+}
diff --git a/ucspi-tcp-0.88/taia_uint.c b/ucspi-tcp-0.88/taia_uint.c
new file mode 100644
index 0000000..167936c
--- /dev/null
+++ b/ucspi-tcp-0.88/taia_uint.c
@@ -0,0 +1,10 @@
+#include "taia.h"
+
+/* XXX: breaks tai encapsulation */
+
+void taia_uint(struct taia *t,unsigned int s)
+{
+ t->sec.x = s;
+ t->nano = 0;
+ t->atto = 0;
+}
diff --git a/ucspi-tcp-0.88/tcpcat.sh b/ucspi-tcp-0.88/tcpcat.sh
new file mode 100644
index 0000000..2825411
--- /dev/null
+++ b/ucspi-tcp-0.88/tcpcat.sh
@@ -0,0 +1 @@
+exec HOME/bin/tcpclient -RHl0 -- "${1-0}" "${2-17}" sh -c 'exec cat <&6'
diff --git a/ucspi-tcp-0.88/tcpclient.c b/ucspi-tcp-0.88/tcpclient.c
new file mode 100644
index 0000000..9f6d7f2
--- /dev/null
+++ b/ucspi-tcp-0.88/tcpclient.c
@@ -0,0 +1,224 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netdb.h>
+#include "sig.h"
+#include "exit.h"
+#include "sgetopt.h"
+#include "uint16.h"
+#include "fmt.h"
+#include "scan.h"
+#include "str.h"
+#include "ip4.h"
+#include "uint16.h"
+#include "socket.h"
+#include "fd.h"
+#include "stralloc.h"
+#include "buffer.h"
+#include "error.h"
+#include "strerr.h"
+#include "pathexec.h"
+#include "timeoutconn.h"
+#include "remoteinfo.h"
+#include "dns.h"
+
+#define FATAL "tcpclient: fatal: "
+#define CONNECT "tcpclient: unable to connect to "
+
+void nomem(void)
+{
+ strerr_die2x(111,FATAL,"out of memory");
+}
+void usage(void)
+{
+ strerr_die1x(100,"tcpclient: usage: tcpclient \
+[ -hHrRdDqQv ] \
+[ -i localip ] \
+[ -p localport ] \
+[ -T timeoutconn ] \
+[ -l localname ] \
+[ -t timeoutinfo ] \
+host port program");
+}
+
+int verbosity = 1;
+int flagdelay = 1;
+int flagremoteinfo = 1;
+int flagremotehost = 1;
+unsigned long itimeout = 26;
+unsigned long ctimeout[2] = { 2, 58 };
+
+char iplocal[4] = { 0,0,0,0 };
+uint16 portlocal = 0;
+char *forcelocal = 0;
+
+char ipremote[4];
+uint16 portremote;
+
+char *hostname;
+static stralloc addresses;
+static stralloc moreaddresses;
+
+static stralloc tmp;
+static stralloc fqdn;
+char strnum[FMT_ULONG];
+char ipstr[IP4_FMT];
+
+char seed[128];
+
+main(int argc,char **argv)
+{
+ unsigned long u;
+ int opt;
+ char *x;
+ int j;
+ int s;
+ int cloop;
+
+ dns_random_init(seed);
+
+ close(6);
+ close(7);
+ sig_ignore(sig_pipe);
+
+ while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t: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 't': scan_ulong(optarg,&itimeout); break;
+ case 'T': j = scan_ulong(optarg,&ctimeout[0]);
+ if (optarg[j] == '+') ++j;
+ scan_ulong(optarg + j,&ctimeout[1]);
+ break;
+ case 'i': if (!ip4_scan(optarg,iplocal)) usage(); break;
+ case 'p': scan_ulong(optarg,&u); portlocal = u; break;
+ default: usage();
+ }
+ argv += optind;
+
+ if (!verbosity)
+ buffer_2->fd = -1;
+
+ hostname = *argv;
+ if (!hostname) usage();
+ if (str_equal(hostname,"")) hostname = "127.0.0.1";
+ if (str_equal(hostname,"0")) hostname = "127.0.0.1";
+
+ x = *++argv;
+ if (!x) usage();
+ if (!x[scan_ulong(x,&u)])
+ portremote = u;
+ else {
+ struct servent *se;
+ se = getservbyname(x,"tcp");
+ if (!se)
+ strerr_die3x(111,FATAL,"unable to figure out port number for ",x);
+ portremote = ntohs(se->s_port);
+ /* i continue to be amazed at the stupidity of the s_port interface */
+ }
+
+ if (!*++argv) usage();
+
+ if (!stralloc_copys(&tmp,hostname)) nomem();
+ if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1)
+ strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": ");
+ if (addresses.len < 4)
+ strerr_die3x(111,FATAL,"no IP address for ",hostname);
+
+ if (addresses.len == 4) {
+ ctimeout[0] += ctimeout[1];
+ ctimeout[1] = 0;
+ }
+
+ for (cloop = 0;cloop < 2;++cloop) {
+ if (!stralloc_copys(&moreaddresses,"")) nomem();
+ for (j = 0;j + 4 <= addresses.len;j += 4) {
+ s = socket_tcp();
+ if (s == -1)
+ strerr_die2sys(111,FATAL,"unable to create socket: ");
+ if (socket_bind4(s,iplocal,portlocal) == -1)
+ strerr_die2sys(111,FATAL,"unable to bind socket: ");
+ if (timeoutconn(s,addresses.s + j,portremote,ctimeout[cloop]) == 0)
+ goto CONNECTED;
+ close(s);
+ if (!cloop && ctimeout[1] && (errno == error_timeout)) {
+ if (!stralloc_catb(&moreaddresses,addresses.s + j,4)) nomem();
+ }
+ else {
+ strnum[fmt_ulong(strnum,portremote)] = 0;
+ ipstr[ip4_fmt(ipstr,addresses.s + j)] = 0;
+ strerr_warn5(CONNECT,ipstr," port ",strnum,": ",&strerr_sys);
+ }
+ }
+ if (!stralloc_copy(&addresses,&moreaddresses)) nomem();
+ }
+
+ _exit(111);
+
+
+
+ CONNECTED:
+
+ if (!flagdelay)
+ socket_tcpnodelay(s); /* if it fails, bummer */
+
+ if (!pathexec_env("PROTO","TCP")) nomem();
+
+ if (socket_local4(s,iplocal,&portlocal) == -1)
+ strerr_die2sys(111,FATAL,"unable to get local address: ");
+
+ strnum[fmt_ulong(strnum,portlocal)] = 0;
+ if (!pathexec_env("TCPLOCALPORT",strnum)) nomem();
+ ipstr[ip4_fmt(ipstr,iplocal)] = 0;
+ if (!pathexec_env("TCPLOCALIP",ipstr)) nomem();
+
+ x = forcelocal;
+ if (!x)
+ if (dns_name4(&tmp,iplocal) == 0) {
+ if (!stralloc_0(&tmp)) nomem();
+ x = tmp.s;
+ }
+ if (!pathexec_env("TCPLOCALHOST",x)) nomem();
+
+ if (socket_remote4(s,ipremote,&portremote) == -1)
+ strerr_die2sys(111,FATAL,"unable to get remote address: ");
+
+ strnum[fmt_ulong(strnum,portremote)] = 0;
+ if (!pathexec_env("TCPREMOTEPORT",strnum)) nomem();
+ ipstr[ip4_fmt(ipstr,ipremote)] = 0;
+ if (!pathexec_env("TCPREMOTEIP",ipstr)) nomem();
+ if (verbosity >= 2)
+ strerr_warn4("tcpclient: connected to ",ipstr," port ",strnum,0);
+
+ x = 0;
+ if (flagremotehost)
+ if (dns_name4(&tmp,ipremote) == 0) {
+ if (!stralloc_0(&tmp)) nomem();
+ x = tmp.s;
+ }
+ if (!pathexec_env("TCPREMOTEHOST",x)) nomem();
+
+ x = 0;
+ if (flagremoteinfo)
+ if (remoteinfo(&tmp,ipremote,portremote,iplocal,portlocal,itimeout) == 0) {
+ if (!stralloc_0(&tmp)) nomem();
+ x = tmp.s;
+ }
+ if (!pathexec_env("TCPREMOTEINFO",x)) nomem();
+
+ if (fd_move(6,s) == -1)
+ strerr_die2sys(111,FATAL,"unable to set up descriptor 6: ");
+ if (fd_copy(7,6) == -1)
+ strerr_die2sys(111,FATAL,"unable to set up descriptor 7: ");
+ sig_uncatch(sig_pipe);
+
+ pathexec(argv);
+ strerr_die4sys(111,FATAL,"unable to run ",*argv,": ");
+}
diff --git a/ucspi-tcp-0.88/tcprules.c b/ucspi-tcp-0.88/tcprules.c
new file mode 100644
index 0000000..a684ac5
--- /dev/null
+++ b/ucspi-tcp-0.88/tcprules.c
@@ -0,0 +1,175 @@
+#include "strerr.h"
+#include "stralloc.h"
+#include "getln.h"
+#include "buffer.h"
+#include "exit.h"
+#include "fmt.h"
+#include "byte.h"
+#include "cdb_make.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 cdb_make c;
+
+void nomem(void)
+{
+ strerr_die2x(111,FATAL,"out of memory");
+}
+void usage(void)
+{
+ strerr_die1x(100,"tcprules: usage: tcprules rules.cdb rules.tmp");
+}
+void die_bad(void)
+{
+ if (!stralloc_0(&line)) nomem();
+ strerr_die3x(100,FATAL,"unable to parse this line: ",line.s);
+}
+void die_write(void)
+{
+ strerr_die4sys(111,FATAL,"unable to write to ",fntemp,": ");
+}
+
+char strnum[FMT_ULONG];
+stralloc sanum = {0};
+
+void getnum(char *buf,int len,unsigned long *u)
+{
+ if (!stralloc_copyb(&sanum,buf,len)) nomem();
+ if (!stralloc_0(&sanum)) nomem();
+ if (sanum.s[scan_ulong(sanum.s,u)]) die_bad();
+}
+
+void doaddressdata(void)
+{
+ int i;
+ int left;
+ int right;
+ unsigned long bot;
+ unsigned long top;
+
+ if (byte_chr(address.s,address.len,'=') == address.len)
+ 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)) nomem();
+ if (!stralloc_catb(&key,strnum,fmt_ulong(strnum,bot))) nomem();
+ if (!stralloc_catb(&key,address.s + right,address.len - right)) nomem();
+ if (cdb_make_add(&c,key.s,key.len,data.s,data.len) == -1) die_write();
+ ++bot;
+ }
+
+ return;
+ }
+ }
+
+ if (cdb_make_add(&c,address.s,address.len,data.s,data.len) == -1) die_write();
+}
+
+main(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 (cdb_make_start(&c,fd) == -1) die_write();
+
+ while (match) {
+ if (getln(buffer_0,&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)) nomem();
+ if (!stralloc_copys(&data,"")) nomem();
+
+ x += colon + 1; len -= colon + 1;
+
+ if ((len >= 4) && byte_equal(x,4,"deny")) {
+ if (!stralloc_catb(&data,"D",2)) 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)) nomem();
+ if (!stralloc_catb(&data,x + 1,i)) 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)) nomem();
+ if (!stralloc_0(&data)) nomem();
+ x += i + 1; len -= i + 1;
+ break;
+ default:
+ die_bad();
+ }
+
+ doaddressdata();
+ }
+
+ if (cdb_make_finish(&c) == -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/ucspi-tcp-0.88/tcprulescheck.c b/ucspi-tcp-0.88/tcprulescheck.c
new file mode 100644
index 0000000..a961d50
--- /dev/null
+++ b/ucspi-tcp-0.88/tcprulescheck.c
@@ -0,0 +1,57 @@
+#include "byte.h"
+#include "buffer.h"
+#include "strerr.h"
+#include "env.h"
+#include "rules.h"
+
+void found(char *data,unsigned int datalen)
+{
+ unsigned int next0;
+
+ buffer_puts(buffer_1,"rule ");
+ buffer_put(buffer_1,rules_name.s,rules_name.len);
+ buffer_puts(buffer_1,":\n");
+ while ((next0 = byte_chr(data,datalen,0)) < datalen) {
+ switch(data[0]) {
+ case 'D':
+ buffer_puts(buffer_1,"deny connection\n");
+ buffer_flush(buffer_1);
+ _exit(0);
+ case '+':
+ buffer_puts(buffer_1,"set environment variable ");
+ buffer_puts(buffer_1,data + 1);
+ buffer_puts(buffer_1,"\n");
+ break;
+ }
+ ++next0;
+ data += next0; datalen -= next0;
+ }
+ buffer_puts(buffer_1,"allow connection\n");
+ buffer_flush(buffer_1);
+ _exit(0);
+}
+
+main(int argc,char **argv)
+{
+ char *fnrules;
+ int fd;
+ char *ip;
+ char *info;
+ char *host;
+
+ fnrules = argv[1];
+ if (!fnrules)
+ strerr_die1x(100,"tcprulescheck: usage: tcprulescheck rules.cdb");
+
+ ip = env_get("TCPREMOTEIP");
+ if (!ip) ip = "0.0.0.0";
+ info = env_get("TCPREMOTEINFO");
+ host = env_get("TCPREMOTEHOST");
+
+ fd = open_read(fnrules);
+ if ((fd == -1) || (rules(found,fd,ip,host,info) == -1))
+ strerr_die3sys(111,"tcprulescheck: fatal: unable to read ",fnrules,": ");
+
+ buffer_putsflush(buffer_1,"default:\nallow connection\n");
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/tcpserver.c b/ucspi-tcp-0.88/tcpserver.c
new file mode 100644
index 0000000..979a0be
--- /dev/null
+++ b/ucspi-tcp-0.88/tcpserver.c
@@ -0,0 +1,426 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netdb.h>
+#include "uint16.h"
+#include "str.h"
+#include "byte.h"
+#include "fmt.h"
+#include "scan.h"
+#include "ip4.h"
+#include "fd.h"
+#include "exit.h"
+#include "env.h"
+#include "prot.h"
+#include "open.h"
+#include "wait.h"
+#include "readwrite.h"
+#include "stralloc.h"
+#include "alloc.h"
+#include "buffer.h"
+#include "error.h"
+#include "strerr.h"
+#include "sgetopt.h"
+#include "pathexec.h"
+#include "socket.h"
+#include "ndelay.h"
+#include "remoteinfo.h"
+#include "rules.h"
+#include "sig.h"
+#include "dns.h"
+
+int verbosity = 1;
+int flagkillopts = 1;
+int flagdelay = 1;
+char *banner = "";
+int flagremoteinfo = 1;
+int flagremotehost = 1;
+int flagparanoid = 0;
+unsigned long timeout = 26;
+
+static stralloc tcpremoteinfo;
+
+uint16 localport;
+char localportstr[FMT_ULONG];
+char localip[4];
+char localipstr[IP4_FMT];
+static stralloc localhostsa;
+char *localhost = 0;
+
+uint16 remoteport;
+char remoteportstr[FMT_ULONG];
+char remoteip[4];
+char remoteipstr[IP4_FMT];
+static stralloc remotehostsa;
+char *remotehost = 0;
+
+char strnum[FMT_ULONG];
+char strnum2[FMT_ULONG];
+
+static stralloc tmp;
+static stralloc fqdn;
+static stralloc addresses;
+
+char bspace[16];
+buffer b;
+
+
+
+/* ---------------------------- child */
+
+#define DROP "tcpserver: warning: dropping connection, "
+
+int flagdeny = 0;
+int flagallownorules = 0;
+char *fnrules = 0;
+
+void drop_nomem(void)
+{
+ strerr_die2sys(111,DROP,"out of memory");
+}
+void cats(char *s)
+{
+ if (!stralloc_cats(&tmp,s)) drop_nomem();
+}
+void append(char *ch)
+{
+ if (!stralloc_append(&tmp,ch)) drop_nomem();
+}
+void safecats(char *s)
+{
+ char ch;
+ int i;
+
+ for (i = 0;i < 100;++i) {
+ ch = s[i];
+ if (!ch) return;
+ if (ch < 33) ch = '?';
+ if (ch > 126) ch = '?';
+ if (ch == '%') ch = '?'; /* logger stupidity */
+ if (ch == ':') ch = '?';
+ append(&ch);
+ }
+ cats("...");
+}
+void env(char *s,char *t)
+{
+ if (!pathexec_env(s,t)) drop_nomem();
+}
+void drop_rules(void)
+{
+ strerr_die4sys(111,DROP,"unable to read ",fnrules,": ");
+}
+
+void found(char *data,unsigned int datalen)
+{
+ unsigned int next0;
+ unsigned int split;
+
+ while ((next0 = byte_chr(data,datalen,0)) < datalen) {
+ switch(data[0]) {
+ case 'D':
+ flagdeny = 1;
+ break;
+ case '+':
+ split = str_chr(data + 1,'=');
+ if (data[1 + split] == '=') {
+ data[1 + split] = 0;
+ env(data + 1,data + 1 + split + 1);
+ }
+ break;
+ }
+ ++next0;
+ data += next0; datalen -= next0;
+ }
+}
+
+void doit(int t)
+{
+ int j;
+
+ remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0;
+
+ if (verbosity >= 2) {
+ strnum[fmt_ulong(strnum,getpid())] = 0;
+ strerr_warn4("tcpserver: pid ",strnum," from ",remoteipstr,0);
+ }
+
+ if (flagkillopts)
+ socket_ipoptionskill(t);
+ if (!flagdelay)
+ socket_tcpnodelay(t);
+
+ if (*banner) {
+ buffer_init(&b,write,t,bspace,sizeof bspace);
+ if (buffer_putsflush(&b,banner) == -1)
+ strerr_die2sys(111,DROP,"unable to print banner: ");
+ }
+
+ if (socket_local4(t,localip,&localport) == -1)
+ strerr_die2sys(111,DROP,"unable to get local address: ");
+
+ localipstr[ip4_fmt(localipstr,localip)] = 0;
+ remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;
+
+ if (!localhost)
+ if (dns_name4(&localhostsa,localip) == 0)
+ if (localhostsa.len) {
+ if (!stralloc_0(&localhostsa)) drop_nomem();
+ localhost = localhostsa.s;
+ }
+ env("PROTO","TCP");
+ env("TCPLOCALIP",localipstr);
+ env("TCPLOCALPORT",localportstr);
+ env("TCPLOCALHOST",localhost);
+
+ if (flagremotehost)
+ if (dns_name4(&remotehostsa,remoteip) == 0)
+ if (remotehostsa.len) {
+ if (flagparanoid)
+ if (dns_ip4(&tmp,&remotehostsa) == 0)
+ for (j = 0;j + 4 <= tmp.len;j += 4)
+ if (byte_equal(remoteip,4,tmp.s + j)) {
+ flagparanoid = 0;
+ break;
+ }
+ if (!flagparanoid) {
+ if (!stralloc_0(&remotehostsa)) drop_nomem();
+ remotehost = remotehostsa.s;
+ }
+ }
+ env("TCPREMOTEIP",remoteipstr);
+ env("TCPREMOTEPORT",remoteportstr);
+ env("TCPREMOTEHOST",remotehost);
+
+ if (flagremoteinfo) {
+ if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout) == -1)
+ flagremoteinfo = 0;
+ if (!stralloc_0(&tcpremoteinfo)) drop_nomem();
+ }
+ env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
+
+ if (fnrules) {
+ int fdrules;
+ fdrules = open_read(fnrules);
+ if (fdrules == -1) {
+ if (errno != error_noent) drop_rules();
+ if (!flagallownorules) drop_rules();
+ }
+ else {
+ if (rules(found,fdrules,remoteipstr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules();
+ close(fdrules);
+ }
+ }
+
+ if (verbosity >= 2) {
+ strnum[fmt_ulong(strnum,getpid())] = 0;
+ if (!stralloc_copys(&tmp,"tcpserver: ")) drop_nomem();
+ safecats(flagdeny ? "deny" : "ok");
+ cats(" "); safecats(strnum);
+ cats(" "); if (localhost) safecats(localhost);
+ cats(":"); safecats(localipstr);
+ cats(":"); safecats(localportstr);
+ cats(" "); if (remotehost) safecats(remotehost);
+ cats(":"); safecats(remoteipstr);
+ cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
+ cats(":"); safecats(remoteportstr);
+ cats("\n");
+ buffer_putflush(buffer_2,tmp.s,tmp.len);
+ }
+
+ if (flagdeny) _exit(100);
+}
+
+
+
+/* ---------------------------- parent */
+
+#define FATAL "tcpserver: fatal: "
+
+void usage(void)
+{
+ strerr_warn1("\
+tcpserver: usage: tcpserver \
+[ -1UXpPhHrRoOdDqQv ] \
+[ -c limit ] \
+[ -x rules.cdb ] \
+[ -B banner ] \
+[ -g gid ] \
+[ -u uid ] \
+[ -b backlog ] \
+[ -l localname ] \
+[ -t timeout ] \
+host port program",0);
+ _exit(100);
+}
+
+unsigned long limit = 40;
+unsigned long numchildren = 0;
+
+int flag1 = 0;
+unsigned long backlog = 20;
+unsigned long uid = 0;
+unsigned long gid = 0;
+
+void printstatus(void)
+{
+ if (verbosity < 2) return;
+ strnum[fmt_ulong(strnum,numchildren)] = 0;
+ strnum2[fmt_ulong(strnum2,limit)] = 0;
+ strerr_warn4("tcpserver: status: ",strnum,"/",strnum2,0);
+}
+
+void sigterm()
+{
+ _exit(0);
+}
+
+void sigchld()
+{
+ int wstat;
+ int pid;
+
+ while ((pid = wait_nohang(&wstat)) > 0) {
+ if (verbosity >= 2) {
+ strnum[fmt_ulong(strnum,pid)] = 0;
+ strnum2[fmt_ulong(strnum2,wstat)] = 0;
+ strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0);
+ }
+ if (numchildren) --numchildren; printstatus();
+ }
+}
+
+main(int argc,char **argv)
+{
+ char *hostname;
+ char *portname;
+ int opt;
+ struct servent *se;
+ char *x;
+ unsigned long u;
+ int s;
+ int t;
+
+ while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof)
+ switch(opt) {
+ case 'b': scan_ulong(optarg,&backlog); break;
+ case 'c': scan_ulong(optarg,&limit); break;
+ case 'X': flagallownorules = 1; break;
+ case 'x': fnrules = optarg; break;
+ case 'B': banner = 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 'U': x = env_get("UID"); if (x) scan_ulong(x,&uid);
+ x = env_get("GID"); if (x) scan_ulong(x,&gid); break;
+ case 'u': scan_ulong(optarg,&uid); break;
+ case 'g': scan_ulong(optarg,&gid); break;
+ case '1': flag1 = 1; break;
+ case 'l': localhost = optarg; break;
+ default: usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!verbosity)
+ buffer_2->fd = -1;
+
+ hostname = *argv++;
+ if (!hostname) usage();
+ if (str_equal(hostname,"")) hostname = "0.0.0.0";
+ if (str_equal(hostname,"0")) hostname = "0.0.0.0";
+
+ x = *argv++;
+ if (!x) usage();
+ if (!x[scan_ulong(x,&u)])
+ localport = u;
+ else {
+ se = getservbyname(x,"tcp");
+ if (!se)
+ strerr_die3x(111,FATAL,"unable to figure out port number for ",x);
+ localport = ntohs(se->s_port);
+ }
+
+ if (!*argv) usage();
+
+ sig_block(sig_child);
+ sig_catch(sig_child,sigchld);
+ sig_catch(sig_term,sigterm);
+ sig_ignore(sig_pipe);
+
+ if (!stralloc_copys(&tmp,hostname))
+ strerr_die2x(111,FATAL,"out of memory");
+ if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1)
+ strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": ");
+ if (addresses.len < 4)
+ strerr_die3x(111,FATAL,"no IP address for ",hostname);
+ byte_copy(localip,4,addresses.s);
+
+ s = socket_tcp();
+ if (s == -1)
+ strerr_die2sys(111,FATAL,"unable to create socket: ");
+ if (socket_bind4_reuse(s,localip,localport) == -1)
+ strerr_die2sys(111,FATAL,"unable to bind: ");
+ if (socket_local4(s,localip,&localport) == -1)
+ strerr_die2sys(111,FATAL,"unable to get local address: ");
+ if (socket_listen(s,backlog) == -1)
+ strerr_die2sys(111,FATAL,"unable to listen: ");
+ ndelay_off(s);
+
+ if (gid) if (prot_gid(gid) == -1)
+ strerr_die2sys(111,FATAL,"unable to set gid: ");
+ if (uid) if (prot_uid(uid) == -1)
+ strerr_die2sys(111,FATAL,"unable to set uid: ");
+
+
+ localportstr[fmt_ulong(localportstr,localport)] = 0;
+ if (flag1) {
+ buffer_init(&b,write,1,bspace,sizeof bspace);
+ buffer_puts(&b,localportstr);
+ buffer_puts(&b,"\n");
+ buffer_flush(&b);
+ }
+
+ close(0);
+ close(1);
+ printstatus();
+
+ for (;;) {
+ while (numchildren >= limit) sig_pause();
+
+ sig_unblock(sig_child);
+ t = socket_accept4(s,remoteip,&remoteport);
+ sig_block(sig_child);
+
+ if (t == -1) continue;
+ ++numchildren; printstatus();
+
+ switch(fork()) {
+ case 0:
+ close(s);
+ doit(t);
+ if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1))
+ strerr_die2sys(111,DROP,"unable to set up descriptors: ");
+ sig_uncatch(sig_child);
+ sig_unblock(sig_child);
+ sig_uncatch(sig_term);
+ sig_uncatch(sig_pipe);
+ pathexec(argv);
+ strerr_die4sys(111,DROP,"unable to run ",*argv,": ");
+ case -1:
+ strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
+ --numchildren; printstatus();
+ }
+ close(t);
+ }
+}
diff --git a/ucspi-tcp-0.88/timeoutconn.c b/ucspi-tcp-0.88/timeoutconn.c
new file mode 100644
index 0000000..2a8b0aa
--- /dev/null
+++ b/ucspi-tcp-0.88/timeoutconn.c
@@ -0,0 +1,34 @@
+#include "ndelay.h"
+#include "socket.h"
+#include "iopause.h"
+#include "error.h"
+#include "timeoutconn.h"
+
+int timeoutconn(int s,char ip[4],uint16 port,unsigned int timeout)
+{
+ struct taia now;
+ struct taia deadline;
+ iopause_fd x;
+
+ if (socket_connect4(s,ip,port) == -1) {
+ if ((errno != error_wouldblock) && (errno != error_inprogress)) return -1;
+ x.fd = s;
+ x.events = IOPAUSE_WRITE;
+ taia_now(&now);
+ taia_uint(&deadline,timeout);
+ taia_add(&deadline,&now,&deadline);
+ for (;;) {
+ taia_now(&now);
+ iopause(&x,1,&deadline,&now);
+ if (x.revents) break;
+ if (taia_less(&deadline,&now)) {
+ errno = error_timeout; /* note that connect attempt is continuing */
+ return -1;
+ }
+ }
+ if (!socket_connected(s)) return -1;
+ }
+
+ if (ndelay_off(s) == -1) return -1;
+ return 0;
+}
diff --git a/ucspi-tcp-0.88/timeoutconn.h b/ucspi-tcp-0.88/timeoutconn.h
new file mode 100644
index 0000000..7f9dcc9
--- /dev/null
+++ b/ucspi-tcp-0.88/timeoutconn.h
@@ -0,0 +1,8 @@
+#ifndef TIMEOUTCONN_H
+#define TIMEOUTCONN_H
+
+#include "uint16.h"
+
+extern int timeoutconn(int,char *,uint16,unsigned int);
+
+#endif
diff --git a/ucspi-tcp-0.88/trycpp.c b/ucspi-tcp-0.88/trycpp.c
new file mode 100644
index 0000000..3ab455b
--- /dev/null
+++ b/ucspi-tcp-0.88/trycpp.c
@@ -0,0 +1,7 @@
+main()
+{
+#ifdef NeXT
+ printf("nextstep\n"); exit(0);
+#endif
+ printf("unknown\n"); exit(0);
+}
diff --git a/ucspi-tcp-0.88/trylsock.c b/ucspi-tcp-0.88/trylsock.c
new file mode 100644
index 0000000..fbce408
--- /dev/null
+++ b/ucspi-tcp-0.88/trylsock.c
@@ -0,0 +1,4 @@
+main()
+{
+ ;
+}
diff --git a/ucspi-tcp-0.88/trypoll.c b/ucspi-tcp-0.88/trypoll.c
new file mode 100644
index 0000000..249824d
--- /dev/null
+++ b/ucspi-tcp-0.88/trypoll.c
@@ -0,0 +1,18 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include <poll.h>
+
+main()
+{
+ struct pollfd x;
+
+ x.fd = open("trypoll.c",O_RDONLY);
+ if (x.fd == -1) _exit(111);
+ x.events = POLLIN;
+ if (poll(&x,1,10) == -1) _exit(1);
+ if (x.revents != POLLIN) _exit(1);
+
+ /* XXX: try to detect and avoid poll() imitation libraries */
+
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/trysgact.c b/ucspi-tcp-0.88/trysgact.c
new file mode 100644
index 0000000..98a4b20
--- /dev/null
+++ b/ucspi-tcp-0.88/trysgact.c
@@ -0,0 +1,10 @@
+#include <signal.h>
+
+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/ucspi-tcp-0.88/trysgprm.c b/ucspi-tcp-0.88/trysgprm.c
new file mode 100644
index 0000000..2797eea
--- /dev/null
+++ b/ucspi-tcp-0.88/trysgprm.c
@@ -0,0 +1,10 @@
+#include <signal.h>
+
+main()
+{
+ sigset_t ss;
+
+ sigemptyset(&ss);
+ sigaddset(&ss,SIGCHLD);
+ sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
+}
diff --git a/ucspi-tcp-0.88/tryshsgr.c b/ucspi-tcp-0.88/tryshsgr.c
new file mode 100644
index 0000000..f55ff60
--- /dev/null
+++ b/ucspi-tcp-0.88/tryshsgr.c
@@ -0,0 +1,14 @@
+main()
+{
+ short x[4];
+
+ x[0] = x[1] = 1;
+ if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1);
+
+ if (getgroups(1,x) == -1) _exit(1);
+ if (x[1] != 1) _exit(1);
+ x[1] = 2;
+ if (getgroups(1,x) == -1) _exit(1);
+ if (x[1] != 2) _exit(1);
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/trysysel.c b/ucspi-tcp-0.88/trysysel.c
new file mode 100644
index 0000000..f6ed055
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/tryulong32.c b/ucspi-tcp-0.88/tryulong32.c
new file mode 100644
index 0000000..63156e6
--- /dev/null
+++ b/ucspi-tcp-0.88/tryulong32.c
@@ -0,0 +1,11 @@
+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/ucspi-tcp-0.88/tryulong64.c b/ucspi-tcp-0.88/tryulong64.c
new file mode 100644
index 0000000..01965cb
--- /dev/null
+++ b/ucspi-tcp-0.88/tryulong64.c
@@ -0,0 +1,11 @@
+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(1);
+ _exit(0);
+}
diff --git a/ucspi-tcp-0.88/tryvfork.c b/ucspi-tcp-0.88/tryvfork.c
new file mode 100644
index 0000000..cc39699
--- /dev/null
+++ b/ucspi-tcp-0.88/tryvfork.c
@@ -0,0 +1,4 @@
+main()
+{
+ vfork();
+}
diff --git a/ucspi-tcp-0.88/trywaitp.c b/ucspi-tcp-0.88/trywaitp.c
new file mode 100644
index 0000000..64d807e
--- /dev/null
+++ b/ucspi-tcp-0.88/trywaitp.c
@@ -0,0 +1,7 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+
+main()
+{
+ waitpid(0,0,0);
+}
diff --git a/ucspi-tcp-0.88/uint16.h b/ucspi-tcp-0.88/uint16.h
new file mode 100644
index 0000000..34ab9f4
--- /dev/null
+++ b/ucspi-tcp-0.88/uint16.h
@@ -0,0 +1,11 @@
+#ifndef UINT16_H
+#define UINT16_H
+
+typedef unsigned short uint16;
+
+extern void uint16_pack(char *,uint16);
+extern void uint16_pack_big(char *,uint16);
+extern void uint16_unpack(char *,uint16 *);
+extern void uint16_unpack_big(char *,uint16 *);
+
+#endif
diff --git a/ucspi-tcp-0.88/uint16_pack.c b/ucspi-tcp-0.88/uint16_pack.c
new file mode 100644
index 0000000..17dbfe6
--- /dev/null
+++ b/ucspi-tcp-0.88/uint16_pack.c
@@ -0,0 +1,13 @@
+#include "uint16.h"
+
+void uint16_pack(char s[2],uint16 u)
+{
+ s[0] = u & 255;
+ s[1] = u >> 8;
+}
+
+void uint16_pack_big(char s[2],uint16 u)
+{
+ s[1] = u & 255;
+ s[0] = u >> 8;
+}
diff --git a/ucspi-tcp-0.88/uint16_unpack.c b/ucspi-tcp-0.88/uint16_unpack.c
new file mode 100644
index 0000000..18b5b12
--- /dev/null
+++ b/ucspi-tcp-0.88/uint16_unpack.c
@@ -0,0 +1,23 @@
+#include "uint16.h"
+
+void uint16_unpack(char s[2],uint16 *u)
+{
+ uint16 result;
+
+ result = (unsigned char) s[1];
+ result <<= 8;
+ result += (unsigned char) s[0];
+
+ *u = result;
+}
+
+void uint16_unpack_big(char s[2],uint16 *u)
+{
+ uint16 result;
+
+ result = (unsigned char) s[0];
+ result <<= 8;
+ result += (unsigned char) s[1];
+
+ *u = result;
+}
diff --git a/ucspi-tcp-0.88/uint32.h1 b/ucspi-tcp-0.88/uint32.h1
new file mode 100644
index 0000000..68d7231
--- /dev/null
+++ b/ucspi-tcp-0.88/uint32.h1
@@ -0,0 +1,11 @@
+#ifndef UINT32_H
+#define UINT32_H
+
+typedef unsigned int uint32;
+
+extern void uint32_pack(char *,uint32);
+extern void uint32_pack_big(char *,uint32);
+extern void uint32_unpack(char *,uint32 *);
+extern void uint32_unpack_big(char *,uint32 *);
+
+#endif
diff --git a/ucspi-tcp-0.88/uint32.h2 b/ucspi-tcp-0.88/uint32.h2
new file mode 100644
index 0000000..b5c7f40
--- /dev/null
+++ b/ucspi-tcp-0.88/uint32.h2
@@ -0,0 +1,11 @@
+#ifndef UINT32_H
+#define UINT32_H
+
+typedef unsigned long uint32;
+
+extern void uint32_pack(char *,uint32);
+extern void uint32_pack_big(char *,uint32);
+extern void uint32_unpack(char *,uint32 *);
+extern void uint32_unpack_big(char *,uint32 *);
+
+#endif
diff --git a/ucspi-tcp-0.88/uint32_pack.c b/ucspi-tcp-0.88/uint32_pack.c
new file mode 100644
index 0000000..76bc670
--- /dev/null
+++ b/ucspi-tcp-0.88/uint32_pack.c
@@ -0,0 +1,21 @@
+#include "uint32.h"
+
+void uint32_pack(char s[4],uint32 u)
+{
+ s[0] = u & 255;
+ u >>= 8;
+ s[1] = u & 255;
+ u >>= 8;
+ s[2] = u & 255;
+ s[3] = u >> 8;
+}
+
+void uint32_pack_big(char s[4],uint32 u)
+{
+ s[3] = u & 255;
+ u >>= 8;
+ s[2] = u & 255;
+ u >>= 8;
+ s[1] = u & 255;
+ s[0] = u >> 8;
+}
diff --git a/ucspi-tcp-0.88/uint32_unpack.c b/ucspi-tcp-0.88/uint32_unpack.c
new file mode 100644
index 0000000..f484644
--- /dev/null
+++ b/ucspi-tcp-0.88/uint32_unpack.c
@@ -0,0 +1,31 @@
+#include "uint32.h"
+
+void uint32_unpack(char s[4],uint32 *u)
+{
+ uint32 result;
+
+ result = (unsigned char) s[3];
+ result <<= 8;
+ result += (unsigned char) s[2];
+ result <<= 8;
+ result += (unsigned char) s[1];
+ result <<= 8;
+ result += (unsigned char) s[0];
+
+ *u = result;
+}
+
+void uint32_unpack_big(char s[4],uint32 *u)
+{
+ uint32 result;
+
+ result = (unsigned char) s[0];
+ result <<= 8;
+ result += (unsigned char) s[1];
+ result <<= 8;
+ result += (unsigned char) s[2];
+ result <<= 8;
+ result += (unsigned char) s[3];
+
+ *u = result;
+}
diff --git a/ucspi-tcp-0.88/uint64.h1 b/ucspi-tcp-0.88/uint64.h1
new file mode 100644
index 0000000..206fc09
--- /dev/null
+++ b/ucspi-tcp-0.88/uint64.h1
@@ -0,0 +1,8 @@
+#ifndef UINT64_H
+#define UINT64_H
+
+/* sysdep: -ulong64 */
+
+typedef unsigned long long uint64;
+
+#endif
diff --git a/ucspi-tcp-0.88/uint64.h2 b/ucspi-tcp-0.88/uint64.h2
new file mode 100644
index 0000000..8a0f315
--- /dev/null
+++ b/ucspi-tcp-0.88/uint64.h2
@@ -0,0 +1,8 @@
+#ifndef UINT64_H
+#define UINT64_H
+
+/* sysdep: +ulong64 */
+
+typedef unsigned long uint64;
+
+#endif
diff --git a/ucspi-tcp-0.88/wait.h b/ucspi-tcp-0.88/wait.h
new file mode 100644
index 0000000..cdb77c3
--- /dev/null
+++ b/ucspi-tcp-0.88/wait.h
@@ -0,0 +1,14 @@
+#ifndef WAIT_H
+#define WAIT_H
+
+extern int wait_pid();
+extern int wait_nohang();
+extern int wait_stop();
+extern int wait_stopnohang();
+
+#define wait_crashed(w) ((w) & 127)
+#define wait_exitcode(w) ((w) >> 8)
+#define wait_stopsig(w) ((w) >> 8)
+#define wait_stopped(w) (((w) & 127) == 127)
+
+#endif
diff --git a/ucspi-tcp-0.88/wait_nohang.c b/ucspi-tcp-0.88/wait_nohang.c
new file mode 100644
index 0000000..bea2774
--- /dev/null
+++ b/ucspi-tcp-0.88/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/ucspi-tcp-0.88/wait_pid.c b/ucspi-tcp-0.88/wait_pid.c
new file mode 100644
index 0000000..d7a7e84
--- /dev/null
+++ b/ucspi-tcp-0.88/wait_pid.c
@@ -0,0 +1,39 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "error.h"
+#include "haswaitp.h"
+
+#ifdef HASWAITPID
+
+int wait_pid(wstat,pid) int *wstat; int pid;
+{
+ int r;
+
+ do
+ r = waitpid(pid,wstat,0);
+ while ((r == -1) && (errno == error_intr));
+ return r;
+}
+
+#else
+
+/* XXX untested */
+/* XXX breaks down with more than two children */
+static int oldpid = 0;
+static int oldwstat; /* defined if(oldpid) */
+
+int wait_pid(wstat,pid) int *wstat; int pid;
+{
+ int r;
+
+ if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; }
+
+ do {
+ r = wait(wstat);
+ if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; }
+ }
+ while ((r == -1) && (errno == error_intr));
+ return r;
+}
+
+#endif
diff --git a/ucspi-tcp-0.88/warn-auto.sh b/ucspi-tcp-0.88/warn-auto.sh
new file mode 100644
index 0000000..36d2313
--- /dev/null
+++ b/ucspi-tcp-0.88/warn-auto.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+# WARNING: This file was auto-generated. Do not edit!
diff --git a/ucspi-tcp-0.88/warn-shsgr b/ucspi-tcp-0.88/warn-shsgr
new file mode 100644
index 0000000..37c351e
--- /dev/null
+++ b/ucspi-tcp-0.88/warn-shsgr
@@ -0,0 +1,3 @@
+Oops. Your getgroups() returned 0, and setgroups() failed; this means
+that I can't reliably do my shsgr test. Please either ``make'' as root
+or ``make'' while you're in one or more supplementary groups.
diff --git a/ucspi-tcp-0.88/who@.sh b/ucspi-tcp-0.88/who@.sh
new file mode 100644
index 0000000..5c7550f
--- /dev/null
+++ b/ucspi-tcp-0.88/who@.sh
@@ -0,0 +1 @@
+HOME/bin/tcpclient -RHl0 -- "${1-0}" 11 sh -c 'exec HOME/bin/delcr <&6' | cat -v
diff --git a/ucspi-tcp-0.88/x86cpuid.c b/ucspi-tcp-0.88/x86cpuid.c
new file mode 100644
index 0000000..900d7d5
--- /dev/null
+++ b/ucspi-tcp-0.88/x86cpuid.c
@@ -0,0 +1,38 @@
+#include <signal.h>
+
+void nope()
+{
+ exit(1);
+}
+
+main()
+{
+ unsigned long x[4];
+ unsigned long y[4];
+ int i;
+ int j;
+ char c;
+
+ signal(SIGILL,nope);
+
+ x[0] = 0;
+ x[1] = 0;
+ x[2] = 0;
+ x[3] = 0;
+
+ asm volatile(".byte 15;.byte 162" : "=a"(x[0]),"=b"(x[1]),"=c"(x[3]),"=d"(x[2]) : "0"(0) );
+ if (!x[0]) return 0;
+ asm volatile(".byte 15;.byte 162" : "=a"(y[0]),"=b"(y[1]),"=c"(y[2]),"=d"(y[3]) : "0"(1) );
+
+ for (i = 1;i < 4;++i)
+ for (j = 0;j < 4;++j) {
+ c = x[i] >> (8 * j);
+ if (c < 32) c = 32;
+ if (c > 126) c = 126;
+ putchar(c);
+ }
+
+ printf("-%08x-%08x\n",y[0],y[3]);
+
+ return 0;
+}